diff --git a/.github/workflows/arduino_esp32.yaml b/.github/workflows/arduino_esp32.yaml index 1bc0f27e4..a1c386616 100644 --- a/.github/workflows/arduino_esp32.yaml +++ b/.github/workflows/arduino_esp32.yaml @@ -51,7 +51,7 @@ jobs: mkdir -p $ARDUINO_BASE cd $ARDUINO_BASE - platformio init -b esp32thing_plus -O "build_flags=-DZ_FEATURE_LINK_BLUETOOTH=1 -DZENOH_DEBUG=3 -DZENOH_COMPILER_GCC" -O "lib_ldf_mode=deep+" + platformio init -b esp32thing_plus -O "board_build.cmake_extra_args=-DZ_FEATURE_LINK_BLUETOOTH=1" -O "build_flags=-DZENOH_DEBUG=3 -DZENOH_COMPILER_GCC" -O "lib_ldf_mode=deep+" cd $ARDUINO_BASE/lib ln -s $ZENOH_PICO_BASE diff --git a/.github/workflows/build-check.yaml b/.github/workflows/build-check.yaml index b372314fa..59a3f172c 100644 --- a/.github/workflows/build-check.yaml +++ b/.github/workflows/build-check.yaml @@ -65,7 +65,6 @@ jobs: run: | sudo apt install -y ninja-build Z_FEATURE_RAWETH_TRANSPORT=1 CMAKE_GENERATOR=Ninja make - zenoh_build: name: Build Zenoh from source @@ -128,6 +127,19 @@ jobs: if: always() run: kill ${{ steps.run-zenoh.outputs.zenohd-pid }} + unstable_build: + name: Check compilation with unstable API + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build with unstable + run: | + sudo apt install -y ninja-build + Z_FEATURE_UNSTABLE_API=1 CMAKE_GENERATOR=Ninja make + + st_build: needs: zenoh_build name: Build and test in single thread on ubuntu-latest @@ -196,3 +208,50 @@ jobs: - name: Kill Zenoh router if: always() run: kill ${{ steps.run-zenoh.outputs.zenohd-pid }} + + attachment_test: + needs: zenoh_build + name: Test attachments + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Download Zenoh artifacts + uses: actions/download-artifact@v4 + with: + name: ${{ needs.zenoh_build.outputs.artifact-name }} + + - name: Unzip Zenoh artifacts + run: unzip ${{ needs.zenoh_build.outputs.artifact-name }} -d zenoh-standalone + + - id: run-zenoh + name: Run Zenoh router + run: | + RUST_LOG=debug ./zenoh-standalone/zenohd & + echo "zenohd-pid=$!" >> $GITHUB_OUTPUT + + - name: Build project and run test + run: | + sudo apt install -y ninja-build + CMAKE_GENERATOR=Ninja make + python3 ./build/tests/attachment.py + timeout-minutes: 5 + + - name: Kill Zenoh router + if: always() + run: kill ${{ steps.run-zenoh.outputs.zenohd-pid }} + + no_routeur: + name: Test examples without router + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build & test pico + run: | + sudo apt install -y ninja-build + CMAKE_GENERATOR=Ninja make + python3 ./build/tests/no_router.py + timeout-minutes: 5 diff --git a/.github/workflows/emscripten.yaml b/.github/workflows/emscripten.yaml index a240c7188..c097789dc 100644 --- a/.github/workflows/emscripten.yaml +++ b/.github/workflows/emscripten.yaml @@ -34,5 +34,5 @@ jobs: - name: Compile debug run: | mkdir build - emcmake cmake -E env CFLAGS="-DZ_FEATURE_LINK_WS=1 -DZ_FEATURE_LINK_TCP=0 -DZ_FEATURE_LINK_UDP_MULTICAST=0 -DZ_FEATURE_LINK_UDP_UNICAST=0 -DZ_FEATURE_SCOUTING_UDP=0" cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_STANDARD=11 -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=OFF -DBUILD_MULTICAST=OFF -DBUILD_INTEGRATION=OFF -DBUILD_TOOLS=OFF -DZENOH_DEBUG=3 -H. -Bbuild + emcmake cmake -DBUILD_SHARED_LIBS=OFF -DCMAKE_C_STANDARD=11 -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=OFF -DBUILD_MULTICAST=OFF -DBUILD_INTEGRATION=OFF -DBUILD_TOOLS=OFF -DZENOH_DEBUG=3 -DZ_FEATURE_LINK_WS=1 -DZ_FEATURE_LINK_TCP=0 -DZ_FEATURE_LINK_UDP_MULTICAST=0 -DZ_FEATURE_LINK_UDP_UNICAST=0 -DZ_FEATURE_SCOUTING_UDP=0 -H. -Bbuild make -C build diff --git a/.github/workflows/freertos_plus_tcp.yaml b/.github/workflows/freertos_plus_tcp.yaml index c3e56e62b..8e29b7bcb 100644 --- a/.github/workflows/freertos_plus_tcp.yaml +++ b/.github/workflows/freertos_plus_tcp.yaml @@ -37,11 +37,6 @@ jobs: - name: Build examples run: | cd examples/freertos_plus_tcp - cmake -Bbuild -G"Ninja Multi-Config" + cmake -Bbuild -G"Ninja Multi-Config" -DZ_FEATURE_LINK_UDP_MULTICAST=0 -DZ_CONFIG_SOCKET_TIMEOUT=1000 cmake --build ./build --config Debug cmake --build ./build --config Release - env: - Z_FEATURE_PUBLICATION: 1 - Z_FEATURE_SUBSCRIPTION: 1 - Z_FEATURE_QUERYABLE: 1 - Z_FEATURE_QUERY: 1 diff --git a/.github/workflows/mbed.yaml b/.github/workflows/mbed.yaml index d3c799cd3..5d7a57b7d 100644 --- a/.github/workflows/mbed.yaml +++ b/.github/workflows/mbed.yaml @@ -51,7 +51,7 @@ jobs: mkdir -p $MBED_BASE cd $MBED_BASE - pio init -b nucleo_f767zi --project-option="framework=mbed" --project-option="build_flags=-DZ_FEATURE_LINK_SERIAL=1 -DZENOH_DEBUG=3 -DZENOH_COMPILER_GCC" + pio init -b nucleo_f767zi --project-option="framework=mbed" --project-option="board_build.cmake_extra_args=-DZ_FEATURE_LINK_SERIAL=1" -O "build_flags=-DZENOH_DEBUG=3 -DZENOH_COMPILER_GCC" cd $MBED_BASE/lib ln -s $ZENOH_PICO_BASE diff --git a/.github/workflows/zephyr.yaml b/.github/workflows/zephyr.yaml index 20c7082fe..3cf503c04 100644 --- a/.github/workflows/zephyr.yaml +++ b/.github/workflows/zephyr.yaml @@ -49,7 +49,7 @@ jobs: mkdir -p $ZEPHYR_BASE cd $ZEPHYR_BASE - pio init -b nucleo_f767zi --project-option="framework=zephyr" --project-option="build_flags=-DZ_FEATURE_LINK_SERIAL=1 -DZENOH_DEBUG=3" + pio init -b nucleo_f767zi --project-option="framework=zephyr" --project-option="board_build.cmake_extra_args=-DZ_FEATURE_LINK_SERIAL=1 -DZENOH_DEBUG=3" cd $ZEPHYR_BASE/lib ln -s $ZENOH_PICO_BASE diff --git a/CMakeLists.txt b/CMakeLists.txt index c33e1fcd0..1cd4b89b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -26,11 +26,19 @@ set(ZENOH_PICO_MAJOR ${PROJECT_VERSION_MAJOR}) set(ZENOH_PICO_MINOR ${PROJECT_VERSION_MINOR}) set(ZENOH_PICO_PATCH ${PROJECT_VERSION_PATCH}) set(ZENOH_PICO_TWEAK ${PROJECT_VERSION_TWEAK}) + configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h @ONLY ) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/library.json.in + ${CMAKE_CURRENT_SOURCE_DIR}/library.json + @ONLY +) + set(project_version "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") if(NOT DEFINED PROJECT_VERSION_TWEAK) set(project_version "${project_version}") @@ -49,8 +57,6 @@ option(BUILD_SHARED_LIBS "Build shared libraries if ON, otherwise build static l option(WITH_ZEPHYR "Build for Zephyr RTOS" OFF) option(WITH_FREERTOS_PLUS_TCP "Build for FreeRTOS RTOS and FreeRTOS-Plus-TCP network stack" OFF) set(ZENOH_DEBUG 0 CACHE STRING "Use this to set the ZENOH_DEBUG variable") -set(FRAG_MAX_SIZE 0 CACHE STRING "Use this to override the maximum size for fragmented messages") -set(BATCH_UNICAST_SIZE 0 CACHE STRING "Use this to override the maximum unicast batch size") set(CMAKE_EXPORT_COMPILE_COMMANDS ON CACHE INTERNAL "") if(CMAKE_EXPORT_COMPILE_COMMANDS) set(CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES @@ -65,6 +71,42 @@ elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") endif() endif() +# Language options +if(NOT CMAKE_C_STANDARD) + if(c_std_11 IN_LIST CMAKE_C_COMPILE_FEATURES) + set(CMAKE_C_STANDARD 11) + message(STATUS "Setting C11 as the C Standard") + else() + # C99 pedantic doesn't like unix header anonymous structure + set(CMAKE_C_STANDARD 99) + message(STATUS "Setting C99 as the C Standard") + endif() +endif() +set(CMAKE_C_STANDARD_REQUIRED TRUE) + +# Compile options +if(CMAKE_BUILD_TYPE MATCHES "RELEASE" OR "Release") + if(UNIX) + add_compile_options(-pipe -O3) + elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") + add_compile_options(-pipe -O3) + endif() +else() + if(UNIX) + add_compile_options(-c -Wall -Wextra -Werror -Wshadow -Wunused -Wstrict-prototypes -pipe -g -O0) + # C99 pedantic doesn't like struct anonymous in unix header + if (NOT CMAKE_C_STANDARD STREQUAL "99") + add_compile_options(-Wpedantic) + endif() + # add_compile_options(-Wconversion) + # add_link_options(-fsanitize=address) + elseif(MSVC) + add_compile_options(/W4 /WX /Od /wd4127) + elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") + add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -pipe -g -O0) + endif() +endif() + set(Libname "zenohpico") if(BUILD_SHARED_LIBS) add_library(${Libname} SHARED) @@ -77,16 +119,6 @@ function(add_definition value) target_compile_definitions(${Libname} PUBLIC ${value}) endfunction() -if(NOT CMAKE_C_STANDARD) - if(c_std_11 IN_LIST CMAKE_C_COMPILE_FEATURES) - set(CMAKE_C_STANDARD 11) - message(STATUS "Setting C11 as the C Standard") - else() - set(CMAKE_C_STANDARD 99) - message(STATUS "Setting C99 as the C Standard") - endif() -endif() -set(CMAKE_C_STANDARD_REQUIRED TRUE) add_definition(ZENOH_C_STANDARD=${CMAKE_C_STANDARD}) # while in development, use timestamp for patch version: @@ -145,48 +177,66 @@ endif() add_definition(ZENOH_DEBUG=${ZENOH_DEBUG}) -if(FRAG_MAX_SIZE) - add_definition(Z_FRAG_MAX_SIZE=${FRAG_MAX_SIZE}) -endif() -if (BATCH_UNICAST_SIZE) - add_definition(Z_BATCH_UNICAST_SIZE=${BATCH_UNICAST_SIZE}) -endif() # Zenoh pico feature configuration options -set(Z_FEATURE_MULTI_THREAD 1 CACHE STRING "Toggle multithread feature") +set(FRAG_MAX_SIZE 4096 CACHE STRING "Use this to override the maximum size for fragmented messages") +set(BATCH_UNICAST_SIZE 2048 CACHE STRING "Use this to override the maximum unicast batch size") +set(BATCH_MULTICAST_SIZE 2048 CACHE STRING "Use this to override the maximum multicast batch size") +set(Z_CONFIG_SOCKET_TIMEOUT 100 CACHE STRING "Default socket timeout in milliseconds") + +set(Z_FEATURE_UNSTABLE_API 0 CACHE STRING "Toggle unstable Zenoh-C API") set(Z_FEATURE_PUBLICATION 1 CACHE STRING "Toggle publication feature") set(Z_FEATURE_SUBSCRIPTION 1 CACHE STRING "Toggle subscription feature") set(Z_FEATURE_QUERY 1 CACHE STRING "Toggle query feature") set(Z_FEATURE_QUERYABLE 1 CACHE STRING "Toggle queryable feature") -set(Z_FEATURE_RAWETH_TRANSPORT 0 CACHE STRING "Toggle raw ethernet transport feature") -set(Z_FEATURE_ATTACHMENT 1 CACHE STRING "Toggle attachment feature") -add_definition(Z_FEATURE_MULTI_THREAD=${Z_FEATURE_MULTI_THREAD}) -add_definition(Z_FEATURE_PUBLICATION=${Z_FEATURE_PUBLICATION}) -add_definition(Z_FEATURE_SUBSCRIPTION=${Z_FEATURE_SUBSCRIPTION}) -add_definition(Z_FEATURE_QUERY=${Z_FEATURE_QUERY}) -add_definition(Z_FEATURE_QUERYABLE=${Z_FEATURE_QUERYABLE}) -add_definition(Z_FEATURE_RAWETH_TRANSPORT=${Z_FEATURE_RAWETH_TRANSPORT}) -add_definition(Z_FEATURE_ATTACHMENT=${Z_FEATURE_ATTACHMENT}) +set(Z_FEATURE_INTEREST 1 CACHE STRING "Toggle interests") +set(Z_FEATURE_FRAGMENTATION 1 CACHE STRING "Toggle fragmentation") +set(Z_FEATURE_ENCODING_VALUES 1 CACHE STRING "Toggle encoding values") +set(Z_FEATURE_MULTI_THREAD 1 CACHE STRING "Toggle multithread") +set(Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION 0 CACHE STRING "Toggle dynamic memory allocation") + +set(Z_FEATURE_LINK_TCP 1 CACHE STRING "Toggle TCP links") +set(Z_FEATURE_LINK_BLUETOOTH 0 CACHE STRING "Toggle Bluetooth links") +set(Z_FEATURE_LINK_WS 0 CACHE STRING "Toggle WebSocket links") +set(Z_FEATURE_LINK_SERIAL 0 CACHE STRING "Toggle Serial links") +set(Z_FEATURE_SCOUTING_UDP 1 CACHE STRING "Toggle UDP scouting") +set(Z_FEATURE_LINK_UDP_MULTICAST 1 CACHE STRING "Toggle UDP multicast links") +set(Z_FEATURE_LINK_UDP_UNICAST 1 CACHE STRING "Toggle UDP unicast links") +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_INTEREST 1 CACHE STRING "Toggle interest feature") + add_compile_definitions("Z_BUILD_DEBUG=$") message(STATUS "Building with feature confing:\n\ +* UNSTABLE_API: ${Z_FEATURE_UNSTABLE_API}\n\ * MULTI-THREAD: ${Z_FEATURE_MULTI_THREAD}\n\ * PUBLICATION: ${Z_FEATURE_PUBLICATION}\n\ * SUBSCRIPTION: ${Z_FEATURE_SUBSCRIPTION}\n\ * QUERY: ${Z_FEATURE_QUERY}\n\ * QUERYABLE: ${Z_FEATURE_QUERYABLE}\n\ -* ATTACHMENT: ${Z_FEATURE_ATTACHMENT}\n\ +* INTEREST: ${Z_FEATURE_INTEREST}\n\ * RAWETH: ${Z_FEATURE_RAWETH_TRANSPORT}") +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico.h + @ONLY +) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico/config.h.in + ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico/config.h + @ONLY +) + # Print summary of CMAKE configurations message(STATUS "Building in ${CMAKE_BUILD_TYPE} mode") message(STATUS "Build shared library: ${BUILD_SHARED_LIBS}") message(STATUS "Zenoh Level Log: ${ZENOH_DEBUG}") -if(FRAG_MAX_SIZE) - message(STATUS "Fragmented message max size: ${FRAG_MAX_SIZE}") -endif() -if(BATCH_UNICAST_SIZE) - message(STATUS "Unicast batch max size: ${BATCH_UNICAST_SIZE}") -endif() +message(STATUS "Fragmented message max size: ${FRAG_MAX_SIZE}") +message(STATUS "Unicast batch max size: ${BATCH_UNICAST_SIZE}") +message(STATUS "Multicast batch max size: ${BATCH_MULTICAST_SIZE}") message(STATUS "Build for Zephyr RTOS: ${WITH_ZEPHYR}") message(STATUS "Build for FreeRTOS-Plus-TCP: ${WITH_FREERTOS_PLUS_TCP}") message(STATUS "Configuring for ${CMAKE_SYSTEM_NAME}") @@ -202,30 +252,11 @@ if(CHECK_THREADS) find_package(Threads REQUIRED) endif() -if(CMAKE_BUILD_TYPE MATCHES "DEBUG") - if(UNIX) - add_compile_options(-c -Wall -Wextra -Werror -Wshadow -Wpedantic -Wunused -Wstrict-prototypes -pipe -g -O0) - # add_compile_options(-Wconversion) - # add_link_options(-fsanitize=address) - elseif(MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /std:c11 /experimental:c11atomics") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /experimental:c11atomics") - add_compile_options(/W4 /WX /Od) - elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") - add_compile_options(-Wall -Wextra -Wno-unused-parameter -Wmissing-prototypes -pipe -g -O0) - endif() -elseif(CMAKE_BUILD_TYPE MATCHES "RELEASE") - if(UNIX) - add_compile_options(-pipe -O3) - elseif(MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /std:c11 /experimental:c11atomics") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /experimental:c11atomics") - elseif(CMAKE_SYSTEM_NAME MATCHES "Generic") - add_compile_options(-pipe -O3) - endif() +if(MSVC) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /std:c11 /experimental:c11atomics") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest /experimental:c11atomics") endif() - file(GLOB_RECURSE PublicHeaders "include/zenoh-pico/api/*.h" "include/zenoh-pico/collections/*.h" @@ -242,13 +273,13 @@ target_include_directories(${Libname} PUBLIC ${PROJECT_SOURCE_DIR}/include) file(GLOB_RECURSE Sources "src/api/*.c" "src/collections/*.c" - "src/deprecated/*.c" "src/link/*.c" "src/net/*.c" "src/protocol/*.c" "src/session/*.c" "src/transport/*.c" "src/utils/*.c" + "src/system/platform-common.c" ) if(WITH_ZEPHYR) @@ -315,6 +346,11 @@ install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/include/zenoh-pico DESTINATION include COMPONENT Headers ) +if(BUILD_SHARED_LIBS) + set(LIBNAME ${CMAKE_SHARED_LIBRARY_PREFIX}${Libname}${CMAKE_SHARED_LIBRARY_SUFFIX}) +else() + set(LIBNAME ${CMAKE_STATIC_LIBRARY_PREFIX}${Libname}${CMAKE_STATIC_LIBRARY_SUFFIX}) +endif() set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/zenohpico") # Generate Config.cmake @@ -356,6 +392,8 @@ if(UNIX OR MSVC) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/tests") add_executable(z_data_struct_test ${PROJECT_SOURCE_DIR}/tests/z_data_struct_test.c) + add_executable(z_channels_test ${PROJECT_SOURCE_DIR}/tests/z_channels_test.c) + add_executable(z_collections_test ${PROJECT_SOURCE_DIR}/tests/z_collections_test.c) add_executable(z_endpoint_test ${PROJECT_SOURCE_DIR}/tests/z_endpoint_test.c) add_executable(z_iobuf_test ${PROJECT_SOURCE_DIR}/tests/z_iobuf_test.c) add_executable(z_msgcodec_test ${PROJECT_SOURCE_DIR}/tests/z_msgcodec_test.c) @@ -366,8 +404,15 @@ if(UNIX OR MSVC) add_executable(z_test_fragment_rx ${PROJECT_SOURCE_DIR}/tests/z_test_fragment_rx.c) add_executable(z_perf_tx ${PROJECT_SOURCE_DIR}/tests/z_perf_tx.c) add_executable(z_perf_rx ${PROJECT_SOURCE_DIR}/tests/z_perf_rx.c) + add_executable(z_bytes_test ${PROJECT_SOURCE_DIR}/tests/z_bytes_test.c) + add_executable(z_api_bytes_test ${PROJECT_SOURCE_DIR}/tests/z_api_bytes_test.c) + add_executable(z_api_encoding_test ${PROJECT_SOURCE_DIR}/tests/z_api_encoding_test.c) + add_executable(z_api_config_test ${PROJECT_SOURCE_DIR}/tests/z_api_config_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}) @@ -378,20 +423,34 @@ if(UNIX OR MSVC) 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_api_config_test ${Libname}) + target_link_libraries(z_refcount_test ${Libname}) 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) configure_file(${PROJECT_SOURCE_DIR}/tests/fragment.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fragment.py COPYONLY) configure_file(${PROJECT_SOURCE_DIR}/tests/single_thread.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/single_thread.py COPYONLY) + configure_file(${PROJECT_SOURCE_DIR}/tests/attachment.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/attachment.py COPYONLY) + configure_file(${PROJECT_SOURCE_DIR}/tests/no_router.py ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/no_router.py COPYONLY) enable_testing() add_test(z_data_struct_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_data_struct_test) + add_test(z_channels_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_channels_test) + add_test(z_collections_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_collections_test) add_test(z_endpoint_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_endpoint_test) add_test(z_iobuf_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_iobuf_test) add_test(z_msgcodec_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_msgcodec_test) add_test(z_keyexpr_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_keyexpr_test) add_test(z_api_null_drop_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_null_drop_test) add_test(z_api_double_drop_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_double_drop_test) + add_test(z_bytes_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_bytes_test) + add_test(z_api_bytes_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_bytes_test) + add_test(z_api_encoding_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_encoding_test) + add_test(z_api_config_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_api_config_test) + add_test(z_refcount_test ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/z_refcount_test) endif() if(BUILD_MULTICAST) @@ -455,7 +514,11 @@ if(PACKAGING) if(PACKAGING MATCHES "DEB") if(NOT DEBARCH) - set(DEBARCH ${CMAKE_SYSTEM_PROCESSOR}) + execute_process( + COMMAND dpkg --print-architecture + OUTPUT_VARIABLE DEBARCH + OUTPUT_STRIP_TRAILING_WHITESPACE + ) endif() message(STATUS "Configure DEB packaging for Linux ${DEBARCH}") diff --git a/GNUmakefile b/GNUmakefile index 89b7c9334..fcbbbb4d8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -51,14 +51,20 @@ ZENOH_DEBUG?=0 # Feature config toggle # Accepted values: 0, 1 +Z_FEATURE_UNSTABLE_API?=0 Z_FEATURE_MULTI_THREAD?=1 Z_FEATURE_PUBLICATION?=1 Z_FEATURE_SUBSCRIPTION?=1 Z_FEATURE_QUERY?=1 Z_FEATURE_QUERYABLE?=1 -Z_FEATURE_ATTACHMENT?=1 +Z_FEATURE_INTEREST?=1 Z_FEATURE_RAWETH_TRANSPORT?=0 +# Buffer sizes +FRAG_MAX_SIZE?=300000 +BATCH_UNICAST_SIZE?=65535 +BATCH_MULTICAST_SIZE?=8096 + # zenoh-pico/ directory ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) @@ -73,9 +79,10 @@ CROSSIMG_PREFIX=zenoh-pico_ # - ARM: old versions of dockcross/dockcross were creating some issues since they used an old GCC (4.8.3) which lacks (even using -std=gnu11) CMAKE_OPT=-DZENOH_DEBUG=$(ZENOH_DEBUG) -DBUILD_EXAMPLES=$(BUILD_EXAMPLES) -DCMAKE_BUILD_TYPE=$(BUILD_TYPE) -DBUILD_TESTING=$(BUILD_TESTING) -DBUILD_MULTICAST=$(BUILD_MULTICAST)\ - -DZ_FEATURE_MULTI_THREAD=$(Z_FEATURE_MULTI_THREAD) \ + -DZ_FEATURE_MULTI_THREAD=$(Z_FEATURE_MULTI_THREAD) -DZ_FEATURE_INTEREST=$(Z_FEATURE_INTEREST) -DZ_FEATURE_UNSTABLE_API=$(Z_FEATURE_UNSTABLE_API)\ -DZ_FEATURE_PUBLICATION=$(Z_FEATURE_PUBLICATION) -DZ_FEATURE_SUBSCRIPTION=$(Z_FEATURE_SUBSCRIPTION) -DZ_FEATURE_QUERY=$(Z_FEATURE_QUERY) -DZ_FEATURE_QUERYABLE=$(Z_FEATURE_QUERYABLE)\ - -DZ_FEATURE_RAWETH_TRANSPORT=$(Z_FEATURE_RAWETH_TRANSPORT) -DZ_FEATURE_ATTACHMENT=$(Z_FEATURE_ATTACHMENT) -DBUILD_INTEGRATION=$(BUILD_INTEGRATION) -DBUILD_TOOLS=$(BUILD_TOOLS) -DBUILD_SHARED_LIBS=$(BUILD_SHARED_LIBS) -H. + -DZ_FEATURE_RAWETH_TRANSPORT=$(Z_FEATURE_RAWETH_TRANSPORT) -DFRAG_MAX_SIZE=$(FRAG_MAX_SIZE) -DBATCH_UNICAST_SIZE=$(BATCH_UNICAST_SIZE) -DBATCH_MULTICAST_SIZE=$(BATCH_MULTICAST_SIZE)\ + -DBUILD_INTEGRATION=$(BUILD_INTEGRATION) -DBUILD_TOOLS=$(BUILD_TOOLS) -DBUILD_SHARED_LIBS=$(BUILD_SHARED_LIBS) -H. ifeq ($(FORCE_C99), ON) CMAKE_OPT += -DCMAKE_C_STANDARD=99 diff --git a/PackageConfig.cmake.in b/PackageConfig.cmake.in index 800ceff6c..b84b6c3ec 100644 --- a/PackageConfig.cmake.in +++ b/PackageConfig.cmake.in @@ -14,18 +14,37 @@ @PACKAGE_INIT@ -add_library(__zenohpico_static STATIC IMPORTED GLOBAL) -add_library(zenohpico::static ALIAS __zenohpico_static) -set_property(TARGET __zenohpico_static PROPERTY IMPORTED_LOCATION "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@STATICLIB@") +set(ZENOHPICO_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@) +set(CMAKE_SYSTEM_NAME @CMAKE_SYSTEM_NAME@) -add_library(__zenohpico_lib SHARED IMPORTED GLOBAL) -add_library(zenohpico::lib ALIAS __zenohpico_lib) -set_target_properties(__zenohpico_lib PROPERTIES IMPORTED_NO_SONAME TRUE) -set_property(TARGET __zenohpico_lib PROPERTY IMPORTED_LOCATION "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@DYLIB@") -if(NOT ("@IMPLIB@" STREQUAL "")) - set_property(TARGET __zenohpico_lib PROPERTY IMPORTED_IMPLIB "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@IMPLIB@") +set(ZENOHPICO_FEATURE_UNSTABLE_API @Z_FEATURE_UNSTABLE_API@) +set(ZENOHPICO_FEATURE_MULTI_THREAD @Z_FEATURE_MULTI_THREAD@) +set(ZENOHPICO_FEATURE_PUBLICATION @Z_FEATURE_PUBLICATION@) +set(ZENOHPICO_FEATURE_SUBSCRIPTION @Z_FEATURE_SUBSCRIPTION@) +set(ZENOHPICO_FEATURE_QUERY @Z_FEATURE_QUERY@) +set(ZENOHPICO_FEATURE_QUERYABLE @Z_FEATURE_QUERYABLE@) +set(ZENOHPICO_FEATURE_RAWETH_TRANSPORT @Z_FEATURE_RAWETH_TRANSPORT@) +set(ZENOHPICO_FEATURE_INTEREST @Z_FEATURE_INTEREST@) + +if(ZENOHPICO_BUILD_SHARED_LIBS) + if (NOT TARGET __zenohpico_lib) + add_library(__zenohpico_lib SHARED IMPORTED GLOBAL) + add_library(zenohpico::lib ALIAS __zenohpico_lib) + set_target_properties(__zenohpico_lib PROPERTIES IMPORTED_NO_SONAME TRUE) + set_property(TARGET __zenohpico_lib PROPERTY IMPORTED_LOCATION "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@LIBNAME@") + if(NOT ("@IMPLIB@" STREQUAL "")) + set_property(TARGET __zenohpico_lib PROPERTY IMPORTED_IMPLIB "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@IMPLIB@") + endif() + target_include_directories(__zenohpico_lib INTERFACE "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@") + endif() +else() + if (NOT TARGET __zenohpico_static) + add_library(__zenohpico_static STATIC IMPORTED GLOBAL) + add_library(zenohpico::lib ALIAS __zenohpico_static) + set_property(TARGET __zenohpico_static PROPERTY IMPORTED_LOCATION "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_LIBDIR@/@LIBNAME@") + target_include_directories(__zenohpico_static INTERFACE "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@") + endif() endif() -target_include_directories(__zenohpico_lib INTERFACE "@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@") if(CMAKE_SYSTEM_NAME MATCHES "Linux") add_compile_definitions(ZENOH_LINUX) diff --git a/README.md b/README.md index 6eb1a2ee8..034fd2232 100644 --- a/README.md +++ b/README.md @@ -399,3 +399,26 @@ And on another shell, do: $ ./z_pub -m peer -l udp/224.0.0.123:7447#iface=lo0 ``` A publisher will start publishing over UDP multicast and the **zenoh** router will take care of forwarding data from the Zenoh-Pico publisher to the Zenoh-Pico subscriber. + +## Troubleshooting + +### Activate debug logs +By default debug logs are deactivated but if you're encountering issues they can help you finding the cause. To activate them you need to pass the build flag value: `-DZENOH_DEBUG=3` + +### Error when opening a session on a microcontroller +If you get an error when opening the session even though everything is setup correctly, it might be because the default buffer sizes are too large for the limited memory available on your system. + +The first thing to try is to reduce the values of the following configuration options (found in `CMakeLists.txt`): +* BATCH_UNICAST_SIZE: The maximum size of a packet in client mode. +* BATCH_MULTICAST_SIZE: The maximum size of a packet in peer mode. +* FRAG_MAX_SIZE: The maximum size of a message that can be fragmented into multiple packets. + +Until you find values that suits both your app requirements and your system memory constraints. + +These values can also be passed directly as cmake args. For example, in a `platformio.ini` you might write: +``` +board_build.cmake_extra_args= + -DBATCH_UNICAST_SIZE=1024 + -DFRAG_MAX_SIZE=2048 +``` + diff --git a/ci/scripts/build-linux.bash b/ci/scripts/build-linux.bash index 00b9f97df..3d3a33ca4 100644 --- a/ci/scripts/build-linux.bash +++ b/ci/scripts/build-linux.bash @@ -5,7 +5,7 @@ set -xeo pipefail # Repository readonly repo=${REPO:?input REPO is required} # Release number -readonly version=${VERSION:?input TARGET is required} +readonly version=${VERSION:?input VERSION is required} # Build target readonly target=${TARGET:?input TARGET is required} diff --git a/docs/api.rst b/docs/api.rst index 1b925de03..1fea537d1 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -25,33 +25,19 @@ Enums .. autocenum:: constants.h::z_whatami_t .. autocenum:: constants.h::zp_keyexpr_canon_status_t .. autocenum:: constants.h::z_sample_kind_t -.. autocenum:: constants.h::z_encoding_prefix_t .. autocenum:: constants.h::z_consolidation_mode_t .. autocenum:: constants.h::z_reliability_t -.. autocenum:: constants.h::z_reply_tag_t .. autocenum:: constants.h::z_congestion_control_t .. autocenum:: constants.h::z_priority_t -.. autocenum:: constants.h::z_submode_t .. autocenum:: constants.h::z_query_target_t Data Structures ~~~~~~~~~~~~~~~ .. autoctype:: types.h::z_zint_t -.. autoctype:: types.h::z_bytes_t .. autoctype:: types.h::z_id_t -.. autoctype:: types.h::z_string_t -.. autoctype:: types.h::z_keyexpr_t -.. autoctype:: types.h::z_config_t -.. autoctype:: types.h::z_session_t -.. autoctype:: types.h::z_subscriber_t -.. autoctype:: types.h::z_pull_subscriber_t -.. autoctype:: types.h::z_publisher_t -.. autoctype:: types.h::z_queryable_t -.. autoctype:: types.h::z_encoding_t -.. autoctype:: types.h::z_value_t +.. autoctype:: types.h::z_timestamp_t .. autoctype:: types.h::z_subscriber_options_t -.. autoctype:: types.h::z_pull_subscriber_options_t .. autoctype:: types.h::z_query_consolidation_t .. autoctype:: types.h::z_publisher_options_t .. autoctype:: types.h::z_queryable_options_t @@ -61,82 +47,170 @@ Data Structures .. autoctype:: types.h::z_publisher_put_options_t .. autoctype:: types.h::z_publisher_delete_options_t .. autoctype:: types.h::z_get_options_t -.. autoctype:: types.h::z_sample_t -.. autoctype:: types.h::z_hello_t -.. autoctype:: types.h::z_reply_t -.. autoctype:: types.h::z_reply_data_t .. autoctype:: types.h::zp_task_read_options_t .. autoctype:: types.h::zp_task_lease_options_t .. autoctype:: types.h::zp_read_options_t .. autoctype:: types.h::zp_send_keep_alive_options_t - -Arrays -~~~~~~ -.. c:type:: z_str_array_t - - Represents an array of ``char *``. - - Operations over :c:type:`z_str_array_t` must be done using the provided functions: - - - ``char *z_str_array_get(z_str_array_t *a, size_t k);`` - - ``size_t z_str_array_len(z_str_array_t *a);`` - - ``_Bool z_str_array_array_is_empty(z_str_array_t *a);`` +.. autoctype:: types.h::zp_send_join_options_t +.. autoctype:: types.h::z_bytes_reader_t +.. autoctype:: types.h::z_bytes_iterator_t +.. autoctype:: types.h::z_bytes_writer_t + Owned Types ~~~~~~~~~~~ -Like most ``z_owned_X_t`` types, you may obtain an instance of ``z_X_t`` by loaning it using ``z_X_loan(&val)``. -The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is equivalent to writing ``z_X_loan(&val)``. - -Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -To make this fact more obvious when reading your code, consider using ``z_move(val)`` instead of ``&val`` as the argument. -After a move, ``val`` will still exist, but will no longer be valid. The destructors are double-free-safe, but other functions will still trust that your ``val`` is valid. +TODO: owned type description -To check if ``val`` is still valid, you may use ``z_X_check(&val)`` or ``z_check(val)`` if your compiler supports ``_Generic``, which will return ``true`` if ``val`` is valid. +.. c:type:: z_owned_slice_t + + Represents an array of bytes. .. c:type:: z_owned_bytes_t + + Represents an array of bytes container. - A zenoh-allocated :c:type:`z_bytes_t`. - -.. c:type:: z_owned_str_t +.. c:type:: z_owned_string_t - A zenoh-allocated :c:type:`char *`. + Represents a string without null-terminator. .. c:type:: z_owned_keyexpr_t - A zenoh-allocated :c:type:`z_keyexpr_t`. + Represents a key expression in Zenoh. .. c:type:: z_owned_config_t - A zenoh-allocated :c:type:`z_config_t`. + Represents a Zenoh configuration, used to configure Zenoh sessions upon opening. .. c:type:: z_owned_session_t - A zenoh-allocated :c:type:`z_session_t`. + Represents a Zenoh Session. .. c:type:: z_owned_subscriber_t - A zenoh-allocated :c:type:`z_subscriber_t`. - -.. c:type:: z_owned_pull_subscriber_t - - A zenoh-allocated :c:type:`z_pull_subscriber_t`. + Represents a Zenoh Subscriber entity. .. c:type:: z_owned_publisher_t - A zenoh-allocated :c:type:`z_publisher_t`. + Represents a Zenoh Publisher entity. .. c:type:: z_owned_queryable_t - A zenoh-allocated :c:type:`z_queryable_t`. + Represents a Zenoh Queryable entity. + +.. c:type:: z_owned_query_t + + Represents a Zenoh Query entity, received by Zenoh queryable entities. + +.. c:type:: z_owned_encoding_t + + Represents the encoding of a payload, in a MIME-like format. + +.. c:type:: z_owned_reply_err_t + + Represents a Zenoh reply error value. + +.. c:type:: z_owned_sample_t + + Represents a data sample. + +.. c:type:: z_owned_hello_t + + Represents the content of a `hello` message returned by a zenoh entity as a reply to a `scout` message. .. c:type:: z_owned_reply_t - A zenoh-allocated :c:type:`z_reply_t`. + Represents the reply to a query. + +.. c:type:: z_owned_string_array_t + + Represents an array of non null-terminated string. + +Loaned Types +~~~~~~~~~~~ + +TODO: loaned type description + +.. c:type:: z_loaned_slice_t + + Represents an array of bytes. + +.. c:type:: z_loaned_bytes_t + + Represents an array of bytes container. + +.. c:type:: z_loaned_string_t + + Represents a string without null-terminator. + +.. c:type:: z_loaned_keyexpr_t + + Represents a key expression in Zenoh. + +.. c:type:: z_loaned_config_t + + Represents a Zenoh configuration, used to configure Zenoh sessions upon opening. + +.. c:type:: z_loaned_session_t + + Represents a Zenoh Session. + +.. c:type:: z_loaned_subscriber_t + + Represents a Zenoh Subscriber entity. + +.. c:type:: z_loaned_publisher_t + + Represents a Zenoh Publisher entity. + +.. c:type:: z_loaned_queryable_t + + Represents a Zenoh Queryable entity. + +.. c:type:: z_loaned_query_t + + Represents a Zenoh Query entity, received by Zenoh queryable entities. + +.. c:type:: z_loaned_encoding_t + + Represents the encoding of a payload, in a MIME-like format. + +.. c:type:: z_loaned_reply_err_t + + Represents a Zenoh reply error. + +.. c:type:: z_loaned_sample_t + + Represents a data sample. + +.. c:type:: z_loaned_hello_t -.. c:type:: z_owned_str_array_t + Represents the content of a `hello` message returned by a zenoh entity as a reply to a `scout` message. - A zenoh-allocated :c:type:`z_str_array_t`. +.. c:type:: z_loaned_reply_t + + Represents the reply to a query. + +.. c:type:: z_loaned_string_array_t + + Represents an array of non null-terminated string. + +View Types +~~~~~~~~~~~ + +TODO: view type description + +.. c:type:: z_view_string_t + + Represents a string without null-terminator. + +.. c:type:: z_view_keyexpr_t + + Represents a key expression in Zenoh. + +.. c:type:: z_view_string_array_t + + Represents an array of non null-terminated string. Closures ~~~~~~~~ @@ -153,12 +227,45 @@ It is guaranteed that: - ``drop`` will only be called **once**, and **after every** ``call`` has ended. - The two previous guarantees imply that ``call`` and ``drop`` are never called concurrently. +Represents a `sample` closure. + +.. c:type:: types.h::z_owned_closure_sample_t + +Represents a loaned `sample` closure. + +.. c:type:: types.h::z_loaned_closure_sample_t + +Represents a `query` closure. + +.. c:type:: types.h::z_owned_closure_query_t + +Represents a loaned `query` closure. + +.. c:type:: types.h::z_loaned_closure_query_t + +Represents a `reply` closure. + +.. c:type:: types.h::z_owned_closure_reply_t + +Represents a loaned `reply` closure. + +.. c:type:: types.h::z_loaned_closure_reply_t + +Represents a `hello` closure. + +.. c:type:: types.h::z_owned_closure_hello_t -.. autoctype:: types.h::z_owned_closure_sample_t -.. autoctype:: types.h::z_owned_closure_query_t -.. autoctype:: types.h::z_owned_closure_reply_t -.. autoctype:: types.h::z_owned_closure_hello_t -.. autoctype:: types.h::z_owned_closure_zid_t +Represents a loaned `hello` closure. + +.. c:type:: types.h::z_loaned_closure_hello_t + +Represents a `Zenoh id` closure. + +.. c:type:: types.h::z_owned_closure_zid_t + +Represents a loaned `Zenoh id` closure. + +.. c:type:: types.h::z_loaned_closure_zid_t Zenoh Functions @@ -168,38 +275,92 @@ Macros ~~~~~~ .. autocmacro:: macros.h::z_loan .. autocmacro:: macros.h::z_move -.. autocmacro:: macros.h::z_check .. autocmacro:: macros.h::z_clone .. autocmacro:: macros.h::z_drop .. autocmacro:: macros.h::z_closure -.. autocmacro:: macros.h::z_null Primitives ~~~~~~~~~~ -.. autocfunction:: primitives.h::z_keyexpr -.. autocfunction:: primitives.h::z_keyexpr_to_string -.. autocfunction:: primitives.h::zp_keyexpr_resolve -.. autocfunction:: primitives.h::z_keyexpr_is_initialized +.. autocfunction:: primitives.h::z_view_string_from_str +.. autocfunction:: primitives.h::z_view_keyexpr_from_str +.. autocfunction:: primitives.h::z_view_keyexpr_from_str_unchecked +.. autocfunction:: primitives.h::z_view_keyexpr_from_str_autocanonize +.. autocfunction:: primitives.h::z_keyexpr_as_view_string .. autocfunction:: primitives.h::z_keyexpr_is_canon -.. autocfunction:: primitives.h::zp_keyexpr_is_canon_null_terminated .. autocfunction:: primitives.h::z_keyexpr_canonize -.. autocfunction:: primitives.h::zp_keyexpr_canonize_null_terminated .. autocfunction:: primitives.h::z_keyexpr_includes -.. autocfunction:: primitives.h::zp_keyexpr_includes_null_terminated .. autocfunction:: primitives.h::z_keyexpr_intersects -.. autocfunction:: primitives.h::zp_keyexpr_intersect_null_terminated .. autocfunction:: primitives.h::z_keyexpr_equals -.. autocfunction:: primitives.h::zp_keyexpr_equals_null_terminated +.. autocfunction:: primitives.h::z_keyexpr_relation_to +.. autocfunction:: primitives.h::z_keyexpr_concat +.. autocfunction:: primitives.h::z_keyexpr_join .. autocfunction:: primitives.h::z_config_new .. autocfunction:: primitives.h::z_config_default +.. autocfunction:: primitives.h::z_config_client +.. autocfunction:: primitives.h::z_config_peer .. autocfunction:: primitives.h::zp_config_get .. autocfunction:: primitives.h::zp_config_insert -.. autocfunction:: primitives.h::z_scouting_config_default -.. autocfunction:: primitives.h::z_scouting_config_from -.. autocfunction:: primitives.h::zp_scouting_config_get -.. autocfunction:: primitives.h::zp_scouting_config_insert -.. autocfunction:: primitives.h::z_encoding_default +.. autocfunction:: primitives.h::z_encoding_from_str +.. autocfunction:: primitives.h::z_encoding_from_substr +.. autocfunction:: primitives.h::z_encoding_set_schema_from_str +.. autocfunction:: primitives.h::z_encoding_set_schema_from_substr +.. autocfunction:: primitives.h::z_encoding_to_string +.. autocfunction:: primitives.h::z_reply_err_payload +.. autocfunction:: primitives.h::z_reply_err_encoding +.. autocfunction:: primitives.h::z_slice_from_buf +.. autocfunction:: primitives.h::z_slice_copy_from_buf +.. autocfunction:: primitives.h::z_slice_data +.. autocfunction:: primitives.h::z_slice_len +.. autocfunction:: primitives.h::z_slice_empty +.. autocfunction:: primitives.h::z_slice_is_empty +.. autocfunction:: primitives.h::z_bytes_deserialize_into_int8 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_int16 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_int32 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_int64 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_uint8 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_uint16 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_uint32 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_uint64 +.. autocfunction:: primitives.h::z_bytes_deserialize_into_float +.. autocfunction:: primitives.h::z_bytes_deserialize_into_double +.. autocfunction:: primitives.h::z_bytes_deserialize_into_slice +.. autocfunction:: primitives.h::z_bytes_deserialize_into_string +.. autocfunction:: primitives.h::z_bytes_serialize_from_int8 +.. autocfunction:: primitives.h::z_bytes_serialize_from_int16 +.. autocfunction:: primitives.h::z_bytes_serialize_from_int32 +.. autocfunction:: primitives.h::z_bytes_serialize_from_int64 +.. autocfunction:: primitives.h::z_bytes_serialize_from_uint8 +.. autocfunction:: primitives.h::z_bytes_serialize_from_uint16 +.. autocfunction:: primitives.h::z_bytes_serialize_from_uint32 +.. autocfunction:: primitives.h::z_bytes_serialize_from_uint64 +.. autocfunction:: primitives.h::z_bytes_serialize_from_float +.. autocfunction:: primitives.h::z_bytes_serialize_from_double +.. autocfunction:: primitives.h::z_bytes_from_slice +.. autocfunction:: primitives.h::z_bytes_serialize_from_slice +.. autocfunction:: primitives.h::z_bytes_from_buf +.. autocfunction:: primitives.h::z_bytes_serialize_from_buf +.. autocfunction:: primitives.h::z_bytes_from_static_buf +.. autocfunction:: primitives.h::z_bytes_from_string +.. autocfunction:: primitives.h::z_bytes_serialize_from_string +.. autocfunction:: primitives.h::z_bytes_from_str +.. autocfunction:: primitives.h::z_bytes_serialize_from_str +.. autocfunction:: primitives.h::z_bytes_from_static_str +.. autocfunction:: primitives.h::z_bytes_empty +.. autocfunction:: primitives.h::z_bytes_len +.. autocfunction:: primitives.h::z_bytes_is_empty +.. autocfunction:: primitives.h::z_bytes_get_iterator +.. autocfunction:: primitives.h::z_bytes_iterator_next +.. autocfunction:: primitives.h::z_bytes_get_reader +.. autocfunction:: primitives.h::z_bytes_reader_read +.. autocfunction:: primitives.h::z_bytes_reader_read_bounded +.. autocfunction:: primitives.h::z_bytes_reader_seek +.. autocfunction:: primitives.h::z_bytes_reader_tell +.. autocfunction:: primitives.h::z_bytes_get_writer +.. autocfunction:: primitives.h::z_bytes_writer_write_all +.. autocfunction:: primitives.h::z_bytes_writer_append +.. autocfunction:: primitives.h::z_bytes_writer_append_bounded +.. autocfunction:: primitives.h::z_timestamp_check .. autocfunction:: primitives.h::z_query_target_default .. autocfunction:: primitives.h::z_query_consolidation_auto .. autocfunction:: primitives.h::z_query_consolidation_default @@ -207,28 +368,43 @@ Primitives .. autocfunction:: primitives.h::z_query_consolidation_monotonic .. autocfunction:: primitives.h::z_query_consolidation_none .. autocfunction:: primitives.h::z_query_parameters +.. autocfunction:: primitives.h::z_query_payload +.. autocfunction:: primitives.h::z_query_encoding +.. autocfunction:: primitives.h::z_query_attachment .. autocfunction:: primitives.h::z_query_keyexpr -.. autocfunction:: primitives.h::z_query_value -.. autocfunction:: primitives.h::z_value_is_initialized .. autocfunction:: primitives.h::z_closure_sample .. autocfunction:: primitives.h::z_closure_query .. autocfunction:: primitives.h::z_closure_reply .. autocfunction:: primitives.h::z_closure_hello .. autocfunction:: primitives.h::z_closure_zid +.. autocfunction:: primitives.h::z_sample_loan +.. autocfunction:: primitives.h::z_string_data +.. autocfunction:: primitives.h::z_string_len +.. autocfunction:: primitives.h::z_string_from_str +.. autocfunction:: primitives.h::z_string_copy_from_str +.. autocfunction:: primitives.h::z_string_copy_from_substr +.. autocfunction:: primitives.h::z_string_empty +.. autocfunction:: primitives.h::z_string_is_empty +.. autocfunction:: primitives.h::z_hello_zid +.. autocfunction:: primitives.h::z_hello_whatami +.. autocfunction:: primitives.h::z_hello_locators +.. autocfunction:: primitives.h::z_whatami_to_view_string .. autocfunction:: primitives.h::z_scout .. autocfunction:: primitives.h::z_open .. autocfunction:: primitives.h::z_close .. autocfunction:: primitives.h::z_info_peers_zid .. autocfunction:: primitives.h::z_info_routers_zid .. autocfunction:: primitives.h::z_info_zid +.. autocfunction:: primitives.h::z_sample_keyexpr +.. autocfunction:: primitives.h::z_sample_payload +.. autocfunction:: primitives.h::z_sample_timestamp +.. autocfunction:: primitives.h::z_sample_encoding +.. autocfunction:: primitives.h::z_sample_kind +.. autocfunction:: primitives.h::z_sample_attachment .. autocfunction:: primitives.h::z_put_options_default .. autocfunction:: primitives.h::z_delete_options_default .. autocfunction:: primitives.h::z_put .. autocfunction:: primitives.h::z_delete -.. autocfunction:: primitives.h::z_get_options_default -.. autocfunction:: primitives.h::z_get -.. autocfunction:: primitives.h::z_declare_keyexpr -.. autocfunction:: primitives.h::z_undeclare_keyexpr .. autocfunction:: primitives.h::z_publisher_options_default .. autocfunction:: primitives.h::z_declare_publisher .. autocfunction:: primitives.h::z_undeclare_publisher @@ -236,20 +412,30 @@ Primitives .. autocfunction:: primitives.h::z_publisher_delete_options_default .. autocfunction:: primitives.h::z_publisher_put .. autocfunction:: primitives.h::z_publisher_delete -.. autocfunction:: primitives.h::z_subscriber_options_default -.. autocfunction:: primitives.h::z_declare_subscriber -.. autocfunction:: primitives.h::z_undeclare_subscriber -.. autocfunction:: primitives.h::z_pull_subscriber_options_default -.. autocfunction:: primitives.h::z_declare_pull_subscriber -.. autocfunction:: primitives.h::z_undeclare_pull_subscriber -.. autocfunction:: primitives.h::z_subscriber_pull +.. autocfunction:: primitives.h::z_get_options_default +.. autocfunction:: primitives.h::z_get +.. autocfunction:: primitives.h::z_reply_is_ok +.. autocfunction:: primitives.h::z_reply_ok +.. autocfunction:: primitives.h::z_reply_err .. autocfunction:: primitives.h::z_queryable_options_default .. autocfunction:: primitives.h::z_declare_queryable .. autocfunction:: primitives.h::z_undeclare_queryable +.. autocfunction:: primitives.h::z_query_reply_options_default .. autocfunction:: primitives.h::z_query_reply -.. autocfunction:: primitives.h::z_reply_is_ok -.. autocfunction:: primitives.h::z_reply_ok -.. autocfunction:: primitives.h::z_reply_err +.. autocfunction:: primitives.h::z_query_reply_del_options_default +.. autocfunction:: primitives.h::z_query_reply_del +.. autocfunction:: primitives.h::z_query_reply_err_options_default +.. autocfunction:: primitives.h::z_query_reply_err +.. autocfunction:: primitives.h::z_keyexpr_from_str +.. autocfunction:: primitives.h::z_keyexpr_from_substr +.. autocfunction:: primitives.h::z_keyexpr_from_str_autocanonize +.. autocfunction:: primitives.h::z_keyexpr_from_substr_autocanonize +.. autocfunction:: primitives.h::z_declare_keyexpr +.. autocfunction:: primitives.h::z_undeclare_keyexpr +.. autocfunction:: primitives.h::z_subscriber_options_default +.. autocfunction:: primitives.h::z_declare_subscriber +.. autocfunction:: primitives.h::z_undeclare_subscriber +.. autocfunction:: primitives.h::z_subscriber_keyexpr .. autocfunction:: primitives.h::zp_task_read_options_default .. autocfunction:: primitives.h::zp_start_read_task .. autocfunction:: primitives.h::zp_stop_read_task @@ -259,4 +445,6 @@ Primitives .. autocfunction:: primitives.h::zp_read_options_default .. autocfunction:: primitives.h::zp_read .. autocfunction:: primitives.h::zp_send_keep_alive_options_default -.. autocfunction:: primitives.h::zp_send_keep_alive \ No newline at end of file +.. autocfunction:: primitives.h::zp_send_keep_alive +.. autocfunction:: primitives.h::zp_send_join_options_default +.. autocfunction:: primitives.h::zp_send_join diff --git a/docs/conf.py b/docs/conf.py index 471dda880..4ad571076 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -29,8 +29,13 @@ extensions = ['sphinx_c_autodoc', 'sphinx_c_autodoc.napoleon'] language = 'c' c_autodoc_roots = ['../include/zenoh-pico/api/'] -c_autodoc_compilation_args = ["-DZ_FEATURE_PUBLICATION=1", "-DZ_FEATURE_SUBSCRIPTION=1", - "-DZ_FEATURE_QUERY=1", "-DZ_FEATURE_QUERYABLE=1"] +c_autodoc_compilation_args = [ + "-DZ_FEATURE_UNSTABLE_API=1", + "-DZ_FEATURE_PUBLICATION=1", + "-DZ_FEATURE_SUBSCRIPTION=1", + "-DZ_FEATURE_QUERY=1", + "-DZ_FEATURE_QUERYABLE=1", +] # -- Options for HTML output ------------------------------------------------- html_theme = 'sphinx_rtd_theme' @@ -51,4 +56,4 @@ raise ValueError("Windows not supported yet for building docs.") else: - Config.set_library_file('/usr/lib/llvm-14/lib/libclang.so.1') # Required for readthedocs + Config.set_library_file('/usr/lib/llvm-14/lib/libclang.so.1') # Required for readthedocs diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 05e76b29b..ba3dd8139 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -36,11 +36,18 @@ if(UNIX) add_example(z_put unix/c11/z_put.c) add_example(z_pub unix/c11/z_pub.c) add_example(z_pub_st unix/c11/z_pub_st.c) + add_example(z_pub_attachment unix/c11/z_pub_attachment.c) add_example(z_sub unix/c11/z_sub.c) + add_example(z_sub_channel unix/c11/z_sub_channel.c) add_example(z_sub_st unix/c11/z_sub_st.c) + add_example(z_sub_attachment unix/c11/z_sub_attachment.c) add_example(z_pull unix/c11/z_pull.c) add_example(z_get unix/c11/z_get.c) + add_example(z_get_channel unix/c11/z_get_channel.c) + add_example(z_get_attachment unix/c11/z_get_attachment.c) add_example(z_queryable unix/c11/z_queryable.c) + add_example(z_queryable_channel unix/c11/z_queryable_channel.c) + add_example(z_queryable_attachment unix/c11/z_queryable_attachment.c) add_example(z_info unix/c11/z_info.c) add_example(z_scout unix/c11/z_scout.c) add_example(z_ping unix/c11/z_ping.c) diff --git a/examples/arduino/z_get.ino b/examples/arduino/z_get.ino index ddd607641..a7689a76f 100644 --- a/examples/arduino/z_get.ino +++ b/examples/arduino/z_get.ino @@ -42,20 +42,22 @@ void reply_dropper(void *ctx) { Serial.println(" >> Received query final notification"); } -void reply_handler(z_owned_reply_t *oreply, void *ctx) { +void reply_handler(const z_loaned_reply_t *oreply, void *ctx) { (void)(ctx); if (z_reply_is_ok(oreply)) { - z_sample_t sample = z_reply_ok(oreply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - std::string val((const char *)sample.payload.start, sample.payload.len); + const z_loaned_sample_t *sample = z_reply_ok(oreply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); Serial.print(" >> [Get listener] Received ("); - Serial.print(z_str_loan(&keystr)); + Serial.write(z_string_data(z_view_string_loan(&keystr)), z_string_len(z_view_string_loan(&keystr))); Serial.print(", "); - Serial.print(val.c_str()); + Serial.write(z_string_data(z_string_loan(&replystr)), z_string_len(z_string_loan(&replystr))); Serial.println(")"); - z_str_drop(z_str_move(&keystr)); + z_string_drop(z_string_move(&replystr)); } else { Serial.println(" >> Received an error"); } @@ -78,16 +80,16 @@ void setup() { Serial.println("OK"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session Serial.print("Opening Zenoh Session..."); - s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + if (z_open(&s, z_config_move(&config)) < 0) { Serial.println("Unable to open session!"); while (1) { ; @@ -96,8 +98,8 @@ void setup() { Serial.println("OK"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); Serial.println("Zenoh setup finished!"); @@ -110,12 +112,19 @@ void loop() { Serial.print("Sending Query "); Serial.print(KEYEXPR); Serial.println(" ..."); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (strcmp(VALUE, "") != 0) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)VALUE, strlen(VALUE)); + z_bytes_from_static_str(&payload, VALUE); + opts.payload = z_bytes_move(&payload); } - z_owned_closure_reply_t callback = z_closure_reply(reply_handler, reply_dropper, NULL); - if (z_get(z_session_loan(&s), z_keyexpr(KEYEXPR), "", z_closure_reply_move(&callback), &opts) < 0) { + z_owned_closure_reply_t callback; + z_closure_reply(&callback, reply_handler, reply_dropper, NULL); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_get(z_session_loan(&s), z_view_keyexpr_loan(&ke), "", z_closure_reply_move(&callback), &opts) < 0) { Serial.println("Unable to send query."); } } diff --git a/examples/arduino/z_pub.ino b/examples/arduino/z_pub.ino index ce0a14621..490ce04c1 100644 --- a/examples/arduino/z_pub.ino +++ b/examples/arduino/z_pub.ino @@ -55,16 +55,17 @@ void setup() { Serial.println("OK"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session Serial.print("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { Serial.println("Unable to open session!"); while (1) { ; @@ -73,15 +74,16 @@ void setup() { Serial.println("OK"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); // Declare Zenoh publisher Serial.print("Declaring publisher for "); Serial.print(KEYEXPR); Serial.println("..."); - pub = z_declare_publisher(z_session_loan(&s), z_keyexpr(KEYEXPR), NULL); - if (!z_publisher_check(&pub)) { + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_publisher(&pub, z_session_loan(&s), z_view_keyexpr_loan(&ke), NULL) < 0) { Serial.println("Unable to declare publisher for key expression!"); while (1) { ; @@ -97,13 +99,18 @@ void loop() { delay(1000); char buf[256]; sprintf(buf, "[%4d] %s", idx++, VALUE); + Serial.print("Writing Data ('"); Serial.print(KEYEXPR); Serial.print("': '"); Serial.print(buf); Serial.println("')"); - if (z_publisher_put(z_publisher_loan(&pub), (const uint8_t *)buf, strlen(buf), NULL) < 0) { + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + if (z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL) < 0) { Serial.println("Error while publishing data"); } } diff --git a/examples/arduino/z_pull.ino b/examples/arduino/z_pull.ino index 5dc150adf..4e0a19624 100644 --- a/examples/arduino/z_pull.ino +++ b/examples/arduino/z_pull.ino @@ -34,21 +34,10 @@ #define KEYEXPR "demo/example/**" -z_owned_pull_subscriber_t sub; -int idx = 0; +const size_t INTERVAL = 5000; +const size_t SIZE = 3; -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - std::string val((const char *)sample->payload.start, sample->payload.len); - - Serial.print(" >> [Subscription listener] Received ("); - Serial.print(z_str_loan(&keystr)); - Serial.print(", "); - Serial.print(val.c_str()); - Serial.println(")"); - - z_str_drop(z_str_move(&keystr)); -} +z_owned_ring_handler_sample_t handler; void setup() { // Initialize Serial for debug @@ -67,16 +56,17 @@ void setup() { Serial.println("OK"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session Serial.print("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { Serial.println("Unable to open session!"); while (1) { ; @@ -84,22 +74,24 @@ void setup() { } Serial.println("OK"); - // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); - - // Declare Zenoh subscriber - Serial.print("Declaring Subscriber on "); - Serial.print(KEYEXPR); - Serial.println(" ..."); - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); - sub = z_declare_pull_subscriber(z_session_loan(&s), z_keyexpr(KEYEXPR), z_closure_sample_move(&callback), NULL); - if (!z_pull_subscriber_check(&sub)) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { + printf("Unable to start read and lease tasks\n"); + z_close(z_session_move(&s)); + return; + } + + printf("Declaring Subscriber on '%s'...\n", KEYEXPR); + z_owned_closure_sample_t closure; + z_ring_channel_sample_new(&closure, &handler, SIZE); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&closure), + NULL) < 0) { Serial.println("Unable to declare subscriber."); - while (1) { - ; - } + return; } + Serial.println("OK"); Serial.println("Zenoh setup finished!"); @@ -107,11 +99,26 @@ void setup() { } void loop() { - delay(1000); - char buf[256]; - sprintf(buf, "[%4d] Pulling...", idx++); - Serial.println(buf); - z_subscriber_pull(z_pull_subscriber_loan(&sub)); + z_owned_sample_t sample; + z_result_t res; + for (res = z_ring_handler_sample_try_recv(z_ring_handler_sample_loan(&handler), &sample); res == Z_OK; + res = z_ring_handler_sample_try_recv(z_ring_handler_sample_loan(&handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_sample_loan(&sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_sample_loan(&sample)), &value); + Serial.print(">> [Subscriber] Pulled ("); + Serial.write(z_string_data(z_view_string_loan(&keystr)), z_string_len(z_view_string_loan(&keystr))); + Serial.print(": "); + Serial.write(z_string_data(z_string_loan(&value)), z_string_len(z_string_loan(&value))); + Serial.println(")"); + + z_string_drop(z_string_move(&value)); + z_sample_drop(z_sample_move(&sample)); + } + if (res == Z_CHANNEL_NODATA) { + delay(INTERVAL); + } } #else void setup() { diff --git a/examples/arduino/z_queryable.ino b/examples/arduino/z_queryable.ino index b6e3c7ed5..b1ee9ab8f 100644 --- a/examples/arduino/z_queryable.ino +++ b/examples/arduino/z_queryable.ino @@ -35,18 +35,31 @@ #define KEYEXPR "demo/example/zenoh-pico-queryable" #define VALUE "[ARDUINO]{ESP32} Queryable from Zenoh-Pico!" -void query_handler(const z_query_t *query, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); +void query_handler(const z_loaned_query_t *query, void *arg) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + Serial.print(" >> [Queryable handler] Received Query '"); + Serial.write(z_string_data(z_view_string_loan(&keystr)), z_string_len(z_view_string_loan(&keystr))); + Serial.println("'"); + + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_string_loan(&payload_string)) > 1) { + Serial.print(" with value '"); + Serial.write(z_string_data(z_string_loan(&payload_string)), z_string_len(z_string_loan(&payload_string))); + Serial.println("'"); + } + z_string_drop(z_string_move(&payload_string)); - Serial.print(" >> [Queryable handler] Replying Data ('"); - Serial.print(z_str_loan(&keystr)); - Serial.print("': '"); - Serial.print(VALUE); - Serial.println("')"); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); - z_query_reply(query, z_keyexpr(KEYEXPR), (const unsigned char *)VALUE, strlen(VALUE), NULL); + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, VALUE); - z_str_drop(z_str_move(&keystr)); + z_query_reply(query, z_view_keyexpr_loan(&ke), z_bytes_move(&reply_payload), NULL); } void setup() { @@ -66,16 +79,17 @@ void setup() { Serial.println("OK"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session Serial.print("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { Serial.println("Unable to open session!"); while (1) { ; @@ -84,17 +98,20 @@ void setup() { Serial.println("OK"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); // Declare Zenoh queryable Serial.print("Declaring Queryable on "); Serial.print(KEYEXPR); Serial.println(" ..."); - z_owned_closure_query_t callback = z_closure_query(query_handler, NULL, NULL); - z_owned_queryable_t qable = - z_declare_queryable(z_session_loan(&s), z_keyexpr(KEYEXPR), z_closure_query_move(&callback), NULL); - if (!z_queryable_check(&qable)) { + z_owned_closure_query_t callback; + z_closure_query(&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(&qable, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_query_move(&callback), + NULL) < 0) { Serial.println("Unable to declare queryable."); while (1) { ; diff --git a/examples/arduino/z_scout.ino b/examples/arduino/z_scout.ino index 632b50295..7af5da089 100644 --- a/examples/arduino/z_scout.ino +++ b/examples/arduino/z_scout.ino @@ -44,22 +44,19 @@ void fprintzid(z_id_t zid) { } } -void fprintwhatami(unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - Serial.print("'Router'"); - } else if (whatami == Z_WHATAMI_PEER) { - Serial.print("'Peer'"); - } else { - Serial.print("'Other'"); - } +void fprintwhatami(z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + Serial.write(z_string_data(z_view_string_loan(&s)), z_string_len(z_view_string_loan(&s))); } -void fprintlocators(const z_str_array_t *locs) { +void fprintlocators(const z_loaned_string_array_t *locs) { Serial.print("["); - size_t len = z_str_array_len(locs); + size_t len = z_string_array_len(locs); for (unsigned int i = 0; i < len; i++) { Serial.print("'"); - Serial.print(*z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + Serial.write(z_string_data(str), z_string_len(str)); Serial.print("'"); if (i < len - 1) { Serial.print(", "); @@ -68,18 +65,18 @@ void fprintlocators(const z_str_array_t *locs) { Serial.print("]"); } -void fprinthello(const z_hello_t hello) { +void fprinthello(const z_loaned_hello_t *hello) { Serial.print(" >> Hello { zid: "); - fprintzid(hello.zid); + fprintzid(z_hello_zid(hello)); Serial.print(", whatami: "); - fprintwhatami(hello.whatami); + fprintwhatami(z_hello_whatami(hello)); Serial.print(", locators: "); - fprintlocators(&hello.locators); + fprintlocators(z_hello_locators(hello)); Serial.println(" }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(z_hello_loan(hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(hello); Serial.println(""); (*(int *)context)++; } @@ -114,8 +111,10 @@ void setup() { void loop() { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure_hello(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure_hello(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_scouting_config_move(&config), z_closure_hello_move(&closure)); + z_scout(z_config_move(&config), z_closure_hello_move(&closure), NULL); } diff --git a/examples/arduino/z_sub.ino b/examples/arduino/z_sub.ino index 9abc75df0..c538a5eca 100644 --- a/examples/arduino/z_sub.ino +++ b/examples/arduino/z_sub.ino @@ -34,17 +34,19 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - std::string val((const char *)sample->payload.start, sample->payload.len); +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); Serial.print(" >> [Subscription listener] Received ("); - Serial.print(z_str_loan(&keystr)); + Serial.write(z_string_data(z_view_string_loan(&keystr)), z_string_len(z_view_string_loan(&keystr))); Serial.print(", "); - Serial.print(val.c_str()); + Serial.write(z_string_data(z_string_loan(&value)), z_string_len(z_string_loan(&value))); Serial.println(")"); - z_str_drop(z_str_move(&keystr)); + z_string_drop(z_string_move(&value)); } void setup() { @@ -64,16 +66,17 @@ void setup() { Serial.println("OK"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session Serial.print("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { Serial.println("Unable to open session!"); while (1) { ; @@ -82,17 +85,20 @@ void setup() { Serial.println("OK"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); // Declare Zenoh subscriber Serial.print("Declaring Subscriber on "); Serial.print(KEYEXPR); Serial.println(" ..."); - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); - z_owned_subscriber_t sub = - z_declare_subscriber(z_session_loan(&s), z_keyexpr(KEYEXPR), z_closure_sample_move(&callback), NULL); - if (!z_subscriber_check(&sub)) { + z_owned_closure_sample_t callback; + z_closure_sample(&callback, data_handler, NULL, NULL); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&callback), + NULL) < 0) { Serial.println("Unable to declare subscriber."); while (1) { ; diff --git a/examples/espidf/z_get.c b/examples/espidf/z_get.c index a8e06549f..ec200e8a2 100644 --- a/examples/espidf/z_get.c +++ b/examples/espidf/z_get.c @@ -103,12 +103,17 @@ void wifi_init_sta(void) { void reply_dropper(void *ctx) { printf(" >> Received query final notification\n"); } -void reply_handler(z_owned_reply_t *oreply, void *ctx) { +void reply_handler(const z_loaned_reply_t *oreply, void *ctx) { if (z_reply_is_ok(oreply)) { - z_sample_t sample = z_reply_ok(oreply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(" >> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); - z_drop(z_move(keystr)); + const z_loaned_sample_t *sample = z_reply_ok(oreply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(" >> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), + (int)z_string_len(z_loan(replystr)), z_string_data(z_loan(replystr))); + z_drop(z_move(replystr)); } else { printf(" >> Received an error\n"); } @@ -132,43 +137,48 @@ void app_main() { printf("OK!\n"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); while (1) { sleep(5); printf("Sending Query '%s'...\n", KEYEXPR); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (strcmp(VALUE, "") != 0) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)VALUE, strlen(VALUE)); + z_bytes_from_static_str(&payload, VALUE); + opts.payload = z_move(payload); } - z_owned_closure_reply_t callback = z_closure(reply_handler, reply_dropper); - if (z_get(z_loan(s), z_keyexpr(KEYEXPR), "", z_move(callback), &opts) < 0) { + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, reply_dropper); + 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); } } printf("Closing Zenoh Session..."); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); printf("OK!\n"); diff --git a/examples/espidf/z_pub.c b/examples/espidf/z_pub.c index b55336f94..df5bc7def 100644 --- a/examples/espidf/z_pub.c +++ b/examples/espidf/z_pub.c @@ -119,28 +119,31 @@ void app_main() { printf("OK!\n"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); printf("Declaring publisher for '%s'...", KEYEXPR); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(KEYEXPR), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); exit(-1); } @@ -151,16 +154,17 @@ void app_main() { sleep(1); sprintf(buf, "[%4d] %s", idx, VALUE); printf("Putting Data ('%s': '%s')...\n", KEYEXPR, buf); - z_publisher_put(z_loan(pub), (const uint8_t*)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); } printf("Closing Zenoh Session..."); z_undeclare_publisher(z_move(pub)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); printf("OK!\n"); } diff --git a/examples/espidf/z_pull.c b/examples/espidf/z_pull.c index e686190fd..573d8cf50 100644 --- a/examples/espidf/z_pull.c +++ b/examples/espidf/z_pull.c @@ -48,6 +48,9 @@ static int s_retry_count = 0; #define KEYEXPR "demo/example/**" +const size_t INTERVAL = 5000; +const size_t SIZE = 3; + static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); @@ -100,13 +103,6 @@ void wifi_init_sta(void) { vEventGroupDelete(s_event_group_handler); } -void data_handler(const z_sample_t* sample, void* arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(" >> [Subscriber handler] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); -} - void app_main() { esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { @@ -125,47 +121,65 @@ void app_main() { printf("OK!\n"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); - // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + exit(-1); + } - printf("Declaring Subscriber on '%s'...", KEYEXPR); - z_owned_closure_sample_t callback = z_closure(data_handler); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + printf("Declaring Subscriber on '%s'...\n", KEYEXPR); + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, SIZE); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); exit(-1); } - printf("OK!\n"); - int idx = 0; - while (1) { - sleep(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_loan(sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", INTERVAL, SIZE); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_try_recv(z_loan(handler), &sample); res == Z_OK; res = z_try_recv(z_loan(handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_loan(sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_loan(sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + z_drop(z_move(sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", INTERVAL); + z_sleep_ms(INTERVAL); + } else { + break; + } } - printf("Closing Zenoh Session..."); - z_undeclare_pull_subscriber(z_move(sub)); - - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_subscriber(z_move(sub)); + z_drop(z_move(handler)); z_close(z_move(s)); printf("OK!\n"); diff --git a/examples/espidf/z_queryable.c b/examples/espidf/z_queryable.c index 15b4e9afd..41fe2b642 100644 --- a/examples/espidf/z_queryable.c +++ b/examples/espidf/z_queryable.c @@ -101,13 +101,31 @@ void wifi_init_sta(void) { vEventGroupDelete(s_event_group_handler); } -void query_handler(z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - printf(">> [Queryable handler] Received Query '%s%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); - z_query_reply(query, z_keyexpr(KEYEXPR), (const unsigned char *)VALUE, strlen(VALUE), NULL); - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); + } + z_drop(z_move(payload_string)); + + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, VALUE); + + z_query_reply(query, z_loan(ke), z_move(reply_payload), NULL); } void app_main() { @@ -128,30 +146,34 @@ void app_main() { printf("OK!\n"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); - z_owned_closure_query_t callback = z_closure(query_handler); - z_owned_queryable_t qable = z_declare_queryable(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(qable)) { + z_owned_closure_query_t callback; + z_closure(&callback, query_handler); + z_owned_queryable_t qable; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare queryable.\n"); exit(-1); } @@ -165,10 +187,6 @@ void app_main() { printf("Closing Zenoh Session..."); z_undeclare_queryable(z_move(qable)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); printf("OK!\n"); } diff --git a/examples/espidf/z_scout.c b/examples/espidf/z_scout.c index 3b45a5a6a..9866a2806 100644 --- a/examples/espidf/z_scout.c +++ b/examples/espidf/z_scout.c @@ -99,41 +99,38 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_loan(s)), z_string_data(z_loan(s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_hello_loan(hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; } @@ -167,8 +164,10 @@ void app_main() { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure_hello(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure_hello(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_scouting_config_move(&config), z_closure_hello_move(&closure)); + z_scout(z_config_move(&config), z_closure_hello_move(&closure), NULL); } diff --git a/examples/espidf/z_sub.c b/examples/espidf/z_sub.c index 467160440..fa9e8eeef 100644 --- a/examples/espidf/z_sub.c +++ b/examples/espidf/z_sub.c @@ -100,11 +100,15 @@ void wifi_init_sta(void) { vEventGroupDelete(s_event_group_handler); } -void data_handler(const z_sample_t* sample, void* arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(" >> [Subscriber handler] Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample->payload.len, - sample->payload.start); - z_str_drop(z_str_move(&keystr)); +void data_handler(const z_loaned_sample_t* sample, void* arg) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(" >> [Subscriber handler] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&value)), + z_string_data(z_string_loan(&value))); + z_string_drop(z_string_move(&value)); } void app_main() { @@ -125,29 +129,33 @@ void app_main() { printf("OK!\n"); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); printf("Declaring Subscriber on '%s'...", KEYEXPR); - z_owned_closure_sample_t callback = z_closure(data_handler); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); exit(-1); } @@ -160,10 +168,6 @@ void app_main() { printf("Closing Zenoh Session..."); z_undeclare_subscriber(z_move(sub)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); printf("OK!\n"); } diff --git a/examples/freertos_plus_tcp/CMakeLists.txt b/examples/freertos_plus_tcp/CMakeLists.txt index 8130e0a23..83f890f30 100644 --- a/examples/freertos_plus_tcp/CMakeLists.txt +++ b/examples/freertos_plus_tcp/CMakeLists.txt @@ -61,15 +61,6 @@ target_link_libraries(zenohpico freertos_kernel freertos_plus_tcp ) -target_compile_definitions(zenohpico - PUBLIC - Z_FEATURE_MULTI_THREAD=1 - Z_FEATURE_LINK_TCP=1 - Z_FEATURE_SCOUTING_UDP=1 - Z_FEATURE_LINK_UDP_UNICAST=1 - Z_FEATURE_LINK_UDP_MULTICAST=0 - Z_CONFIG_SOCKET_TIMEOUT=1000 -) add_library(main OBJECT main.c) target_link_libraries(main diff --git a/examples/freertos_plus_tcp/z_get.c b/examples/freertos_plus_tcp/z_get.c index 09c1d3507..63407ab48 100644 --- a/examples/freertos_plus_tcp/z_get.c +++ b/examples/freertos_plus_tcp/z_get.c @@ -36,63 +36,70 @@ void reply_dropper(void *ctx) { printf(">> Received query final notification\n"); } -void reply_handler(z_owned_reply_t *reply, void *ctx) { +void reply_handler(const z_loaned_reply_t *reply, void *ctx) { (void)(ctx); if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); - z_drop(z_move(keystr)); + const z_loaned_sample_t *sample = z_reply_ok(reply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(">> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), + (int)z_string_len(z_loan(replystr)), z_string_data(z_loan(replystr))); + z_drop(z_move(replystr)); } else { printf(">> Received an error\n"); } } void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return; } - z_keyexpr_t ke = z_keyexpr(KEYEXPR); - if (!z_check(ke)) { - printf("%s is not a valid key expression\n", KEYEXPR); + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, KEYEXPR) < 0) { + printf("%s is not a valid key expression", KEYEXPR); return; } while (1) { z_sleep_s(5); printf("Sending Query '%s'...\n", KEYEXPR); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (strcmp(VALUE, "") != 0) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)VALUE, strlen(VALUE)); + z_bytes_from_static_str(&payload, VALUE); + opts.payload = z_move(payload); } - z_owned_closure_reply_t callback = z_closure(reply_handler, reply_dropper); - if (z_get(z_loan(s), ke, "", z_move(callback), &opts) < 0) { + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, reply_dropper); + if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return; } } - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); } #else diff --git a/examples/freertos_plus_tcp/z_pub.c b/examples/freertos_plus_tcp/z_pub.c index abb4594f4..886d309db 100644 --- a/examples/freertos_plus_tcp/z_pub.c +++ b/examples/freertos_plus_tcp/z_pub.c @@ -32,15 +32,16 @@ #define VALUE "[FreeRTOS-Plus-TCP] Pub from Zenoh-Pico!" void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } @@ -74,15 +75,18 @@ void app_main(void) { zp_task_lease_options_t lease_task_opt = {.task_attributes = &lease_task_attr}; // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), &read_task_opt) < 0 || zp_start_lease_task(z_loan(s), &lease_task_opt) < 0) { + if (zp_start_read_task(z_loan_mut(s), &read_task_opt) < 0 || + zp_start_lease_task(z_loan_mut(s), &lease_task_opt) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return; } printf("Declaring publisher for '%s'...\n", KEYEXPR); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(KEYEXPR), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return; } @@ -93,17 +97,17 @@ void app_main(void) { snprintf(buf, 256, "[%4d] %s", idx, VALUE); printf("Putting Data ('%s': '%s')...\n", KEYEXPR, buf); - z_publisher_put_options_t options = z_publisher_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put_options_t options; + z_publisher_put_options_default(&options); + z_publisher_put(z_loan(pub), z_move(payload), &options); } + // Clean-up z_undeclare_publisher(z_move(pub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); } #else diff --git a/examples/freertos_plus_tcp/z_pub_st.c b/examples/freertos_plus_tcp/z_pub_st.c index 5803030c4..d485fb2b3 100644 --- a/examples/freertos_plus_tcp/z_pub_st.c +++ b/examples/freertos_plus_tcp/z_pub_st.c @@ -33,22 +33,25 @@ #define N 2147483647 // max int value by default void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } printf("Declaring publisher for '%s'...\n", KEYEXPR); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(KEYEXPR), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return; } @@ -59,7 +62,12 @@ void app_main(void) { if (z_clock_elapsed_ms(&now) > 1000) { snprintf(buf, 256, "[%4d] %s", idx, VALUE); printf("Putting Data ('%s': '%s')...\n", KEYEXPR, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); ++idx; now = z_clock_now(); diff --git a/examples/freertos_plus_tcp/z_pull.c b/examples/freertos_plus_tcp/z_pull.c index 3e8a04d6e..abd9fb89e 100644 --- a/examples/freertos_plus_tcp/z_pull.c +++ b/examples/freertos_plus_tcp/z_pull.c @@ -14,7 +14,7 @@ #include -#if Z_FEATURE_PUBLICATION == 1 +#if Z_FEATURE_SUBSCRIPTION == 1 #define CLIENT_OR_PEER 0 // 0: Client mode; 1: Peer mode #if CLIENT_OR_PEER == 0 #define MODE "client" @@ -28,55 +28,67 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *ctx) { - (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); -} +const size_t INTERVAL = 5000; +const size_t SIZE = 3; void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return; } - z_owned_closure_sample_t callback = z_closure(data_handler); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, SIZE); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); return; } - int idx = 0; - while (1) { - z_sleep_s(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_loan(sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", INTERVAL, SIZE); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_try_recv(z_loan(handler), &sample); res == Z_OK; res = z_try_recv(z_loan(handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_loan(sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_loan(sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + z_drop(z_move(sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", INTERVAL); + z_sleep_ms(INTERVAL); + } else { + break; + } } - z_undeclare_pull_subscriber(z_move(sub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_subscriber(z_move(sub)); + z_drop(z_move(handler)); z_close(z_move(s)); } diff --git a/examples/freertos_plus_tcp/z_put.c b/examples/freertos_plus_tcp/z_put.c index 1253af540..f7ef2714c 100644 --- a/examples/freertos_plus_tcp/z_put.c +++ b/examples/freertos_plus_tcp/z_put.c @@ -30,40 +30,46 @@ #define VALUE "[FreeRTOS-Plus-TCP] Pub from Zenoh-Pico!" void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return; } printf("Declaring key expression '%s'...\n", KEYEXPR); - z_owned_keyexpr_t ke = z_declare_keyexpr(z_loan(s), z_keyexpr(KEYEXPR)); - if (!z_check(ke)) { + z_owned_keyexpr_t ke; + z_view_keyexpr_t vke; + z_view_keyexpr_from_str_unchecked(&vke, KEYEXPR); + if (z_declare_keyexpr(&ke, z_loan(s), z_loan(vke)) < 0) { printf("Unable to declare key expression!\n"); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); return; } printf("Putting Data ('%s': '%s')...\n", KEYEXPR, VALUE); - z_put_options_t options = z_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - if (z_put(z_loan(s), z_loan(ke), (const uint8_t *)VALUE, strlen(VALUE), &options) < 0) { + z_put_options_t options; + z_put_options_default(&options); + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_static_str(&payload, VALUE); + + if (z_put(z_loan(s), z_loan(ke), z_move(payload), &options) < 0) { printf("Oh no! Put has failed...\n"); } @@ -72,9 +78,7 @@ void app_main(void) { } // Clean up - z_undeclare_keyexpr(z_loan(s), z_move(ke)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_keyexpr(z_move(ke), z_loan(s)); z_close(z_move(s)); } #else diff --git a/examples/freertos_plus_tcp/z_queryable.c b/examples/freertos_plus_tcp/z_queryable.c index 6e4a36b30..94122b262 100644 --- a/examples/freertos_plus_tcp/z_queryable.c +++ b/examples/freertos_plus_tcp/z_queryable.c @@ -29,52 +29,65 @@ #define KEYEXPR "demo/example/zenoh-pico-queryable" #define VALUE "[FreeRTOS-Plus-TCP] Queryable from Zenoh-Pico!" -void query_handler(const z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); - printf(" >> [Queryable handler] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); - if (payload_value.payload.len > 0) { - printf(" with value '%.*s'\n", (int)payload_value.payload.len, payload_value.payload.start); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); } - z_query_reply_options_t options = z_query_reply_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr(KEYEXPR), (const unsigned char *)VALUE, strlen(VALUE), &options); - z_drop(z_move(keystr)); + z_drop(z_move(payload_string)); + + z_query_reply_options_t options; + z_query_reply_options_default(&options); + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, VALUE); + + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), &options); } void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return; } - z_keyexpr_t ke = z_keyexpr(KEYEXPR); - if (!z_check(ke)) { - printf("%s is not a valid key expression\n", KEYEXPR); + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, KEYEXPR) < 0) { + printf("%s is not a valid key expression", KEYEXPR); return; } printf("Creating Queryable on '%s'...\n", KEYEXPR); - z_owned_closure_query_t callback = z_closure(query_handler); - z_owned_queryable_t qable = z_declare_queryable(z_loan(s), ke, z_move(callback), NULL); - if (!z_check(qable)) { + z_owned_closure_query_t callback; + z_closure(&callback, query_handler); + z_owned_queryable_t qable; + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); return; } @@ -85,10 +98,6 @@ void app_main(void) { z_undeclare_queryable(z_move(qable)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); } #else diff --git a/examples/freertos_plus_tcp/z_scout.c b/examples/freertos_plus_tcp/z_scout.c index 0f3087eee..0f59f2416 100644 --- a/examples/freertos_plus_tcp/z_scout.c +++ b/examples/freertos_plus_tcp/z_scout.c @@ -33,41 +33,38 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_loan(s)), z_string_data(z_loan(s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_loan(*hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; } @@ -85,8 +82,10 @@ void drop(void *context) { void app_main(void) { int *context = (int *)pvPortMalloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_move(config), z_move(closure)); + z_scout(z_move(config), z_move(closure), NULL); } diff --git a/examples/freertos_plus_tcp/z_sub.c b/examples/freertos_plus_tcp/z_sub.c index 9331619a6..e3a226313 100644 --- a/examples/freertos_plus_tcp/z_sub.c +++ b/examples/freertos_plus_tcp/z_sub.c @@ -28,39 +28,46 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); } void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return; } - z_owned_closure_sample_t callback = z_closure(data_handler); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return; } @@ -71,10 +78,6 @@ void app_main(void) { z_undeclare_subscriber(z_move(sub)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); } #else diff --git a/examples/freertos_plus_tcp/z_sub_st.c b/examples/freertos_plus_tcp/z_sub_st.c index 20ff5d636..e05bc45cd 100644 --- a/examples/freertos_plus_tcp/z_sub_st.c +++ b/examples/freertos_plus_tcp/z_sub_st.c @@ -31,33 +31,40 @@ int msg_nb = 0; -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); msg_nb++; } void app_main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return; } - z_owned_closure_sample_t callback = z_closure(data_handler); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); printf("Declaring Subscriber on '%s'...\n", KEYEXPR); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return; } diff --git a/examples/mbed/z_get.cpp b/examples/mbed/z_get.cpp index 905ac4e1c..aa61ae937 100644 --- a/examples/mbed/z_get.cpp +++ b/examples/mbed/z_get.cpp @@ -33,12 +33,18 @@ void reply_dropper(void *ctx) { printf(" >> Received query final notification\n"); } -void reply_handler(z_owned_reply_t *oreply, void *ctx) { +void reply_handler(const z_loaned_reply_t *oreply, void *ctx) { if (z_reply_is_ok(oreply)) { - z_sample_t sample = z_reply_ok(oreply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(" >> Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample.payload.len, sample.payload.start); - z_str_drop(z_str_move(&keystr)); + const z_loaned_sample_t *sample = z_reply_ok(oreply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(" >> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&replystr)), + z_string_data(z_string_loan(&replystr))); + z_string_drop(z_string_move(&replystr)); } else { printf(" >> Received an error\n"); } @@ -52,43 +58,48 @@ int main(int argc, char **argv) { net.connect(); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); while (1) { z_sleep_s(5); printf("Sending Query '%s'...\n", KEYEXPR); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (strcmp(VALUE, "") != 0) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)VALUE, strlen(VALUE)); + z_bytes_from_static_str(&payload, VALUE); + opts.payload = z_bytes_move(&payload); } - z_owned_closure_reply_t callback = z_closure_reply(reply_handler, reply_dropper, NULL); - if (z_get(z_session_loan(&s), z_keyexpr(KEYEXPR), "", z_closure_reply_move(&callback), &opts) < 0) { + z_owned_closure_reply_t callback; + z_closure_reply(&callback, reply_handler, reply_dropper, NULL); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_get(z_session_loan(&s), z_view_keyexpr_loan(&ke), "", z_closure_reply_move(&callback), &opts) < 0) { printf("Unable to send query.\n"); exit(-1); } } printf("Closing Zenoh Session..."); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); z_close(z_session_move(&s)); printf("OK!\n"); diff --git a/examples/mbed/z_pub.cpp b/examples/mbed/z_pub.cpp index 0fb939071..eb8e3edc6 100644 --- a/examples/mbed/z_pub.cpp +++ b/examples/mbed/z_pub.cpp @@ -39,28 +39,31 @@ int main(int argc, char **argv) { net.connect(); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); printf("Declaring publisher for '%s'...", KEYEXPR); - z_owned_publisher_t pub = z_declare_publisher(z_session_loan(&s), z_keyexpr(KEYEXPR), NULL); - if (!z_publisher_check(&pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_publisher(&pub, z_session_loan(&s), z_view_keyexpr_loan(&ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); exit(-1); } @@ -71,16 +74,17 @@ int main(int argc, char **argv) { z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, VALUE); printf("Putting Data ('%s': '%s')...\n", KEYEXPR, buf); - z_publisher_put(z_publisher_loan(&pub), (const uint8_t *)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL); } printf("Closing Zenoh Session..."); z_undeclare_publisher(z_publisher_move(&pub)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); - z_close(z_session_move(&s)); printf("OK!\n"); diff --git a/examples/mbed/z_pull.cpp b/examples/mbed/z_pull.cpp index fa9ece75f..9b86f0347 100644 --- a/examples/mbed/z_pull.cpp +++ b/examples/mbed/z_pull.cpp @@ -30,12 +30,8 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(" >> [Subscriber handler] Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample->payload.len, - sample->payload.start); - z_str_drop(z_str_move(&keystr)); -} +const size_t INTERVAL = 5000; +const size_t SIZE = 3; int main(int argc, char **argv) { randLIB_seed_random(); @@ -45,48 +41,68 @@ int main(int argc, char **argv) { net.connect(); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); - // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + // Start read and lease tasks for zenoh-pico + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { + printf("Unable to start read and lease tasks\n"); + z_close(z_session_move(&s)); + return -1; + } - printf("Declaring Subscriber on '%s'...", KEYEXPR); - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); - z_owned_pull_subscriber_t sub = - z_declare_pull_subscriber(z_session_loan(&s), z_keyexpr(KEYEXPR), z_closure_sample_move(&callback), NULL); - if (!z_pull_subscriber_check(&sub)) { + printf("Declaring Subscriber on '%s'...\n", KEYEXPR); + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, SIZE); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&closure), + NULL) < 0) { printf("Unable to declare subscriber.\n"); - exit(-1); + return -1; } - printf("OK!\n"); - int idx = 0; - while (1) { - z_sleep_s(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_pull_subscriber_loan(&sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", INTERVAL, SIZE); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_ring_handler_sample_try_recv(z_ring_handler_sample_loan(&handler), &sample); res == Z_OK; + res = z_ring_handler_sample_try_recv(z_ring_handler_sample_loan(&handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_sample_loan(&sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_sample_loan(&sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&value)), + z_string_data(z_string_loan(&value))); + z_string_drop(z_string_move(&value)); + z_sample_drop(z_sample_move(&sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", INTERVAL); + z_sleep_ms(INTERVAL); + } else { + break; + } } - printf("Closing Zenoh Session..."); - z_undeclare_pull_subscriber(z_pull_subscriber_move(&sub)); - - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); + z_undeclare_subscriber(z_subscriber_move(&sub)); + z_ring_handler_sample_drop(z_ring_handler_sample_move(&handler)); z_close(z_session_move(&s)); printf("OK!\n"); diff --git a/examples/mbed/z_queryable.cpp b/examples/mbed/z_queryable.cpp index b0b9358bf..d9bba3d52 100644 --- a/examples/mbed/z_queryable.cpp +++ b/examples/mbed/z_queryable.cpp @@ -31,13 +31,29 @@ #define KEYEXPR "demo/example/zenoh-pico-queryable" #define VALUE "[MBedOS]{nucleo-F767ZI} Queryable from Zenoh-Pico!" -void query_handler(const z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - printf(" >> [Queryable handler] Received Query '%s%.*s'\n", z_str_loan(&keystr), (int)pred.len, pred.start); - z_query_reply(query, z_keyexpr(KEYEXPR), (const unsigned char *)VALUE, strlen(VALUE), NULL); - z_str_drop(z_str_move(&keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_view_string_loan(¶ms)), + z_string_data(z_view_string_loan(¶ms))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_string_loan(&payload_string)) > 1) { + printf(" with value '%.*s'\n", (int)z_string_len(z_string_loan(&payload_string)), + z_string_data(z_string_loan(&payload_string))); + } + z_string_drop(z_string_move(&payload_string)); + + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, VALUE); + + z_query_reply(query, z_query_keyexpr(query), z_bytes_move(&reply_payload), NULL); } int main(int argc, char **argv) { @@ -48,31 +64,35 @@ int main(int argc, char **argv) { net.connect(); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); - z_owned_closure_query_t callback = z_closure_query(query_handler, NULL, NULL); - z_owned_queryable_t qable = - z_declare_queryable(z_session_loan(&s), z_keyexpr(KEYEXPR), z_closure_query_move(&callback), NULL); - if (!z_queryable_check(&qable)) { + z_owned_closure_query_t callback; + z_closure_query(&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(&qable, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_query_move(&callback), + NULL) < 0) { printf("Unable to declare queryable.\n"); exit(-1); } @@ -86,10 +106,6 @@ int main(int argc, char **argv) { printf("Closing Zenoh Session..."); z_undeclare_queryable(z_queryable_move(&qable)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); - z_close(z_session_move(&s)); printf("OK!\n"); diff --git a/examples/mbed/z_scout.cpp b/examples/mbed/z_scout.cpp index c3cdf5d41..c227acabc 100644 --- a/examples/mbed/z_scout.cpp +++ b/examples/mbed/z_scout.cpp @@ -41,41 +41,38 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_view_string_loan(&s)), z_string_data(z_view_string_loan(&s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_hello_loan(hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; } @@ -99,10 +96,12 @@ int main(void) { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure_hello(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure_hello(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_scouting_config_move(&config), z_closure_hello_move(&closure)); + z_scout(z_config_move(&config), z_closure_hello_move(&closure), NULL); return 0; } diff --git a/examples/mbed/z_sub.cpp b/examples/mbed/z_sub.cpp index b60f82d44..78edd365c 100644 --- a/examples/mbed/z_sub.cpp +++ b/examples/mbed/z_sub.cpp @@ -30,11 +30,15 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(" >> [Subscriber handler] Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample->payload.len, - sample->payload.start); - z_str_drop(z_str_move(&keystr)); +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(" >> [Subscriber handler] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&value)), + z_string_data(z_string_loan(&value))); + z_string_drop(z_string_move(&value)); } int main(int argc, char **argv) { @@ -45,30 +49,34 @@ int main(int argc, char **argv) { net.connect(); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_session_loan(&s), NULL); - zp_start_lease_task(z_session_loan(&s), NULL); + zp_start_read_task(z_session_loan_mut(&s), NULL); + zp_start_lease_task(z_session_loan_mut(&s), NULL); printf("Declaring Subscriber on '%s'...", KEYEXPR); - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); - z_owned_subscriber_t sub = - z_declare_subscriber(z_session_loan(&s), z_keyexpr(KEYEXPR), z_closure_sample_move(&callback), NULL); - if (!z_subscriber_check(&sub)) { + z_owned_closure_sample_t callback; + z_closure_sample(&callback, data_handler, NULL, NULL); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&callback), + NULL) < 0) { printf("Unable to declare subscriber.\n"); exit(-1); } @@ -81,10 +89,6 @@ int main(int argc, char **argv) { printf("Closing Zenoh Session..."); z_undeclare_subscriber(z_subscriber_move(&sub)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); - z_close(z_session_move(&s)); printf("OK!\n"); diff --git a/examples/unix/c11/z_get.c b/examples/unix/c11/z_get.c index f98426a15..fc0fb0900 100644 --- a/examples/unix/c11/z_get.c +++ b/examples/unix/c11/z_get.c @@ -19,25 +19,37 @@ #include #if Z_FEATURE_QUERY == 1 && Z_FEATURE_MULTI_THREAD == 1 -static z_condvar_t cond; -static z_mutex_t mutex; +static z_owned_condvar_t cond; +static z_owned_mutex_t mutex; + +const char *kind_to_str(z_sample_kind_t kind); void reply_dropper(void *ctx) { (void)(ctx); printf(">> Received query final notification\n"); - z_condvar_signal(&cond); - z_condvar_free(&cond); + z_condvar_signal(z_loan_mut(cond)); + z_drop(z_move(cond)); } -void reply_handler(z_owned_reply_t *reply, void *ctx) { +void reply_handler(const z_loaned_reply_t *reply, void *ctx) { (void)(ctx); if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); - z_drop(z_move(keystr)); + const z_loaned_sample_t *sample = z_reply_ok(reply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(">> Received %s ('%.*s': '%.*s')\n", kind_to_str(z_sample_kind(sample)), + (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(replystr)), + z_string_data(z_loan(replystr))); + z_drop(z_move(replystr)); } else { - printf(">> Received an error\n"); + const z_loaned_reply_err_t *err = z_reply_err(reply); + z_owned_string_t errstr; + z_bytes_deserialize_into_string(z_reply_err_payload(err), &errstr); + printf(">> Received an error: %.*s\n", (int)z_string_len(z_loan(errstr)), z_string_data(z_loan(errstr))); + z_drop(z_move(errstr)); } } @@ -81,57 +93,70 @@ int main(int argc, char **argv) { z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_keyexpr_t ke = z_keyexpr(keyexpr); - if (!z_check(ke)) { + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { printf("%s is not a valid key expression", keyexpr); return -1; } - z_mutex_lock(&mutex); + z_mutex_lock(z_loan_mut(mutex)); printf("Sending Query '%s'...\n", keyexpr); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (value != NULL) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)value, strlen(value)); + z_bytes_from_static_str(&payload, value); + opts.payload = z_bytes_move(&payload); } - z_owned_closure_reply_t callback = z_closure(reply_handler, reply_dropper); - if (z_get(z_loan(s), ke, "", z_move(callback), &opts) < 0) { + + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, reply_dropper); + if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; } - z_condvar_wait(&cond, &mutex); - z_mutex_unlock(&mutex); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); + z_mutex_unlock(z_loan_mut(mutex)); z_close(z_move(s)); - return 0; } + +const char *kind_to_str(z_sample_kind_t kind) { + switch (kind) { + case Z_SAMPLE_KIND_PUT: + return "PUT"; + case Z_SAMPLE_KIND_DELETE: + return "DELETE"; + default: + return "UNKNOWN"; + } +} #else int main(void) { printf( diff --git a/examples/unix/c11/z_get_attachment.c b/examples/unix/c11/z_get_attachment.c new file mode 100644 index 000000000..022b70d7d --- /dev/null +++ b/examples/unix/c11/z_get_attachment.c @@ -0,0 +1,246 @@ +// +// 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 +#include +#include +#include +#include +#include + +typedef struct kv_pair_t { + const char *key; + const char *value; +} kv_pair_t; + +typedef struct kv_pairs_tx_t { + const kv_pair_t *data; + uint32_t len; + uint32_t current_idx; +} kv_pairs_tx_t; + +typedef struct kv_pair_decoded_t { + z_owned_string_t key; + z_owned_string_t value; +} kv_pair_decoded_t; + +typedef struct kv_pairs_rx_t { + kv_pair_decoded_t *data; + uint32_t len; + uint32_t current_idx; +} kv_pairs_rx_t; + +#define KVP_LEN 16 + +#if Z_FEATURE_QUERY == 1 && Z_FEATURE_MULTI_THREAD == 1 +static z_owned_condvar_t cond; +static z_owned_mutex_t mutex; + +_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { + kv_pairs_tx_t *kvs = (kv_pairs_tx_t *)(context); + z_owned_bytes_t k, v; + if (kvs->current_idx >= kvs->len) { + return false; + } else { + z_bytes_serialize_from_str(&k, kvs->data[kvs->current_idx].key); + z_bytes_serialize_from_str(&v, kvs->data[kvs->current_idx].value); + z_bytes_from_pair(kv_pair, z_move(k), z_move(v)); + kvs->current_idx++; + return true; + } +} + +void parse_attachment(kv_pairs_rx_t *kvp, const z_loaned_bytes_t *attachment) { + z_owned_bytes_t kv, first, second; + z_bytes_iterator_t iter = z_bytes_get_iterator(attachment); + + while (kvp->current_idx < kvp->len && z_bytes_iterator_next(&iter, &kv)) { + z_bytes_deserialize_into_pair(z_loan(kv), &first, &second); + z_bytes_deserialize_into_string(z_loan(first), &kvp->data[kvp->current_idx].key); + z_bytes_deserialize_into_string(z_loan(second), &kvp->data[kvp->current_idx].value); + z_bytes_drop(z_bytes_move(&first)); + z_bytes_drop(z_bytes_move(&second)); + z_bytes_drop(z_bytes_move(&kv)); + kvp->current_idx++; + } +} + +void print_attachment(kv_pairs_rx_t *kvp) { + printf(" with attachment:\n"); + for (uint32_t i = 0; i < kvp->current_idx; i++) { + printf(" %d: %.*s, %.*s\n", i, (int)z_string_len(z_loan(kvp->data[i].key)), + z_string_data(z_loan(kvp->data[i].key)), (int)z_string_len(z_loan(kvp->data[i].value)), + z_string_data(z_loan(kvp->data[i].value))); + } +} + +void drop_attachment(kv_pairs_rx_t *kvp) { + for (size_t i = 0; i < kvp->current_idx; i++) { + z_string_drop(z_string_move(&kvp->data[i].key)); + z_string_drop(z_string_move(&kvp->data[i].value)); + } + z_free(kvp->data); +} + +void reply_dropper(void *ctx) { + (void)(ctx); + printf(">> Received query final notification\n"); + z_condvar_signal(z_loan_mut(cond)); + z_drop(z_move(cond)); +} + +void reply_handler(const z_loaned_reply_t *reply, void *ctx) { + (void)(ctx); + if (z_reply_is_ok(reply)) { + const z_loaned_sample_t *sample = z_reply_ok(reply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + z_owned_string_t encoding; + z_encoding_to_string(z_sample_encoding(sample), &encoding); + + printf(">> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), + (int)z_string_len(z_loan(replystr)), z_string_data(z_loan(replystr))); + printf(" with encoding: %.*s\n", (int)z_string_len(z_loan(encoding)), z_string_data(z_loan(encoding))); + + // Check attachment + kv_pairs_rx_t kvp = { + .current_idx = 0, .len = KVP_LEN, .data = (kv_pair_decoded_t *)malloc(KVP_LEN * sizeof(kv_pair_decoded_t))}; + parse_attachment(&kvp, z_sample_attachment(sample)); + if (kvp.current_idx > 0) { + print_attachment(&kvp); + } + drop_attachment(&kvp); + + z_drop(z_move(replystr)); + z_drop(z_move(encoding)); + } else { + printf(">> Received an error\n"); + } +} + +int main(int argc, char **argv) { + const char *keyexpr = "demo/example/**"; + const char *mode = "client"; + const char *clocator = NULL; + const char *llocator = NULL; + const char *value = NULL; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:v:l:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'v': + value = optarg; + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_mutex_init(&mutex); + z_condvar_init(&cond); + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + return -1; + } + + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { + printf("%s is not a valid key expression", keyexpr); + return -1; + } + + z_mutex_lock(z_loan_mut(mutex)); + printf("Sending Query '%s'...\n", keyexpr); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; + if (value != NULL) { + z_bytes_from_static_str(&payload, value); + opts.payload = z_bytes_move(&payload); + } + + // Add attachment value + kv_pair_t kvs[1]; + kvs[0] = (kv_pair_t){.key = "test_key", .value = "test_value"}; + kv_pairs_tx_t ctx = (kv_pairs_tx_t){.data = kvs, .current_idx = 0, .len = 1}; + z_owned_bytes_t attachment; + z_bytes_from_iter(&attachment, create_attachment_iter, (void *)&ctx); + opts.attachment = z_move(attachment); + + // Add encoding value + z_owned_encoding_t encoding; + z_encoding_from_str(&encoding, "zenoh/string;utf8"); + opts.encoding = z_move(encoding); + + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, reply_dropper); + if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { + printf("Unable to send query.\n"); + return -1; + } + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); + z_mutex_unlock(z_loan_mut(mutex)); + + z_close(z_move(s)); + return 0; +} +#else +int main(void) { + printf( + "ERROR: Zenoh pico was compiled without Z_FEATURE_QUERY or Z_FEATURE_MULTI_THREAD but this example requires " + "them.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_get_channel.c b/examples/unix/c11/z_get_channel.c new file mode 100644 index 000000000..156e917a2 --- /dev/null +++ b/examples/unix/c11/z_get_channel.c @@ -0,0 +1,137 @@ +// +// Copyright (c) 2024 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 +#include +#include +#include +#include +#include + +#if Z_FEATURE_QUERY == 1 && Z_FEATURE_MULTI_THREAD == 1 + +int main(int argc, char **argv) { + const char *keyexpr = "demo/example/**"; + const char *mode = "client"; + const char *clocator = NULL; + const char *llocator = NULL; + const char *value = NULL; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:v:l:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'v': + value = optarg; + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + return -1; + } + + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { + printf("%s is not a valid key expression", keyexpr); + return -1; + } + + printf("Sending Query '%s'...\n", keyexpr); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; + if (value != NULL) { + z_bytes_from_static_str(&payload, value); + opts.payload = z_bytes_move(&payload); + } + z_owned_closure_reply_t closure; + z_owned_ring_handler_reply_t handler; + z_ring_channel_reply_new(&closure, &handler, 1); + if (z_get(z_loan(s), z_loan(ke), "", z_move(closure), &opts) < 0) { + printf("Unable to send query.\n"); + return -1; + } + + z_owned_reply_t reply; + for (z_result_t res = z_recv(z_loan(handler), &reply); res == Z_OK; res = z_recv(z_loan(handler), &reply)) { + if (z_reply_is_ok(z_loan(reply))) { + const z_loaned_sample_t *sample = z_reply_ok(z_loan(reply)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(">> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), + (int)z_string_len(z_loan(replystr)), z_string_data(z_loan(replystr))); + z_drop(z_move(replystr)); + } else { + printf(">> Received an error\n"); + } + } + + z_drop(z_move(handler)); + + z_close(z_move(s)); + + return 0; +} +#else +int main(void) { + printf( + "ERROR: Zenoh pico was compiled without Z_FEATURE_QUERY or Z_FEATURE_MULTI_THREAD but this example requires " + "them.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_info.c b/examples/unix/c11/z_info.c index 455fe17c7..5b0fa48c6 100644 --- a/examples/unix/c11/z_info.c +++ b/examples/unix/c11/z_info.c @@ -56,24 +56,25 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; @@ -84,18 +85,16 @@ int main(int argc, char **argv) { print_zid(&self_id, NULL); printf("Routers IDs:\n"); - z_owned_closure_zid_t callback = z_closure(print_zid); + z_owned_closure_zid_t callback; + z_closure(&callback, print_zid); 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(print_zid); + z_owned_closure_zid_t callback2; + z_closure(&callback2, print_zid); z_info_peers_zid(z_loan(s), z_move(callback2)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); } diff --git a/examples/unix/c11/z_ping.c b/examples/unix/c11/z_ping.c index f4da4dd18..cc1bd5de1 100644 --- a/examples/unix/c11/z_ping.c +++ b/examples/unix/c11/z_ping.c @@ -27,17 +27,17 @@ #define DEFAULT_PING_NB 100 #define DEFAULT_WARMUP_MS 1000 -static z_condvar_t cond; -static z_mutex_t mutex; +static z_owned_condvar_t cond; +static z_owned_mutex_t mutex; -void callback(const z_sample_t* sample, void* context) { +void callback(const z_loaned_sample_t* sample, void* context) { (void)sample; (void)context; - z_condvar_signal(&cond); + z_condvar_signal(z_loan_mut(cond)); } void drop(void* context) { (void)context; - z_condvar_free(&cond); + z_drop(z_move(cond)); } struct args_t { @@ -63,31 +63,35 @@ int main(int argc, char** argv) { } z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = z_config_default(); - z_owned_session_t session = z_open(z_move(config)); - if (!z_check(session)) { + z_owned_config_t config; + z_config_default(&config); + z_owned_session_t session; + if (z_open(&session, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } - if (zp_start_read_task(z_loan(session), NULL) < 0 || zp_start_lease_task(z_loan(session), NULL) < 0) { + if (zp_start_read_task(z_loan_mut(session), NULL) < 0 || zp_start_lease_task(z_loan_mut(session), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&session)); return -1; } - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); + z_view_keyexpr_t ping; + z_view_keyexpr_from_str_unchecked(&ping, "test/ping"); + z_view_keyexpr_t pong; + z_view_keyexpr_from_str_unchecked(&pong, "test/pong"); - z_owned_publisher_t pub = z_declare_publisher(z_loan(session), ping, NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_loan(session), z_loan(ping), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } - z_owned_closure_sample_t respond = z_closure(callback, drop, NULL); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), pong, z_move(respond), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t respond; + z_closure(&respond, callback, drop, NULL); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(session), z_loan(pong), z_move(respond), NULL) < 0) { printf("Unable to declare subscriber for key expression.\n"); return -1; } @@ -96,36 +100,41 @@ int main(int argc, char** argv) { for (unsigned int i = 0; i < args.size; i++) { data[i] = (uint8_t)(i % 10); } - z_mutex_lock(&mutex); + z_mutex_lock(z_loan_mut(mutex)); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); z_clock_t warmup_start = z_clock_now(); unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - z_publisher_put(z_loan(pub), data, args.size, NULL); - z_condvar_wait(&cond, &mutex); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); elapsed_us = z_clock_elapsed_us(&warmup_start); } } unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (unsigned int i = 0; i < args.number_of_pings; i++) { z_clock_t measure_start = z_clock_now(); - z_publisher_put(z_loan(pub), data, args.size, NULL); - z_condvar_wait(&cond, &mutex); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); results[i] = z_clock_elapsed_us(&measure_start); } for (unsigned int i = 0; i < args.number_of_pings; i++) { printf("%d bytes: seq=%d rtt=%luµs, lat=%luµs\n", args.size, i, results[i], results[i] / 2); } - z_mutex_unlock(&mutex); + z_mutex_unlock(z_loan_mut(mutex)); z_free(results); z_free(data); z_drop(z_move(pub)); z_drop(z_move(sub)); - zp_stop_read_task(z_loan(session)); - zp_stop_lease_task(z_loan(session)); - z_close(z_move(session)); } diff --git a/examples/unix/c11/z_pong.c b/examples/unix/c11/z_pong.c index dc958e1bb..7bcc970ff 100644 --- a/examples/unix/c11/z_pong.c +++ b/examples/unix/c11/z_pong.c @@ -16,13 +16,15 @@ #include "zenoh-pico.h" #if Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_PUBLICATION == 1 -void callback(const z_sample_t* sample, void* context) { - z_publisher_t pub = z_loan(*(z_owned_publisher_t*)context); - z_publisher_put(pub, sample->payload.start, sample->payload.len, NULL); +void callback(const z_loaned_sample_t* sample, void* context) { + const z_loaned_publisher_t* pub = z_loan(*(z_owned_publisher_t*)context); + z_owned_bytes_t payload; + z_bytes_clone(&payload, z_sample_payload(sample)); + z_publisher_put(pub, z_move(payload), NULL); } void drop(void* context) { z_owned_publisher_t* pub = (z_owned_publisher_t*)context; - z_drop(pub); + z_drop(z_move(*pub)); // A note on lifetimes: // here, `sub` takes ownership of `pub` and will drop it before returning from its own `drop`, // which makes passing a pointer to the stack safe as long as `sub` is dropped in a scope where `pub` is still @@ -32,30 +34,34 @@ void drop(void* context) { int main(int argc, char** argv) { (void)argc; (void)argv; - z_owned_config_t config = z_config_default(); - z_owned_session_t session = z_open(z_move(config)); - if (!z_check(session)) { + z_owned_config_t config; + z_config_default(&config); + z_owned_session_t session; + if (z_open(&session, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } - if (zp_start_read_task(z_loan(session), NULL) < 0 || zp_start_lease_task(z_loan(session), NULL) < 0) { + if (zp_start_read_task(z_loan_mut(session), NULL) < 0 || zp_start_lease_task(z_loan_mut(session), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&session)); return -1; } - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); - z_owned_publisher_t pub = z_declare_publisher(z_loan(session), pong, NULL); - if (!z_check(pub)) { + z_view_keyexpr_t pong; + z_view_keyexpr_from_str_unchecked(&pong, "test/pong"); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_loan(session), z_loan(pong), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_owned_closure_sample_t respond = z_closure(callback, drop, (void*)z_move(pub)); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), ping, z_move(respond), NULL); - if (!z_check(sub)) { + z_view_keyexpr_t ping; + z_view_keyexpr_from_str_unchecked(&ping, "test/ping"); + z_owned_closure_sample_t respond; + z_closure(&respond, callback, drop, (void*)(&pub)); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(session), z_loan(ping), z_move(respond), NULL) < 0) { printf("Unable to declare subscriber for key expression.\n"); return -1; } @@ -65,9 +71,6 @@ int main(int argc, char** argv) { z_drop(z_move(sub)); - zp_stop_read_task(z_loan(session)); - zp_stop_lease_task(z_loan(session)); - z_close(z_move(session)); } #else diff --git a/examples/unix/c11/z_pub.c b/examples/unix/c11/z_pub.c index 786ed58b5..55ae68745 100644 --- a/examples/unix/c11/z_pub.c +++ b/examples/unix/c11/z_pub.c @@ -66,56 +66,61 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); + z_close(z_move(s)); return -1; } - + // Wait for joins in peer mode + if (strcmp(mode, "peer") == 0) { + printf("Waiting for joins...\n"); + sleep(3); + } + // Declare publisher printf("Declaring publisher for '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } + // Publish data printf("Press CTRL-C to quit...\n"); char buf[256]; for (int idx = 0; idx < n; ++idx) { - sleep(1); + z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put_options_t options = z_publisher_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); - } + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + z_publisher_put(z_loan(pub), z_move(payload), NULL); + } + // Clean up z_undeclare_publisher(z_move(pub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); - return 0; } #else diff --git a/examples/unix/c11/z_pub_attachment.c b/examples/unix/c11/z_pub_attachment.c new file mode 100644 index 000000000..d143af387 --- /dev/null +++ b/examples/unix/c11/z_pub_attachment.c @@ -0,0 +1,190 @@ +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +#include "zenoh-pico/system/platform.h" + +typedef struct kv_pair_t { + const char *key; + const char *value; +} kv_pair_t; + +typedef struct kv_pairs_t { + const kv_pair_t *data; + uint32_t len; + uint32_t current_idx; +} kv_pairs_t; + +#if Z_FEATURE_PUBLICATION == 1 + +_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { + kv_pairs_t *kvs = (kv_pairs_t *)(context); + z_owned_bytes_t k, v; + if (kvs->current_idx >= kvs->len) { + return false; + } else { + z_bytes_serialize_from_str(&k, kvs->data[kvs->current_idx].key); + z_bytes_serialize_from_str(&v, kvs->data[kvs->current_idx].value); + z_bytes_from_pair(kv_pair, z_move(k), z_move(v)); + kvs->current_idx++; + return true; + } +} + +int main(int argc, char **argv) { + const char *keyexpr = "demo/example/zenoh-pico-pub"; + char *const default_value = "Pub from Pico!"; + char *value = default_value; + const char *mode = "client"; + char *clocator = NULL; + char *llocator = NULL; + int n = 2147483647; // max int value by default + + int opt; + while ((opt = getopt(argc, argv, "k:v:e:m:l:n:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'v': + value = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'n': + n = atoi(optarg); + break; + case '?': + if (optopt == 'k' || optopt == 'v' || optopt == 'e' || optopt == 'm' || optopt == 'l' || + optopt == 'n') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_move(s)); + return -1; + } + // Wait for joins in peer mode + if (strcmp(mode, "peer") == 0) { + printf("Waiting for joins...\n"); + sleep(3); + } + // Declare publisher + printf("Declaring publisher for '%s'...\n", keyexpr); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { + printf("Unable to declare publisher for key expression!\n"); + return -1; + } + + z_publisher_put_options_t options; + z_publisher_put_options_default(&options); + + // Allocate attachment + kv_pair_t kvs[2]; + kvs[0] = (kv_pair_t){.key = "source", .value = "C"}; + z_owned_bytes_t attachment; + + // Allocate buffer + char buf_ind[16]; + + // Create encoding + z_owned_encoding_t encoding; + + // Create timestamp + z_timestamp_t ts; + z_timestamp_new(&ts, z_loan(s)); + + // Publish data + printf("Press CTRL-C to quit...\n"); + char buf[256]; + for (int idx = 0; idx < n; ++idx) { + z_sleep_s(1); + sprintf(buf, "[%4d] %s", idx, value); + printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + // Add attachment value + sprintf(buf_ind, "%d", idx); + kvs[1] = (kv_pair_t){.key = "index", .value = buf_ind}; + kv_pairs_t ctx = (kv_pairs_t){.data = kvs, .current_idx = 0, .len = 2}; + z_bytes_from_iter(&attachment, create_attachment_iter, (void *)&ctx); + options.attachment = z_move(attachment); + + // Add encoding value + z_encoding_from_str(&encoding, "zenoh/string;utf8"); + options.encoding = z_move(encoding); + + // Add timestamp + options.timestamp = &ts; + + z_publisher_put(z_loan(pub), z_move(payload), &options); + } + // Clean up + z_undeclare_publisher(z_move(pub)); + z_close(z_move(s)); + return 0; +} +#else +int main(void) { + printf("ERROR: Zenoh pico was compiled without Z_FEATURE_PUBLICATION but this example requires it.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_pub_st.c b/examples/unix/c11/z_pub_st.c index deb9e1f60..be0de263a 100644 --- a/examples/unix/c11/z_pub_st.c +++ b/examples/unix/c11/z_pub_st.c @@ -63,25 +63,28 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } printf("Declaring publisher for '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } @@ -92,7 +95,12 @@ int main(int argc, char **argv) { sleep(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); zp_read(z_loan(s), NULL); zp_send_keep_alive(z_loan(s), NULL); diff --git a/examples/unix/c11/z_pub_thr.c b/examples/unix/c11/z_pub_thr.c index 9711ed46c..056983410 100644 --- a/examples/unix/c11/z_pub_thr.c +++ b/examples/unix/c11/z_pub_thr.c @@ -19,6 +19,12 @@ #include "zenoh-pico.h" #if Z_FEATURE_PUBLICATION == 1 + +void z_free_with_context(void *ptr, void *context) { + (void)context; + z_free(ptr); +} + int main(int argc, char **argv) { if (argc < 2) { printf("USAGE:\n\tz_pub_thr []\n\n"); @@ -26,46 +32,52 @@ int main(int argc, char **argv) { } char *keyexpr = "test/thr"; size_t len = (size_t)atoi(argv[1]); - uint8_t *value = (uint8_t *)malloc(len); + uint8_t *value = (uint8_t *)z_malloc(len); memset(value, 1, len); // Set config - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (argc > 2) { - if (zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[2])) < 0) { + if (zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { printf("Couldn't insert locator in config: %s\n", argv[2]); exit(-1); } } // Open session - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); exit(-1); } // Declare publisher - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); exit(-1); } + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, len, z_free_with_context, NULL); // Send packets while (1) { - z_publisher_put(z_loan(pub), (const uint8_t *)value, len, NULL); + // Clone payload + z_owned_bytes_t p; + z_bytes_clone(&p, z_loan(payload)); + z_publisher_put(z_loan(pub), z_move(p), NULL); } // Clean up z_undeclare_publisher(z_move(pub)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); - free(value); + z_drop(z_move(payload)); exit(0); } #else diff --git a/examples/unix/c11/z_pull.c b/examples/unix/c11/z_pull.c index 8f1414622..34de6bed2 100644 --- a/examples/unix/c11/z_pull.c +++ b/examples/unix/c11/z_pull.c @@ -19,20 +19,14 @@ #include #if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *ctx) { - (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); -} - int main(int argc, char **argv) { const char *keyexpr = "demo/example/**"; char *locator = NULL; + size_t interval = 5000; + size_t size = 3; int opt; - while ((opt = getopt(argc, argv, "k:e:")) != -1) { + while ((opt = getopt(argc, argv, "k:e:i:s:")) != -1) { switch (opt) { case 'k': keyexpr = optarg; @@ -40,8 +34,14 @@ int main(int argc, char **argv) { case 'e': locator = optarg; break; + case 'i': + interval = (size_t)atoi(optarg); + break; + case 's': + size = (size_t)atoi(optarg); + break; case '?': - if (optopt == 'k' || optopt == 'e') { + if (optopt == 'k' || optopt == 'e' || optopt == 'i' || optopt == 's') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); } else { fprintf(stderr, "Unknown option `-%c'.\n", optopt); @@ -52,46 +52,62 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_owned_closure_sample_t callback = z_closure(data_handler); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, size); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } - printf("Press CTRL-C to quit...\n"); - int idx = 0; - while (1) { - sleep(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_loan(sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", interval, size); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_try_recv(z_loan(handler), &sample); res == Z_OK; res = z_try_recv(z_loan(handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_loan(sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_loan(sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + z_drop(z_move(sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", interval); + z_sleep_ms(interval); + } else { + break; + } } - z_undeclare_pull_subscriber(z_move(sub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_subscriber(z_move(sub)); + z_drop(z_move(handler)); z_close(z_move(s)); diff --git a/examples/unix/c11/z_put.c b/examples/unix/c11/z_put.c index 19c6b051a..628870f09 100644 --- a/examples/unix/c11/z_put.c +++ b/examples/unix/c11/z_put.c @@ -61,59 +61,49 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } printf("Declaring key expression '%s'...\n", keyexpr); - z_owned_keyexpr_t ke = z_declare_keyexpr(z_loan(s), z_keyexpr(keyexpr)); - if (!z_check(ke)) { - printf("Unable to declare key expression!\n"); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_view_keyexpr_t vke; + z_view_keyexpr_from_str(&vke, keyexpr); + z_owned_keyexpr_t ke; + if (z_declare_keyexpr(&ke, z_loan(s), z_loan(vke)) < 0) { z_close(z_move(s)); return -1; } + // Create payload + z_owned_bytes_t payload; + z_bytes_from_static_str(&payload, value); + printf("Putting Data ('%s': '%s')...\n", keyexpr, value); - z_put_options_t options = z_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); -#if Z_FEATURE_ATTACHMENT == 1 - z_owned_bytes_map_t map = z_bytes_map_new(); - z_bytes_map_insert_by_alias(&map, _z_bytes_wrap((uint8_t *)"hi", 2), _z_bytes_wrap((uint8_t *)"there", 5)); - options.attachment = z_bytes_map_as_attachment(&map); -#endif - if (z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)value, strlen(value), &options) < 0) { + if (z_put(z_loan(s), z_loan(ke), z_move(payload), NULL) < 0) { printf("Oh no! Put has failed...\n"); } - -#if Z_FEATURE_ATTACHMENT == 1 - z_bytes_map_drop(&map); -#endif - // Clean up - z_undeclare_keyexpr(z_loan(s), z_move(ke)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_keyexpr(z_move(ke), z_loan(s)); z_close(z_move(s)); return 0; } diff --git a/examples/unix/c11/z_queryable.c b/examples/unix/c11/z_queryable.c index 47001ec1f..77a6c1fc3 100644 --- a/examples/unix/c11/z_queryable.c +++ b/examples/unix/c11/z_queryable.c @@ -21,29 +21,61 @@ #if Z_FEATURE_QUERYABLE == 1 const char *keyexpr = "demo/example/zenoh-pico-queryable"; const char *value = "Queryable from Pico!"; +const char *error = "Demo error"; +static int msg_nb = 0; +static enum { REPLY_DATA, REPLY_DELETE, REPLY_ERR } reply_kind = REPLY_DATA; +bool reply_err = false; -void query_handler(const z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); - printf(" >> [Queryable handler] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); - if (payload_value.payload.len > 0) { - printf(" with value '%.*s'\n", (int)payload_value.payload.len, payload_value.payload.start); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); } - z_query_reply_options_t options = z_query_reply_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr(keyexpr), (const unsigned char *)value, strlen(value), &options); - z_drop(z_move(keystr)); + z_drop(z_move(payload_string)); + + switch (reply_kind) { + case REPLY_DATA: { + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, value); + + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), NULL); + break; + } + case REPLY_DELETE: { + z_query_reply_del(query, z_query_keyexpr(query), NULL); + break; + } + case REPLY_ERR: { + // Reply error encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, error); + + z_query_reply_err(query, z_move(reply_payload), NULL); + break; + } + } + msg_nb++; } int main(int argc, char **argv) { const char *mode = "client"; char *clocator = NULL; char *llocator = NULL; + int n = 0; int opt; - while ((opt = getopt(argc, argv, "k:e:m:v:l:")) != -1) { + while ((opt = getopt(argc, argv, "k:e:m:v:l:n:df")) != -1) { switch (opt) { case 'k': keyexpr = optarg; @@ -60,8 +92,18 @@ int main(int argc, char **argv) { case 'v': value = optarg; break; + case 'n': + n = atoi(optarg); + break; + case 'd': + reply_kind = REPLY_DELETE; + break; + case 'f': + reply_kind = REPLY_ERR; + break; case '?': - if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l') { + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l' || + optopt == 'n') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); } else { fprintf(stderr, "Unknown option `-%c'.\n", optopt); @@ -72,54 +114,55 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_keyexpr_t ke = z_keyexpr(keyexpr); - if (!z_check(ke)) { + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { printf("%s is not a valid key expression", keyexpr); return -1; } printf("Creating Queryable on '%s'...\n", keyexpr); - z_owned_closure_query_t callback = z_closure(query_handler); - z_owned_queryable_t qable = z_declare_queryable(z_loan(s), ke, z_move(callback), NULL); - if (!z_check(qable)) { + z_owned_closure_query_t callback; + z_closure(&callback, query_handler); + z_owned_queryable_t qable; + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); return -1; } printf("Press CTRL-C to quit...\n"); while (1) { + if ((n != 0) && (msg_nb >= n)) { + break; + } sleep(1); } z_undeclare_queryable(z_move(qable)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); return 0; diff --git a/examples/unix/c11/z_queryable_attachment.c b/examples/unix/c11/z_queryable_attachment.c new file mode 100644 index 000000000..0f9a54184 --- /dev/null +++ b/examples/unix/c11/z_queryable_attachment.c @@ -0,0 +1,260 @@ +// +// 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 +#include +#include +#include +#include +#include + +typedef struct kv_pair_t { + const char *key; + const char *value; +} kv_pair_t; + +typedef struct kv_pairs_tx_t { + const kv_pair_t *data; + uint32_t len; + uint32_t current_idx; +} kv_pairs_tx_t; + +typedef struct kv_pair_decoded_t { + z_owned_string_t key; + z_owned_string_t value; +} kv_pair_decoded_t; + +typedef struct kv_pairs_rx_t { + kv_pair_decoded_t *data; + uint32_t len; + uint32_t current_idx; +} kv_pairs_rx_t; + +#define KVP_LEN 16 + +#if Z_FEATURE_QUERYABLE == 1 +const char *keyexpr = "demo/example/zenoh-pico-queryable"; +const char *value = "Queryable from Pico!"; +static int msg_nb = 0; + +size_t kv_pairs_size(kv_pairs_tx_t *kvp) { + size_t ret = 0; + for (size_t i = 0; i < kvp->len; i++) { + // Size fields + ret += 2 * sizeof(uint32_t); + // Data size + ret += strlen(kvp->data[i].key) + strlen(kvp->data[i].value); + } + return ret; +} + +_Bool create_attachment_iter(z_owned_bytes_t *kv_pair, void *context) { + kv_pairs_tx_t *kvs = (kv_pairs_tx_t *)(context); + z_owned_bytes_t k, v; + if (kvs->current_idx >= kvs->len) { + return false; + } else { + z_bytes_serialize_from_str(&k, kvs->data[kvs->current_idx].key); + z_bytes_serialize_from_str(&v, kvs->data[kvs->current_idx].value); + z_bytes_from_pair(kv_pair, z_move(k), z_move(v)); + kvs->current_idx++; + return true; + } +} + +void parse_attachment(kv_pairs_rx_t *kvp, const z_loaned_bytes_t *attachment) { + z_owned_bytes_t kv, first, second; + z_bytes_iterator_t iter = z_bytes_get_iterator(attachment); + + while (kvp->current_idx < kvp->len && z_bytes_iterator_next(&iter, &kv)) { + z_bytes_deserialize_into_pair(z_loan(kv), &first, &second); + z_bytes_deserialize_into_string(z_loan(first), &kvp->data[kvp->current_idx].key); + z_bytes_deserialize_into_string(z_loan(second), &kvp->data[kvp->current_idx].value); + z_bytes_drop(z_bytes_move(&first)); + z_bytes_drop(z_bytes_move(&second)); + z_bytes_drop(z_bytes_move(&kv)); + kvp->current_idx++; + } +} + +void print_attachment(kv_pairs_rx_t *kvp) { + printf(" with attachment:\n"); + for (uint32_t i = 0; i < kvp->current_idx; i++) { + printf(" %d: %.*s, %.*s\n", i, (int)z_string_len(z_loan(kvp->data[i].key)), + z_string_data(z_loan(kvp->data[i].key)), (int)z_string_len(z_loan(kvp->data[i].value)), + z_string_data(z_loan(kvp->data[i].value))); + } +} + +void drop_attachment(kv_pairs_rx_t *kvp) { + for (size_t i = 0; i < kvp->current_idx; i++) { + z_string_drop(z_string_move(&kvp->data[i].key)); + z_string_drop(z_string_move(&kvp->data[i].value)); + } + z_free(kvp->data); +} + +void query_handler(const z_loaned_query_t *query, void *ctx) { + (void)(ctx); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process encoding + z_owned_string_t encoding; + z_encoding_to_string(z_query_encoding(query), &encoding); + printf(" with encoding: %.*s\n", (int)z_string_len(z_loan(encoding)), z_string_data(z_loan(encoding))); + + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); + } + // Check attachment + kv_pairs_rx_t kvp = { + .current_idx = 0, .len = KVP_LEN, .data = (kv_pair_decoded_t *)malloc(KVP_LEN * sizeof(kv_pair_decoded_t))}; + parse_attachment(&kvp, z_query_attachment(query)); + if (kvp.current_idx > 0) { + print_attachment(&kvp); + } + drop_attachment(&kvp); + z_drop(z_move(payload_string)); + z_drop(z_move(encoding)); + + // Reply payload + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, value); + + z_query_reply_options_t options; + z_query_reply_options_default(&options); + + // Reply attachment + kv_pair_t kvs[1]; + kvs[0] = (kv_pair_t){.key = "reply_key", .value = "reply_value"}; + kv_pairs_tx_t kv_ctx = (kv_pairs_tx_t){.data = kvs, .current_idx = 0, .len = 1}; + z_owned_bytes_t attachment; + z_bytes_from_iter(&attachment, create_attachment_iter, (void *)&kv_ctx); + options.attachment = z_move(attachment); + + // Reply encoding + z_owned_encoding_t reply_encoding; + z_encoding_from_str(&reply_encoding, "zenoh/string;utf8"); + options.encoding = z_move(reply_encoding); + + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), &options); + msg_nb++; +} + +int main(int argc, char **argv) { + const char *mode = "client"; + char *clocator = NULL; + char *llocator = NULL; + int n = 0; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:v:l:n:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'v': + value = optarg; + break; + case 'n': + n = atoi(optarg); + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l' || + optopt == 'n') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + return -1; + } + + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { + printf("%s is not a valid key expression", keyexpr); + return -1; + } + + printf("Creating Queryable on '%s'...\n", keyexpr); + z_owned_closure_query_t callback; + z_closure(&callback, query_handler); + z_owned_queryable_t qable; + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { + printf("Unable to create queryable.\n"); + return -1; + } + + printf("Press CTRL-C to quit...\n"); + while (1) { + if ((n != 0) && (msg_nb >= n)) { + break; + } + sleep(1); + } + + z_undeclare_queryable(z_move(qable)); + + z_close(z_move(s)); + + return 0; +} +#else +int main(void) { + printf("ERROR: Zenoh pico was compiled without Z_FEATURE_QUERYABLE but this example requires it.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_queryable_channel.c b/examples/unix/c11/z_queryable_channel.c new file mode 100644 index 000000000..1073bbda9 --- /dev/null +++ b/examples/unix/c11/z_queryable_channel.c @@ -0,0 +1,140 @@ +// +// Copyright (c) 2024 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 +#include +#include +#include +#include +#include + +#if Z_FEATURE_QUERYABLE == 1 +const char *keyexpr = "demo/example/zenoh-pico-queryable"; +const char *value = "Queryable from Pico!"; + +int main(int argc, char **argv) { + const char *mode = "client"; + char *clocator = NULL; + char *llocator = NULL; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:v:l:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'v': + value = optarg; + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'v' || optopt == 'l') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + return -1; + } + + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { + printf("%s is not a valid key expression", keyexpr); + return -1; + } + + printf("Creating Queryable on '%s'...\n", keyexpr); + z_owned_closure_query_t closure; + z_owned_ring_handler_query_t handler; + z_ring_channel_query_new(&closure, &handler, 10); + z_owned_queryable_t qable; + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { + printf("Unable to create queryable.\n"); + return -1; + } + + z_owned_query_t query; + for (z_result_t res = z_recv(z_loan(handler), &query); res == Z_OK; res = z_recv(z_loan(handler), &query)) { + const z_loaned_query_t *q = z_loan(query); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(q), &keystr); + z_view_string_t params; + z_query_parameters(q, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(z_loan(query)), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); + } + z_drop(z_move(payload_string)); + + z_query_reply_options_t options; + z_query_reply_options_default(&options); + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, value); + + z_query_reply(q, z_query_keyexpr(q), z_move(reply_payload), &options); + z_drop(z_move(query)); + } + + z_drop(z_move(handler)); + z_undeclare_queryable(z_move(qable)); + + z_close(z_move(s)); + + return 0; +} +#else +int main(void) { + printf("ERROR: Zenoh pico was compiled without Z_FEATURE_QUERYABLE but this example requires it.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_scout.c b/examples/unix/c11/z_scout.c index 3a6950aad..9c190017f 100644 --- a/examples/unix/c11/z_scout.c +++ b/examples/unix/c11/z_scout.c @@ -31,44 +31,40 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_loan(s)), z_string_data(z_loan(s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_loan(*hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; - z_drop(hello); } void drop(void *context) { @@ -87,10 +83,12 @@ int main(int argc, char **argv) { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_move(config), z_move(closure)); + z_scout(z_move(config), z_move(closure), NULL); sleep(1); return 0; } diff --git a/examples/unix/c11/z_sub.c b/examples/unix/c11/z_sub.c index 8bfedcade..a2fd5ba3f 100644 --- a/examples/unix/c11/z_sub.c +++ b/examples/unix/c11/z_sub.c @@ -22,26 +22,18 @@ #if Z_FEATURE_SUBSCRIPTION == 1 -#if Z_FEATURE_ATTACHMENT == 1 -int8_t attachment_handler(z_bytes_t key, z_bytes_t value, void *ctx) { - (void)ctx; - printf(">>> %.*s: %.*s\n", (int)key.len, key.start, (int)value.len, value.start); - return 0; -} -#endif +static int msg_nb = 0; -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); -#if Z_FEATURE_ATTACHMENT == 1 - if (z_attachment_check(&sample->attachment)) { - printf("Attachement found\n"); - z_attachment_iterate(sample->attachment, attachment_handler, NULL); - } -#endif - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + msg_nb++; } int main(int argc, char **argv) { @@ -49,9 +41,10 @@ int main(int argc, char **argv) { const char *mode = "client"; char *clocator = NULL; char *llocator = NULL; + int n = 0; int opt; - while ((opt = getopt(argc, argv, "k:e:m:l:")) != -1) { + while ((opt = getopt(argc, argv, "k:e:m:l:n:")) != -1) { switch (opt) { case 'k': keyexpr = optarg; @@ -65,8 +58,11 @@ int main(int argc, char **argv) { case 'l': llocator = optarg; break; + case 'n': + n = atoi(optarg); + break; case '?': - if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'l') { + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'l' || optopt == 'n') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); } else { fprintf(stderr, "Unknown option `-%c'.\n", optopt); @@ -77,50 +73,51 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_owned_closure_sample_t callback = z_closure(data_handler); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } printf("Press CTRL-C to quit...\n"); while (1) { + if ((n != 0) && (msg_nb >= n)) { + break; + } sleep(1); } - + // Clean up z_undeclare_subscriber(z_move(sub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); - return 0; } #else diff --git a/examples/unix/c11/z_sub_attachment.c b/examples/unix/c11/z_sub_attachment.c new file mode 100644 index 000000000..1e826d210 --- /dev/null +++ b/examples/unix/c11/z_sub_attachment.c @@ -0,0 +1,192 @@ +// +// 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 +#include +#include +#include +#include +#include +#include +#include + +typedef struct kv_pair_t { + z_owned_string_t key; + z_owned_string_t value; +} kv_pair_t; + +typedef struct kv_pairs_t { + kv_pair_t *data; + uint32_t len; + uint32_t current_idx; +} kv_pairs_t; + +#define KVP_LEN 16 + +#if Z_FEATURE_SUBSCRIPTION == 1 + +static int msg_nb = 0; + +void parse_attachment(kv_pairs_t *kvp, const z_loaned_bytes_t *attachment) { + z_owned_bytes_t kv, first, second; + z_bytes_iterator_t iter = z_bytes_get_iterator(attachment); + + while (kvp->current_idx < kvp->len && z_bytes_iterator_next(&iter, &kv)) { + z_bytes_deserialize_into_pair(z_loan(kv), &first, &second); + z_bytes_deserialize_into_string(z_loan(first), &kvp->data[kvp->current_idx].key); + z_bytes_deserialize_into_string(z_loan(second), &kvp->data[kvp->current_idx].value); + z_bytes_drop(z_bytes_move(&first)); + z_bytes_drop(z_bytes_move(&second)); + z_bytes_drop(z_bytes_move(&kv)); + kvp->current_idx++; + } +} + +void print_attachment(kv_pairs_t *kvp) { + printf(" with attachment:\n"); + for (uint32_t i = 0; i < kvp->current_idx; i++) { + printf(" %d: %.*s, %.*s\n", i, (int)z_string_len(z_loan(kvp->data[i].key)), + z_string_data(z_loan(kvp->data[i].key)), (int)z_string_len(z_loan(kvp->data[i].value)), + z_string_data(z_loan(kvp->data[i].value))); + } +} + +void drop_attachment(kv_pairs_t *kvp) { + for (size_t i = 0; i < kvp->current_idx; i++) { + z_string_drop(z_string_move(&kvp->data[i].key)); + z_string_drop(z_string_move(&kvp->data[i].value)); + } + z_free(kvp->data); +} + +void data_handler(const z_loaned_sample_t *sample, void *ctx) { + (void)(ctx); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + z_owned_string_t encoding; + z_encoding_to_string(z_sample_encoding(sample), &encoding); + + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + printf(" with encoding: %.*s\n", (int)z_string_len(z_loan(encoding)), z_string_data(z_loan(encoding))); + + // Check timestamp + const z_timestamp_t *ts = z_sample_timestamp(sample); + if (ts != NULL) { + printf(" with timestamp: %" PRIu64 "\n", z_timestamp_ntp64_time(ts)); + } + // Check attachment + kv_pairs_t kvp = {.current_idx = 0, .len = KVP_LEN, .data = (kv_pair_t *)malloc(KVP_LEN * sizeof(kv_pair_t))}; + parse_attachment(&kvp, z_sample_attachment(sample)); + if (kvp.current_idx > 0) { + print_attachment(&kvp); + } + drop_attachment(&kvp); + z_drop(z_move(value)); + z_drop(z_move(encoding)); + msg_nb++; +} + +int main(int argc, char **argv) { + const char *keyexpr = "demo/example/**"; + const char *mode = "client"; + char *clocator = NULL; + char *llocator = NULL; + int n = 0; + + int opt; + while ((opt = getopt(argc, argv, "k:e:m:l:n:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + clocator = optarg; + break; + case 'm': + mode = optarg; + break; + case 'l': + llocator = optarg; + break; + case 'n': + n = atoi(optarg); + break; + case '?': + if (optopt == 'k' || optopt == 'e' || optopt == 'm' || optopt == 'l' || optopt == 'n') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); + } + if (llocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + return -1; + } + + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); + printf("Declaring Subscriber on '%s'...\n", keyexpr); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { + printf("Unable to declare subscriber.\n"); + return -1; + } + + printf("Press CTRL-C to quit...\n"); + while (1) { + if ((n != 0) && (msg_nb >= n)) { + break; + } + sleep(1); + } + // Clean up + z_undeclare_subscriber(z_move(sub)); + z_close(z_move(s)); + return 0; +} +#else +int main(void) { + printf("ERROR: Zenoh pico was compiled without Z_FEATURE_SUBSCRIPTION but this example requires it.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_sub_channel.c b/examples/unix/c11/z_sub_channel.c new file mode 100644 index 000000000..96ef9da44 --- /dev/null +++ b/examples/unix/c11/z_sub_channel.c @@ -0,0 +1,104 @@ +// +// 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 +#include +#include +#include +#include +#include + +#if Z_FEATURE_SUBSCRIPTION == 1 +int main(int argc, char **argv) { + const char *keyexpr = "demo/example/**"; + char *locator = NULL; + + int opt; + while ((opt = getopt(argc, argv, "k:e:")) != -1) { + switch (opt) { + case 'k': + keyexpr = optarg; + break; + case 'e': + locator = optarg; + break; + case '?': + if (optopt == 'k' || optopt == 'e') { + fprintf(stderr, "Option -%c requires an argument.\n", optopt); + } else { + fprintf(stderr, "Unknown option `-%c'.\n", optopt); + } + return 1; + default: + return -1; + } + } + + z_owned_config_t config; + z_config_default(&config); + if (locator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); + } + + printf("Opening session...\n"); + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { + printf("Unable to open session!\n"); + return -1; + } + + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + return -1; + } + + printf("Declaring Subscriber on '%s'...\n", keyexpr); + z_owned_closure_sample_t closure; + z_owned_fifo_handler_sample_t handler; + z_fifo_channel_sample_new(&closure, &handler, 3); + + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { + printf("Unable to declare subscriber.\n"); + return -1; + } + + z_owned_sample_t sample; + for (z_result_t res = z_recv(z_loan(handler), &sample); res == Z_OK; res = z_recv(z_loan(handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_loan(sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_loan(sample)), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + z_drop(z_move(sample)); + } + + z_undeclare_subscriber(z_move(sub)); + z_drop(z_move(handler)); + + z_close(z_move(s)); + + return 0; +} +#else +int main(void) { + printf("ERROR: Zenoh pico was compiled without Z_FEATURE_SUBSCRIPTION but this example requires it.\n"); + return -2; +} +#endif diff --git a/examples/unix/c11/z_sub_st.c b/examples/unix/c11/z_sub_st.c index 8e825a06e..1f138911c 100644 --- a/examples/unix/c11/z_sub_st.c +++ b/examples/unix/c11/z_sub_st.c @@ -23,12 +23,15 @@ static int msg_nb = 0; -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); msg_nb++; } @@ -69,26 +72,30 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } - z_owned_closure_sample_t callback = z_closure(data_handler); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } diff --git a/examples/unix/c11/z_sub_thr.c b/examples/unix/c11/z_sub_thr.c index 788b25b03..8c9941451 100644 --- a/examples/unix/c11/z_sub_thr.c +++ b/examples/unix/c11/z_sub_thr.c @@ -39,7 +39,7 @@ z_stats_t *z_stats_make(void) { return stats; } -void on_sample(const z_sample_t *sample, void *context) { +void on_sample(const z_loaned_sample_t *sample, void *context) { (void)sample; z_stats_t *stats = (z_stats_t *)context; stats->count++; @@ -69,32 +69,36 @@ void drop_stats(void *context) { int main(int argc, char **argv) { char *keyexpr = "test/thr"; - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); // Set config if (argc > 1) { - if (zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[1])) < 0) { + if (zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]) < 0) { printf("Failed to insert locator in config: %s\n", argv[1]); exit(-1); } } // Open session - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); exit(-1); } // Declare Subscriber/resource z_stats_t *context = z_stats_make(); - z_owned_closure_sample_t callback = z_closure(on_sample, drop_stats, (void *)context); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t callback; + z_closure(&callback, on_sample, drop_stats, (void *)context); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create subscriber.\n"); exit(-1); } @@ -106,8 +110,6 @@ int main(int argc, char **argv) { // Clean up z_undeclare_subscriber(z_move(sub)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); exit(0); } diff --git a/examples/unix/c99/z_get.c b/examples/unix/c99/z_get.c index 7bec8e497..9b039855d 100644 --- a/examples/unix/c99/z_get.c +++ b/examples/unix/c99/z_get.c @@ -19,23 +19,29 @@ #include #if Z_FEATURE_QUERY == 1 && Z_FEATURE_MULTI_THREAD == 1 -z_condvar_t cond; -z_mutex_t mutex; +z_owned_condvar_t cond; +z_owned_mutex_t mutex; void reply_dropper(void *ctx) { (void)(ctx); printf(">> Received query final notification\n"); - z_condvar_signal(&cond); - z_condvar_free(&cond); + z_condvar_signal(z_condvar_loan_mut(&cond)); + z_condvar_drop(z_condvar_move(&cond)); } -void reply_handler(z_owned_reply_t *reply, void *ctx) { +void reply_handler(const z_loaned_reply_t *reply, void *ctx) { (void)(ctx); if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample.payload.len, sample.payload.start); - z_str_drop(z_str_move(&keystr)); + const z_loaned_sample_t *sample = z_reply_ok(reply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(">> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&replystr)), + z_string_data(z_string_loan(&replystr))); + z_string_drop(z_string_move(&replystr)); } else { printf(">> Received an error\n"); } @@ -81,52 +87,54 @@ int main(int argc, char **argv) { z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; } - z_keyexpr_t ke = z_keyexpr(keyexpr); - if (!z_keyexpr_is_initialized(&ke)) { + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { printf("%s is not a valid key expression", keyexpr); return -1; } - z_mutex_lock(&mutex); + z_mutex_lock(z_mutex_loan_mut(&mutex)); printf("Sending Query '%s'...\n", keyexpr); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (value != NULL) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)value, strlen(value)); + z_bytes_from_static_str(&payload, value); + opts.payload = z_bytes_move(&payload); } - z_owned_closure_reply_t callback = z_closure_reply(reply_handler, reply_dropper, NULL); - if (z_get(z_session_loan(&s), ke, "", z_closure_reply_move(&callback), &opts) < 0) { + z_owned_closure_reply_t callback; + z_closure_reply(&callback, reply_handler, reply_dropper, NULL); + if (z_get(z_session_loan(&s), z_view_keyexpr_loan(&ke), "", z_closure_reply_move(&callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; } - z_condvar_wait(&cond, &mutex); - z_mutex_unlock(&mutex); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); + z_condvar_wait(z_condvar_loan_mut(&cond), z_mutex_loan_mut(&mutex)); + z_mutex_unlock(z_mutex_loan_mut(&mutex)); z_close(z_session_move(&s)); diff --git a/examples/unix/c99/z_info.c b/examples/unix/c99/z_info.c index c978af3b4..b19a2dfae 100644 --- a/examples/unix/c99/z_info.c +++ b/examples/unix/c99/z_info.c @@ -56,24 +56,25 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; @@ -84,18 +85,16 @@ int main(int argc, char **argv) { print_zid(&self_id, NULL); printf("Routers IDs:\n"); - z_owned_closure_zid_t callback = z_closure_zid(print_zid, NULL, NULL); + z_owned_closure_zid_t callback; + z_closure_zid(&callback, print_zid, NULL, NULL); z_info_routers_zid(z_session_loan(&s), z_closure_zid_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_zid(print_zid, NULL, NULL); + z_owned_closure_zid_t callback2; + z_closure_zid(&callback2, print_zid, NULL, NULL); z_info_peers_zid(z_session_loan(&s), z_closure_zid_move(&callback2)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); - z_close(z_session_move(&s)); } diff --git a/examples/unix/c99/z_ping.c b/examples/unix/c99/z_ping.c index 673943898..f001c3a60 100644 --- a/examples/unix/c99/z_ping.c +++ b/examples/unix/c99/z_ping.c @@ -22,23 +22,23 @@ #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/system/platform.h" -#if Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_PUBLICATION == 1 +#if Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_PUBLICATION == 1 && Z_FEATURE_MULTI_THREAD == 1 #define DEFAULT_PKT_SIZE 8 #define DEFAULT_PING_NB 100 #define DEFAULT_WARMUP_MS 1000 -static z_condvar_t cond; -static z_mutex_t mutex; +static z_owned_condvar_t cond; +static z_owned_mutex_t mutex; -void callback(const z_sample_t* sample, void* context) { +void callback(const z_loaned_sample_t* sample, void* context) { (void)sample; (void)context; - z_condvar_signal(&cond); + z_condvar_signal(z_condvar_loan_mut(&cond)); } void drop(void* context) { (void)context; - z_condvar_free(&cond); + z_condvar_drop(z_condvar_move(&cond)); } struct args_t { @@ -64,32 +64,36 @@ int main(int argc, char** argv) { } z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = z_config_default(); - z_owned_session_t session = z_open(z_config_move(&config)); - if (!z_session_check(&session)) { + z_owned_config_t config; + z_config_default(&config); + z_owned_session_t session; + if (z_open(&session, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } - if (zp_start_read_task(z_session_loan(&session), NULL) < 0 || - zp_start_lease_task(z_session_loan(&session), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&session), NULL) < 0 || + zp_start_lease_task(z_session_loan_mut(&session), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&session)); return -1; } - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_owned_publisher_t pub = z_declare_publisher(z_session_loan(&session), ping, NULL); - if (!z_publisher_check(&pub)) { + z_view_keyexpr_t ping; + z_view_keyexpr_from_str_unchecked(&ping, "test/ping"); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_session_loan(&session), z_view_keyexpr_loan(&ping), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); - z_owned_closure_sample_t respond = z_closure_sample(callback, drop, NULL); - z_owned_subscriber_t sub = - z_declare_subscriber(z_session_loan(&session), pong, z_closure_sample_move(&respond), NULL); - if (!z_subscriber_check(&sub)) { + z_view_keyexpr_t pong; + z_view_keyexpr_from_str_unchecked(&pong, "test/pong"); + z_owned_closure_sample_t respond; + z_closure_sample(&respond, callback, drop, NULL); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_session_loan(&session), z_view_keyexpr_loan(&pong), + z_closure_sample_move(&respond), NULL) < 0) { printf("Unable to declare subscriber for key expression.\n"); return -1; } @@ -98,36 +102,42 @@ int main(int argc, char** argv) { for (unsigned int i = 0; i < args.size; i++) { data[i] = (uint8_t)(i % 10); } - z_mutex_lock(&mutex); + z_mutex_lock(z_mutex_loan_mut(&mutex)); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); z_clock_t warmup_start = z_clock_now(); unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - z_publisher_put(z_publisher_loan(&pub), data, args.size, NULL); - z_condvar_wait(&cond, &mutex); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); + + z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL); + z_condvar_wait(z_condvar_loan_mut(&cond), z_mutex_loan_mut(&mutex)); elapsed_us = z_clock_elapsed_us(&warmup_start); } } unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (unsigned int i = 0; i < args.number_of_pings; i++) { z_clock_t measure_start = z_clock_now(); - z_publisher_put(z_publisher_loan(&pub), data, args.size, NULL); - z_condvar_wait(&cond, &mutex); + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); + + z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL); + z_condvar_wait(z_condvar_loan_mut(&cond), z_mutex_loan_mut(&mutex)); results[i] = z_clock_elapsed_us(&measure_start); } for (unsigned int i = 0; i < args.number_of_pings; i++) { printf("%d bytes: seq=%d rtt=%luµs, lat=%luµs\n", args.size, i, results[i], results[i] / 2); } - z_mutex_unlock(&mutex); + z_mutex_unlock(z_mutex_loan_mut(&mutex)); z_free(results); z_free(data); z_undeclare_subscriber(z_subscriber_move(&sub)); z_undeclare_publisher(z_publisher_move(&pub)); - zp_stop_read_task(z_session_loan(&session)); - zp_stop_lease_task(z_session_loan(&session)); - z_close(z_session_move(&session)); } @@ -176,8 +186,8 @@ struct args_t parse_args(int argc, char** argv) { #else int main(void) { printf( - "ERROR: Zenoh pico was compiled without Z_FEATURE_SUBSCRIPTION or Z_FEATURE_PUBLICATION but this example " - "requires them.\n"); + "ERROR: Zenoh pico was compiled without Z_FEATURE_SUBSCRIPTION or Z_FEATURE_PUBLICATION or " + "Z_FEATURE_MULTI_THREAD but this example requires them.\n"); return -2; } #endif diff --git a/examples/unix/c99/z_pong.c b/examples/unix/c99/z_pong.c index 73f93d9a1..d5c51e616 100644 --- a/examples/unix/c99/z_pong.c +++ b/examples/unix/c99/z_pong.c @@ -17,13 +17,16 @@ #include "zenoh-pico/api/primitives.h" #if Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_PUBLICATION == 1 -void callback(const z_sample_t* sample, void* context) { - z_publisher_t pub = z_publisher_loan((z_owned_publisher_t*)context); - z_publisher_put(pub, sample->payload.start, sample->payload.len, NULL); +void callback(const z_loaned_sample_t* sample, void* context) { + const z_loaned_publisher_t* pub = z_publisher_loan((z_owned_publisher_t*)context); + z_owned_bytes_t payload; + z_bytes_clone(&payload, z_sample_payload(sample)); + z_publisher_put(pub, z_bytes_move(&payload), NULL); } + void drop(void* context) { z_owned_publisher_t* pub = (z_owned_publisher_t*)context; - z_undeclare_publisher(pub); + z_undeclare_publisher(z_publisher_move(pub)); // A note on lifetimes: // here, `sub` takes ownership of `pub` and will drop it before returning from its own `drop`, // which makes passing a pointer to the stack safe as long as `sub` is dropped in a scope where `pub` is still @@ -33,32 +36,36 @@ void drop(void* context) { int main(int argc, char** argv) { (void)argc; (void)argv; - z_owned_config_t config = z_config_default(); - z_owned_session_t session = z_open(z_config_move(&config)); - if (!z_session_check(&session)) { + z_owned_config_t config; + z_config_default(&config); + z_owned_session_t session; + if (z_open(&session, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } - if (zp_start_read_task(z_session_loan(&session), NULL) < 0 || - zp_start_lease_task(z_session_loan(&session), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&session), NULL) < 0 || + zp_start_lease_task(z_session_loan_mut(&session), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&session)); return -1; } - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); - z_owned_publisher_t pub = z_declare_publisher(z_session_loan(&session), pong, NULL); - if (!z_publisher_check(&pub)) { + z_view_keyexpr_t pong; + z_view_keyexpr_from_str_unchecked(&pong, "test/pong"); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_session_loan(&session), z_view_keyexpr_loan(&pong), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_owned_closure_sample_t respond = z_closure_sample(callback, drop, (void*)z_publisher_move(&pub)); - z_owned_subscriber_t sub = - z_declare_subscriber(z_session_loan(&session), ping, z_closure_sample_move(&respond), NULL); - if (!z_subscriber_check(&sub)) { + z_view_keyexpr_t ping; + z_view_keyexpr_from_str_unchecked(&ping, "test/ping"); + z_owned_closure_sample_t respond; + z_closure_sample(&respond, callback, drop, (void*)(&pub)); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_session_loan(&session), z_view_keyexpr_loan(&ping), + z_closure_sample_move(&respond), NULL) < 0) { printf("Unable to declare subscriber for key expression.\n"); return -1; } @@ -68,9 +75,6 @@ int main(int argc, char** argv) { z_undeclare_subscriber(z_subscriber_move(&sub)); - zp_stop_read_task(z_session_loan(&session)); - zp_stop_lease_task(z_session_loan(&session)); - z_close(z_session_move(&session)); } #else diff --git a/examples/unix/c99/z_pub.c b/examples/unix/c99/z_pub.c index a81065c9e..e2e8fd2c9 100644 --- a/examples/unix/c99/z_pub.c +++ b/examples/unix/c99/z_pub.c @@ -62,32 +62,35 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; } printf("Declaring publisher for '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_session_loan(&s), z_keyexpr(keyexpr), NULL); - if (!z_publisher_check(&pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_session_loan(&s), z_view_keyexpr_loan(&ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } @@ -95,18 +98,18 @@ int main(int argc, char **argv) { printf("Press CTRL-C to quit...\n"); char *buf = (char *)malloc(256); for (int idx = 0; idx < n; ++idx) { - sleep(1); + z_sleep_s(1); snprintf(buf, 256, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put_options_t options = z_publisher_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_publisher_loan(&pub), (const uint8_t *)buf, strlen(buf), &options); + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL); } // Clean up z_undeclare_publisher(z_publisher_move(&pub)); - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); z_close(z_session_move(&s)); return 0; } diff --git a/examples/unix/c99/z_pub_st.c b/examples/unix/c99/z_pub_st.c index f39b3753b..a5c514e1a 100644 --- a/examples/unix/c99/z_pub_st.c +++ b/examples/unix/c99/z_pub_st.c @@ -62,25 +62,28 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } printf("Declaring publisher for '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_session_loan(&s), z_keyexpr(keyexpr), NULL); - if (!z_publisher_check(&pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_session_loan(&s), z_view_keyexpr_loan(&ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } @@ -92,7 +95,12 @@ int main(int argc, char **argv) { if (z_clock_elapsed_ms(&now) > 1000) { snprintf(buf, 256, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put(z_publisher_loan(&pub), (const uint8_t *)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_publisher_loan(&pub), z_bytes_move(&payload), NULL); ++idx; now = z_clock_now(); diff --git a/examples/unix/c99/z_pull.c b/examples/unix/c99/z_pull.c index 323ad0155..5250a8ce4 100644 --- a/examples/unix/c99/z_pull.c +++ b/examples/unix/c99/z_pull.c @@ -18,21 +18,17 @@ #include #include -#if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *ctx) { - (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample->payload.len, - sample->payload.start); - z_str_drop(z_str_move(&keystr)); -} +#include "zenoh-pico/api/primitives.h" +#if Z_FEATURE_SUBSCRIPTION == 1 int main(int argc, char **argv) { const char *keyexpr = "demo/example/**"; char *locator = NULL; + size_t interval = 5000; + size_t size = 3; int opt; - while ((opt = getopt(argc, argv, "k:e:")) != -1) { + while ((opt = getopt(argc, argv, "k:e:i:s:")) != -1) { switch (opt) { case 'k': keyexpr = optarg; @@ -40,8 +36,14 @@ int main(int argc, char **argv) { case 'e': locator = optarg; break; + case 'i': + interval = (size_t)atoi(optarg); + break; + case 's': + size = (size_t)atoi(optarg); + break; case '?': - if (optopt == 'k' || optopt == 'e') { + if (optopt == 'k' || optopt == 'e' || optopt == 'i' || optopt == 's') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); } else { fprintf(stderr, "Unknown option `-%c'.\n", optopt); @@ -52,47 +54,65 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (locator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; } - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_pull_subscriber_t sub = - z_declare_pull_subscriber(z_session_loan(&s), z_keyexpr(keyexpr), z_closure_sample_move(&callback), NULL); - if (!z_pull_subscriber_check(&sub)) { + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, size); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&closure), + NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } - printf("Press CTRL-C to quit...\n"); - int idx = 0; - while (1) { - sleep(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_pull_subscriber_loan(&sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", interval, size); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_ring_handler_sample_try_recv(z_ring_handler_sample_loan(&handler), &sample); res == Z_OK; + res = z_ring_handler_sample_try_recv(z_ring_handler_sample_loan(&handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_sample_loan(&sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_sample_loan(&sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&value)), + z_string_data(z_string_loan(&value))); + z_string_drop(z_string_move(&value)); + z_sample_drop(z_sample_move(&sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", interval); + z_sleep_ms(interval); + } else { + break; + } } - z_undeclare_pull_subscriber(z_pull_subscriber_move(&sub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); + z_undeclare_subscriber(z_subscriber_move(&sub)); + z_ring_handler_sample_drop(z_ring_handler_sample_move(&handler)); z_close(z_session_move(&s)); diff --git a/examples/unix/c99/z_put.c b/examples/unix/c99/z_put.c index 453444869..ce9daad7e 100644 --- a/examples/unix/c99/z_put.c +++ b/examples/unix/c99/z_put.c @@ -57,50 +57,51 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; } printf("Declaring key expression '%s'...\n", keyexpr); - z_owned_keyexpr_t ke = z_declare_keyexpr(z_session_loan(&s), z_keyexpr(keyexpr)); - if (!z_keyexpr_check(&ke)) { + z_view_keyexpr_t vke; + z_view_keyexpr_from_str(&vke, keyexpr); + z_owned_keyexpr_t ke; + if (z_declare_keyexpr(&ke, z_session_loan(&s), z_view_keyexpr_loan(&vke)) < 0) { printf("Unable to declare key expression!\n"); - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); z_close(z_session_move(&s)); return -1; } + // Create payload + z_owned_bytes_t payload; + z_bytes_from_static_str(&payload, value); + printf("Putting Data ('%s': '%s')...\n", keyexpr, value); - z_put_options_t options = z_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - if (z_put(z_session_loan(&s), z_keyexpr_loan(&ke), (const uint8_t *)value, strlen(value), &options) < 0) { + if (z_put(z_session_loan(&s), z_keyexpr_loan(&ke), z_bytes_move(&payload), NULL) < 0) { printf("Oh no! Put has failed...\n"); } // Clean up - z_undeclare_keyexpr(z_session_loan(&s), z_keyexpr_move(&ke)); - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); + z_undeclare_keyexpr(z_keyexpr_move(&ke), z_session_loan(&s)); z_close(z_session_move(&s)); return 0; } diff --git a/examples/unix/c99/z_queryable.c b/examples/unix/c99/z_queryable.c index c6ccf555c..b22ba98e5 100644 --- a/examples/unix/c99/z_queryable.c +++ b/examples/unix/c99/z_queryable.c @@ -22,15 +22,29 @@ const char *keyexpr = "demo/example/zenoh-pico-queryable"; const char *value = "Queryable from Pico!"; -void query_handler(const z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - printf(" >> [Queryable handler] Received Query '%s%.*s'\n", z_str_loan(&keystr), (int)pred.len, pred.start); - z_query_reply_options_t options = z_query_reply_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr(keyexpr), (const unsigned char *)value, strlen(value), &options); - z_str_drop(z_str_move(&keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_view_string_loan(¶ms)), + z_string_data(z_view_string_loan(¶ms))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_string_loan(&payload_string)) > 1) { + printf(" with value '%.*s'\n", (int)z_string_len(z_string_loan(&payload_string)), + z_string_data(z_string_loan(&payload_string))); + } + z_string_drop(z_string_move(&payload_string)); + + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, value); + + z_query_reply(query, z_query_keyexpr(query), z_bytes_move(&reply_payload), NULL); } int main(int argc, char **argv) { @@ -68,39 +82,43 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; } - z_keyexpr_t ke = z_keyexpr(keyexpr); - if (!z_keyexpr_is_initialized(&ke)) { + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { printf("%s is not a valid key expression", keyexpr); return -1; } + z_owned_closure_query_t callback; + z_closure_query(&callback, query_handler, NULL, NULL); + printf("Creating Queryable on '%s'...\n", keyexpr); - z_owned_closure_query_t callback = z_closure_query(query_handler, NULL, NULL); - z_owned_queryable_t qable = z_declare_queryable(z_session_loan(&s), ke, z_closure_query_move(&callback), NULL); - if (!z_queryable_check(&qable)) { + z_owned_queryable_t qable; + if (z_declare_queryable(&qable, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_query_move(&callback), + NULL) < 0) { printf("Unable to create queryable.\n"); return -1; } @@ -112,10 +130,6 @@ int main(int argc, char **argv) { z_undeclare_queryable(z_queryable_move(&qable)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); - z_close(z_session_move(&s)); return 0; diff --git a/examples/unix/c99/z_scout.c b/examples/unix/c99/z_scout.c index e9453bf96..22ee39e31 100644 --- a/examples/unix/c99/z_scout.c +++ b/examples/unix/c99/z_scout.c @@ -30,44 +30,40 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_view_string_loan(&s)), z_string_data(z_view_string_loan(&s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_hello_loan(hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; - z_hello_drop(hello); } void drop(void *context) { @@ -86,10 +82,12 @@ int main(int argc, char **argv) { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure_hello(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure_hello(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_scouting_config_move(&config), z_closure_hello_move(&closure)); + z_scout(z_config_move(&config), z_closure_hello_move(&closure), NULL); sleep(1); return 0; } diff --git a/examples/unix/c99/z_sub.c b/examples/unix/c99/z_sub.c index 185c742ed..6bfbddf86 100644 --- a/examples/unix/c99/z_sub.c +++ b/examples/unix/c99/z_sub.c @@ -20,12 +20,16 @@ #include #if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { (void)(arg); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample->payload.len, - sample->payload.start); - z_str_drop(z_str_move(&keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&value)), + z_string_data(z_string_loan(&value))); + z_string_drop(z_string_move(&value)); } int main(int argc, char **argv) { @@ -61,34 +65,39 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_session_loan(&s), NULL) < 0 || zp_start_lease_task(z_session_loan(&s), NULL) < 0) { + if (zp_start_read_task(z_session_loan_mut(&s), NULL) < 0 || zp_start_lease_task(z_session_loan_mut(&s), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&s)); return -1; } - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); + z_owned_closure_sample_t callback; + z_closure_sample(&callback, data_handler, NULL, NULL); + printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_subscriber_t sub = - z_declare_subscriber(z_session_loan(&s), z_keyexpr(keyexpr), z_closure_sample_move(&callback), NULL); - if (!z_subscriber_check(&sub)) { + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&callback), + NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } @@ -100,10 +109,6 @@ int main(int argc, char **argv) { z_undeclare_subscriber(z_subscriber_move(&sub)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_session_loan(&s)); - zp_stop_lease_task(z_session_loan(&s)); - z_close(z_session_move(&s)); return 0; diff --git a/examples/unix/c99/z_sub_st.c b/examples/unix/c99/z_sub_st.c index 765bf3d5a..4335308a7 100644 --- a/examples/unix/c99/z_sub_st.c +++ b/examples/unix/c99/z_sub_st.c @@ -23,12 +23,16 @@ static int msg_nb = 0; -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { (void)(arg); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_str_loan(&keystr), (int)sample->payload.len, - sample->payload.start); - z_str_drop(z_str_move(&keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_view_string_loan(&keystr)), + z_string_data(z_view_string_loan(&keystr)), (int)z_string_len(z_string_loan(&value)), + z_string_data(z_string_loan(&value))); + z_string_drop(z_string_move(&value)); msg_nb++; } @@ -69,27 +73,32 @@ int main(int argc, char **argv) { } } - z_owned_config_t config = z_config_default(); - zp_config_insert(z_config_loan(&config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_MODE_KEY, mode); if (clocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_CONNECT_KEY, clocator); } if (llocator != NULL) { - zp_config_insert(z_config_loan(&config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_config_loan_mut(&config), Z_CONFIG_LISTEN_KEY, llocator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_config_move(&config)); - if (!z_session_check(&s)) { + z_owned_session_t s; + if (z_open(&s, z_config_move(&config)) < 0) { printf("Unable to open session!\n"); return -1; } - z_owned_closure_sample_t callback = z_closure_sample(data_handler, NULL, NULL); + z_owned_closure_sample_t callback; + z_closure_sample(&callback, data_handler, NULL, NULL); + printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_subscriber_t sub = - z_declare_subscriber(z_session_loan(&s), z_keyexpr(keyexpr), z_closure_sample_move(&callback), NULL); - if (!z_subscriber_check(&sub)) { + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_session_loan(&s), z_view_keyexpr_loan(&ke), z_closure_sample_move(&callback), + NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } diff --git a/examples/windows/z_get.c b/examples/windows/z_get.c index 597287afd..c6032e470 100644 --- a/examples/windows/z_get.c +++ b/examples/windows/z_get.c @@ -18,23 +18,28 @@ #include #if Z_FEATURE_QUERY == 1 && Z_FEATURE_MULTI_THREAD == 1 -z_condvar_t cond; -z_mutex_t mutex; +z_owned_condvar_t cond; +z_owned_mutex_t mutex; void reply_dropper(void *ctx) { (void)(ctx); printf(">> Received query final notification\n"); - z_condvar_signal(&cond); - z_condvar_free(&cond); + z_condvar_signal(z_loan_mut(cond)); + z_drop(z_move(cond)); } -void reply_handler(z_owned_reply_t *reply, void *ctx) { +void reply_handler(const z_loaned_reply_t *reply, void *ctx) { (void)(ctx); if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); - z_drop(z_move(keystr)); + const z_loaned_sample_t *sample = z_reply_ok(reply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(">> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), + (int)z_string_len(z_loan(replystr)), z_string_data(z_loan(replystr))); + z_drop(z_move(replystr)); } else { printf(">> Received an error\n"); } @@ -50,48 +55,50 @@ int main(int argc, char **argv) { z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_keyexpr_t ke = z_keyexpr(keyexpr); - if (!z_check(ke)) { + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { printf("%s is not a valid key expression", keyexpr); return -1; } - z_mutex_lock(&mutex); + z_mutex_lock(z_loan_mut(mutex)); printf("Sending Query '%s'...\n", keyexpr); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); + // Value encoding + z_owned_bytes_t payload; if (value != NULL) { - opts.value.payload = _z_bytes_wrap((const uint8_t *)value, strlen(value)); + z_bytes_from_static_str(&payload, value); + opts.payload = z_move(payload); } - z_owned_closure_reply_t callback = z_closure(reply_handler, reply_dropper); - if (z_get(z_loan(s), ke, "", z_move(callback), &opts) < 0) { + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, reply_dropper); + if (z_get(z_loan(s), z_loan(ke), "", z_move(callback), &opts) < 0) { printf("Unable to send query.\n"); return -1; } - z_condvar_wait(&cond, &mutex); - z_mutex_unlock(&mutex); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); + z_mutex_unlock(z_loan_mut(mutex)); z_close(z_move(s)); diff --git a/examples/windows/z_info.c b/examples/windows/z_info.c index 7967e1aa2..c560d0248 100644 --- a/examples/windows/z_info.c +++ b/examples/windows/z_info.c @@ -32,21 +32,22 @@ int main(int argc, char **argv) { const char *mode = "client"; char *locator = NULL; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; @@ -57,18 +58,16 @@ int main(int argc, char **argv) { print_zid(&self_id, NULL); printf("Routers IDs:\n"); - z_owned_closure_zid_t callback = z_closure(print_zid); + z_owned_closure_zid_t callback; + z_closure(&callback, print_zid); 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(print_zid); + z_owned_closure_zid_t callback2; + z_closure(&callback2, print_zid); z_info_peers_zid(z_loan(s), z_move(callback2)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); } diff --git a/examples/windows/z_ping.c b/examples/windows/z_ping.c index 262e21659..acc807324 100644 --- a/examples/windows/z_ping.c +++ b/examples/windows/z_ping.c @@ -27,17 +27,17 @@ #define DEFAULT_PING_NB 100 #define DEFAULT_WARMUP_MS 1000 -static z_condvar_t cond; -static z_mutex_t mutex; +static z_owned_condvar_t cond; +static z_owned_mutex_t mutex; -void callback(const z_sample_t* sample, void* context) { +void callback(const z_loaned_sample_t* sample, void* context) { (void)sample; (void)context; - z_condvar_signal(&cond); + z_condvar_signal(z_loan_mut(cond)); } void drop(void* context) { (void)context; - z_condvar_free(&cond); + z_drop(z_move(cond)); } struct args_t { @@ -63,30 +63,34 @@ int main(int argc, char** argv) { } z_mutex_init(&mutex); z_condvar_init(&cond); - z_owned_config_t config = z_config_default(); - z_owned_session_t session = z_open(z_move(config)); - if (!z_check(session)) { + z_owned_config_t config; + z_config_default(&config); + z_owned_session_t session; + if (z_open(&session, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } - if (zp_start_read_task(z_loan(session), NULL) < 0 || zp_start_lease_task(z_loan(session), NULL) < 0) { + if (zp_start_read_task(z_loan_mut(session), NULL) < 0 || zp_start_lease_task(z_loan_mut(session), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&session)); return -1; } - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_owned_publisher_t pub = z_declare_publisher(z_loan(session), ping, NULL); - if (!z_check(pub)) { + z_view_keyexpr_t ping; + z_view_keyexpr_from_str_unchecked(&ping, "test/ping"); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_loan(session), z_loan(ping), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); - z_owned_closure_sample_t respond = z_closure(callback, drop, NULL); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), pong, z_move(respond), NULL); - if (!z_check(sub)) { + z_view_keyexpr_t pong; + z_view_keyexpr_from_str_unchecked(&pong, "test/pong"); + z_owned_closure_sample_t respond; + z_closure(&respond, callback, drop, NULL); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(session), z_loan(pong), z_move(respond), NULL) < 0) { printf("Unable to declare subscriber for key expression.\n"); return -1; } @@ -95,36 +99,42 @@ int main(int argc, char** argv) { for (unsigned int i = 0; i < args.size; i++) { data[i] = i % 10; } - z_mutex_lock(&mutex); + z_mutex_lock(z_loan_mut(mutex)); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); z_clock_t warmup_start = z_clock_now(); unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - z_publisher_put(z_loan(pub), data, args.size, NULL); - z_condvar_wait(&cond, &mutex); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); elapsed_us = z_clock_elapsed_us(&warmup_start); } } unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (unsigned int i = 0; i < args.number_of_pings; i++) { z_clock_t measure_start = z_clock_now(); - z_publisher_put(z_loan(pub), data, args.size, NULL); - z_condvar_wait(&cond, &mutex); + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, args.size, NULL, NULL); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); + z_condvar_wait(z_loan_mut(cond), z_loan_mut(mutex)); results[i] = z_clock_elapsed_us(&measure_start); } for (unsigned int i = 0; i < args.number_of_pings; i++) { printf("%d bytes: seq=%d rtt=%luus, lat=%luus\n", args.size, i, results[i], results[i] / 2); } - z_mutex_unlock(&mutex); + z_mutex_unlock(z_loan_mut(mutex)); z_free(results); z_free(data); z_drop(z_move(pub)); z_drop(z_move(sub)); - zp_stop_read_task(z_loan(session)); - zp_stop_lease_task(z_loan(session)); - z_close(z_move(session)); } diff --git a/examples/windows/z_pong.c b/examples/windows/z_pong.c index dc958e1bb..7bcc970ff 100644 --- a/examples/windows/z_pong.c +++ b/examples/windows/z_pong.c @@ -16,13 +16,15 @@ #include "zenoh-pico.h" #if Z_FEATURE_SUBSCRIPTION == 1 && Z_FEATURE_PUBLICATION == 1 -void callback(const z_sample_t* sample, void* context) { - z_publisher_t pub = z_loan(*(z_owned_publisher_t*)context); - z_publisher_put(pub, sample->payload.start, sample->payload.len, NULL); +void callback(const z_loaned_sample_t* sample, void* context) { + const z_loaned_publisher_t* pub = z_loan(*(z_owned_publisher_t*)context); + z_owned_bytes_t payload; + z_bytes_clone(&payload, z_sample_payload(sample)); + z_publisher_put(pub, z_move(payload), NULL); } void drop(void* context) { z_owned_publisher_t* pub = (z_owned_publisher_t*)context; - z_drop(pub); + z_drop(z_move(*pub)); // A note on lifetimes: // here, `sub` takes ownership of `pub` and will drop it before returning from its own `drop`, // which makes passing a pointer to the stack safe as long as `sub` is dropped in a scope where `pub` is still @@ -32,30 +34,34 @@ void drop(void* context) { int main(int argc, char** argv) { (void)argc; (void)argv; - z_owned_config_t config = z_config_default(); - z_owned_session_t session = z_open(z_move(config)); - if (!z_check(session)) { + z_owned_config_t config; + z_config_default(&config); + z_owned_session_t session; + if (z_open(&session, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } - if (zp_start_read_task(z_loan(session), NULL) < 0 || zp_start_lease_task(z_loan(session), NULL) < 0) { + if (zp_start_read_task(z_loan_mut(session), NULL) < 0 || zp_start_lease_task(z_loan_mut(session), NULL) < 0) { printf("Unable to start read and lease tasks\n"); z_close(z_session_move(&session)); return -1; } - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); - z_owned_publisher_t pub = z_declare_publisher(z_loan(session), pong, NULL); - if (!z_check(pub)) { + z_view_keyexpr_t pong; + z_view_keyexpr_from_str_unchecked(&pong, "test/pong"); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_loan(session), z_loan(pong), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_owned_closure_sample_t respond = z_closure(callback, drop, (void*)z_move(pub)); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), ping, z_move(respond), NULL); - if (!z_check(sub)) { + z_view_keyexpr_t ping; + z_view_keyexpr_from_str_unchecked(&ping, "test/ping"); + z_owned_closure_sample_t respond; + z_closure(&respond, callback, drop, (void*)(&pub)); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(session), z_loan(ping), z_move(respond), NULL) < 0) { printf("Unable to declare subscriber for key expression.\n"); return -1; } @@ -65,9 +71,6 @@ int main(int argc, char** argv) { z_drop(z_move(sub)); - zp_stop_read_task(z_loan(session)); - zp_stop_lease_task(z_loan(session)); - z_close(z_move(session)); } #else diff --git a/examples/windows/z_pub.c b/examples/windows/z_pub.c index ce62da93d..4c1413d7f 100644 --- a/examples/windows/z_pub.c +++ b/examples/windows/z_pub.c @@ -27,29 +27,32 @@ int main(int argc, char **argv) { const char *mode = "client"; char *locator = NULL; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); + z_close(z_move(s)); return -1; } printf("Declaring publisher for '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } @@ -57,23 +60,22 @@ int main(int argc, char **argv) { printf("Press CTRL-C to quit...\n"); char *buf = (char *)malloc(256); for (int idx = 0; 1; ++idx) { - Sleep(1); + z_sleep_s(1); snprintf(buf, 256, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put_options_t options = z_publisher_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_str(&payload, buf, NULL, NULL); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); } + // Clean-up z_undeclare_publisher(z_move(pub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - + zp_stop_read_task(z_loan_mut(s)); + zp_stop_lease_task(z_loan_mut(s)); z_close(z_move(s)); - free(buf); return 0; } diff --git a/examples/windows/z_pub_st.c b/examples/windows/z_pub_st.c index 6d6f59d87..b459a3874 100644 --- a/examples/windows/z_pub_st.c +++ b/examples/windows/z_pub_st.c @@ -29,22 +29,25 @@ int main(int argc, char **argv) { const char *mode = "client"; char *locator = NULL; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } printf("Declaring publisher for '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); return -1; } @@ -56,7 +59,12 @@ int main(int argc, char **argv) { if (z_clock_elapsed_ms(&now) > 1000) { snprintf(buf, 256, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); ++idx; now = z_clock_now(); diff --git a/examples/windows/z_pull.c b/examples/windows/z_pull.c index 0ec172471..4c4e9a22b 100644 --- a/examples/windows/z_pull.c +++ b/examples/windows/z_pull.c @@ -18,60 +18,70 @@ #include #if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *ctx) { - (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); -} - int main(int argc, char **argv) { (void)(argc); (void)(argv); const char *keyexpr = "demo/example/**"; char *locator = NULL; + size_t interval = 5000; + size_t size = 3; - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_owned_closure_sample_t callback = z_closure(data_handler); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, size); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } - printf("Press CTRL-C to quit...\n"); - int idx = 0; - while (1) { - Sleep(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_loan(sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", interval, size); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_try_recv(z_loan(handler), &sample); res == Z_OK; res = z_try_recv(z_loan(handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_loan(sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_loan(sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + z_drop(z_move(sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", interval); + z_sleep_ms(interval); + } else { + break; + } } - z_undeclare_pull_subscriber(z_move(sub)); - - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_subscriber(z_move(sub)); + z_drop(z_move(handler)); z_close(z_move(s)); diff --git a/examples/windows/z_put.c b/examples/windows/z_put.c index 32f7802a7..44f9bba1d 100644 --- a/examples/windows/z_put.c +++ b/examples/windows/z_put.c @@ -27,47 +27,48 @@ int main(int argc, char **argv) { const char *mode = "client"; char *locator = NULL; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } printf("Declaring key expression '%s'...\n", keyexpr); - z_owned_keyexpr_t ke = z_declare_keyexpr(z_loan(s), z_keyexpr(keyexpr)); - if (!z_check(ke)) { + z_view_keyexpr_t vke; + z_view_keyexpr_from_str(&vke, keyexpr); + z_owned_keyexpr_t ke; + if (z_declare_keyexpr(&ke, z_loan(s), z_loan(vke)) < 0) { printf("Unable to declare key expression!\n"); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); return -1; } + // Create payload + z_owned_bytes_t payload; + z_bytes_from_static_str(&payload, value); + printf("Putting Data ('%s': '%s')...\n", keyexpr, value); - z_put_options_t options = z_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - if (z_put(z_loan(s), z_loan(ke), (const uint8_t *)value, strlen(value), &options) < 0) { + if (z_put(z_loan(s), z_loan(ke), z_move(payload), NULL) < 0) { printf("Oh no! Put has failed...\n"); } // Clean up - z_undeclare_keyexpr(z_loan(s), z_move(ke)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_keyexpr(z_move(ke), z_loan(s)); z_close(z_move(s)); return 0; } diff --git a/examples/windows/z_queryable.c b/examples/windows/z_queryable.c index ea504d0e7..897254a35 100644 --- a/examples/windows/z_queryable.c +++ b/examples/windows/z_queryable.c @@ -21,19 +21,29 @@ const char *keyexpr = "demo/example/zenoh-pico-queryable"; const char *value = "Queryable from Pico!"; -void query_handler(const z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); - printf(" >> [Queryable handler] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); - if (payload_value.payload.len > 0) { - printf(" with value '%.*s'\n", (int)payload_value.payload.len, payload_value.payload.start); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); } - z_query_reply_options_t options = z_query_reply_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr(keyexpr), (const unsigned char *)value, strlen(value), &options); - z_drop(z_move(keystr)); + z_drop(z_move(payload_string)); + + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, value); + + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), NULL); } int main(int argc, char **argv) { @@ -41,35 +51,37 @@ int main(int argc, char **argv) { (void)(argv); char *locator = NULL; - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_keyexpr_t ke = z_keyexpr(keyexpr); - if (!z_check(ke)) { + z_view_keyexpr_t ke; + if (z_view_keyexpr_from_str(&ke, keyexpr) < 0) { printf("%s is not a valid key expression", keyexpr); return -1; } printf("Creating Queryable on '%s'...\n", keyexpr); - z_owned_closure_query_t callback = z_closure(query_handler); - z_owned_queryable_t qable = z_declare_queryable(z_loan(s), ke, z_move(callback), NULL); - if (!z_check(qable)) { + z_owned_closure_query_t callback; + z_closure(&callback, query_handler); + z_owned_queryable_t qable; + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create queryable.\n"); return -1; } @@ -81,10 +93,6 @@ int main(int argc, char **argv) { z_undeclare_queryable(z_move(qable)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); return 0; diff --git a/examples/windows/z_scout.c b/examples/windows/z_scout.c index 378a61327..cc1aa5eb4 100644 --- a/examples/windows/z_scout.c +++ b/examples/windows/z_scout.c @@ -30,41 +30,38 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_loan(s)), z_string_data(z_loan(s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_loan(*hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; } @@ -85,10 +82,12 @@ int main(int argc, char **argv) { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_move(config), z_move(closure)); + z_scout(z_move(config), z_move(closure), NULL); Sleep(1); return 0; } diff --git a/examples/windows/z_sub.c b/examples/windows/z_sub.c index bde475e8b..87b2ed556 100644 --- a/examples/windows/z_sub.c +++ b/examples/windows/z_sub.c @@ -19,12 +19,15 @@ #include #if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); } int main(int argc, char **argv) { @@ -34,30 +37,34 @@ int main(int argc, char **argv) { const char *mode = "client"; char *locator = NULL; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } - z_owned_closure_sample_t callback = z_closure(data_handler); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } @@ -69,10 +76,6 @@ int main(int argc, char **argv) { z_undeclare_subscriber(z_move(sub)); - // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); return 0; diff --git a/examples/windows/z_sub_st.c b/examples/windows/z_sub_st.c index fa91d9e41..3519f1fb6 100644 --- a/examples/windows/z_sub_st.c +++ b/examples/windows/z_sub_st.c @@ -22,13 +22,15 @@ int msg_nb = 0; #if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); - + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(">> [Subscriber] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); msg_nb++; } @@ -39,23 +41,27 @@ int main(int argc, char **argv) { const char *mode = "client"; char *locator = NULL; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); if (locator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(locator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, locator); } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } - z_owned_closure_sample_t callback = z_closure(data_handler); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); printf("Declaring Subscriber on '%s'...\n", keyexpr); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } diff --git a/examples/zephyr/z_get.c b/examples/zephyr/z_get.c index ffe90520a..585ba5cc0 100644 --- a/examples/zephyr/z_get.c +++ b/examples/zephyr/z_get.c @@ -30,15 +30,21 @@ #endif #define KEYEXPR "demo/example/**" +#define VALUE "" void reply_dropper(void *ctx) { printf(" >> Received query final notification\n"); } -void reply_handler(z_owned_reply_t *oreply, void *ctx) { +void reply_handler(const z_loaned_reply_t *oreply, void *ctx) { if (z_reply_is_ok(oreply)) { - z_sample_t sample = z_reply_ok(oreply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(" >> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); - z_drop(z_move(keystr)); + const z_loaned_sample_t *sample = z_reply_ok(oreply); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t replystr; + z_bytes_deserialize_into_string(z_sample_payload(sample), &replystr); + + printf(" >> Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), + (int)z_string_len(z_loan(replystr)), z_string_data(z_loan(replystr))); + z_drop(z_move(replystr)); } else { printf(" >> Received an error\n"); } @@ -48,41 +54,49 @@ int main(int argc, char **argv) { sleep(5); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); while (1) { sleep(5); printf("Sending Query '%s'...\n", KEYEXPR); - z_get_options_t opts = z_get_options_default(); + z_get_options_t opts; + z_get_options_default(&opts); opts.target = Z_QUERY_TARGET_ALL; - z_owned_closure_reply_t callback = z_closure(reply_handler, reply_dropper); - if (z_get(z_loan(s), z_keyexpr(KEYEXPR), "", z_move(callback), &opts) < 0) { + // Value encoding + z_owned_bytes_t payload; + if (strcmp(VALUE, "") != 0) { + z_bytes_from_static_str(&payload, VALUE); + opts.payload = z_move(payload); + } + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, reply_dropper); + 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); } } printf("Closing Zenoh Session..."); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); printf("OK!\n"); diff --git a/examples/zephyr/z_pub.c b/examples/zephyr/z_pub.c index 1f47be9a0..5ef9b5166 100644 --- a/examples/zephyr/z_pub.c +++ b/examples/zephyr/z_pub.c @@ -36,28 +36,31 @@ int main(int argc, char **argv) { sleep(5); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); printf("Declaring publisher for '%s'...", KEYEXPR); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(KEYEXPR), NULL); - if (!z_check(pub)) { + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + z_owned_publisher_t pub; + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); exit(-1); } @@ -68,16 +71,17 @@ int main(int argc, char **argv) { sleep(1); sprintf(buf, "[%4d] %s", idx, VALUE); printf("Putting Data ('%s': '%s')...\n", KEYEXPR, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), NULL); + + // Create payload + z_owned_bytes_t payload; + z_bytes_serialize_from_str(&payload, buf); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); } printf("Closing Zenoh Session..."); z_undeclare_publisher(z_move(pub)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); printf("OK!\n"); diff --git a/examples/zephyr/z_pull.c b/examples/zephyr/z_pull.c index c96baff84..08912026f 100644 --- a/examples/zephyr/z_pull.c +++ b/examples/zephyr/z_pull.c @@ -29,58 +29,72 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(" >> [Subscriber handler] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); -} +const size_t INTERVAL = 5000; +const size_t SIZE = 3; int main(int argc, char **argv) { sleep(5); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); - // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + // Start read and lease tasks for zenoh-pico + 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_close(z_session_move(&s)); + exit(-1); + } - printf("Declaring Subscriber on '%s'...", KEYEXPR); - z_owned_closure_sample_t callback = z_closure(data_handler); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + printf("Declaring Subscriber on '%s'...\n", KEYEXPR); + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, SIZE); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, KEYEXPR); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(closure), NULL) < 0) { printf("Unable to declare subscriber.\n"); exit(-1); } - printf("OK!\n"); - int idx = 0; - while (1) { - sleep(1); - printf("[%4d] Pulling...\n", idx++); - z_subscriber_pull(z_loan(sub)); + printf("Pulling data every %zu ms... Ring size: %zd\n", INTERVAL, SIZE); + z_owned_sample_t sample; + while (true) { + z_result_t res; + for (res = z_try_recv(z_loan(handler), &sample); res == Z_OK; res = z_try_recv(z_loan(handler), &sample)) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(z_loan(sample)), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(z_loan(sample)), &value); + printf(">> [Subscriber] Pulled ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); + z_drop(z_move(sample)); + } + if (res == Z_CHANNEL_NODATA) { + printf(">> [Subscriber] Nothing to pull... sleep for %zu ms\n", INTERVAL); + z_sleep_ms(INTERVAL); + } else { + break; + } } - printf("Closing Zenoh Session..."); - z_undeclare_pull_subscriber(z_move(sub)); - - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + z_undeclare_subscriber(z_move(sub)); + z_drop(z_move(handler)); z_close(z_move(s)); printf("OK!\n"); diff --git a/examples/zephyr/z_queryable.c b/examples/zephyr/z_queryable.c index febdaabe2..02deecc9f 100644 --- a/examples/zephyr/z_queryable.c +++ b/examples/zephyr/z_queryable.c @@ -31,43 +31,62 @@ #define KEYEXPR "demo/example/zenoh-pico-queryable" #define VALUE "[STSTM32]{nucleo-F767ZI} Queryable from Zenoh-Pico!" -void query_handler(const z_query_t *query, void *ctx) { +void query_handler(const z_loaned_query_t *query, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - printf(" >> [Queryable handler] Received Query '%s%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); - z_query_reply(query, z_keyexpr(KEYEXPR), (const unsigned char *)VALUE, strlen(VALUE), NULL); - z_drop(z_move(keystr)); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_query_keyexpr(query), &keystr); + z_view_string_t params; + z_query_parameters(query, ¶ms); + printf(" >> [Queryable handler] Received Query '%.*s%.*s'\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(params)), z_string_data(z_loan(params))); + // Process value + z_owned_string_t payload_string; + z_bytes_deserialize_into_string(z_query_payload(query), &payload_string); + if (z_string_len(z_loan(payload_string)) > 0) { + printf(" with value '%.*s'\n", (int)z_string_len(z_loan(payload_string)), + z_string_data(z_loan(payload_string))); + } + z_drop(z_move(payload_string)); + + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, VALUE); + + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), NULL); } int main(int argc, char **argv) { sleep(5); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); // Declare Zenoh queryable printf("Declaring Queryable on %s...", KEYEXPR); - z_owned_closure_query_t callback = z_closure(query_handler); - z_owned_queryable_t qable = z_declare_queryable(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(qable)) { + z_owned_closure_query_t callback; + z_closure(&callback, query_handler); + z_owned_queryable_t qable; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + if (z_declare_queryable(&qable, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare queryable.\n"); exit(-1); } @@ -81,10 +100,6 @@ int main(int argc, char **argv) { printf("Closing Zenoh Session..."); z_undeclare_queryable(z_move(qable)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); printf("OK!\n"); diff --git a/examples/zephyr/z_scout.c b/examples/zephyr/z_scout.c index e9e221194..84eacae2f 100644 --- a/examples/zephyr/z_scout.c +++ b/examples/zephyr/z_scout.c @@ -27,41 +27,38 @@ void fprintzid(FILE *stream, z_id_t zid) { } } -void fprintwhatami(FILE *stream, unsigned int whatami) { - if (whatami == Z_WHATAMI_ROUTER) { - fprintf(stream, "\"Router\""); - } else if (whatami == Z_WHATAMI_PEER) { - fprintf(stream, "\"Peer\""); - } else { - fprintf(stream, "\"Other\""); - } +void fprintwhatami(FILE *stream, z_whatami_t whatami) { + z_view_string_t s; + z_whatami_to_view_string(whatami, &s); + fprintf(stream, "\"%.*s\"", (int)z_string_len(z_loan(s)), z_string_data(z_loan(s))); } -void fprintlocators(FILE *stream, const z_str_array_t *locs) { +void fprintlocators(FILE *stream, const z_loaned_string_array_t *locs) { fprintf(stream, "["); - for (unsigned int i = 0; i < z_str_array_len(locs); i++) { + for (unsigned int i = 0; i < z_string_array_len(locs); i++) { fprintf(stream, "\""); - fprintf(stream, "%s", *z_str_array_get(locs, i)); + const z_loaned_string_t *str = z_string_array_get(locs, i); + fprintf(stream, "%.*s", (int)z_string_len(str), z_string_data(str)); fprintf(stream, "\""); - if (i < z_str_array_len(locs) - 1) { + if (i < z_string_array_len(locs) - 1) { fprintf(stream, ", "); } } fprintf(stream, "]"); } -void fprinthello(FILE *stream, const z_hello_t hello) { +void fprinthello(FILE *stream, const z_loaned_hello_t *hello) { fprintf(stream, "Hello { zid: "); - fprintzid(stream, hello.zid); + fprintzid(stream, z_hello_zid(hello)); fprintf(stream, ", whatami: "); - fprintwhatami(stream, hello.whatami); + fprintwhatami(stream, z_hello_whatami(hello)); fprintf(stream, ", locators: "); - fprintlocators(stream, &hello.locators); + fprintlocators(stream, z_hello_locators(hello)); fprintf(stream, " }"); } -void callback(z_owned_hello_t *hello, void *context) { - fprinthello(stdout, z_hello_loan(hello)); +void callback(const z_loaned_hello_t *hello, void *context) { + fprinthello(stdout, hello); fprintf(stdout, "\n"); (*(int *)context)++; } @@ -81,10 +78,12 @@ int main(void) { int *context = (int *)malloc(sizeof(int)); *context = 0; - z_owned_scouting_config_t config = z_scouting_config_default(); - z_owned_closure_hello_t closure = z_closure_hello(callback, drop, context); + z_owned_config_t config; + z_config_default(&config); + z_owned_closure_hello_t closure; + z_closure_hello(&closure, callback, drop, context); printf("Scouting...\n"); - z_scout(z_scouting_config_move(&config), z_closure_hello_move(&closure)); + z_scout(z_config_move(&config), z_closure_hello_move(&closure), NULL); return 0; } diff --git a/examples/zephyr/z_sub.c b/examples/zephyr/z_sub.c index ce0a0e73d..d792b4979 100644 --- a/examples/zephyr/z_sub.c +++ b/examples/zephyr/z_sub.c @@ -29,40 +29,47 @@ #define KEYEXPR "demo/example/**" -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(" >> [Subscriber handler] Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample->payload.len, - sample->payload.start); - z_drop(z_move(keystr)); +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + printf(" >> [Subscriber handler] Received ('%.*s': '%.*s')\n", (int)z_string_len(z_loan(keystr)), + z_string_data(z_loan(keystr)), (int)z_string_len(z_loan(value)), z_string_data(z_loan(value))); + z_drop(z_move(value)); } int main(int argc, char **argv) { sleep(5); // Initialize Zenoh Session and other parameters - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(MODE)); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, MODE); if (strcmp(CONNECT, "") != 0) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(CONNECT)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, CONNECT); } // Open Zenoh session printf("Opening Zenoh Session..."); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("OK\n"); // Start the receive and the session lease loop for zenoh-pico - zp_start_read_task(z_loan(s), NULL); - zp_start_lease_task(z_loan(s), NULL); + zp_start_read_task(z_loan_mut(s), NULL); + zp_start_lease_task(z_loan_mut(s), NULL); printf("Declaring Subscriber on '%s'...", KEYEXPR); - z_owned_closure_sample_t callback = z_closure(data_handler); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(KEYEXPR), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str_unchecked(&ke, KEYEXPR); + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); exit(-1); } @@ -75,10 +82,6 @@ int main(int argc, char **argv) { printf("Closing Zenoh Session..."); z_undeclare_subscriber(z_move(sub)); - // Stop the receive and the session lease loop for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); - z_close(z_move(s)); printf("OK!\n"); diff --git a/include/zenoh-pico.h b/include/zenoh-pico.h index 5cf6625eb..a41138ff3 100644 --- a/include/zenoh-pico.h +++ b/include/zenoh-pico.h @@ -17,15 +17,17 @@ #ifndef ZENOH_PICO_H #define ZENOH_PICO_H -#define ZENOH_PICO "0.11.0.0" -#define ZENOH_PICO_MAJOR 0 -#define ZENOH_PICO_MINOR 11 +#define ZENOH_PICO "1.0.0.0" +#define ZENOH_PICO_MAJOR 1 +#define ZENOH_PICO_MINOR 0 #define ZENOH_PICO_PATCH 0 #define ZENOH_PICO_TWEAK 0 #include "zenoh-pico/api/constants.h" +#include "zenoh-pico/api/handlers.h" #include "zenoh-pico/api/macros.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" +#include "zenoh-pico/config.h" #endif /* ZENOH_PICO_H */ diff --git a/include/zenoh-pico.h.in b/include/zenoh-pico.h.in index 736ab3ff2..1db75cd76 100644 --- a/include/zenoh-pico.h.in +++ b/include/zenoh-pico.h.in @@ -24,8 +24,10 @@ #define ZENOH_PICO_TWEAK @ZENOH_PICO_TWEAK@ #include "zenoh-pico/api/constants.h" +#include "zenoh-pico/api/handlers.h" #include "zenoh-pico/api/macros.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" +#include "zenoh-pico/config.h" #endif /* ZENOH_PICO_H */ diff --git a/include/zenoh-pico/api/constants.h b/include/zenoh-pico/api/constants.h index 9e9e095ca..d91fc3441 100644 --- a/include/zenoh-pico/api/constants.h +++ b/include/zenoh-pico/api/constants.h @@ -22,7 +22,7 @@ extern "C" { #endif /** - * What values. + * What bitmask for scouting. * * Enumerators: * Z_WHAT_ROUTER: Router. @@ -32,7 +32,11 @@ extern "C" { typedef enum { Z_WHAT_ROUTER = 0x01, // Router Z_WHAT_PEER = 0x02, // Peer - Z_WHAT_CLIENT = 0x03 // Client + Z_WHAT_CLIENT = 0x04, // Client + Z_WHAT_ROUTER_PEER = (0x01 | 0x02), + Z_WHAT_ROUTER_CLIENT = (0x01 | 0x04), + Z_WHAT_PEER_CLIENT = (0x02 | 0x04), + Z_WHAT_ROUTER_PEER_CLIENT = ((0x01 | 0x02) | 0x04), } z_what_t; /** @@ -43,8 +47,12 @@ typedef enum { * Z_WHATAMI_PEER: Bitmask to filter for Zenoh peers. * Z_WHATAMI_CLIENT: Bitmask to filter for Zenoh clients. */ -typedef enum { Z_WHATAMI_ROUTER = 0x00, Z_WHATAMI_PEER = 0x01, Z_WHATAMI_CLIENT = 0x02 } z_whatami_t; -#define Z_WHATAMI_DEFAULT Z_WHATAMI_ROUTER +typedef enum z_whatami_t { + Z_WHATAMI_ROUTER = 0x01, + Z_WHATAMI_PEER = 0x02, + Z_WHATAMI_CLIENT = 0x04, +} z_whatami_t; +#define Z_WHATAMI_DEFAULT Z_WHATAMI_ROUTER; /** * Status values for keyexpr canonization operation. @@ -75,6 +83,22 @@ typedef enum { Z_KEYEXPR_CANON_CONTAINS_UNBOUND_DOLLAR = -8 } zp_keyexpr_canon_status_t; +/** + * Intersection level of 2 key expressions. + * + * Enumerators: + * Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT: 2 key expression do not intersect. + * Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS: 2 key expressions intersect, i.e. there exists at least one key expression + * that is included by both. Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES: First key expression is the superset of second one. + * Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS: 2 key expressions are equal. + */ +typedef enum { + Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT = 0, + Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS = 1, + Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES = 2, + Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS = 3, +} z_keyexpr_intersection_level_t; + /** * Sample kind values. * @@ -86,55 +110,91 @@ typedef enum { Z_SAMPLE_KIND_PUT = 0, Z_SAMPLE_KIND_DELETE = 1 } z_sample_kind_t #define Z_SAMPLE_KIND_DEFAULT Z_SAMPLE_KIND_PUT /** - * Zenoh encoding values. - * These values are based on already existing HTTP MIME types and extended with other relevant encodings. + * Default encoding values used by Zenoh. * - * Enumerators: - * Z_ENCODING_PREFIX_EMPTY: Encoding not defined. - * Z_ENCODING_PREFIX_APP_OCTET_STREAM: ``application/octet-stream``. Default value for all other cases. An unknown - * file type should use this type. Z_ENCODING_PREFIX_APP_CUSTOM: Custom application type. Non IANA standard. - * Z_ENCODING_PREFIX_TEXT_PLAIN: ``text/plain``. Default value for textual files. A textual file should be - * human-readable and must not contain binary data. Z_ENCODING_PREFIX_APP_PROPERTIES: Application properties - * type. Non IANA standard. Z_ENCODING_PREFIX_APP_JSON: ``application/json``. JSON format. - * Z_ENCODING_PREFIX_APP_SQL: Application sql type. Non IANA standard. Z_ENCODING_PREFIX_APP_INTEGER: Application - * integer type. Non IANA standard. Z_ENCODING_PREFIX_APP_FLOAT: Application float type. Non IANA standard. - * Z_ENCODING_PREFIX_APP_XML: ``application/xml``. XML. - * Z_ENCODING_PREFIX_APP_XHTML_XML: ``application/xhtml+xml``. XHTML. - * Z_ENCODING_PREFIX_APP_X_WWW_FORM_URLENCODED: ``application/x-www-form-urlencoded``. The keys and values are - * encoded in key-value tuples separated by '&', with a '=' between the key and the value. - * Z_ENCODING_PREFIX_TEXT_JSON: Text JSON. Non IANA standard. Z_ENCODING_PREFIX_TEXT_HTML: ``text/html``. HyperText - * Markup Language (HTML). Z_ENCODING_PREFIX_TEXT_XML: ``text/xml``. `Application/xml` is recommended as of RFC - * 7303 (section 4.1), but `text/xml` is still used sometimes. Z_ENCODING_PREFIX_TEXT_CSS: ``text/css``. - * Cascading Style Sheets (CSS). Z_ENCODING_PREFIX_TEXT_CSV: ``text/csv``. Comma-separated values (CSV). - * Z_ENCODING_PREFIX_TEXT_JAVASCRIPT: ``text/javascript``. JavaScript. - * Z_ENCODING_PREFIX_IMAGE_JPEG: ``image/jpeg``. JPEG images. - * Z_ENCODING_PREFIX_IMAGE_PNG: ``image/png``. Portable Network Graphics. - * Z_ENCODING_PREFIX_IMAGE_GIF: ``image/gif``. Graphics Interchange Format (GIF). + * An encoding has a similar role to Content-type in HTTP: it indicates, when present, how data should be interpreted by + * the application. + * + * Please note the Zenoh protocol does not impose any encoding value nor it operates on it. + * It can be seen as some optional metadata that is carried over by Zenoh in such a way the application may perform + * different operations depending on the encoding value. + * + * A set of associated constants are provided to cover the most common encodings for user convenience. + * This is particularly useful in helping Zenoh to perform additional wire-level optimizations. + * + * Register your encoding metadata from a string with :c:func:`z_encoding_from_str`. To get the optimization, you need + * Z_FEATURE_ENCODING_VALUES to 1 and your string should follow the format: ";" + * + * E.g: "text/plain;utf8" + * + * Here is the list of constants: */ -typedef enum { - Z_ENCODING_PREFIX_EMPTY = 0, - Z_ENCODING_PREFIX_APP_OCTET_STREAM = 1, - Z_ENCODING_PREFIX_APP_CUSTOM = 2, // non iana standard - Z_ENCODING_PREFIX_TEXT_PLAIN = 3, - Z_ENCODING_PREFIX_APP_PROPERTIES = 4, // non iana standard - Z_ENCODING_PREFIX_APP_JSON = 5, // if not readable from casual users - Z_ENCODING_PREFIX_APP_SQL = 6, - Z_ENCODING_PREFIX_APP_INTEGER = 7, // non iana standard - Z_ENCODING_PREFIX_APP_FLOAT = 8, // non iana standard - Z_ENCODING_PREFIX_APP_XML = 9, // if not readable from casual users (RFC 3023, section 3) - Z_ENCODING_PREFIX_APP_XHTML_XML = 10, - Z_ENCODING_PREFIX_APP_X_WWW_FORM_URLENCODED = 11, - Z_ENCODING_PREFIX_TEXT_JSON = 12, // non iana standard - if readable from casual users - Z_ENCODING_PREFIX_TEXT_HTML = 13, - Z_ENCODING_PREFIX_TEXT_XML = 14, // if readable from casual users (RFC 3023, section 3) - Z_ENCODING_PREFIX_TEXT_CSS = 15, - Z_ENCODING_PREFIX_TEXT_CSV = 16, - Z_ENCODING_PREFIX_TEXT_JAVASCRIPT = 17, - Z_ENCODING_PREFIX_IMAGE_JPEG = 18, - Z_ENCODING_PREFIX_IMAGE_PNG = 19, - Z_ENCODING_PREFIX_IMAGE_GIF = 20 -} z_encoding_prefix_t; -#define Z_ENCODING_PREFIX_DEFAULT Z_ENCODING_PREFIX_EMPTY +// "zenoh/bytes" +// "zenoh/int8" +// "zenoh/int16" +// "zenoh/int32" +// "zenoh/int64" +// "zenoh/int128" +// "zenoh/uint8" +// "zenoh/uint16" +// "zenoh/uint32" +// "zenoh/uint64" +// "zenoh/uint128" +// "zenoh/float32" +// "zenoh/float64" +// "zenoh/bool" +// "zenoh/string" +// "zenoh/error" +// "application/octet-stream" +// "text/plain" +// "application/json" +// "text/json" +// "application/cdr" +// "application/cbor" +// "application/yaml" +// "text/yaml" +// "text/json5" +// "application/python-serialized-object" +// "application/protobuf" +// "application/java-serialized-object" +// "application/openmetrics-text" +// "image/png" +// "image/jpeg" +// "image/gif" +// "image/bmp" +// "image/webp" +// "application/xml" +// "application/x-www-form-urlencoded" +// "text/html" +// "text/xml" +// "text/css" +// "text/javascript" +// "text/markdown" +// "text/csv" +// "application/sql" +// "application/coap-payload" +// "application/json-patch+json" +// "application/json-seq" +// "application/jsonpath" +// "application/jwt" +// "application/mp4" +// "application/soap+xml" +// "application/yang" +// "audio/aac" +// "audio/flac" +// "audio/mp4" +// "audio/ogg" +// "audio/vorbis" +// "video/h261" +// "video/h263" +// "video/h264" +// "video/h265" +// "video/h266" +// "video/mp4" +// "video/ogg" +// "video/raw" +// "video/vp8" +// "video/vp9" /** * Consolidation mode values. @@ -167,16 +227,6 @@ typedef enum { typedef enum { Z_RELIABILITY_BEST_EFFORT = 1, Z_RELIABILITY_RELIABLE = 0 } z_reliability_t; #define Z_RELIABILITY_DEFAULT Z_RELIABILITY_RELIABLE -/** - * Reply tag values. - * - * Enumerators: - * Z_REPLY_TAG_DATA: Tag identifying that the reply contains some data. - * Z_REPLY_TAG_FINAL: Tag identifying that the reply does not contain any data and that there will be no more - * replies for this query. - */ -typedef enum { Z_REPLY_TAG_DATA = 0, Z_REPLY_TAG_FINAL = 1 } z_reply_tag_t; - /** * Congestion control values. * @@ -214,16 +264,6 @@ typedef enum { } z_priority_t; #define Z_PRIORITY_DEFAULT Z_PRIORITY_DATA -/** - * Subscription mode values. - * - * Enumerators: - * Z_SUBMODE_PUSH: Defines the subscription with a push paradigm. - * Z_SUBMODE_PULL: Defines the subscription with a pull paradigm. - */ -typedef enum { Z_SUBMODE_PUSH = 0, Z_SUBMODE_PULL = 1 } z_submode_t; -#define Z_SUBMODE_DEFAULT Z_SUBMODE_PUSH - /** * Query target values. * diff --git a/include/zenoh-pico/api/handlers.h b/include/zenoh-pico/api/handlers.h new file mode 100644 index 000000000..25b4444df --- /dev/null +++ b/include/zenoh-pico/api/handlers.h @@ -0,0 +1,207 @@ +// +// Copyright (c) 2024 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 INCLUDE_ZENOH_PICO_API_HANDLERS_H +#define INCLUDE_ZENOH_PICO_API_HANDLERS_H + +#include + +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/fifo_mt.h" +#include "zenoh-pico/collections/ring_mt.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" + +#ifdef __cplusplus +extern "C" { +#endif +// -- Channel +#define _Z_CHANNEL_DEFINE_IMPL(handler_type, handler_name, handler_new_f_name, callback_type, callback_new_f, \ + collection_type, collection_new_f, collection_free_f, collection_push_f, \ + collection_pull_f, collection_try_pull_f, collection_close_f, elem_owned_type, \ + elem_loaned_type, elem_clone_f, elem_move_f, elem_drop_f, elem_null_f) \ + typedef struct { \ + collection_type *collection; \ + } handler_type; \ + \ + _Z_OWNED_TYPE_VALUE(handler_type, handler_name) \ + \ + static inline void _z_##handler_name##_elem_free(void **elem) { \ + elem_drop_f(elem_move_f((elem_owned_type *)*elem)); \ + z_free(*elem); \ + *elem = NULL; \ + } \ + static inline void _z_##handler_name##_elem_move(void *dst, void *src) { \ + memcpy(dst, src, sizeof(elem_owned_type)); \ + z_free(src); \ + } \ + static inline void _z_##handler_name##_close(void *context) { \ + int8_t ret = collection_close_f((collection_type *)context); \ + if (ret < 0) { \ + _Z_ERROR("%s failed: %i", #collection_push_f, ret); \ + } \ + } \ + static inline void _z_##handler_name##_send(const elem_loaned_type *elem, void *context) { \ + elem_owned_type *internal_elem = (elem_owned_type *)z_malloc(sizeof(elem_owned_type)); \ + if (internal_elem == NULL) { \ + _Z_ERROR("Out of memory"); \ + return; \ + } \ + elem_clone_f(internal_elem, elem); \ + int8_t ret = collection_push_f(internal_elem, context, _z_##handler_name##_elem_free); \ + if (ret != _Z_RES_OK) { \ + _Z_ERROR("%s failed: %i", #collection_push_f, ret); \ + } \ + } \ + static inline int8_t z_##handler_name##_recv(const z_loaned_##handler_name##_t *handler, elem_owned_type *elem) { \ + elem_null_f(elem); \ + int8_t ret = collection_pull_f(elem, (collection_type *)handler->collection, _z_##handler_name##_elem_move); \ + if (ret == _Z_RES_CHANNEL_CLOSED) { \ + return Z_CHANNEL_DISCONNECTED; \ + } \ + if (ret != _Z_RES_OK) { \ + _Z_ERROR("%s failed: %i", #collection_pull_f, ret); \ + return ret; \ + } \ + return _Z_RES_OK; \ + } \ + static inline int8_t z_##handler_name##_try_recv(const z_loaned_##handler_name##_t *handler, \ + elem_owned_type *elem) { \ + elem_null_f(elem); \ + int8_t ret = \ + collection_try_pull_f(elem, (collection_type *)handler->collection, _z_##handler_name##_elem_move); \ + if (ret == _Z_RES_CHANNEL_CLOSED) { \ + return Z_CHANNEL_DISCONNECTED; \ + } else if (ret == _Z_RES_CHANNEL_NODATA) { \ + return Z_CHANNEL_NODATA; \ + } \ + if (ret != _Z_RES_OK) { \ + _Z_ERROR("%s failed: %i", #collection_try_pull_f, ret); \ + return ret; \ + } \ + return _Z_RES_OK; \ + } \ + \ + static inline void _z_##handler_name##_clear(handler_type *handler) { \ + if (handler != NULL && handler->collection != NULL) { \ + collection_free_f(handler->collection, _z_##handler_name##_elem_free); \ + handler->collection = NULL; \ + } \ + } \ + static inline _Bool _z_##handler_name##_check(const handler_type *handler) { return handler->collection == NULL; } \ + static inline handler_type _z_##handler_name##_null(void) { \ + handler_type h; \ + h.collection = NULL; \ + 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 int8_t handler_new_f_name(callback_type *callback, z_owned_##handler_name##_t *handler, \ + size_t capacity) { \ + if (capacity < 1) { \ + return _Z_ERR_INVALID; \ + } \ + handler->_val.collection = collection_new_f(capacity); \ + if (handler->_val.collection == NULL) { \ + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; \ + } \ + callback_new_f(callback, _z_##handler_name##_send, _z_##handler_name##_close, handler->_val.collection); \ + return _Z_RES_OK; \ + } + +#define _Z_CHANNEL_DEFINE(item_name, kind_name) \ + _Z_CHANNEL_DEFINE_IMPL(/* handler_type */ _z_##kind_name##_handler_##item_name##_t, \ + /* handler_name */ kind_name##_handler_##item_name, \ + /* handler_new_f_name */ z_##kind_name##_channel_##item_name##_new, \ + /* callback_type */ z_owned_closure_##item_name##_t, \ + /* callback_new_f */ z_closure_##item_name, \ + /* collection_type */ _z_##kind_name##_mt_t, \ + /* collection_new_f */ _z_##kind_name##_mt_new, \ + /* collection_free_f */ _z_##kind_name##_mt_free, \ + /* collection_push_f */ _z_##kind_name##_mt_push, \ + /* collection_pull_f */ _z_##kind_name##_mt_pull, \ + /* collection_try_pull_f */ _z_##kind_name##_mt_try_pull, \ + /* collection_close_f */ _z_##kind_name##_mt_close, \ + /* elem_owned_type */ z_owned_##item_name##_t, \ + /* elem_loaned_type */ z_loaned_##item_name##_t, \ + /* elem_clone_f */ z_##item_name##_clone, \ + /* elem_move_f */ z_##item_name##_move, \ + /* 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); + +// This macro defines: +// z_ring_channel_sample_new() +// z_owned_ring_handler_sample_t/z_loaned_ring_handler_sample_t +_Z_CHANNEL_DEFINE(sample, ring) + +// This macro defines: +// z_fifo_channel_sample_new() +// z_owned_fifo_handler_sample_t/z_loaned_fifo_handler_sample_t +_Z_CHANNEL_DEFINE(sample, fifo) + +#if Z_FEATURE_QUERYABLE == 1 +// This macro defines: +// z_ring_channel_query_new() +// z_owned_ring_handler_query_t/z_loaned_ring_handler_query_t +_Z_CHANNEL_DEFINE(query, ring) + +// This macro defines: +// z_fifo_channel_query_new() +// z_owned_fifo_handler_query_t/z_loaned_fifo_handler_query_t +_Z_CHANNEL_DEFINE(query, fifo) +#else // Z_FEATURE_QUERYABLE +_Z_CHANNEL_DEFINE_DUMMY(query, ring) +_Z_CHANNEL_DEFINE_DUMMY(query, fifo) +#endif // Z_FEATURE_QUERYABLE + +#if Z_FEATURE_QUERY == 1 +// This macro defines: +// z_ring_channel_reply_new() +// z_owned_ring_handler_reply_t/z_loaned_ring_handler_reply_t +_Z_CHANNEL_DEFINE(reply, ring) + +// This macro defines: +// z_fifo_channel_reply_new() +// z_owned_fifo_handler_reply_t/z_loaned_fifo_handler_reply_t +_Z_CHANNEL_DEFINE(reply, fifo) +#else // Z_FEATURE_QUERY +_Z_CHANNEL_DEFINE_DUMMY(reply, ring) +_Z_CHANNEL_DEFINE_DUMMY(reply, fifo) +#endif // Z_FEATURE_QUERY + +#ifdef __cplusplus +} +#endif + +#endif // INCLUDE_ZENOH_PICO_API_HANDLERS_H diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index c7cb700a9..4dedda8dc 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -14,6 +14,7 @@ #ifndef ZENOH_PICO_API_MACROS_H #define ZENOH_PICO_API_MACROS_H +#include "zenoh-pico/api/handlers.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" @@ -34,16 +35,59 @@ */ #define z_loan(x) _Generic((x), \ - z_owned_keyexpr_t : z_keyexpr_loan, \ - z_owned_config_t : z_config_loan, \ - z_owned_scouting_config_t : z_scouting_config_loan, \ - z_owned_session_t : z_session_loan, \ - z_owned_pull_subscriber_t : z_pull_subscriber_loan, \ - z_owned_publisher_t : z_publisher_loan, \ - z_owned_reply_t : z_reply_loan, \ - z_owned_hello_t : z_hello_loan, \ - z_owned_str_t : z_str_loan, \ - z_owned_str_array_t : z_str_array_loan \ + z_owned_keyexpr_t : z_keyexpr_loan, \ + z_view_keyexpr_t : z_view_keyexpr_loan, \ + z_owned_config_t : z_config_loan, \ + z_owned_session_t : z_session_loan, \ + z_owned_subscriber_t : z_subscriber_loan, \ + z_owned_publisher_t : z_publisher_loan, \ + z_owned_queryable_t : z_queryable_loan, \ + z_owned_reply_t : z_reply_loan, \ + z_owned_hello_t : z_hello_loan, \ + z_owned_string_t : z_string_loan, \ + z_view_string_t : z_view_string_loan, \ + z_owned_string_array_t : z_string_array_loan, \ + z_owned_sample_t : z_sample_loan, \ + z_owned_query_t : z_query_loan, \ + z_owned_slice_t : z_slice_loan, \ + z_owned_bytes_t : z_bytes_loan, \ + z_owned_encoding_t : z_encoding_loan, \ + z_owned_task_t : z_task_loan, \ + z_owned_mutex_t : z_mutex_loan, \ + z_owned_condvar_t : z_condvar_loan, \ + z_owned_fifo_handler_query_t : z_fifo_handler_query_loan, \ + z_owned_fifo_handler_reply_t : z_fifo_handler_reply_loan, \ + z_owned_fifo_handler_sample_t : z_fifo_handler_sample_loan, \ + z_owned_ring_handler_query_t : z_ring_handler_query_loan, \ + z_owned_ring_handler_reply_t : z_ring_handler_reply_loan, \ + z_owned_ring_handler_sample_t : z_ring_handler_sample_loan, \ + z_owned_reply_err_t : z_reply_err_loan, \ + z_owned_closure_sample_t : z_closure_sample_loan, \ + z_owned_closure_reply_t : z_closure_reply_loan, \ + z_owned_closure_query_t : z_closure_query_loan, \ + z_owned_closure_hello_t : z_closure_hello_loan, \ + z_owned_closure_zid_t : z_closure_zid_loan \ + )(&x) + +#define z_loan_mut(x) _Generic((x), \ + z_owned_keyexpr_t : z_keyexpr_loan_mut, \ + z_owned_config_t : z_config_loan_mut, \ + z_owned_session_t : z_session_loan_mut, \ + z_owned_publisher_t : z_publisher_loan_mut, \ + z_owned_queryable_t : z_queryable_loan_mut, \ + z_owned_reply_t : z_reply_loan_mut, \ + z_owned_hello_t : z_hello_loan_mut, \ + z_owned_string_t : z_string_loan_mut, \ + z_view_string_t : z_view_string_loan_mut, \ + z_owned_string_array_t : z_string_array_loan_mut, \ + z_owned_sample_t : z_sample_loan_mut, \ + z_owned_query_t : z_query_loan_mut, \ + z_owned_slice_t : z_slice_loan_mut, \ + z_owned_bytes_t : z_bytes_loan_mut, \ + z_owned_task_t : z_task_loan_mut, \ + z_owned_mutex_t : z_mutex_loan_mut, \ + z_owned_condvar_t : z_condvar_loan_mut, \ + z_owned_reply_err_t : z_reply_err_loan_mut \ )(&x) /** * Defines a generic function for dropping any of the ``z_owned_X_t`` types. @@ -52,49 +96,38 @@ * x: The instance to drop. */ #define z_drop(x) _Generic((x), \ - z_owned_keyexpr_t * : z_keyexpr_drop, \ - z_owned_config_t * : z_config_drop, \ - z_owned_scouting_config_t * : z_scouting_config_drop, \ - z_owned_session_t * : z_session_drop, \ - z_owned_subscriber_t * : z_subscriber_drop, \ - z_owned_pull_subscriber_t * : z_pull_subscriber_drop, \ - z_owned_publisher_t * : z_publisher_drop, \ - z_owned_queryable_t * : z_queryable_drop, \ - z_owned_reply_t * : z_reply_drop, \ - z_owned_hello_t * : z_hello_drop, \ - z_owned_str_t * : z_str_drop, \ - z_owned_str_array_t * : z_str_array_drop, \ - z_owned_closure_sample_t * : z_closure_sample_drop, \ - z_owned_closure_query_t * : z_closure_query_drop, \ - z_owned_closure_reply_t * : z_closure_reply_drop, \ - z_owned_closure_hello_t * : z_closure_hello_drop, \ - z_owned_closure_zid_t * : z_closure_zid_drop \ + z_moved_keyexpr_t* : z_keyexpr_drop, \ + z_moved_config_t* : z_config_drop, \ + z_moved_session_t* : z_session_drop, \ + z_moved_subscriber_t* : z_subscriber_drop, \ + z_moved_publisher_t* : z_publisher_drop, \ + z_moved_queryable_t* : z_queryable_drop, \ + z_moved_reply_t* : z_reply_drop, \ + z_moved_hello_t* : z_hello_drop, \ + z_moved_string_t* : z_string_drop, \ + z_moved_string_array_t* : z_string_array_drop, \ + z_moved_sample_t* : z_sample_drop, \ + z_moved_query_t* : z_query_drop, \ + z_moved_encoding_t* : z_encoding_drop, \ + z_moved_slice_t* : z_slice_drop, \ + z_moved_bytes_t* : z_bytes_drop, \ + z_moved_closure_sample_t* : z_closure_sample_drop, \ + z_moved_closure_query_t* : z_closure_query_drop, \ + z_moved_closure_reply_t* : z_closure_reply_drop, \ + z_moved_closure_hello_t* : z_closure_hello_drop, \ + z_moved_closure_zid_t* : z_closure_zid_drop, \ + z_moved_task_t* : z_task_join, \ + z_moved_mutex_t* : z_mutex_drop, \ + z_moved_condvar_t* : z_condvar_drop, \ + z_moved_fifo_handler_query_t* : z_fifo_handler_query_drop, \ + z_moved_fifo_handler_reply_t* : z_fifo_handler_reply_drop, \ + z_moved_fifo_handler_sample_t* : z_fifo_handler_sample_drop, \ + z_moved_ring_handler_query_t* : z_ring_handler_query_drop, \ + z_moved_ring_handler_reply_t* : z_ring_handler_reply_drop, \ + z_moved_ring_handler_sample_t* : z_ring_handler_sample_drop, \ + z_moved_reply_err_t* : z_reply_err_drop \ )(x) -/** - * Defines a generic function for making null object of any of the ``z_owned_X_t`` types. - * - * Returns: - * Returns the uninitialized instance of `x`. - */ -#define z_null(x) (*x = _Generic((x), \ - z_owned_session_t * : z_session_null, \ - z_owned_publisher_t * : z_publisher_null, \ - z_owned_keyexpr_t * : z_keyexpr_null, \ - z_owned_config_t * : z_config_null, \ - z_owned_scouting_config_t * : z_scouting_config_null, \ - z_owned_pull_subscriber_t * : z_pull_subscriber_null, \ - z_owned_subscriber_t * : z_subscriber_null, \ - z_owned_queryable_t * : z_queryable_null, \ - z_owned_reply_t * : z_reply_null, \ - z_owned_hello_t * : z_hello_null, \ - z_owned_str_t * : z_str_null, \ - z_owned_closure_sample_t * : z_closure_sample_null, \ - z_owned_closure_query_t * : z_closure_query_null, \ - z_owned_closure_reply_t * : z_closure_reply_null, \ - z_owned_closure_hello_t * : z_closure_hello_null, \ - z_owned_closure_zid_t * : z_closure_zid_null \ - )()) /** * Defines a generic function for checking the validity of any of the ``z_owned_X_t`` types. * @@ -105,22 +138,28 @@ * Returns ``true`` if valid, or ``false`` otherwise. */ -#define z_check(x) _Generic((x), \ - z_owned_keyexpr_t : z_keyexpr_check, \ - z_keyexpr_t : z_keyexpr_is_initialized, \ - z_value_t : z_value_is_initialized, \ - z_owned_config_t : z_config_check, \ - z_owned_scouting_config_t : z_scouting_config_check, \ - z_owned_session_t : z_session_check, \ - z_owned_subscriber_t : z_subscriber_check, \ - z_owned_pull_subscriber_t : z_pull_subscriber_check, \ - z_owned_publisher_t : z_publisher_check, \ - z_owned_queryable_t : z_queryable_check, \ - z_owned_reply_t : z_reply_check, \ - z_owned_hello_t : z_hello_check, \ - z_owned_str_t : z_str_check, \ - z_owned_str_array_t : z_str_array_check, \ - z_bytes_t : z_bytes_check \ +#define z_internal_check(x) _Generic((x), \ + z_owned_keyexpr_t : z_internal_keyexpr_check, \ + z_owned_reply_err_t : z_internal_reply_err_check, \ + z_owned_config_t : z_internal_config_check, \ + z_owned_session_t : z_internal_session_check, \ + z_owned_subscriber_t : z_internal_subscriber_check, \ + z_owned_publisher_t : z_internal_publisher_check, \ + z_owned_queryable_t : z_internal_queryable_check, \ + z_owned_reply_t : z_internal_reply_check, \ + z_owned_hello_t : z_internal_hello_check, \ + z_owned_string_t : z_internal_string_check, \ + z_owned_string_array_t : z_internal_string_array_check, \ + z_owned_closure_sample_t : z_internal_closure_sample_check, \ + z_owned_closure_query_t : z_internal_closure_query_check, \ + z_owned_closure_reply_t : z_internal_closure_reply_check, \ + z_owned_closure_hello_t : z_internal_closure_hello_check, \ + z_owned_closure_zid_t : z_internal_closure_zid_check, \ + z_owned_slice_t : z_internal_slice_check, \ + z_owned_bytes_t : z_internal_bytes_check, \ + z_owned_sample_t : z_internal_sample_check, \ + z_owned_query_t : z_internal_query_check, \ + z_owned_encoding_t : z_internal_encoding_check \ )(&x) /** @@ -130,13 +169,33 @@ * x: The closure to call */ #define z_call(x, ...) \ - _Generic((x), z_owned_closure_sample_t : z_closure_sample_call, \ - z_owned_closure_query_t : z_closure_query_call, \ - z_owned_closure_reply_t : z_closure_reply_call, \ - z_owned_closure_hello_t : z_closure_hello_call, \ - z_owned_closure_zid_t : z_closure_zid_call \ + _Generic((x), z_loaned_closure_sample_t : z_closure_sample_call, \ + z_loaned_closure_query_t : z_closure_query_call, \ + z_loaned_closure_reply_t : z_closure_reply_call, \ + z_loaned_closure_hello_t : z_closure_hello_call, \ + z_loaned_closure_zid_t : z_closure_zid_call \ ) (&x, __VA_ARGS__) +#define z_try_recv(x, ...) \ + _Generic((x), \ + const z_loaned_fifo_handler_query_t* : z_fifo_handler_query_try_recv, \ + const z_loaned_fifo_handler_reply_t* : z_fifo_handler_reply_try_recv, \ + const z_loaned_fifo_handler_sample_t* : z_fifo_handler_sample_try_recv, \ + const z_loaned_ring_handler_query_t* : z_ring_handler_query_try_recv, \ + const z_loaned_ring_handler_reply_t* : z_ring_handler_reply_try_recv, \ + const z_loaned_ring_handler_sample_t* : z_ring_handler_sample_try_recv \ + )(x, __VA_ARGS__) + +#define z_recv(x, ...) \ + _Generic((x), \ + const z_loaned_fifo_handler_query_t* : z_fifo_handler_query_recv, \ + const z_loaned_fifo_handler_reply_t* : z_fifo_handler_reply_recv, \ + const z_loaned_fifo_handler_sample_t* : z_fifo_handler_sample_recv, \ + const z_loaned_ring_handler_query_t* : z_ring_handler_query_recv, \ + const z_loaned_ring_handler_reply_t* : z_ring_handler_reply_recv, \ + const z_loaned_ring_handler_sample_t* : z_ring_handler_sample_recv \ + )(x, __VA_ARGS__) + /** * Defines a generic function for moving any of the ``z_owned_X_t`` types. * @@ -147,77 +206,147 @@ * Returns the instance associated with `x`. */ #define z_move(x) _Generic((x), \ - z_owned_keyexpr_t : z_keyexpr_move, \ - z_owned_config_t : z_config_move, \ - z_owned_scouting_config_t : z_scouting_config_move, \ - z_owned_session_t : z_session_move, \ - z_owned_subscriber_t : z_subscriber_move, \ - z_owned_pull_subscriber_t : z_pull_subscriber_move, \ - z_owned_publisher_t : z_publisher_move, \ - z_owned_queryable_t : z_queryable_move, \ - z_owned_reply_t : z_reply_move, \ - z_owned_hello_t : z_hello_move, \ - z_owned_str_t : z_str_move, \ - z_owned_str_array_t : z_str_array_move, \ - z_owned_closure_sample_t : z_closure_sample_move, \ - z_owned_closure_query_t : z_closure_query_move, \ - z_owned_closure_reply_t : z_closure_reply_move, \ - z_owned_closure_hello_t : z_closure_hello_move, \ - z_owned_closure_zid_t : z_closure_zid_move \ + z_owned_keyexpr_t : z_keyexpr_move, \ + z_owned_config_t : z_config_move, \ + z_owned_session_t : z_session_move, \ + z_owned_subscriber_t : z_subscriber_move, \ + z_owned_publisher_t : z_publisher_move, \ + z_owned_queryable_t : z_queryable_move, \ + z_owned_reply_t : z_reply_move, \ + z_owned_hello_t : z_hello_move, \ + z_owned_string_t : z_string_move, \ + z_owned_string_array_t : z_string_array_move, \ + z_owned_closure_sample_t : z_closure_sample_move, \ + z_owned_closure_query_t : z_closure_query_move, \ + z_owned_closure_reply_t : z_closure_reply_move, \ + z_owned_closure_hello_t : z_closure_hello_move, \ + z_owned_closure_zid_t : z_closure_zid_move, \ + z_owned_sample_t : z_sample_move, \ + z_owned_query_t : z_query_move, \ + z_owned_slice_t : z_slice_move, \ + z_owned_bytes_t : z_bytes_move, \ + z_owned_encoding_t : z_encoding_move, \ + z_owned_task_t : z_task_move, \ + z_owned_mutex_t : z_mutex_move, \ + z_owned_condvar_t : z_condvar_move, \ + z_owned_ring_handler_query_t : z_ring_handler_query_move, \ + z_owned_ring_handler_reply_t : z_ring_handler_reply_move, \ + z_owned_ring_handler_sample_t : z_ring_handler_sample_move, \ + z_owned_fifo_handler_query_t : z_fifo_handler_query_move, \ + z_owned_fifo_handler_reply_t : z_fifo_handler_reply_move, \ + z_owned_fifo_handler_sample_t : z_fifo_handler_sample_move, \ + z_owned_reply_err_t : z_reply_err_move \ )(&x) +/** + * Defines a generic function for extracting the ``z_owned_X_t`` type from ``z_moved_X_t`` + * + * Parameters: + * x: The pointer to destinaton ``z_owned_X_t`` + * src: The source ``z_moved_X_t`` + * + * Returns: + * Returns the instance associated with `x`. + */ +#define z_take(this_, x) \ + _Generic((this_), \ + z_owned_bytes_t *: z_bytes_take, \ + z_owned_closure_hello_t *: z_closure_hello_take, \ + z_owned_closure_query_t *: z_closure_query_take, \ + z_owned_closure_reply_t *: z_closure_reply_take, \ + z_owned_closure_sample_t *: z_closure_sample_take, \ + z_owned_closure_zid_t * : z_closure_zid_take, \ + z_owned_condvar_t *: z_condvar_take, \ + z_owned_config_t *: z_config_take, \ + z_owned_encoding_t *: z_encoding_take, \ + z_owned_fifo_handler_query_t *: z_fifo_handler_query_take, \ + z_owned_fifo_handler_reply_t *: z_fifo_handler_reply_take, \ + z_owned_fifo_handler_sample_t *: z_fifo_handler_sample_take,\ + z_owned_hello_t *: z_hello_take, \ + z_owned_keyexpr_t *: z_keyexpr_take, \ + z_owned_mutex_t *: z_mutex_take, \ + z_owned_publisher_t *: z_publisher_take, \ + z_owned_query_t *: z_query_take, \ + z_owned_queryable_t *: z_queryable_take, \ + z_owned_reply_t *: z_reply_take, \ + z_owned_reply_err_t *: z_reply_err_take, \ + z_owned_ring_handler_query_t *: z_ring_handler_query_take, \ + z_owned_ring_handler_reply_t *: z_ring_handler_reply_take, \ + z_owned_ring_handler_sample_t *: z_ring_handler_sample_take,\ + z_owned_sample_t *: z_sample_take, \ + z_owned_session_t *: z_session_take, \ + z_owned_slice_t *: z_slice_take, \ + z_owned_string_array_t *: z_string_array_take, \ + z_owned_string_t *: z_string_take, \ + z_owned_subscriber_t *: z_subscriber_take \ + )(this_, x) + /** * Defines a generic function for cloning any of the ``z_owned_X_t`` types. * * Parameters: - * x: The instance to clone. + * x: The clone storage. + * y: The instance to clone. * * Returns: * Returns the cloned instance of `x`. */ -#define z_clone(x) _Generic((x), \ +#define z_clone(x, y) _Generic((x), \ z_owned_keyexpr_t : z_keyexpr_clone, \ - z_owned_config_t : z_config_clone, \ z_owned_session_t : z_session_clone, \ z_owned_subscriber_t : z_subscriber_clone, \ - z_owned_pull_subscriber_t : z_pull_subscriber_clone, \ z_owned_publisher_t : z_publisher_clone, \ z_owned_queryable_t : z_queryable_clone, \ + z_owned_query_t : z_query_clone, \ + z_owned_sample_t : z_sample_clone, \ + z_owned_bytes_t : z_bytes_clone, \ + z_owned_encoding_t : z_encoding_clone, \ + z_owned_reply_err_t : z_reply_err_clone, \ z_owned_reply_t : z_reply_clone, \ z_owned_hello_t : z_hello_clone, \ - z_owned_str_t : z_str_clone, \ - z_owned_str_array_t : z_str_array_clone \ - )(&x) + z_owned_string_t : z_string_clone, \ + z_owned_string_array_t : z_string_array_clone, \ + z_owned_config_t : z_config_clone \ + )(&x, y) /** * Defines a generic function for making null object of any of the ``z_owned_X_t`` types. * - * Returns: - * Returns the uninitialized instance of `x`. + * Parameters: + * x: The instance to nullify. */ -#define z_null(x) (*x = _Generic((x), \ - z_owned_session_t * : z_session_null, \ - z_owned_publisher_t * : z_publisher_null, \ - z_owned_keyexpr_t * : z_keyexpr_null, \ - z_owned_config_t * : z_config_null, \ - z_owned_scouting_config_t * : z_scouting_config_null, \ - z_owned_pull_subscriber_t * : z_pull_subscriber_null, \ - z_owned_subscriber_t * : z_subscriber_null, \ - z_owned_queryable_t * : z_queryable_null, \ - z_owned_reply_t * : z_reply_null, \ - z_owned_hello_t * : z_hello_null, \ - z_owned_str_t * : z_str_null, \ - z_owned_closure_sample_t * : z_closure_sample_null, \ - z_owned_closure_query_t * : z_closure_query_null, \ - z_owned_closure_reply_t * : z_closure_reply_null, \ - z_owned_closure_hello_t * : z_closure_hello_null, \ - z_owned_closure_zid_t * : z_closure_zid_null \ - )()) +#define z_internal_null(x) _Generic((x), \ + z_owned_session_t * : z_internal_session_null, \ + z_owned_publisher_t * : z_internal_publisher_null, \ + z_owned_keyexpr_t * : z_internal_keyexpr_null, \ + z_owned_config_t * : z_internal_config_null, \ + z_owned_subscriber_t * : z_internal_subscriber_null, \ + z_owned_queryable_t * : z_internal_queryable_null, \ + z_owned_query_t * : z_internal_query_null, \ + z_owned_reply_t * : z_internal_reply_null, \ + z_owned_hello_t * : z_internal_hello_null, \ + z_owned_string_t * : z_internal_string_null, \ + z_owned_string_array_t * : z_internal_string_array_null, \ + z_owned_slice_t *: z_internal_slice_null, \ + z_owned_bytes_t *: z_internal_bytes_null, \ + z_owned_closure_sample_t * : z_internal_closure_sample_null, \ + z_owned_closure_query_t * : z_internal_closure_query_null, \ + z_owned_closure_reply_t * : z_internal_closure_reply_null, \ + z_owned_closure_hello_t * : z_internal_closure_hello_null, \ + z_owned_closure_zid_t * : z_internal_closure_zid_null, \ + z_owned_sample_t * : z_internal_sample_null, \ + z_owned_encoding_t * : z_internal_encoding_null, \ + z_owned_reply_err_t * : z_internal_reply_err_null \ + )(x) // clang-format on -#define _z_closure_overloader(callback, dropper, ctx, ...) \ - { .call = callback, .drop = dropper, .context = ctx } +#define _z_closure_overloader(closure, callback, dropper, ctx, ...) \ + do { \ + (closure)->_val.call = callback; \ + (closure)->_val.drop = dropper; \ + (closure)->_val.context = ctx; \ + } while (0); /** * Defines a variadic macro to ease the definition of callback closures. @@ -232,113 +361,541 @@ */ #define z_closure(...) _z_closure_overloader(__VA_ARGS__, 0, 0, 0) -#else +#else // __cplusplus // clang-format off -template struct zenoh_loan_type { typedef T type; }; -template inline typename zenoh_loan_type::type z_loan(const T&); - -template<> struct zenoh_loan_type{ typedef z_session_t type; }; -template<> struct zenoh_loan_type{ typedef z_keyexpr_t type; }; -template<> struct zenoh_loan_type{ typedef z_config_t type; }; -template<> struct zenoh_loan_type{ typedef z_publisher_t type; }; -template<> struct zenoh_loan_type{ typedef z_pull_subscriber_t type; }; -template<> struct zenoh_loan_type{ typedef z_hello_t type; }; -template<> struct zenoh_loan_type{ typedef const char* type; }; - -template<> inline z_session_t z_loan(const z_owned_session_t& x) { return z_session_loan(&x); } -template<> inline z_keyexpr_t z_loan(const z_owned_keyexpr_t& x) { return z_keyexpr_loan(&x); } -template<> inline z_config_t z_loan(const z_owned_config_t& x) { return z_config_loan(&x); } -template<> inline z_publisher_t z_loan(const z_owned_publisher_t& x) { return z_publisher_loan(&x); } -template<> inline z_pull_subscriber_t z_loan(const z_owned_pull_subscriber_t& x) { return z_pull_subscriber_loan(&x); } -template<> inline z_hello_t z_loan(const z_owned_hello_t& x) { return z_hello_loan(&x); } -template<> inline const char* z_loan(const z_owned_str_t& x) { return z_str_loan(&x); } - -template struct zenoh_drop_type { typedef T type; }; -template inline typename zenoh_drop_type::type z_drop(T*); - -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; - -template<> inline int8_t z_drop(z_owned_session_t* v) { return z_close(v); } -template<> inline int8_t z_drop(z_owned_publisher_t* v) { return z_undeclare_publisher(v); } -template<> inline void z_drop(z_owned_keyexpr_t* v) { z_keyexpr_drop(v); } -template<> inline void z_drop(z_owned_config_t* v) { z_config_drop(v); } -template<> inline void z_drop(z_owned_scouting_config_t* v) { z_scouting_config_drop(v); } -template<> inline int8_t z_drop(z_owned_pull_subscriber_t* v) { return z_undeclare_pull_subscriber(v); } -template<> inline int8_t z_drop(z_owned_subscriber_t* v) { return z_undeclare_subscriber(v); } -template<> inline int8_t z_drop(z_owned_queryable_t* v) { return z_undeclare_queryable(v); } -template<> inline void z_drop(z_owned_reply_t* v) { z_reply_drop(v); } -template<> inline void z_drop(z_owned_hello_t* v) { z_hello_drop(v); } -template<> inline void z_drop(z_owned_str_t* v) { z_str_drop(v); } -template<> inline void z_drop(z_owned_closure_sample_t* v) { z_closure_sample_drop(v); } -template<> inline void z_drop(z_owned_closure_query_t* v) { z_closure_query_drop(v); } -template<> inline void z_drop(z_owned_closure_reply_t* v) { z_closure_reply_drop(v); } -template<> inline void z_drop(z_owned_closure_hello_t* v) { z_closure_hello_drop(v); } -template<> inline void z_drop(z_owned_closure_zid_t* v) { z_closure_zid_drop(v); } - -inline void z_null(z_owned_session_t& v) { v = z_session_null(); } -inline void z_null(z_owned_publisher_t& v) { v = z_publisher_null(); } -inline void z_null(z_owned_keyexpr_t& v) { v = z_keyexpr_null(); } -inline void z_null(z_owned_config_t& v) { v = z_config_null(); } -inline void z_null(z_owned_scouting_config_t& v) { v = z_scouting_config_null(); } -inline void z_null(z_owned_pull_subscriber_t& v) { v = z_pull_subscriber_null(); } -inline void z_null(z_owned_subscriber_t& v) { v = z_subscriber_null(); } -inline void z_null(z_owned_queryable_t& v) { v = z_queryable_null(); } -inline void z_null(z_owned_reply_t& v) { v = z_reply_null(); } -inline void z_null(z_owned_hello_t& v) { v = z_hello_null(); } -inline void z_null(z_owned_str_t& v) { v = z_str_null(); } -inline void z_null(z_owned_closure_sample_t& v) { v = z_closure_sample_null(); } -inline void z_null(z_owned_closure_query_t& v) { v = z_closure_query_null(); } -inline void z_null(z_owned_closure_reply_t& v) { v = z_closure_reply_null(); } -inline void z_null(z_owned_closure_hello_t& v) { v = z_closure_hello_null(); } -inline void z_null(z_owned_closure_zid_t& v) { v = z_closure_zid_null(); } - -inline bool z_check(const z_owned_session_t& v) { return z_session_check(&v); } -inline bool z_check(const z_owned_publisher_t& v) { return z_publisher_check(&v); } -inline bool z_check(const z_owned_keyexpr_t& v) { return z_keyexpr_check(&v); } -inline bool z_check(const z_keyexpr_t& v) { return z_keyexpr_is_initialized(&v); } -inline bool z_check(const z_owned_config_t& v) { return z_config_check(&v); } -inline bool z_check(const z_owned_scouting_config_t& v) { return z_scouting_config_check(&v); } -inline bool z_check(const z_bytes_t& v) { return z_bytes_check(&v); } -inline bool z_check(const z_owned_subscriber_t& v) { return z_subscriber_check(&v); } -inline bool z_check(const z_owned_pull_subscriber_t& v) { return z_pull_subscriber_check(&v); } -inline bool z_check(const z_owned_queryable_t& v) { return z_queryable_check(&v); } -inline bool z_check(const z_owned_reply_t& v) { return z_reply_check(&v); } -inline bool z_check(const z_owned_hello_t& v) { return z_hello_check(&v); } -inline bool z_check(const z_owned_str_t& v) { return z_str_check(&v); } - -inline void z_call(const z_owned_closure_sample_t &closure, const z_sample_t *sample) + +// z_loan definition +inline const z_loaned_keyexpr_t* z_loan(const z_owned_keyexpr_t& x) { return z_keyexpr_loan(&x); } +inline const z_loaned_keyexpr_t* z_loan(const z_view_keyexpr_t& x) { return z_view_keyexpr_loan(&x); } +inline const z_loaned_config_t* z_loan(const z_owned_config_t& x) { return z_config_loan(&x); } +inline const z_loaned_session_t* z_loan(const z_owned_session_t& x) { return z_session_loan(&x); } +inline const z_loaned_subscriber_t* z_loan(const z_owned_subscriber_t& x) { return z_subscriber_loan(&x); } +inline const z_loaned_publisher_t* z_loan(const z_owned_publisher_t& x) { return z_publisher_loan(&x); } +inline const z_loaned_queryable_t* z_loan(const z_owned_queryable_t& x) { return z_queryable_loan(&x); } +inline const z_loaned_reply_t* z_loan(const z_owned_reply_t& x) { return z_reply_loan(&x); } +inline const z_loaned_hello_t* z_loan(const z_owned_hello_t& x) { return z_hello_loan(&x); } +inline const z_loaned_string_t* z_loan(const z_owned_string_t& x) { return z_string_loan(&x); } +inline const z_loaned_string_t* z_loan(const z_view_string_t& x) { return z_view_string_loan(&x); } +inline const z_loaned_string_array_t* z_loan(const z_owned_string_array_t& x) { return z_string_array_loan(&x); } +inline const z_loaned_sample_t* z_loan(const z_owned_sample_t& x) { return z_sample_loan(&x); } +inline const z_loaned_query_t* z_loan(const z_owned_query_t& x) { return z_query_loan(&x); } +inline const z_loaned_slice_t* z_loan(const z_owned_slice_t& x) { return z_slice_loan(&x); } +inline const z_loaned_bytes_t* z_loan(const z_owned_bytes_t& x) { return z_bytes_loan(&x); } +inline const z_loaned_encoding_t* z_loan(const z_owned_encoding_t& x) { return z_encoding_loan(&x); } +inline const z_loaned_task_t* z_loan(const z_owned_task_t& x) { return z_task_loan(&x); } +inline const z_loaned_mutex_t* z_loan(const z_owned_mutex_t& x) { return z_mutex_loan(&x); } +inline const z_loaned_condvar_t* z_loan(const z_owned_condvar_t& x) { return z_condvar_loan(&x); } +inline const z_loaned_reply_err_t* z_loan(const z_owned_reply_err_t& x) { return z_reply_err_loan(&x); } +inline const z_loaned_closure_sample_t* z_loan(const z_owned_closure_sample_t& x) { return z_closure_sample_loan(&x); } +inline const z_loaned_closure_reply_t* z_loan(const z_owned_closure_reply_t& x) { return z_closure_reply_loan(&x); } +inline const z_loaned_closure_query_t* z_loan(const z_owned_closure_query_t& x) { return z_closure_query_loan(&x); } +inline const z_loaned_closure_hello_t* z_loan(const z_owned_closure_hello_t& x) { return z_closure_hello_loan(&x); } +inline const z_loaned_closure_zid_t* z_loan(const z_owned_closure_zid_t& x) { return z_closure_zid_loan(&x); } +inline const z_loaned_fifo_handler_query_t* z_loan(const z_owned_fifo_handler_query_t& x) { return z_fifo_handler_query_loan(&x); }; +inline const z_loaned_fifo_handler_reply_t* z_loan(const z_owned_fifo_handler_reply_t& x) { return z_fifo_handler_reply_loan(&x); }; +inline const z_loaned_fifo_handler_sample_t* z_loan(const z_owned_fifo_handler_sample_t& x) { return z_fifo_handler_sample_loan(&x); }; +inline const z_loaned_ring_handler_query_t* z_loan(const z_owned_ring_handler_query_t& x) { return z_ring_handler_query_loan(&x); }; +inline const z_loaned_ring_handler_reply_t* z_loan(const z_owned_ring_handler_reply_t& x) { return z_ring_handler_reply_loan(&x); }; +inline const z_loaned_ring_handler_sample_t* z_loan(const z_owned_ring_handler_sample_t& x) { return z_ring_handler_sample_loan(&x); }; + +// z_loan_mut definition +inline z_loaned_keyexpr_t* z_loan_mut(z_owned_keyexpr_t& x) { return z_keyexpr_loan_mut(&x); } +inline z_loaned_keyexpr_t* z_loan_mut(z_view_keyexpr_t& x) { return z_view_keyexpr_loan_mut(&x); } +inline z_loaned_config_t* z_loan_mut(z_owned_config_t& x) { return z_config_loan_mut(&x); } +inline z_loaned_session_t* z_loan_mut(z_owned_session_t& x) { return z_session_loan_mut(&x); } +inline z_loaned_publisher_t* z_loan_mut(z_owned_publisher_t& x) { return z_publisher_loan_mut(&x); } +inline z_loaned_queryable_t* z_loan_mut(z_owned_queryable_t& x) { return z_queryable_loan_mut(&x); } +inline z_loaned_reply_t* z_loan_mut(z_owned_reply_t& x) { return z_reply_loan_mut(&x); } +inline z_loaned_hello_t* z_loan_mut(z_owned_hello_t& x) { return z_hello_loan_mut(&x); } +inline z_loaned_string_t* z_loan_mut(z_owned_string_t& x) { return z_string_loan_mut(&x); } +inline z_loaned_string_t* z_loan_mut(z_view_string_t& x) { return z_view_string_loan_mut(&x); } +inline z_loaned_string_array_t* z_loan_mut(z_owned_string_array_t& x) { return z_string_array_loan_mut(&x); } +inline z_loaned_sample_t* z_loan_mut(z_owned_sample_t& x) { return z_sample_loan_mut(&x); } +inline z_loaned_query_t* z_loan_mut(z_owned_query_t& x) { return z_query_loan_mut(&x); } +inline z_loaned_slice_t* z_loan_mut(z_owned_slice_t& x) { return z_slice_loan_mut(&x); } +inline z_loaned_bytes_t* z_loan_mut(z_owned_bytes_t& x) { return z_bytes_loan_mut(&x); } +inline z_loaned_encoding_t* z_loan_mut(z_owned_encoding_t& x) { return z_encoding_loan_mut(&x); } +inline z_loaned_task_t* z_loan_mut(z_owned_task_t& x) { return z_task_loan_mut(&x); } +inline z_loaned_mutex_t* z_loan_mut(z_owned_mutex_t& x) { return z_mutex_loan_mut(&x); } +inline z_loaned_condvar_t* z_loan_mut(z_owned_condvar_t& x) { return z_condvar_loan_mut(&x); } +inline z_loaned_reply_err_t* z_loan_mut(z_owned_reply_err_t& x) { return z_reply_err_loan_mut(&x); } + +// z_drop definition +inline int8_t z_drop(z_moved_session_t* v) { return z_close(v); } +inline int8_t z_drop(z_moved_publisher_t* v) { return z_undeclare_publisher(v); } +inline void z_drop(z_moved_keyexpr_t* v) { z_keyexpr_drop(v); } +inline void z_drop(z_moved_config_t* v) { z_config_drop(v); } +inline int8_t z_drop(z_moved_subscriber_t* v) { return z_undeclare_subscriber(v); } +inline int8_t z_drop(z_moved_queryable_t* v) { return z_undeclare_queryable(v); } +inline void z_drop(z_moved_reply_t* v) { z_reply_drop(v); } +inline void z_drop(z_moved_hello_t* v) { z_hello_drop(v); } +inline void z_drop(z_moved_string_t* v) { z_string_drop(v); } +inline void z_drop(z_moved_slice_t* v) { z_slice_drop(v); } +inline void z_drop(z_moved_string_array_t* v) { z_string_array_drop(v); } +inline void z_drop(z_moved_sample_t* v) { z_sample_drop(v); } +inline void z_drop(z_moved_query_t* v) { z_query_drop(v); } +inline void z_drop(z_moved_bytes_t* v) { z_bytes_drop(v); } +inline void z_drop(z_moved_encoding_t* v) { z_encoding_drop(v); } +inline void z_drop(z_moved_mutex_t* v) { z_mutex_drop(v); } +inline void z_drop(z_moved_condvar_t* v) { z_condvar_drop(v); } +inline void z_drop(z_moved_reply_err_t* v) { z_reply_err_drop(v); } +inline void z_drop(z_moved_closure_sample_t* v) { z_closure_sample_drop(v); } +inline void z_drop(z_moved_closure_query_t* v) { z_closure_query_drop(v); } +inline void z_drop(z_moved_closure_reply_t* v) { z_closure_reply_drop(v); } +inline void z_drop(z_moved_closure_hello_t* v) { z_closure_hello_drop(v); } +inline void z_drop(z_moved_closure_zid_t* v) { z_closure_zid_drop(v); } +inline void z_drop(z_moved_ring_handler_sample_t* v) { z_ring_handler_sample_drop(v); } +inline void z_drop(z_moved_fifo_handler_sample_t* v) { z_fifo_handler_sample_drop(v); } +inline void z_drop(z_moved_ring_handler_query_t* v) { z_ring_handler_query_drop(v); } +inline void z_drop(z_moved_fifo_handler_query_t* v) { z_fifo_handler_query_drop(v); } +inline void z_drop(z_moved_ring_handler_reply_t* v) { z_ring_handler_reply_drop(v); } +inline void z_drop(z_moved_fifo_handler_reply_t* v) { z_fifo_handler_reply_drop(v); } + +// z_internal_null definition +inline void z_internal_null(z_owned_session_t* v) { z_internal_session_null(v); } +inline void z_internal_null(z_owned_publisher_t* v) { z_internal_publisher_null(v); } +inline void z_internal_null(z_owned_keyexpr_t* v) { z_internal_keyexpr_null(v); } +inline void z_internal_null(z_owned_config_t* v) { z_internal_config_null(v); } +inline void z_internal_null(z_owned_subscriber_t* v) { z_internal_subscriber_null(v); } +inline void z_internal_null(z_owned_queryable_t* v) { z_internal_queryable_null(v); } +inline void z_internal_null(z_owned_query_t* v) { z_internal_query_null(v); } +inline void z_internal_null(z_owned_sample_t* v) { z_internal_sample_null(v); } +inline void z_internal_null(z_owned_reply_t* v) { z_internal_reply_null(v); } +inline void z_internal_null(z_owned_hello_t* v) { z_internal_hello_null(v); } +inline void z_internal_null(z_owned_string_t* v) { z_internal_string_null(v); } +inline void z_internal_null(z_owned_bytes_t* v) { z_internal_bytes_null(v); } +inline void z_internal_null(z_owned_encoding_t* v) { z_internal_encoding_null(v); } +inline void z_internal_null(z_owned_reply_err_t* v) { z_internal_reply_err_null(v); } +inline void z_internal_null(z_owned_closure_sample_t* v) { z_internal_closure_sample_null(v); } +inline void z_internal_null(z_owned_closure_query_t* v) { z_internal_closure_query_null(v); } +inline void z_internal_null(z_owned_closure_reply_t* v) { z_internal_closure_reply_null(v); } +inline void z_internal_null(z_owned_closure_hello_t* v) { z_internal_closure_hello_null(v); } +inline void z_internal_null(z_owned_closure_zid_t* v) { z_internal_closure_zid_null(v); } +inline void z_internal_null(z_owned_ring_handler_query_t* v) { return z_internal_ring_handler_query_null(v); }; +inline void z_internal_null(z_owned_ring_handler_reply_t* v) { return z_internal_ring_handler_reply_null(v); }; +inline void z_internal_null(z_owned_ring_handler_sample_t* v) { return z_internal_ring_handler_sample_null(v); }; +inline void z_internal_null(z_owned_fifo_handler_query_t* v) { return z_internal_fifo_handler_query_null(v); }; +inline void z_internal_null(z_owned_fifo_handler_reply_t* v) { return z_internal_fifo_handler_reply_null(v); }; +inline void z_internal_null(z_owned_fifo_handler_sample_t* v) { return z_internal_fifo_handler_sample_null(v); }; + +// z_internal_check definition +inline bool z_internal_check(const z_owned_session_t& v) { return z_internal_session_check(&v); } +inline bool z_internal_check(const z_owned_publisher_t& v) { return z_internal_publisher_check(&v); } +inline bool z_internal_check(const z_owned_keyexpr_t& v) { return z_internal_keyexpr_check(&v); } +inline bool z_internal_check(const z_owned_config_t& v) { return z_internal_config_check(&v); } +inline bool z_internal_check(const z_owned_subscriber_t& v) { return z_internal_subscriber_check(&v); } +inline bool z_internal_check(const z_owned_queryable_t& v) { return z_internal_queryable_check(&v); } +inline bool z_internal_check(const z_owned_reply_t& v) { return z_internal_reply_check(&v); } +inline bool z_internal_check(const z_owned_query_t& v) { return z_internal_query_check(&v); } +inline bool z_internal_check(const z_owned_hello_t& v) { return z_internal_hello_check(&v); } +inline bool z_internal_check(const z_owned_string_t& v) { return z_internal_string_check(&v); } +inline bool z_internal_check(const z_owned_sample_t& v) { return z_internal_sample_check(&v); } +inline bool z_internal_check(const z_owned_bytes_t& v) { return z_internal_bytes_check(&v); } +inline bool z_internal_check(const z_owned_encoding_t& v) { return z_internal_encoding_check(&v); } +inline bool z_internal_check(const z_owned_reply_err_t& v) { return z_internal_reply_err_check(&v); } +inline bool z_internal_check(const z_owned_fifo_handler_query_t& v) { return z_internal_fifo_handler_query_check(&v); }; +inline bool z_internal_check(const z_owned_fifo_handler_reply_t& v) { return z_internal_fifo_handler_reply_check(&v); }; +inline bool z_internal_check(const z_owned_fifo_handler_sample_t& v) { return z_internal_fifo_handler_sample_check(&v); }; +inline bool z_internal_check(const z_owned_ring_handler_query_t& v) { return z_internal_ring_handler_query_check(&v); }; +inline bool z_internal_check(const z_owned_ring_handler_reply_t& v) { return z_internal_ring_handler_reply_check(&v); }; +inline bool z_internal_check(const z_owned_ring_handler_sample_t& v) { return z_internal_ring_handler_sample_check(&v); }; + +// z_call definition +inline void z_call(const z_loaned_closure_sample_t &closure, const z_loaned_sample_t *sample) { z_closure_sample_call(&closure, sample); } -inline void z_call(const z_owned_closure_query_t &closure, const z_query_t *query) +inline void z_call(const z_loaned_closure_query_t &closure, const z_loaned_query_t *query) { z_closure_query_call(&closure, query); } -inline void z_call(const z_owned_closure_reply_t &closure, z_owned_reply_t *sample) - { z_closure_reply_call(&closure, sample); } -inline void z_call(const z_owned_closure_hello_t &closure, z_owned_hello_t *hello) +inline void z_call(const z_loaned_closure_reply_t &closure, const z_loaned_reply_t *reply) + { z_closure_reply_call(&closure, reply); } +inline void z_call(const z_loaned_closure_hello_t &closure, const z_loaned_hello_t *hello) { z_closure_hello_call(&closure, hello); } -inline void z_call(const z_owned_closure_zid_t &closure, const z_id_t *zid) +inline void z_call(const z_loaned_closure_zid_t &closure, const z_id_t *zid) { z_closure_zid_call(&closure, zid); } + +inline void z_closure( + z_owned_closure_hello_t* closure, + void (*call)(const z_loaned_hello_t*, void*), + void (*drop)(void*) = NULL, + void *context = NULL) { + closure->_val.context = context; + closure->_val.drop = drop; + closure->_val.call = call; +}; +inline void z_closure( + z_owned_closure_query_t* closure, + void (*call)(const z_loaned_query_t*, void*), + void (*drop)(void*) = NULL, + void *context = NULL) { + closure->_val.context = context; + closure->_val.drop = drop; + closure->_val.call = call; +}; +inline void z_closure( + z_owned_closure_reply_t* closure, + void (*call)(const z_loaned_reply_t*, void*), + void (*drop)(void*) = NULL, + void *context = NULL) { + closure->_val.context = context; + closure->_val.drop = drop; + closure->_val.call = call; +}; +inline void z_closure( + z_owned_closure_sample_t* closure, + void (*call)(const z_loaned_sample_t*, void*), + void (*drop)(void*) = NULL, + void *context = NULL) { + closure->_val.context = context; + closure->_val.drop = drop; + closure->_val.call = call; +}; +inline void z_closure( + z_owned_closure_zid_t* closure, + void (*call)(const z_id_t*, void*), + void (*drop)(void*) = NULL, + void *context = NULL) { + closure->_val.context = context; + closure->_val.drop = drop; + closure->_val.call = call; +}; + +inline z_result_t z_try_recv(const z_loaned_fifo_handler_query_t* this_, z_owned_query_t* query) { + return z_fifo_handler_query_try_recv(this_, query); +}; +inline z_result_t z_try_recv(const z_loaned_fifo_handler_reply_t* this_, z_owned_reply_t* reply) { + return z_fifo_handler_reply_try_recv(this_, reply); +}; +inline z_result_t z_try_recv(const z_loaned_fifo_handler_sample_t* this_, z_owned_sample_t* sample) { + return z_fifo_handler_sample_try_recv(this_, sample); +}; +inline z_result_t z_try_recv(const z_loaned_ring_handler_query_t* this_, z_owned_query_t* query) { + return z_ring_handler_query_try_recv(this_, query); +}; +inline z_result_t z_try_recv(const z_loaned_ring_handler_reply_t* this_, z_owned_reply_t* reply) { + return z_ring_handler_reply_try_recv(this_, reply); +}; +inline z_result_t z_try_recv(const z_loaned_ring_handler_sample_t* this_, z_owned_sample_t* sample) { + return z_ring_handler_sample_try_recv(this_, sample); +}; + + +inline z_result_t z_recv(const z_loaned_fifo_handler_query_t* this_, z_owned_query_t* query) { + return z_fifo_handler_query_recv(this_, query); +}; +inline z_result_t z_recv(const z_loaned_fifo_handler_reply_t* this_, z_owned_reply_t* reply) { + return z_fifo_handler_reply_recv(this_, reply); +}; +inline z_result_t z_recv(const z_loaned_fifo_handler_sample_t* this_, z_owned_sample_t* sample) { + return z_fifo_handler_sample_recv(this_, sample); +}; +inline z_result_t z_recv(const z_loaned_ring_handler_query_t* this_, z_owned_query_t* query) { + return z_ring_handler_query_recv(this_, query); +}; +inline z_result_t z_recv(const z_loaned_ring_handler_reply_t* this_, z_owned_reply_t* reply) { + return z_ring_handler_reply_recv(this_, reply); +}; +inline z_result_t z_recv(const z_loaned_ring_handler_sample_t* this_, z_owned_sample_t* sample) { + return z_ring_handler_sample_recv(this_, sample); +}; + // clang-format on -#define _z_closure_overloader(callback, dropper, ctx, ...) \ - { .context = const_cast(static_cast(ctx)), .call = callback, .drop = dropper } -#define z_closure(...) _z_closure_overloader(__VA_ARGS__, NULL, NULL) -#define z_move(x) (&x) +inline z_moved_bytes_t* z_move(z_owned_bytes_t& x) { return z_bytes_move(&x); }; +inline z_moved_closure_hello_t* z_move(z_owned_closure_hello_t& closure) { return z_closure_hello_move(&closure); }; +inline z_moved_closure_query_t* z_move(z_owned_closure_query_t& closure) { return z_closure_query_move(&closure); }; +inline z_moved_closure_reply_t* z_move(z_owned_closure_reply_t& closure) { return z_closure_reply_move(&closure); }; +inline z_moved_closure_sample_t* z_move(z_owned_closure_sample_t& closure) { return z_closure_sample_move(&closure); }; +inline z_moved_closure_zid_t* z_move(z_owned_closure_zid_t& closure) { return z_closure_zid_move(&closure); }; +inline z_moved_config_t* z_move(z_owned_config_t& x) { return z_config_move(&x); }; +inline z_moved_encoding_t* z_move(z_owned_encoding_t& x) { return z_encoding_move(&x); }; +inline z_moved_reply_err_t* z_move(z_owned_reply_err_t& x) { return z_reply_err_move(&x); }; +inline z_moved_hello_t* z_move(z_owned_hello_t& x) { return z_hello_move(&x); }; +inline z_moved_keyexpr_t* z_move(z_owned_keyexpr_t& x) { return z_keyexpr_move(&x); }; +inline z_moved_publisher_t* z_move(z_owned_publisher_t& x) { return z_publisher_move(&x); }; +inline z_moved_query_t* z_move(z_owned_query_t& x) { return z_query_move(&x); }; +inline z_moved_queryable_t* z_move(z_owned_queryable_t& x) { return z_queryable_move(&x); }; +inline z_moved_reply_t* z_move(z_owned_reply_t& x) { return z_reply_move(&x); }; +inline z_moved_sample_t* z_move(z_owned_sample_t& x) { return z_sample_move(&x); }; +inline z_moved_session_t* z_move(z_owned_session_t& x) { return z_session_move(&x); }; +inline z_moved_slice_t* z_move(z_owned_slice_t& x) { return z_slice_move(&x); }; +inline z_moved_string_array_t* z_move(z_owned_string_array_t& x) { return z_string_array_move(&x); }; +inline z_moved_string_t* z_move(z_owned_string_t& x) { return z_string_move(&x); }; +inline z_moved_subscriber_t* z_move(z_owned_subscriber_t& x) { return z_subscriber_move(&x); }; +inline z_moved_fifo_handler_query_t* z_move(z_owned_fifo_handler_query_t& x) { return z_fifo_handler_query_move(&x); }; +inline z_moved_fifo_handler_reply_t* z_move(z_owned_fifo_handler_reply_t& x) { return z_fifo_handler_reply_move(&x); }; +inline z_moved_fifo_handler_sample_t* z_move(z_owned_fifo_handler_sample_t& x) { + return z_fifo_handler_sample_move(&x); +}; +inline z_moved_ring_handler_query_t* z_move(z_owned_ring_handler_query_t& x) { return z_ring_handler_query_move(&x); }; +inline z_moved_ring_handler_reply_t* z_move(z_owned_ring_handler_reply_t& x) { return z_ring_handler_reply_move(&x); }; +inline z_moved_ring_handler_sample_t* z_move(z_owned_ring_handler_sample_t& x) { + return z_ring_handler_sample_move(&x); +}; + +// z_take definition +inline void z_take(z_owned_session_t* this_, z_moved_session_t* v) { return z_session_take(this_, v); } +inline void z_take(z_owned_publisher_t* this_, z_moved_publisher_t* v) { return z_publisher_take(this_, v); } +inline void z_take(z_owned_keyexpr_t* this_, z_moved_keyexpr_t* v) { z_keyexpr_take(this_, v); } +inline void z_take(z_owned_config_t* this_, z_moved_config_t* v) { z_config_take(this_, v); } +inline void z_take(z_owned_subscriber_t* this_, z_moved_subscriber_t* v) { return z_subscriber_take(this_, v); } +inline void z_take(z_owned_queryable_t* this_, z_moved_queryable_t* v) { return z_queryable_take(this_, v); } +inline void z_take(z_owned_reply_t* this_, z_moved_reply_t* v) { z_reply_take(this_, v); } +inline void z_take(z_owned_hello_t* this_, z_moved_hello_t* v) { z_hello_take(this_, v); } +inline void z_take(z_owned_string_t* this_, z_moved_string_t* v) { z_string_take(this_, v); } +inline void z_take(z_owned_slice_t* this_, z_moved_slice_t* v) { z_slice_take(this_, v); } +inline void z_take(z_owned_string_array_t* this_, z_moved_string_array_t* v) { z_string_array_take(this_, v); } +inline void z_take(z_owned_sample_t* this_, z_moved_sample_t* v) { z_sample_take(this_, v); } +inline void z_take(z_owned_query_t* this_, z_moved_query_t* v) { z_query_take(this_, v); } +inline void z_take(z_owned_bytes_t* this_, z_moved_bytes_t* v) { z_bytes_take(this_, v); } +inline void z_take(z_owned_encoding_t* this_, z_moved_encoding_t* v) { z_encoding_take(this_, v); } +inline void z_take(z_owned_mutex_t* this_, z_moved_mutex_t* v) { z_mutex_take(this_, v); } +inline void z_take(z_owned_condvar_t* this_, z_moved_condvar_t* v) { z_condvar_take(this_, v); } +inline void z_take(z_owned_reply_err_t* this_, z_moved_reply_err_t* v) { z_reply_err_take(this_, v); } +inline void z_take(z_owned_closure_sample_t* this_, z_moved_closure_sample_t* v) { z_closure_sample_take(this_, v); } +inline void z_take(z_owned_closure_query_t* this_, z_moved_closure_query_t* v) { z_closure_query_take(this_, v); } +inline void z_take(z_owned_closure_reply_t* this_, z_moved_closure_reply_t* v) { z_closure_reply_take(this_, v); } +inline void z_take(z_owned_closure_hello_t* this_, z_moved_closure_hello_t* v) { z_closure_hello_take(this_, v); } +inline void z_take(z_owned_closure_zid_t* this_, z_moved_closure_zid_t* v) { z_closure_zid_take(this_, v); } +inline void z_take(z_owned_ring_handler_sample_t* this_, z_moved_ring_handler_sample_t* v) { + z_ring_handler_sample_take(this_, v); +} +inline void z_take(z_owned_fifo_handler_sample_t* this_, z_moved_fifo_handler_sample_t* v) { + z_fifo_handler_sample_take(this_, v); +} +inline void z_take(z_owned_ring_handler_query_t* this_, z_moved_ring_handler_query_t* v) { + z_ring_handler_query_take(this_, v); +} +inline void z_take(z_owned_fifo_handler_query_t* this_, z_moved_fifo_handler_query_t* v) { + z_fifo_handler_query_take(this_, v); +} +inline void z_take(z_owned_ring_handler_reply_t* this_, z_moved_ring_handler_reply_t* v) { + z_ring_handler_reply_take(this_, v); +} +inline void z_take(z_owned_fifo_handler_reply_t* this_, z_moved_fifo_handler_reply_t* v) { + z_fifo_handler_reply_take(this_, v); +} +template +struct z_loaned_to_owned_type_t {}; +template +struct z_owned_to_loaned_type_t {}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_bytes_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_bytes_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_config_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_config_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_encoding_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_encoding_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_reply_err_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_reply_err_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_hello_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_hello_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_keyexpr_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_keyexpr_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_publisher_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_publisher_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_query_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_query_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_queryable_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_queryable_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_reply_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_reply_t type; +}; +; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_sample_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_sample_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_session_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_session_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_slice_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_slice_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_string_array_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_string_array_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_string_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_string_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_subscriber_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_subscriber_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_closure_sample_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_closure_sample_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_closure_reply_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_closure_reply_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_closure_query_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_closure_query_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_closure_hello_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_closure_hello_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_closure_zid_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_closure_zid_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_fifo_handler_query_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_fifo_handler_query_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_fifo_handler_reply_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_fifo_handler_reply_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_fifo_handler_sample_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_fifo_handler_sample_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_ring_handler_query_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_ring_handler_query_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_ring_handler_reply_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_ring_handler_reply_t type; +}; +template <> +struct z_loaned_to_owned_type_t { + typedef z_owned_ring_handler_sample_t type; +}; +template <> +struct z_owned_to_loaned_type_t { + typedef z_loaned_ring_handler_sample_t type; +}; #endif #endif /* ZENOH_C_STANDARD != 99 */ diff --git a/include/zenoh-pico/api/olv_macros.h b/include/zenoh-pico/api/olv_macros.h new file mode 100644 index 000000000..9f535b304 --- /dev/null +++ b/include/zenoh-pico/api/olv_macros.h @@ -0,0 +1,219 @@ +// +// Copyright (c) 2024 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 INCLUDE_ZENOH_PICO_API_OLV_MACROS_H +#define INCLUDE_ZENOH_PICO_API_OLV_MACROS_H + +// Gets internal value from refcounted type (e.g. z_loaned_session_t, z_query_t) +#define _Z_RC_IN_VAL(arg) ((arg)->_val) + +// Checks if refcounted type is initialized +#define _Z_RC_IS_NULL(arg) ((arg)->_cnt == NULL) + +// Gets internal value from refcounted owned type (e.g. z_owned_session_t, z_owned_query_t) +#define _Z_OWNED_RC_IN_VAL(arg) ((arg)->_rc._val) + +// Owned/Loaned/View type macros +// +// !!! FOR INTERNAL USAGE ONLY !!! + +#define _Z_MOVED_TYPE(name) \ + typedef struct { \ + z_owned_##name##_t _this; \ + } z_moved_##name##_t; + +#define _Z_LOANED_TYPE(type, name) typedef type z_loaned_##name##_t; + +// For value types +#define _Z_OWNED_TYPE_VALUE(type, name) \ + typedef struct { \ + type _val; \ + } z_owned_##name##_t; \ + _Z_LOANED_TYPE(type, name) \ + _Z_MOVED_TYPE(name) + +// For refcounted types +#define _Z_OWNED_TYPE_RC(type, name) \ + typedef struct { \ + type _rc; \ + } z_owned_##name##_t; \ + _Z_LOANED_TYPE(type, name) \ + _Z_MOVED_TYPE(name) + +#define _Z_VIEW_TYPE(type, name) \ + typedef struct { \ + type _val; \ + } z_view_##name##_t; + +#define _Z_OWNED_FUNCTIONS_DEF(name) \ + void z_internal_##name##_null(z_owned_##name##_t *obj); \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *obj); \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj); \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj); \ + z_moved_##name##_t *z_##name##_move(z_owned_##name##_t *obj); \ + void z_##name##_take(z_owned_##name##_t *obj, z_moved_##name##_t *src); \ + int8_t z_##name##_clone(z_owned_##name##_t *obj, const z_loaned_##name##_t *src); \ + void z_##name##_drop(z_moved_##name##_t *obj); + +#define _Z_OWNED_FUNCTIONS_NO_COPY_DEF(name) \ + void z_internal_##name##_null(z_owned_##name##_t *obj); \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *obj); \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj); \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj); \ + z_moved_##name##_t *z_##name##_move(z_owned_##name##_t *obj); \ + void z_##name##_take(z_owned_##name##_t *obj, z_moved_##name##_t *src); \ + void z_##name##_drop(z_moved_##name##_t *obj); + +#define _Z_OWNED_FUNCTIONS_SYSTEM_DEF(name) \ + void z_internal_##name##_null(z_owned_##name##_t *obj); \ + void z_##name##_take(z_owned_##name##_t *obj, z_moved_##name##_t *src); \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj); \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj); \ + z_moved_##name##_t *z_##name##_move(z_owned_##name##_t *obj); + +#define _Z_VIEW_FUNCTIONS_DEF(name) \ + _Bool z_view_##name##_is_empty(const z_view_##name##_t *obj); \ + const z_loaned_##name##_t *z_view_##name##_loan(const z_view_##name##_t *name); \ + z_loaned_##name##_t *z_view_##name##_loan_mut(z_view_##name##_t *name); \ + void _z_view_##name##_empty(z_view_##name##_t *name); + +#define _Z_OWNED_FUNCTIONS_IMPL_MOVE_TAKE(name) \ + z_moved_##name##_t *z_##name##_move(z_owned_##name##_t *obj) { return (z_moved_##name##_t *)(obj); } \ + void z_##name##_take(z_owned_##name##_t *obj, z_moved_##name##_t *src) { \ + *obj = src->_this; \ + z_internal_##name##_null(&src->_this); \ + } + +#define _Z_OWNED_FUNCTIONS_PTR_IMPL(type, name, f_copy, f_free) \ + _Z_OWNED_FUNCTIONS_IMPL_MOVE_TAKE(name) \ + void z_internal_##name##_null(z_owned_##name##_t *obj) { obj->_val = NULL; } \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *obj) { return obj->_val != NULL; } \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj) { return obj->_val; } \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj) { return obj->_val; } \ + int8_t z_##name##_clone(z_owned_##name##_t *obj, const z_loaned_##name##_t *src) { \ + int8_t ret = _Z_RES_OK; \ + obj->_val = (type *)z_malloc(sizeof(type)); \ + if (obj->_val != NULL) { \ + f_copy(obj->_val, src); \ + } else { \ + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; \ + } \ + return ret; \ + } \ + void z_##name##_drop(z_moved_##name##_t *obj) { \ + if ((obj != NULL) && (obj->_this._val != NULL)) { \ + f_free(obj->_this._val); \ + } \ + } + +#define _Z_OWNED_FUNCTIONS_VALUE_IMPL(type, name, f_check, f_null, f_copy, f_drop) \ + _Z_OWNED_FUNCTIONS_IMPL_MOVE_TAKE(name) \ + void z_internal_##name##_null(z_owned_##name##_t *obj) { obj->_val = f_null(); } \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *obj) { return f_check((&obj->_val)); } \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj) { return &obj->_val; } \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj) { return &obj->_val; } \ + int8_t z_##name##_clone(z_owned_##name##_t *obj, const z_loaned_##name##_t *src) { \ + return f_copy((&obj->_val), src); \ + } \ + void z_##name##_drop(z_moved_##name##_t *obj) { \ + if (obj != NULL) f_drop((&obj->_this._val)); \ + } + +#define _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL_INNER(type, name, f_check, f_null, f_drop, attribute) \ + attribute void z_internal_##name##_null(z_owned_##name##_t *obj) { obj->_val = f_null(); } \ + attribute _Bool z_internal_##name##_check(const z_owned_##name##_t *obj) { return f_check((&obj->_val)); } \ + attribute const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj) { return &obj->_val; } \ + attribute z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj) { return &obj->_val; } \ + attribute z_moved_##name##_t *z_##name##_move(z_owned_##name##_t *obj) { return (z_moved_##name##_t *)(obj); } \ + attribute void z_##name##_take(z_owned_##name##_t *obj, z_moved_##name##_t *src) { \ + *obj = src->_this; \ + z_internal_##name##_null(&src->_this); \ + } \ + attribute void z_##name##_drop(z_moved_##name##_t *obj) { \ + if (obj != NULL) f_drop((&obj->_this._val)); \ + } + +#define _ZP_NOTHING + +#define _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(type, name, f_check, f_null, f_drop) \ + _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL_INNER(type, name, f_check, f_null, f_drop, _ZP_NOTHING) + +#define _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_INLINE_IMPL(type, name, f_check, f_null, f_drop) \ + _Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL_INNER(type, name, f_check, f_null, f_drop, static inline) + +#define _Z_OWNED_FUNCTIONS_RC_IMPL(name) \ + _Z_OWNED_FUNCTIONS_IMPL_MOVE_TAKE(name) \ + void z_internal_##name##_null(z_owned_##name##_t *val) { val->_rc = _z_##name##_rc_null(); } \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *val) { return !_Z_RC_IS_NULL(&val->_rc); } \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *val) { return &val->_rc; } \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *val) { return &val->_rc; } \ + int8_t z_##name##_clone(z_owned_##name##_t *obj, const z_loaned_##name##_t *src) { \ + int8_t ret = _Z_RES_OK; \ + obj->_rc = _z_##name##_rc_clone((z_loaned_##name##_t *)src); \ + if (_Z_RC_IS_NULL(&obj->_rc)) { \ + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; \ + } \ + return ret; \ + } \ + void z_##name##_drop(z_moved_##name##_t *obj) { \ + if (!_Z_RC_IS_NULL(&obj->_this._rc)) { \ + _z_##name##_rc_drop(&obj->_this._rc); \ + } \ + } + +#define _Z_OWNED_FUNCTIONS_SYSTEM_IMPL(type, name) \ + _Z_OWNED_FUNCTIONS_IMPL_MOVE_TAKE(name) \ + void z_internal_##name##_null(z_owned_##name##_t *obj) { (void)obj; } \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *obj) { return &obj->_val; } \ + z_loaned_##name##_t *z_##name##_loan_mut(z_owned_##name##_t *obj) { return &obj->_val; } + +#define _Z_VIEW_FUNCTIONS_IMPL(type, name, f_check, f_null) \ + _Bool z_view_##name##_is_empty(const z_view_##name##_t *obj) { return !f_check((&obj->_val)); } \ + const z_loaned_##name##_t *z_view_##name##_loan(const z_view_##name##_t *obj) { return &obj->_val; } \ + z_loaned_##name##_t *z_view_##name##_loan_mut(z_view_##name##_t *obj) { return &obj->_val; } \ + void z_view_##name##_empty(z_view_##name##_t *obj) { obj->_val = f_null(); } + +#define _Z_OWNED_FUNCTIONS_CLOSURE_DEF(name) \ + void z_internal_##name##_null(z_owned_##name##_t *name); \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *val); \ + z_moved_##name##_t *z_##name##_move(z_owned_##name##_t *val); \ + void z_##name##_take(z_owned_##name##_t *obj, z_moved_##name##_t *src); \ + void z_##name##_drop(z_moved_##name##_t *obj); \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *val); + +#define _Z_OWNED_FUNCTIONS_CLOSURE_IMPL(name, f_call, f_drop) \ + _Z_OWNED_FUNCTIONS_IMPL_MOVE_TAKE(name) \ + void z_internal_##name##_null(z_owned_##name##_t *val) { \ + val->_val.call = NULL; \ + val->_val.drop = NULL; \ + val->_val.context = NULL; \ + } \ + _Bool z_internal_##name##_check(const z_owned_##name##_t *val) { return val->_val.call != NULL; } \ + void z_##name##_drop(z_moved_##name##_t *obj) { \ + if (obj->_this._val.drop != NULL) { \ + (obj->_this._val.drop)(obj->_this._val.context); \ + obj->_this._val.drop = NULL; \ + } \ + obj->_this._val.call = NULL; \ + obj->_this._val.context = NULL; \ + } \ + const z_loaned_##name##_t *z_##name##_loan(const z_owned_##name##_t *val) { return &val->_val; } \ + int8_t z_##name(z_owned_##name##_t *closure, f_call call, f_drop drop, void *context) { \ + closure->_val.call = call; \ + closure->_val.drop = drop; \ + closure->_val.context = context; \ + \ + return _Z_RES_OK; \ + } + +#endif /* INCLUDE_ZENOH_PICO_API_OLV_MACROS_H */ diff --git a/include/zenoh-pico/api/primitives.h b/include/zenoh-pico/api/primitives.h index 6706a1c20..4d5cbeb3f 100644 --- a/include/zenoh-pico/api/primitives.h +++ b/include/zenoh-pico/api/primitives.h @@ -18,6 +18,7 @@ #include #include +#include "olv_macros.h" #include "zenoh-pico/api/types.h" #include "zenoh-pico/net/query.h" #include "zenoh-pico/net/session.h" @@ -31,1038 +32,1880 @@ extern "C" { #endif -/********* Data Types Handlers *********/ -#define z_bytes_wrap _z_bytes_wrap +/** + * Builds a :c:type:`z_view_string_t` by wrapping a ``const char *`` string. + * + * Parameters: + * value: Pointer to a null terminated string. + * str: Pointer to an uninitialized :c:type:`z_view_string_t`. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_view_string_from_str(z_view_string_t *str, const char *value); + +/** + * Builds a :c:type:`z_keyexpr_t` from a null-terminated string. + * It is a loaned key expression that aliases ``name``. + * This function will fail if the string is not in canon form. + * + * Parameters: + * name: Pointer to string representation of the keyexpr as a null terminated string. + * keyexpr: Pointer to an uninitialized :c:type:`z_view_keyexpr_t`. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_view_keyexpr_from_str(z_view_keyexpr_t *keyexpr, const char *name); + +/** + * Builds a :c:type:`z_keyexpr_t` from a null-terminated string. + * It is a loaned key expression that aliases ``name``. + * Input key expression is not checked for correctness. + * + * Parameters: + * name: Pointer to string representation of the keyexpr as a null terminated string. + * keyexpr: Pointer to an uninitialized :c:type:`z_view_keyexpr_t`. + */ +void z_view_keyexpr_from_str_unchecked(z_view_keyexpr_t *keyexpr, const char *name); + +/** + * Builds a :c:type:`z_view_keyexpr_t` from a null-terminated string with auto canonization. + * It is a loaned key expression that aliases ``name``. + * The string is canonized in-place before being passed to keyexpr, possibly shortening it by modifying len. + * May SEGFAULT if `name` is NULL or lies in read-only memory (as values initialized with string literals do). + * `name` must outlive the constructed key expression. + * + * Parameters: + * name: Pointer to string representation of the keyexpr as a null terminated string. + * keyexpr: Pointer to an uninitialized :c:type:`z_view_keyexpr_t`. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_view_keyexpr_from_str_autocanonize(z_view_keyexpr_t *keyexpr, char *name); + +/** + * Builds a :c:type:`z_keyexpr_t` by aliasing a substring. + * It is a loaned key expression that aliases ``name``. + * This function will fail if the string is not in canon form. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_view_keyexpr_t`. + * name: Pointer to string representation of the keyexpr. + * len: Size of the string. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +z_result_t z_view_keyexpr_from_substr(z_view_keyexpr_t *keyexpr, const char *name, size_t len); + +/** + * Builds a :c:type:`z_view_keyexpr_t` from a substring with auto canonization. + * It is a loaned key expression that aliases ``name``. + * The string is canonized in-place before being passed to keyexpr, possibly shortening it by modifying len. + * May SEGFAULT if `name` is NULL or lies in read-only memory (as values initialized with string literals do). + * `name` must outlive the constructed key expression. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_view_keyexpr_t`. + * name: Pointer to string representation of the keyexpr. + * len: Pointer to the size of the string. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +z_result_t z_view_keyexpr_from_substr_autocanonize(z_view_keyexpr_t *keyexpr, char *name, size_t *len); + +/** + * Builds a :c:type:`z_keyexpr_t` from a substring. + * It is a loaned key expression that aliases ``name``. + * Input key expression is not checked for correctness. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_view_keyexpr_t`. + * name: Pointer to string representation of the keyexpr. + * len: Size of the string. + */ +void z_view_keyexpr_from_substr_unchecked(z_view_keyexpr_t *keyexpr, const char *name, size_t len); + +/** + * Gets a null-terminated string view from a :c:type:`z_keyexpr_t`. + * + * Parameters: + * keyexpr: Pointer to a loaned instance of :c:type:`z_keyexpr_t`. + * str: Pointer to an uninitialized :c:type:`z_view_string_t`. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_keyexpr_as_view_string(const z_loaned_keyexpr_t *keyexpr, z_view_string_t *str); + +/** + * Constructs key expression by concatenation of key expression in `left` with a string in `right`. + * Returns 0 in case of success, negative error code otherwise. + * + * To avoid odd behaviors, concatenating a key expression starting with `*` to one ending with `*` is forbidden by this + * operation, as this would extremely likely cause bugs. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t` to store the keyexpr. + * left: Pointer to :c:type:`z_loaned_keyexpr_t` to keyexpr to concatenate to. + * right: Pointer to the start of the substring that will be concatenated. + * len: Length of the substring to concatenate. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_keyexpr_concat(z_owned_keyexpr_t *key, const z_loaned_keyexpr_t *left, const char *right, size_t len); + +/** + * Constructs key expression by performing path-joining (automatically inserting '/'). The resulting key expression is + * automatically canonized. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t` to store the keyexpr. + * left: Pointer to :c:type:`z_loaned_keyexpr_t` to the left part of resulting key expression. + * right: Pointer to :c:type:`z_loaned_keyexpr_t` to the right part of resulting key expression. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_keyexpr_join(z_owned_keyexpr_t *key, const z_loaned_keyexpr_t *left, const z_loaned_keyexpr_t *right); + +/** + * Returns the relation between `left` and `right` from `left`'s point of view. + * + * Note that this is slower than `z_keyexpr_intersects` and `keyexpr_includes`, so you should favor these methods for + * most applications. + * + * Parameters: + * left: Pointer to :c:type:`z_loaned_keyexpr_t` representing left key expression. + * right: Pointer to :c:type:`z_loaned_keyexpr_t` representing right key expression. + * + * Return: + * Relation between `left` and `right` from `left`'s point of view. + */ +z_keyexpr_intersection_level_t z_keyexpr_relation_to(const z_loaned_keyexpr_t *left, const z_loaned_keyexpr_t *right); + +/** + * Checks if a given keyexpr is valid and in canonical form. + * + * Parameters: + * start: Pointer to the keyexpr in its string representation as a non-null terminated string. + * len: Number of characters in ``start``. + * + * Return: + * ``0`` if passed string is a valid (and canon) key expression, or a ``negative value`` otherwise. + * Error codes are defined in :c:enum:`zp_keyexpr_canon_status_t`. + */ +int8_t z_keyexpr_is_canon(const char *start, size_t len); + +/** + * Canonizes of a given keyexpr in string representation. + * The canonization is performed over the passed string, possibly shortening it by modifying ``len``. + * + * Parameters: + * start: Pointer to the keyexpr in its string representation as a non-null terminated string. + * len: Number of characters in ``start``. + * + * Return: + * ``0`` if canonization successful, or a ``negative value`` otherwise. + * Error codes are defined in :c:enum:`zp_keyexpr_canon_status_t`. + */ +int8_t z_keyexpr_canonize(char *start, size_t *len); + +/** + * Checks if a given keyexpr contains another keyexpr in its set. + * + * Parameters: + * l: Pointer to a :c:type:`z_loaned_keyexpr_t`. + * r: Pointer to a :c:type:`z_loaned_keyexpr_t`. + * + * Return: + * ``true`` if ``l`` includes ``r``, i.e. the set defined by ``l`` contains every key belonging to the set + * defined by ``r``. Otherwise, returns ``false``. + */ +_Bool z_keyexpr_includes(const z_loaned_keyexpr_t *l, const z_loaned_keyexpr_t *r); + +/** + * Checks if a given keyexpr intersects with another keyexpr. + * + * Parameters: + * l: Pointer to a :c:type:`z_loaned_keyexpr_t`. + * r: Pointer to a :c:type:`z_loaned_keyexpr_t`. + * + * Return: + * ``true`` if keyexprs intersect, i.e. there exists at least one key which is contained in both of the + * sets defined by ``l`` and ``r``. Otherwise, returns ``false``. + */ +_Bool z_keyexpr_intersects(const z_loaned_keyexpr_t *l, const z_loaned_keyexpr_t *r); + +/** + * Checks if two keyexpr are equal. + * + * Parameters: + * l: Pointer to a :c:type:`z_loaned_keyexpr_t`. + * r: Pointer to a :c:type:`z_loaned_keyexpr_t`. + * + * Return: + * ``true`` if both ``l`` and ``r`` are equal. Otherwise, returns ``false``. + */ +_Bool z_keyexpr_equals(const z_loaned_keyexpr_t *l, const z_loaned_keyexpr_t *r); + +/** + * Builds a new, zenoh-allocated, empty configuration. + * It consists in an empty set of properties for zenoh session configuration. + * + * Parameters: + * config: Pointer to uninitialized :c:type:`z_owned_config_t`. + */ +void z_config_new(z_owned_config_t *config); + +/** + * Builds a new, zenoh-allocated, default configuration. + * It consists in a default set of properties for zenoh session configuration. + * + * Parameters: + * config: Pointer to uninitialized :c:type:`z_owned_config_t`. + * + * Return: + * `0`` in case of success, or a ``negative value`` otherwise. + */ +int8_t z_config_default(z_owned_config_t *config); + +/** + * Clones a zenoh configuration. + * + * Parameters: + * config: Pointer to uninitialized :c:type:`z_owned_config_t`. + * src: Pointer to the :c:type:`z_loaned_config_t` to clone. + */ +void z_config_clone(z_owned_config_t *config, const z_loaned_config_t *src); + +/** + * Builds a new, zenoh-allocated, client configuration. + * + * Parameters: + * config: Pointer to uninitialized :c:type:`z_owned_config_t`. + * locator: Zenoh router locator string, if null multicast scouting will be performed. + * + * Return: + * `0`` in case of success, or a ``negative value`` otherwise. + */ +int8_t z_config_client(z_owned_config_t *config, const char *locator); +/** + * Builds a new, zenoh-allocated, peer configuration. + * + * Parameters: + * config: Pointer to uninitialized :c:type:`z_owned_config_t`. + * locator: Multicast address for peer-to-peer communication. + * + * Return: + * `0`` in case of success, or a ``negative value`` otherwise. + */ +int8_t z_config_peer(z_owned_config_t *config, const char *locator); + +/** + * Gets the property with the given integer key from the configuration. + * + * Parameters: + * config: Pointer to a :c:type:`z_loaned_config_t` to get the property from. + * key: Integer key of the requested property. + * + * Return: + * The requested property value. + */ +const char *zp_config_get(const z_loaned_config_t *config, uint8_t key); + +/** + * Inserts or replaces the property with the given integer key in the configuration. + * + * Parameters: + * config: Pointer to a :c:type:`z_loaned_config_t` to modify. + * key: Integer key of the property to be inserted. + * value: Property value to be inserted. + * + * Return: + * ``0`` if insertion successful, ``negative value`` otherwise. + */ +int8_t zp_config_insert(z_loaned_config_t *config, uint8_t key, const char *value); + +/** + * Builds a :c:type:`z_owned_encoding_t` from a null terminated string. + * + * Parameters: + * encoding: Pointer to an uninitialized :c:type:`z_owned_encoding_t`. + * s: Pointer to the null terminated string to use. + * + * Return: + * ``0`` if creation successful,``negative value`` otherwise. + */ +int8_t z_encoding_from_str(z_owned_encoding_t *encoding, const char *s); + +/** + * Builds a :c:type:`z_owned_encoding_t` from a null terminated string. + * + * Parameters: + * encoding: Pointer to an uninitialized :c:type:`z_owned_encoding_t`. + * s: Pointer to the string to use. + * len: Number of characters from the string s to use. + * + * Return: + * ``0`` if creation successful,``negative value`` otherwise. + */ +int8_t z_encoding_from_substr(z_owned_encoding_t *encoding, const char *s, size_t len); + +/** + * Sets a schema to this encoding from a null-terminated string. Zenoh does not define what a schema is and its + * semantics is left to the implementer. E.g. a common schema for `text/plain` encoding is `utf-8`. + * + * Parameters: + * encoding: Pointer to initialized :c:type:`z_loaned_encoding_t`. + * schema: Pointer to the null terminated string to use as a schema. + * Return: + * ``0`` in case of success,``negative value`` otherwise. + */ +int8_t z_encoding_set_schema_from_str(z_loaned_encoding_t *encoding, const char *schema); + +/** + * Sets a schema to this encoding from a substring. Zenoh does not define what a schema is and its semantics is left + * to the implementer. E.g. a common schema for `text/plain` encoding is `utf-8`. + * + * Parameters: + * encoding: Pointer to initialized :c:type:`z_loaned_encoding_t`. + * schema: Pointer to the substring start. + * len: Number of characters to consider. + * Return: + * ``0`` if in case of success,``negative value`` otherwise. + */ +int8_t z_encoding_set_schema_from_substr(z_loaned_encoding_t *encoding, const char *schema, size_t len); + +/** + * Builds a string from a :c:type:`z_loaned_encoding_t`. + * + * Parameters: + * encoding: Pointer to the :c:type:`z_loaned_encoding_t` to use. + * string: Pointer to an uninitialized :c:type:`z_owned_string_t` to store the string. + * + * Return: + * ``0`` if creation successful,``negative value`` otherwise. + */ +int8_t z_encoding_to_string(const z_loaned_encoding_t *encoding, z_owned_string_t *string); + +/** + * Gets the bytes data from a reply error payload by aliasing it. + * + * Parameters: + * reply_err: Pointer to a :c:type:`z_loaned_reply_err_t` to get data from. + * + * Return: + * Pointer to the data as a :c:type:`z_loaned_bytes_t`. + */ +const z_loaned_bytes_t *z_reply_err_payload(const z_loaned_reply_err_t *reply_err); + +/** + * Gets a reply error encoding by aliasing it. + * + * Parameters: + * query: Pointer to the :c:type:`z_loaned_reply_err_t` to get the encoding from. + * + * Return: + * Pointer to the encoding as a :c:type:`z_loaned_encoding_t`. + */ +const z_loaned_encoding_t *z_reply_err_encoding(const z_loaned_reply_err_t *reply_err); + +/** + * Builds a :c:type:`z_owned_slice_t` by copying a buffer into it. + * + * Parameters: + * slice: Pointer to an uninitialized :c:type:`z_owned_slice_t`. + * data: Pointer to the data that will be copied into slice. + * len: Number of bytes to copy. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_slice_copy_from_buf(z_owned_slice_t *slice, const uint8_t *data, size_t len); + +/** + * Builds a :c:type:`z_owned_slice_t` by transferring ownership over a data to it. + * + * Parameters: + * slice: Pointer to an uninitialized :c:type:`z_owned_slice_t`. + * data: Pointer to the data to be owned by `slice`. + * len: Number of bytes in `data`. + * deleter: A thread-safe delete function to free the `data`. Will be called once when `slice` is dropped. Can be + * NULL, in case if `data` is allocated in static memory. + * context: An optional context to be passed to the `deleter`. + * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. + */ +int8_t z_slice_from_buf(z_owned_slice_t *slice, uint8_t *data, size_t len, void (*deleter)(void *data, void *context), + void *context); /** - * Constructs a :c:type:`z_string_t` departing from a ``const char *``. - * It is a loaned key expression that aliases ``value``. + * Builds an empty :c:type:`z_owned_slice_t`. + * + * Parameters: + * str: Pointer to an uninitialized :c:type:`z_owned_slice_t`. + */ +void z_slice_empty(z_owned_slice_t *slice); + +/** + * Gets date pointer of a bytes array. + * + * Parameters: + * slice: Pointer to a :c:type:`z_loaned_slice_t` to get data from. + * + * Return: + * The data pointer. + */ +const uint8_t *z_slice_data(const z_loaned_slice_t *slice); + +/** + * Gets total number of bytes in a bytes array. + * + * Parameters: + * slice: Pointer to a :c:type:`z_loaned_slice_t` to get length from. + * + * Return: + * The number of bytes. + */ +size_t z_slice_len(const z_loaned_slice_t *slice); + +/** + * Checks if slice is empty + * + * Parameters: + * str: Pointer to a :c:type:`z_loaned_slice_t` to check. + * Return: + * ``true`` if conainer is empty, ``false`` otherwise. + */ +bool z_slice_is_empty(const z_loaned_slice_t *slice); + +/** + * Decodes data into a `int8_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int8_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_int8(const z_loaned_bytes_t *bytes, int8_t *dst); + +/** + * Decodes data into a `int16_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int16_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_int16(const z_loaned_bytes_t *bytes, int16_t *dst); + +/** + * Decodes data into a `int32_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int32_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_int32(const z_loaned_bytes_t *bytes, int32_t *dst); + +/** + * Decodes data into a `int64_t` signed integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`int64_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_int64(const z_loaned_bytes_t *bytes, int64_t *dst); + +/** + * Decodes data into a `uint8_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint8_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_uint8(const z_loaned_bytes_t *bytes, uint8_t *dst); + +/** + * Decodes data into a `uint16_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint16_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_uint16(const z_loaned_bytes_t *bytes, uint16_t *dst); + +/** + * Decodes data into a `uint32_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint32_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_uint32(const z_loaned_bytes_t *bytes, uint32_t *dst); + +/** + * Decodes data into a `uint64_t` unsigned integer. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`uint64_t` to contain the decoded int. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_uint64(const z_loaned_bytes_t *bytes, uint64_t *dst); + +/** + * Decodes data into a `float` floating number. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`float` to contain the decoded float. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_float(const z_loaned_bytes_t *bytes, float *dst); + +/** + * Decodes data into a `double` floating number. + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * dst: Pointer to an uninitialized :c:type:`double` to contain the decoded float. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_double(const z_loaned_bytes_t *bytes, double *dst); + +/** + * Decodes data into a :c:type:`z_owned_slice_t` + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * str: Pointer to an uninitialized :c:type:`z_owned_slice_t` to contain the decoded slice. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst); + +/** + * Decodes data into a :c:type:`z_owned_string_t` + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * str: Pointer to an uninitialized :c:type:`z_owned_string_t` to contain the decoded string. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_string(const z_loaned_bytes_t *bytes, z_owned_string_t *str); + +/** + * Decodes data into a pair of :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * first: Pointer to an uninitialized :c:type:`z_owned_bytes_t` to contain the first element. + * second: Pointer to an uninitialized :c:type:`z_owned_bytes_t` to contain the second element. + * + * Return: + * ``0`` if decode successful, or a ``negative value`` otherwise. + */ +int8_t z_bytes_deserialize_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int8_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_int8(z_owned_bytes_t *bytes, int8_t val); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int16_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_int16(z_owned_bytes_t *bytes, int16_t val); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int32_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_int32(z_owned_bytes_t *bytes, int32_t val); + +/** + * Encodes a signed integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `int64_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_int64(z_owned_bytes_t *bytes, int64_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint8_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_uint8(z_owned_bytes_t *bytes, uint8_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint16_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_uint16(z_owned_bytes_t *bytes, uint16_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint32_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_uint32(z_owned_bytes_t *bytes, uint32_t val); + +/** + * Encodes an unsigned integer into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `uint64_t` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_uint64(z_owned_bytes_t *bytes, uint64_t val); + +/** + * Encodes a floating number into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `float` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_float(z_owned_bytes_t *bytes, float val); + +/** + * Encodes a floating number into a :c:type:`z_owned_bytes_t` + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded int. + * val: `double` value to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_double(z_owned_bytes_t *bytes, double val); + +/** + * Encodes a slice into a :c:type:`z_owned_bytes_t` by copying. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded slice. + * slice: Pointer to the slice to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_slice(z_owned_bytes_t *bytes, const z_loaned_slice_t *slice); + +/** + * Encodes a slice into a :c:type:`z_owned_bytes_t`. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded slice. + * slice: Pointer to the slice to encode. The slice will be consumed upon function return. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_from_slice(z_owned_bytes_t *bytes, z_moved_slice_t *slice); + +/** + * Encodes data into a :c:type:`z_owned_bytes_t`. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded data. + * data: Pointer to the data to encode. Ownership is transferred to the `bytes`. + * len: Number of bytes to encode. + * deleter: A thread-safe delete function to free the `data`. Will be called once when `bytes` is dropped. Can be + * NULL, in case if `data` is allocated in static memory. + * context: An optional context to be passed to the `deleter`. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_from_buf(z_owned_bytes_t *bytes, uint8_t *data, size_t len, void (*deleter)(void *data, void *context), + void *context); + +/** + * Encodes statically allocated constant data into a :c:type:`z_owned_bytes_t` by aliasing. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded data. + * data: Pointer to the statically allocated constant data to encode. + * len: Number of bytes to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_from_static_buf(z_owned_bytes_t *bytes, const uint8_t *data, size_t len); + +/** + * Encodes data into a :c:type:`z_owned_bytes_t` by copying. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded data. + * data: Pointer to the data to encode. Ownership is transferred to the `bytes`. + * len: Number of bytes to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_buf(z_owned_bytes_t *bytes, const uint8_t *data, size_t len); + +/** + * Encodes a string into a :c:type:`z_owned_bytes_t` by copying. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * s: Pointer to the string to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_serialize_from_string(z_owned_bytes_t *bytes, const z_loaned_string_t *s); + +/** + * Encodes a string into a :c:type:`z_owned_bytes_t`. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * s: Pointer to the string to encode. The string will be consumed upon function return. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_from_string(z_owned_bytes_t *bytes, z_moved_string_t *s); + +/** + * Encodes a null-terminated string into a :c:type:`z_owned_bytes_t`. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * value: Pointer to the string to encode. Ownership is transferred to the `bytes`. + * deleter: A thread-safe delete function to free the `value`. Will be called once when `bytes` is dropped. Can be + * NULL, in case if `value` is allocated in static memory. context: An optional context to be passed to the `deleter`. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_from_str(z_owned_bytes_t *bytes, char *value, void (*deleter)(void *value, void *context), + void *context); + +/** + * Encodes a statically allocated constant null-terminated string into a :c:type:`z_owned_bytes_t` by aliasing. + * + * Parameters: + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * value: Pointer to the statically allocated constant string to encode. + * + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. + */ +int8_t z_bytes_from_static_str(z_owned_bytes_t *bytes, const char *value); +/** + * Encodes a null-terminated string into a :c:type:`z_owned_bytes_t` by copying. * * Parameters: - * value: Pointer to null terminated string. + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded string. + * value: Pointer to the string to encode. Ownership is transferred to the `bytes`. * - * Returns: - * The :c:type:`z_string_t` corresponding to the given string. + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. */ -z_string_t z_string_make(const char *value); +int8_t z_bytes_serialize_from_str(z_owned_bytes_t *bytes, const char *value); /** - * Constructs a :c:type:`z_keyexpr_t` departing from a string. - * It is a loaned key expression that aliases ``name``. - * Unlike it's counterpart in zenoh-c, this function does not test passed expression to correctness. - * + * Constructs payload from an iterator to `z_owned_bytes_t`. * Parameters: - * name: Pointer to string representation of the keyexpr as a null terminated string. + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded payload. + * iterator_body: Iterator body function, providing data items. Returning false is treated as iteration end. + * context: Arbitrary context that will be passed to iterator_body. * - * Returns: - * The :c:type:`z_keyexpr_t` corresponding to the given string. + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. */ -z_keyexpr_t z_keyexpr(const char *name); +int8_t z_bytes_from_iter(z_owned_bytes_t *bytes, _Bool (*iterator_body)(z_owned_bytes_t *data, void *context), + void *context); /** - * Constructs a :c:type:`z_keyexpr_t` departing from a string. - * It is a loaned key expression that aliases ``name``. - * Input key expression is not checked for correctness. + * Append a pair of `z_owned_bytes` objects which are consumed in the process. * * Parameters: - * name: Pointer to string representation of the keyexpr as a null terminated string. + * bytes: An uninitialized :c:type:`z_owned_bytes_t` to contain the encoded pair. + * first: Moved first `z_owned_bytes` to encode. + * second: Moved second `z_owned_bytes` to encode. * - * Returns: - * The :c:type:`z_keyexpr_t` corresponding to the given string. + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. */ -z_keyexpr_t z_keyexpr_unchecked(const char *name); +int8_t z_bytes_from_pair(z_owned_bytes_t *bytes, z_moved_bytes_t *first, z_moved_bytes_t *second); /** - * Get null-terminated string departing from a :c:type:`z_keyexpr_t`. - * - * If given keyexpr contains a declared keyexpr, the resulting owned string will be uninitialized. - * In that case, the user must use :c:func:`zp_keyexpr_resolve` to resolve the nesting declarations - * and get its full expanded representation. + * Parameters: + * bytes: Pointer to an unitialized :c:type:`z_lowned_bytes_t` instance. + */ +void z_bytes_empty(z_owned_bytes_t *bytes); + +/** + * Returns total number of bytes in the container. * * Parameters: - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * Return: + * Number of bytes in the container. + */ +size_t z_bytes_len(const z_loaned_bytes_t *bytes); + +/** + * Checks if container is empty * - * Returns: - * The :c:type:`z_owned_str_t` containing key expression string representation if it's possible + * Parameters: + * bytes: Pointer to a :c:type:`z_loaned_bytes_t` to decode. + * Return: + * ``true`` if conainer is empty, ``false`` otherwise. */ -z_owned_str_t z_keyexpr_to_string(z_keyexpr_t keyexpr); +_Bool z_bytes_is_empty(const z_loaned_bytes_t *bytes); /** - * Returns the key expression's internal string by aliasing it. + * Returns an iterator for multi-element serialized data. * * Parameters: - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` + * bytes: Data to iterate over. * - * Returns: - * The :c:type:`z_bytes_t` pointing to key expression string representation if it's possible + * Return: + * The constructed :c:type:`z_bytes_iterator_t`. */ -z_bytes_t z_keyexpr_as_bytes(z_keyexpr_t keyexpr); +z_bytes_iterator_t z_bytes_get_iterator(const z_loaned_bytes_t *bytes); /** - * Indicates if the key expression has been declared but don't guarantee it's still in session. + * Constructs :c:type:`z_owned_bytes_t` object corresponding to the next element of serialized data. * - * If given keyexpr was declared, to retrieve the keyexpr string representation the user must use - * :c:func:zp_keyexpr_resolve + * Will construct null-state `z_owned_bytes_t` when iterator reaches the end (or in case of error). * * Parameters: - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` - * - * Returns: - * Returns ``true`` if the keyexpr was declared or ``false`` otherwise. + * iter: An iterator over multi-element serialized data. + * out: An uninitialized :c:type:`z_owned_bytes_t` that will contained next serialized element. + * Return: + * ``false`` when iterator reaches the end, ``true`` otherwise. */ -_Bool zp_keyexpr_was_declared(const z_keyexpr_t *keyexpr); +_Bool z_bytes_iterator_next(z_bytes_iterator_t *iter, z_owned_bytes_t *out); /** - * Constructs a null-terminated string departing from a :c:type:`z_keyexpr_t` for a given :c:type:`z_session_t`. - * The user is responsible of dropping the returned string using ``z_free``. + * Returns a reader for the `bytes`. + * + * The `bytes` should outlive the reader and should not be modified, while reader is in use. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` to resolve the keyexpr. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to be resolved. + * bytes: Data to read. * - * Returns: - * The string representation of a keyexpr for a given session. + * Return: + * The constructed :c:type:`z_bytes_reader_t`. */ -z_owned_str_t zp_keyexpr_resolve(z_session_t zs, z_keyexpr_t keyexpr); +z_bytes_reader_t z_bytes_get_reader(const z_loaned_bytes_t *bytes); /** - * Checks if a given keyexpr is valid. + * Reads data into specified destination. * * Parameters: - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to be checked. + * reader: Data reader to read from. + * dst: An uninitialized memory location where a new piece of data will be read. Note that it does not involve a copy, + * but only increases reference count. * - * Returns: - * Returns ``true`` if the keyexpr is valid, or ``false`` otherwise. + * Return: + * ​0​ upon success, negative error code otherwise. */ -_Bool z_keyexpr_is_initialized(const z_keyexpr_t *keyexpr); +int8_t z_bytes_reader_read_bounded(z_bytes_reader_t *reader, z_owned_bytes_t *dst); /** - * Check if a given keyexpr is valid and in its canonical form. + * Reads data into specified destination. * * Parameters: - * start: Pointer to the keyexpr in its string representation as a non-null terminated string. - * len: Number of characters in ``start``. + * reader: Data reader to read from. + * dst: Buffer where the read data is written. + * len: Maximum number of bytes to read. * - * Returns: - * Returns ``0`` if the passed string is a valid (and canon) key expression, or a ``negative value`` otherwise. - * Error codes are defined in :c:enum:`zp_keyexpr_canon_status_t`. + * Return: + * Number of bytes read. If return value is smaller than `len`, it means that the end of the data was reached. */ -int8_t z_keyexpr_is_canon(const char *start, size_t len); +size_t z_bytes_reader_read(z_bytes_reader_t *reader, uint8_t *dst, size_t len); /** - * Check if a given keyexpr is valid and in its canonical form. + * Sets the `reader` position indicator for the payload to the value pointed to by offset. + * The new position is exactly `offset` bytes measured from the beginning of the payload if origin is `SEEK_SET`, + * from the current reader position if origin is `SEEK_CUR`, and from the end of the payload if origin is `SEEK_END`. * * Parameters: - * start: Pointer to the keyexpr in its string representation as a null terminated string. - * len: Number of characters in ``start``. + * reader: Data reader to reposition. + * offset: New position ffset in bytes. + * origin: Origin for the new position. * - * Returns: - * Returns ``0`` if the passed string is a valid (and canon) key expression, or a ``negative value`` otherwise. - * Error codes are defined in :c:enum:`zp_keyexpr_canon_status_t`. + * Return: + * ​0​ upon success, negative error code otherwise. */ -int8_t zp_keyexpr_is_canon_null_terminated(const char *start); - +int8_t z_bytes_reader_seek(z_bytes_reader_t *reader, int64_t offset, int origin); /** - * Canonization of a given keyexpr in its its string representation. - * The canonization is performed over the passed string, possibly shortening it by modifying ``len``. + * Gets the read position indicator. * * Parameters: - * start: Pointer to the keyexpr in its string representation as a non-null terminated string. - * len: Number of characters in ``start``. + * reader: Data reader to get position of. * - * Returns: - * Returns ``0`` if the canonization is successful, or a ``negative value`` otherwise. - * Error codes are defined in :c:enum:`zp_keyexpr_canon_status_t`. + * Return: + * Read position indicator on success or -1L if failure occurs. */ -int8_t z_keyexpr_canonize(char *start, size_t *len); +int64_t z_bytes_reader_tell(z_bytes_reader_t *reader); /** - * Canonization of a given keyexpr in its its string representation. - * The canonization is performed over the passed string, possibly shortening it by modifying ``len``. + * Constructs writer for :c:type:`z_loaned_bytes_t`. * * Parameters: - * start: Pointer to the keyexpr in its string representation as a null terminated string. - * len: Number of characters in ``start``. + * bytes: Data container to write to. + * writer: Uninitialized memory location where writer is to be constructed. * - * Returns: - * Returns ``0`` if the canonization is successful, or a ``negative value`` otherwise. - * Error codes are defined in :c:enum:`zp_keyexpr_canon_status_t`. */ -int8_t zp_keyexpr_canonize_null_terminated(char *start); +z_bytes_writer_t z_bytes_get_writer(z_loaned_bytes_t *bytes); /** - * Check if a given keyexpr contains another keyexpr in its set. + * Writes `len` bytes from `src` into underlying :c:type:`z_loaned_bytes_t. * * Parameters: - * l: The first keyexpr. - * r: The second keyexpr. + * writer: A data writer. + * src: Buffer to write from. + * len: Number of bytes to write. * - * Returns: - * Returns ``0`` if ``l`` includes ``r``, i.e. the set defined by ``l`` contains every key belonging to the set - * defined by ``r``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * Return: + * ``0`` if encode successful, ``negative value`` otherwise. */ -int8_t z_keyexpr_includes(z_keyexpr_t l, z_keyexpr_t r); +int8_t z_bytes_writer_write_all(z_bytes_writer_t *writer, const uint8_t *src, size_t len); /** - * Check if a given keyexpr contains another keyexpr in its set. + * Appends bytes. + * This allows to compose a serialized data out of multiple `z_owned_bytes_t` that may point to different memory + * regions. Said in other terms, it allows to create a linear view on different memory regions without copy. * * Parameters: - * l: Pointer to the keyexpr in its string representation as a null terminated string. - * llen: Number of characters in ``l``. - * r: Pointer to the keyexpr in its string representation as a null terminated string. - * rlen: Number of characters in ``r``. + * writer: A data writer. + * bytes: A data to append. * - * Returns: - * Returns ``0`` if ``l`` includes ``r``, i.e. the set defined by ``l`` contains every key belonging to the set - * defined by ``r``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * Return: + * 0 in case of success, negative error code otherwise */ -int8_t zp_keyexpr_includes_null_terminated(const char *l, const char *r); +int8_t z_bytes_writer_append(z_bytes_writer_t *writer, z_moved_bytes_t *bytes); /** - * Check if a given keyexpr intersects with another keyexpr. + * Appends bytes, with boundaries information. It would allow to read the same piece of data using + * :c:func:`z_bytes_reader_read_bounded`. * * Parameters: - * l: The first keyexpr. - * r: The second keyexpr. + * writer: A data writer. + * bytes: A data to append. * - * Returns: - * Returns ``0`` if the keyexprs intersect, i.e. there exists at least one key which is contained in both of the - * sets defined by ``l`` and ``r``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * Return: + * 0 in case of success, negative error code otherwise */ -int8_t z_keyexpr_intersects(z_keyexpr_t l, z_keyexpr_t r); +int8_t z_bytes_writer_append_bounded(z_bytes_writer_t *writer, z_moved_bytes_t *bytes); /** - * Check if a given keyexpr intersects with another keyexpr. + * Create timestamp. * * Parameters: - * l: Pointer to the keyexpr in its string representation as a null terminated string. - * llen: Number of characters in ``l``. - * r: Pointer to the keyexpr in its string representation as a null terminated string. - * rlen: Number of characters in ``r``. + * ts: An uninitialized :c:type:`z_timestamp_t`. + * zs: Pointer to a :c:type:`z_loaned_session_t` to get the id from. * - * Returns: - * Returns ``0`` if the keyexprs intersect, i.e. there exists at least one key which is contained in both of the - * sets defined by ``l`` and ``r``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * Return: + * ``0`` if encode successful, ``negative value`` otherwise (for example if RTC is not available on the system). + */ +int8_t z_timestamp_new(z_timestamp_t *ts, const z_loaned_session_t *zs); + +/** + * Returns NTP64 time associated with this timestamp. + */ +uint64_t z_timestamp_ntp64_time(const z_timestamp_t *ts); + +/** + * Returns id associated with this timestamp. */ -int8_t zp_keyexpr_intersect_null_terminated(const char *l, const char *r); +z_id_t z_timestamp_id(const z_timestamp_t *ts); /** - * Check if a two keyexprs are equal. + * Checks validity of a timestamp * * Parameters: - * l: The first keyexpr. - * r: The second keyexpr. + * ts: Timestamp value to check validity of. * - * Returns: - * Returns ``0`` if both ``l`` and ``r`` are equal. Otherwise, it returns a ``-1``, or other ``negative value`` for - * errors. + * Return: + * ``true`` if timestamp is valid, ``false`` otherwise. */ -int8_t z_keyexpr_equals(z_keyexpr_t l, z_keyexpr_t r); +_Bool z_timestamp_check(z_timestamp_t ts); /** - * Check if a two keyexprs are equal. - * - * Parameters: - * l: Pointer to the keyexpr in its string representation as a null terminated string. - * llen: Number of characters in ``l``. - * r: Pointer to the keyexpr in its string representation as a null terminated string. - * rlen: Number of characters in ``r``. + * Builds a default query target. * - * Returns: - * Returns ``0`` if both ``l`` and ``r`` are equal. Otherwise, it returns a ``-1``, or other ``negative value`` for - * errors. + * Return: + * The constructed :c:type:`z_query_target_t`. */ -int8_t zp_keyexpr_equals_null_terminated(const char *l, const char *r); +z_query_target_t z_query_target_default(void); /** - * Return a new, zenoh-allocated, empty configuration. - * It consists in an empty set of properties for zenoh session configuration. + * Builds an automatic query consolidation :c:type:`z_query_consolidation_t`. + * + * A query consolidation strategy will automatically be selected depending on the query selector. + * If selector contains time range properties, no consolidation is performed. + * Otherwise the :c:func:`z_query_consolidation_latest` strategy is used. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_config_t` by loaning it using - * ``z_config_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_config_loan(&val)``. + * Return: + * The constructed :c:type:`z_query_consolidation_t`. + */ +z_query_consolidation_t z_query_consolidation_auto(void); + +/** + * Builds a default :c:type:`z_query_consolidation_t`. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Return: + * The constructed :c:type:`z_query_consolidation_t`. + */ +z_query_consolidation_t z_query_consolidation_default(void); + +/** + * Builds a latest query consolidation :c:type:`z_query_consolidation_t`. * - * To check if ``val`` is still valid, you may use ``z_config_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * This strategy optimizes bandwidth on all links in the system but will provide a very poor latency. * - * Returns: - * Returns a new, zenoh-allocated, empty configuration. + * Return: + * The constructed :c:type:`z_query_consolidation_t`. */ -z_owned_config_t z_config_new(void); +z_query_consolidation_t z_query_consolidation_latest(void); /** - * Return a new, zenoh-allocated, default configuration. - * It consists in a default set of properties for zenoh session configuration. + * Builds a monotonic query consolidation :c:type:`z_query_consolidation_t`. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_config_t` by loaning it using - * ``z_config_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_config_loan(&val)``. + * This strategy offers the best latency. Replies are directly transmitted to the application when received + * without needing to wait for all replies. This mode does not guarantee that there will be no duplicates. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Return: + * The constructed :c:type:`z_query_consolidation_t`. + */ +z_query_consolidation_t z_query_consolidation_monotonic(void); + +/** + * Builds a no query consolidation :c:type:`z_query_consolidation_t`. * - * To check if ``val`` is still valid, you may use ``z_config_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * This strategy is useful when querying timeseries data bases or when using quorums. * - * Returns: - * Returns a new, zenoh-allocated, default configuration. + * Return: + * The constructed :c:type:`z_query_consolidation_t`. */ -z_owned_config_t z_config_default(void); +z_query_consolidation_t z_query_consolidation_none(void); /** - * Gets the property with the given integer key from the configuration. + * Gets a query parameters field. * * Parameters: - * config: A loaned instance of :c:type:`z_owned_config_t`. - * key: Integer key for the requested property. - * - * Returns: - * Returns the property with the given integer key from the configuration. + * query: Pointer to the :c:type:`z_loaned_query_t` to get the parameters from. + * parameters: Pointer to an uninitialized :c:type:`z_view_string_t` to contain the parameters. */ -const char *zp_config_get(z_config_t config, uint8_t key); +void z_query_parameters(const z_loaned_query_t *query, z_view_string_t *parameters); /** - * Inserts or replaces the property with the given integer key in the configuration. + * Gets a query payload by aliasing it. * * Parameters: - * config: A loaned instance of :c:type:`z_owned_config_t`. - * key: Integer key for the property to be inserted. - * value: Property value to be inserted. + * query: Pointer to the :c:type:`z_loaned_query_t` to get the value from. * - * Returns: - * Returns ``0`` if the insertion is successful, or a ``negative value`` otherwise. + * Return: + * Pointer to the payload as a :c:type:`z_loaned_bytes_t`. */ -int8_t zp_config_insert(z_config_t config, uint8_t key, z_string_t value); +const z_loaned_bytes_t *z_query_payload(const z_loaned_query_t *query); /** - * Return a new, zenoh-allocated, default scouting configuration. - * It consists in a default set of properties for scouting configuration. + * Gets a query encoding by aliasing it. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_scouting_config_t` by loaning it - * using - * ``z_scouting_config_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, - * is equivalent to writing ``z_config_loan(&val)``. + * Parameters: + * query: Pointer to the :c:type:`z_loaned_query_t` to get the value from. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Return: + * Pointer to the encoding as a :c:type:`z_loaned_encoding_t`. + */ +const z_loaned_encoding_t *z_query_encoding(const z_loaned_query_t *query); + +/** + * Gets a query attachment value by aliasing it. * - * To check if ``val`` is still valid, you may use ``z_scouting_config_check(&val)`` or ``z_check(val)`` if your - * compiler supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Parameters: + * query: Pointer to the :c:type:`z_loaned_query_t` to get the attachment from. * - * Returns: - * Returns a new, zenoh-allocated, default scouting configuration. + * Return: + * Pointer to the attachment as a :c:type:`z_loaned_bytes_t`. */ -z_owned_scouting_config_t z_scouting_config_default(void); +const z_loaned_bytes_t *z_query_attachment(const z_loaned_query_t *query); /** - * Return a new, zenoh-allocated, scouting configuration extracted from a :c:type:`z_owned_config_t`. - * It consists in a default set of properties for scouting configuration. - * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_scouting_config_t` by loaning it - * using - * ``z_scouting_config_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, - * is equivalent to writing ``z_config_loan(&val)``. + * Gets a query keyexpr by aliasing it. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Parameters: + * query: Pointer to the :c:type:`z_loaned_query_t` to get the keyexpr from. * - * To check if ``val`` is still valid, you may use ``z_scouting_config_check(&val)`` or ``z_check(val)`` if your - * compiler supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Return: + * The keyexpr wrapped as a:c:type:`z_keyexpr_t`. + */ +const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query); + +/** + * Builds a new sample closure. + * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Parameters: - * config: A loaned instance of :c:type:`z_owned_config_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. * - * Returns: - * Returns a new, zenoh-allocated, default scouting configuration. + * Return: + * The sample closure. */ -z_owned_scouting_config_t z_scouting_config_from(z_config_t config); +int8_t z_closure_sample(z_owned_closure_sample_t *closure, z_data_handler_t call, z_dropper_handler_t drop, + void *context); /** - * Gets the property with the given integer key from the configuration. + * Builds a new query closure. + * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Parameters: - * config: A loaned instance of :c:type:`z_owned_scouting_config_t`. - * key: Integer key for the requested property. + * 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. * - * Returns: - * Returns the property with the given integer key from the configuration. + * Return: + * The query closure. */ -const char *zp_scouting_config_get(z_scouting_config_t config, uint8_t key); +int8_t z_closure_query(z_owned_closure_query_t *closure, z_queryable_handler_t call, z_dropper_handler_t drop, + void *context); /** - * Inserts or replaces the property with the given integer key in the configuration. + * Builds a new reply closure. + * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Parameters: - * config: A loaned instance of :c:type:`z_owned_scouting_config_t`. - * key: Integer key for the property to be inserted. - * value: Property value to be inserted. + * 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. * - * Returns: - * Returns ``0`` if the insertion is successful, or a ``negative value`` otherwise. + * Return: + * The reply closure. */ -int8_t zp_scouting_config_insert(z_scouting_config_t config, uint8_t key, z_string_t value); +int8_t z_closure_reply(z_owned_closure_reply_t *closure, z_reply_handler_t call, z_dropper_handler_t drop, + void *context); /** - * Constructs a :c:type:`z_encoding_t`. + * Builds a new hello closure. + * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Parameters: - * prefix: A known :c:type:`z_encoding_prefix_t`. - * suffix: A custom suffix to be appended to the prefix. + * 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. * - * Returns: - * Returns the constructed :c:type:`z_encoding_t`. + * Return: + * The hello closure. */ -z_encoding_t z_encoding(z_encoding_prefix_t prefix, const char *suffix); +int8_t z_closure_hello(z_owned_closure_hello_t *closure, z_loaned_hello_handler_t call, z_dropper_handler_t drop, + void *context); /** - * Constructs a default encoding. + * Builds a new zid closure. + * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. * - * Returns: - * Returns the constructed :c:type:`z_encoding_t`. + * Parameters: + * 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. + * + * Return: + * The hello closure. */ -z_encoding_t z_encoding_default(void); +int8_t z_closure_zid(z_owned_closure_zid_t *closure, z_id_handler_t call, z_dropper_handler_t drop, void *context); + +/**************** Loans ****************/ +_Z_OWNED_FUNCTIONS_DEF(string) +_Z_OWNED_FUNCTIONS_DEF(keyexpr) +_Z_OWNED_FUNCTIONS_NO_COPY_DEF(config) +_Z_OWNED_FUNCTIONS_DEF(session) +_Z_OWNED_FUNCTIONS_DEF(subscriber) +_Z_OWNED_FUNCTIONS_DEF(publisher) +_Z_OWNED_FUNCTIONS_DEF(queryable) +_Z_OWNED_FUNCTIONS_DEF(hello) +_Z_OWNED_FUNCTIONS_DEF(reply) +_Z_OWNED_FUNCTIONS_DEF(string_array) +_Z_OWNED_FUNCTIONS_DEF(sample) +_Z_OWNED_FUNCTIONS_DEF(query) +_Z_OWNED_FUNCTIONS_DEF(slice) +_Z_OWNED_FUNCTIONS_DEF(bytes) +_Z_OWNED_FUNCTIONS_DEF(reply_err) +_Z_OWNED_FUNCTIONS_DEF(encoding) + +_Z_OWNED_FUNCTIONS_CLOSURE_DEF(closure_sample) +_Z_OWNED_FUNCTIONS_CLOSURE_DEF(closure_query) +_Z_OWNED_FUNCTIONS_CLOSURE_DEF(closure_reply) +_Z_OWNED_FUNCTIONS_CLOSURE_DEF(closure_hello) +_Z_OWNED_FUNCTIONS_CLOSURE_DEF(closure_zid) + +_Z_VIEW_FUNCTIONS_DEF(keyexpr) +_Z_VIEW_FUNCTIONS_DEF(string) /** + * Loans a :c:type:`z_owned_sample_t`. * - * Checks validity of the timestamp + * Parameters: + * sample: Pointer to a :c:type:`z_owned_sample_t` to loan. * + * Return: + * Pointer to the loaned sample as a :c:type:`z_loaned_sample_t`. */ -_Bool z_timestamp_check(z_timestamp_t ts); +const z_loaned_sample_t *z_sample_loan(const z_owned_sample_t *sample); /** - * Constructs a default query target. + * Gets data from a :c:type:`z_loaned_string_t`. * - * Returns: - * Returns the constructed :c:type:`z_query_target_t`. + * Parameters: + * str: Pointer to a :c:type:`z_loaned_string_t` to get data from. + * + * Return: + * Pointer to the string data. */ -z_query_target_t z_query_target_default(void); +const char *z_string_data(const z_loaned_string_t *str); /** - * Automatic query consolidation strategy selection. + * Gets string length from a :c:type:`z_loaned_string_t`. * - * A query consolidation strategy will automatically be selected depending the query selector. - * If the selector contains time range properties, no consolidation is performed. - * Otherwise the :c:func:`z_query_consolidation_latest` strategy is used. + * Parameters: + * str: Pointer to a :c:type:`z_loaned_string_t` to get length from. * - * Returns: - * Returns the constructed :c:type:`z_query_consolidation_t`. + * Return: + * Length of the string. */ -z_query_consolidation_t z_query_consolidation_auto(void); +size_t z_string_len(const z_loaned_string_t *str); /** - * Constructs a default :c:type:`z_query_consolidation_t`. + * Builds a :c:type:`z_string_t` by copying a ``const char *`` string. + * + * Parameters: + * str: Pointer to an uninitialized :c:type:`z_owned_string_t`. + * value: Pointer to a null terminated string to be copied. * - * Returns: - * Returns the constructed :c:type:`z_query_consolidation_t`. + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -z_query_consolidation_t z_query_consolidation_default(void); +int8_t z_string_copy_from_str(z_owned_string_t *str, const char *value); /** - * Latest consolidation. + * Builds a :c:type:`z_owned_string_t` by transferring ownership over a null-terminated string to it. * - * This strategy optimizes bandwidth on all links in the system but will provide a very poor latency. + * Parameters: + * str: Pointer to an uninitialized :c:type:`z_owned_string_t`. + * value: Pointer to a null terminated string to be owned by `str`. + * deleter: A thread-safe delete function to free the `value`. Will be called once when `str` is dropped. Can be + * NULL, in case if `value` is allocated in static memory. + * context: An optional context to be passed to the `deleter`. * - * Returns: - * Returns the constructed :c:type:`z_query_consolidation_t`. + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -z_query_consolidation_t z_query_consolidation_latest(void); +int8_t z_string_from_str(z_owned_string_t *str, char *value, void (*deleter)(void *value, void *context), + void *context); /** - * Monotonic consolidation. + * Builds an empty :c:type:`z_owned_string_t`. * - * This strategy offers the best latency. Replies are directly transmitted to the application when received - * without needing to wait for all replies. This mode does not guarantee that there will be no duplicates. - * - * Returns: - * Returns the constructed :c:type:`z_query_consolidation_t`. + * Parameters: + * str: Pointer to an uninitialized :c:type:`z_owned_string_t`. */ -z_query_consolidation_t z_query_consolidation_monotonic(void); +void z_string_empty(z_owned_string_t *str); /** - * No consolidation. + * Builds a :c:type:`z_string_t` by wrapping a substring specified by ``const char *`` and length `len`. * - * This strategy is useful when querying timeseries data bases or when using quorums. + * Parameters: + * value: Pointer to a string. + * len: String size. + * str: Pointer to an uninitialized :c:type:`z_owned_string_t`. * - * Returns: - * Returns the constructed :c:type:`z_query_consolidation_t`. + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -z_query_consolidation_t z_query_consolidation_none(void); +int8_t z_string_copy_from_substr(z_owned_string_t *str, const char *value, size_t len); /** - * Get a query's value selector by aliasing it. + * Checks if string is empty * * Parameters: - * query: Pointer to the query to get the value selector from. + * str: Pointer to a :c:type:`z_loaned_string_t` to check. + * Return: + * ``true`` if conainer is empty, ``false`` otherwise. + */ +bool z_string_is_empty(const z_loaned_string_t *str); + +/** + * Returns id of Zenoh entity that transmitted hello message. * - * Returns: - * Returns the value selector wrapped as a :c:type:`z_bytes_t`, since value selector is a user-defined representation. + * Parameters: + * hello: Pointer to a :c:type:`z_loaned_hello_t` message. + * Return: + * Id of the Zenoh entity that transmitted hello message. */ -z_bytes_t z_query_parameters(const z_query_t *query); +z_id_t z_hello_zid(const z_loaned_hello_t *hello); /** - * Get a query's payload value by aliasing it. - * Note: This API has been marked as unstable: it works as advertised, but we may change it in a future release. + * Returns type of Zenoh entity that transmitted hello message. * * Parameters: - * query: Pointer to the query to get the value selector from. + * hello: Pointer to a :c:type:`z_loaned_hello_t` message. + * Return: + * Type of the Zenoh entity that transmitted hello message. + */ +z_whatami_t z_hello_whatami(const z_loaned_hello_t *hello); + +/** + * Constructs an array of locators of Zenoh entity that sent hello message. * - * Returns: - * Returns the payload value wrapped as a :c:type:`z_value_t`, since payload value is a user-defined representation. + * Parameters: + * hello: Pointer to a :c:type:`z_loaned_hello_t` message. + * Return: + * :c:type:`z_loaned_string_array_t` containing locators. */ -z_value_t z_query_value(const z_query_t *query); +const z_loaned_string_array_t *z_hello_locators(const z_loaned_hello_t *hello); /** - * Get a query's key by aliasing it. + * Constructs a non-owned non-null-terminated string from the kind of zenoh entity. * + * The string has static storage (i.e. valid until the end of the program). * Parameters: - * query: Pointer to the query to get keyexpr from. + * whatami: A whatami bitmask of zenoh entity kind. + * str_out: An uninitialized memory location where strring will be constructed. * - * Returns: - * Returns the :c:type:`z_keyexpr_t` associated to the query. + * Return: + * ``0`` in case of success, ``negative value`` otherwise. */ -z_keyexpr_t z_query_keyexpr(const z_query_t *query); +int8_t z_whatami_to_view_string(z_whatami_t whatami, z_view_string_t *str_out); +/************* Primitives **************/ /** - * Return a new sample closure. - * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. + * Scouts for other Zenoh entities like routers and/or peers. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_closure_sample_t` by loaning it using - * ``z_closure_sample_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, - * is equivalent to writing ``z_closure_sample_loan(&val)``. - * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Parameters: + * config: Moved :c:type:`z_owned_config_t` to configure the scouting with. + * callback: Moved :c:type:`z_owned_closure_hello_t` callback. + * options: Pointer to a :c:type:`z_scout_options_t` to configure the operation. * - * To check if ``val`` is still valid, you may use ``z_closure_sample_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Return: + * ``0`` if scouting successfully triggered, ``negative value`` otherwise. + */ +int8_t z_scout(z_moved_config_t *config, z_moved_closure_hello_t *callback, const z_scout_options_t *options); + +/** + * Opens a Zenoh session. * * Parameters: - * call: the typical callback function. ``context`` will be passed as its last argument. - * drop: allows the callback's state to be freed. ``context`` will be passed as its last argument. - * context: a pointer to an arbitrary state. + * zs: Pointer to an uninitialized :c:type:`z_owned_session_t` to store the session info. + * config: Moved :c:type:`z_owned_config_t` to configure the session with. * - * Returns: - * Returns a new sample closure. + * Return: + * ``0`` if open successful, ``negative value`` otherwise. */ -z_owned_closure_sample_t z_closure_sample(_z_data_handler_t call, _z_dropper_handler_t drop, void *context); +int8_t z_open(z_owned_session_t *zs, z_moved_config_t *config); /** - * Return a new query closure. - * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. + * Closes a Zenoh session. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_closure_query_t` by loaning it using - * ``z_closure_query_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_closure_query_loan(&val)``. + * Parameters: + * zs: Moved :c:type:`z_owned_session_t` to close. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Return: + * ``0`` if close successful, ``negative value`` otherwise. + */ +int8_t z_close(z_moved_session_t *zs); + +/** + * Fetches Zenoh IDs of all connected peers. * - * To check if ``val`` is still valid, you may use ``z_closure_query_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * The callback will be called once for each ID. It is guaranteed to never be called concurrently, + * and to be dropped before this function exits. * * Parameters: - * call: the typical callback function. ``context`` will be passed as its last argument. - * drop: allows the callback's state to be freed. ``context`` will be passed as its last argument. - * context: a pointer to an arbitrary state. + * zs: Pointer to :c:type:`z_loaned_session_t` to fetch peer id from. + * callback: Moved :c:type:`z_owned_closure_zid_t` callback. * - * Returns: - * Returns a new query closure. + * Return: + * ``0`` if operation successfully triggered, ``negative value`` otherwise. */ -z_owned_closure_query_t z_closure_query(_z_queryable_handler_t call, _z_dropper_handler_t drop, void *context); +int8_t z_info_peers_zid(const z_loaned_session_t *zs, z_moved_closure_zid_t *callback); /** - * Return a new reply closure. - * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. + * Fetches Zenoh IDs of all connected routers. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_closure_reply_t` by loaning it using - * ``z_closure_reply_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_closure_reply_loan(&val)``. - * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. - * - * To check if ``val`` is still valid, you may use ``z_closure_reply_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * The callback will be called once for each ID. It is guaranteed to never be called concurrently, + * and to be dropped before this function exits. * * Parameters: - * call: the typical callback function. ``context`` will be passed as its last argument. - * drop: allows the callback's state to be freed. ``context`` will be passed as its last argument. - * context: a pointer to an arbitrary state. + * zs: Pointer to a :c:type:`z_loaned_session_t` to fetch router id from. + * callback: Moved :c:type:`z_owned_closure_zid_t` callback. * - * Returns: - * Returns a new reply closure. + * Return: + * ``0`` if operation successfully triggered, ``negative value`` otherwise. */ -z_owned_closure_reply_t z_closure_reply(z_owned_reply_handler_t call, _z_dropper_handler_t drop, void *context); +int8_t z_info_routers_zid(const z_loaned_session_t *zs, z_moved_closure_zid_t *callback); /** - * Return a new hello closure. - * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. + * Gets the local Zenoh ID associated to a given Zenoh session. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_closure_hello_t` by loaning it using - * ``z_closure_hello_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, - * is equivalent to writing ``z_closure_hello_loan(&val)``. + * If this function returns an array of 16 zeros, this means the session is invalid. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Parameters: + * zs: Pointer to a :c:type:`z_loaned_session_t` to get the id from. * - * To check if ``val`` is still valid, you may use ``z_closure_hello_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Return: + * The local Zenoh ID of the session as :c:type:`z_id_t`. + */ +z_id_t z_info_zid(const z_loaned_session_t *zs); + +/** + * Converts a Zenoh ID into a string for print purposes. * * Parameters: - * call: the typical callback function. ``context`` will be passed as its last argument. - * drop: allows the callback's state to be freed. ``context`` will be passed as its last argument. - * context: a pointer to an arbitrary state. + * str: Pointer to uninitialized :c:type:`z_owned_string_t` to store the string. + * id: Pointer to the id to convert. * - * Returns: - * Returns a new hello closure. + * Return: + * ``0`` if operation successful, ``negative value`` otherwise. */ -z_owned_closure_hello_t z_closure_hello(z_owned_hello_handler_t call, _z_dropper_handler_t drop, void *context); +z_result_t z_id_to_string(z_owned_string_t *str, z_id_t *id); /** - * Return a new zid closure. - * It consists on a structure that contains all the elements for stateful, memory-leak-free callbacks. - * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_closure_zid_t` by loaning it using - * ``z_closure_zid_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_closure_zid_loan(&val)``. + * Gets the keyexpr from a sample by aliasing it. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Parameters: + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the keyexpr from. * - * To check if ``val`` is still valid, you may use ``z_closure_zid_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Return: + * The keyexpr wrapped as a :c:type:`z_loaned_keyexpr_t`. + */ +const z_loaned_keyexpr_t *z_sample_keyexpr(const z_loaned_sample_t *sample); + +/** + * Gets the payload of a sample by aliasing it. * * Parameters: - * call: the typical callback function. ``context`` will be passed as its last argument. - * drop: allows the callback's state to be freed. ``context`` will be passed as its last argument. - * context: a pointer to an arbitrary state. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the payload from. * - * Returns: - * Returns a new zid closure. + * Return: + * The payload wrapped as a :c:type:`z_loaned_bytes_t`. */ -z_owned_closure_zid_t z_closure_zid(z_id_handler_t call, _z_dropper_handler_t drop, void *context); - -/**************** Loans ****************/ -#define _OWNED_FUNCTIONS(type, ownedtype, name) \ - _Bool z_##name##_check(const ownedtype *name); \ - type z_##name##_loan(const ownedtype *name); \ - ownedtype *z_##name##_move(ownedtype *name); \ - ownedtype z_##name##_clone(ownedtype *name); \ - void z_##name##_drop(ownedtype *name); \ - ownedtype z_##name##_null(void); - -_OWNED_FUNCTIONS(z_str_t, z_owned_str_t, str) -_OWNED_FUNCTIONS(z_keyexpr_t, z_owned_keyexpr_t, keyexpr) -_OWNED_FUNCTIONS(z_config_t, z_owned_config_t, config) -_OWNED_FUNCTIONS(z_scouting_config_t, z_owned_scouting_config_t, scouting_config) -_OWNED_FUNCTIONS(z_session_t, z_owned_session_t, session) -_OWNED_FUNCTIONS(z_subscriber_t, z_owned_subscriber_t, subscriber) -_OWNED_FUNCTIONS(z_pull_subscriber_t, z_owned_pull_subscriber_t, pull_subscriber) -_OWNED_FUNCTIONS(z_publisher_t, z_owned_publisher_t, publisher) -_OWNED_FUNCTIONS(z_queryable_t, z_owned_queryable_t, queryable) -_OWNED_FUNCTIONS(z_hello_t, z_owned_hello_t, hello) -_OWNED_FUNCTIONS(z_reply_t, z_owned_reply_t, reply) -_OWNED_FUNCTIONS(z_str_array_t, z_owned_str_array_t, str_array) - -#define _OWNED_FUNCTIONS_CLOSURE(ownedtype, name) \ - _Bool z_##name##_check(const ownedtype *val); \ - ownedtype *z_##name##_move(ownedtype *val); \ - void z_##name##_drop(ownedtype *val); \ - ownedtype z_##name##_null(void); - -_OWNED_FUNCTIONS_CLOSURE(z_owned_closure_sample_t, closure_sample) -_OWNED_FUNCTIONS_CLOSURE(z_owned_closure_query_t, closure_query) -_OWNED_FUNCTIONS_CLOSURE(z_owned_closure_reply_t, closure_reply) -_OWNED_FUNCTIONS_CLOSURE(z_owned_closure_hello_t, closure_hello) -_OWNED_FUNCTIONS_CLOSURE(z_owned_closure_zid_t, closure_zid) +const z_loaned_bytes_t *z_sample_payload(const z_loaned_sample_t *sample); -/************* Primitives **************/ /** - * Looks for other Zenoh-enabled entities like routers and/or peers. + * Gets the timestamp of a sample by aliasing it. * * Parameters: - * config: A moved instance of :c:type:`z_owned_scouting_config_t` containing the set properties to configure the - * scouting. callback: A moved instance of :c:type:`z_owned_closure_hello_t` containing the callbacks to be called. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the timestamp from. * - * Returns: - * Returns ``0`` if the scouting is successful triggered, or a ``negative value`` otherwise. + * Return: + * The pointer to timestamp wrapped as a :c:type:`z_timestamp_t`. Returns NULL if no timestamp was set. */ -int8_t z_scout(z_owned_scouting_config_t *config, z_owned_closure_hello_t *callback); +const z_timestamp_t *z_sample_timestamp(const z_loaned_sample_t *sample); /** - * Opens a Zenoh session. + * Gets the encoding of a sample by aliasing it. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_session_t` by loaning it using - * ``z_session_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_session_loan(&val)``. - * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Parameters: + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the encoding from. * - * To check if ``val`` is still valid, you may use ``z_session_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Return: + * The encoding wrapped as a :c:type:`z_loaned_encoding_t*`. + */ +const z_loaned_encoding_t *z_sample_encoding(const z_loaned_sample_t *sample); + +/** + * Gets the kind of a sample by aliasing it. * * Parameters: - * config: A moved instance of :c:type:`z_owned_config_t` containing the set properties to configure the session. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the kind from. * - * Returns: - * A :c:type:`z_owned_session_t` with either a valid open session or a failing session. - * Should the session opening fail, ``z_check(val)`` ing the returned value will return ``false``. + * Return: + * The sample kind wrapped as a :c:type:`z_sample_kind_t`. */ -z_owned_session_t z_open(z_owned_config_t *config); +z_sample_kind_t z_sample_kind(const z_loaned_sample_t *sample); /** - * Closes a Zenoh session. + * Got sample qos congestion control value. * * Parameters: - * zs: A moved instance of the the :c:type:`z_owned_session_t` to close. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the congestion control from. * - * Returns: - * Returns ``0`` if the session is successful closed, or a ``negative value`` otherwise. + * Return: + * The congestion control wrapped as a :c:type:`z_congestion_control_t`. */ -int8_t z_close(z_owned_session_t *zs); +z_congestion_control_t z_sample_congestion_control(const z_loaned_sample_t *sample); /** - * Fetches the Zenoh IDs of all connected peers. - * - * :c:var:`callback` will be called once for each ID. It is guaranteed to never be called concurrently, - * and to be dropped before this function exits. + * Got whether sample qos express flag was set or not. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` to inquiry. - * callback: A moved instance of :c:type:`z_owned_closure_zid_t` containing the callbacks to be called. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the express flag from. * - * Returns: - * Returns ``0`` if the info is successful triggered, or a ``negative value`` otherwise. + * Return: + * The express flag value. */ -int8_t z_info_peers_zid(const z_session_t zs, z_owned_closure_zid_t *callback); +bool z_sample_express(const z_loaned_sample_t *sample); /** - * Fetches the Zenoh IDs of all connected routers. - * - * :c:var:`callback` will be called once for each ID. It is guaranteed to never be called concurrently, - * and to be dropped before this function exits. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` to inquiry. - * callback: A moved instance of :c:type:`z_owned_closure_zid_t` containing the callbacks to be called. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the qos from. * - * Returns: - * Returns ``0`` if the info is successful triggered, or a ``negative value`` otherwise. + * Return: + * The priority wrapped as a :c:type:`z_priority_t`. + * Got sample qos priority value. */ -int8_t z_info_routers_zid(const z_session_t zs, z_owned_closure_zid_t *callback); +z_priority_t z_sample_priority(const z_loaned_sample_t *sample); /** - * Get the local Zenoh ID associated to a given Zenoh session. - * - * Unless the :c:type:`z_session_t` is invalid, that ID is guaranteed to be non-zero. - * In other words, this function returning an array of 16 zeros means you failed to pass it a valid session. + * Gets the attachment of a sample by aliasing it. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` to inquiry. + * sample: Pointer to a :c:type:`z_loaned_sample_t` to get the attachment from. * - * Returns: - * Returns the local Zenoh ID of the given :c:type:`z_session_t`. + * Return: + * Pointer to the attachment as a :c:type:`z_loaned_bytes_t`. */ -z_id_t z_info_zid(const z_session_t zs); +const z_loaned_bytes_t *z_sample_attachment(const z_loaned_sample_t *sample); #if Z_FEATURE_PUBLICATION == 1 /** - * Constructs the default values for the put operation. + * Builds a :c:type:`z_put_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_put_options_t`. + * Parameters: + * Pointer to an uninitialized :c:type:`z_put_options_t`. */ -z_put_options_t z_put_options_default(void); + +void z_put_options_default(z_put_options_t *options); /** - * Constructs the default values for the delete operation. + * Builds a :c:type:`z_delete_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_delete_options_t`. + * Parameters: + * Pointer to an uninitialized :c:type:`z_delete_options_t`. */ -z_delete_options_t z_delete_options_default(void); +void z_delete_options_default(z_delete_options_t *options); /** * Puts data for a given keyexpr. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` through where data will be put. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to put. - * payload: Pointer to the data to put. - * payload_len: The length of the ``payload``. - * options: The put options to be applied in the put operation. + * zs: Pointer to a :c:type:`z_loaned_session_t` to put the data through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to put the data for. + * payload: Moved :c:type:`z_owned_bytes_t` containing the data to put. + * options: Pointer to a :c:type:`z_put_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the put operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if put operation successful, ``negative value`` otherwise. */ -int8_t z_put(z_session_t zs, z_keyexpr_t keyexpr, const uint8_t *payload, z_zint_t payload_len, +int8_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, z_moved_bytes_t *payload, const z_put_options_t *options); /** - * Deletes data from a given keyexpr. + * Deletes data for a given keyexpr. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` through where data will be put. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to put. - * options: The delete options to be applied in the delete operation. + * zs: Pointer to a :c:type:`z_loaned_session_t` to delete the data through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to delete the data for. + * options: Pointer to a :c:type:`z_delete_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the delete operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if delete operation successful, ``negative value`` otherwise. */ -int8_t z_delete(z_session_t zs, z_keyexpr_t keyexpr, const z_delete_options_t *options); +int8_t z_delete(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, const z_delete_options_t *options); /** - * Constructs the default values for the publisher entity. + * Builds a :c:type:`z_publisher_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_publisher_options_t`. + * Parameters: + * Pointer to an uninitialized :c:type:`z_delete_options_t`. */ -z_publisher_options_t z_publisher_options_default(void); +void z_publisher_options_default(z_publisher_options_t *options); /** - * Declares a publisher for the given keyexpr. + * Declares a publisher for a given keyexpr. * * Data can be put and deleted with this publisher with the help of the * :c:func:`z_publisher_put` and :c:func:`z_publisher_delete` functions. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_publisher_t` by loaning it using - * ``z_publisher_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_publisher_loan(&val)``. - * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. - * - * To check if ``val`` is still valid, you may use ``z_publisher_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. - * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to declare the publisher. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to associate with the publisher. - * options: The options to apply to the publisher. If ``NULL`` is passed, the default options will be applied. + * zs: Pointer to a :c:type:`z_loaned_session_t` to declare the publisher through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to bind the publisher with. + * options: Pointer to a :c:type:`z_publisher_options_t` to configure the operation. * - * Returns: - * A :c:type:`z_owned_publisher_t` with either a valid publisher or a failing publisher. - * Should the publisher be invalid, ``z_check(val)`` ing the returned value will return ``false``. + * Return: + * ``0`` if declare successful, ``negative value`` otherwise. */ -z_owned_publisher_t z_declare_publisher(z_session_t zs, z_keyexpr_t keyexpr, const z_publisher_options_t *options); +int8_t z_declare_publisher(z_owned_publisher_t *pub, const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, + const z_publisher_options_t *options); /** - * Undeclare the publisher generated by a call to :c:func:`z_declare_publisher`. + * Undeclares a publisher. * * Parameters: - * pub: A moved instance of :c:type:`z_owned_publisher_t` to undeclare. + * pub: Moved :c:type:`z_owned_publisher_t` to undeclare. * - * Returns: - * Returns ``0`` if the undeclare publisher operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if undeclare successful, ``negative value`` otherwise. */ -int8_t z_undeclare_publisher(z_owned_publisher_t *pub); - -z_owned_keyexpr_t z_publisher_keyexpr(z_publisher_t publisher); +int8_t z_undeclare_publisher(z_moved_publisher_t *pub); /** - * Constructs the default values for the put operation via a publisher entity. + * Builds a :c:type:`z_publisher_put_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_publisher_put_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_publisher_put_options_t`. */ -z_publisher_put_options_t z_publisher_put_options_default(void); +void z_publisher_put_options_default(z_publisher_put_options_t *options); /** - * Constructs the default values for the delete operation via a publisher entity. + * Builds a :c:type:`z_publisher_delete_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_publisher_delete_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_publisher_delete_options_t`. */ -z_publisher_delete_options_t z_publisher_delete_options_default(void); +void z_publisher_delete_options_default(z_publisher_delete_options_t *options); /** - * Puts data for the keyexpr associated to the given publisher. + * Puts data for the keyexpr bound to the given publisher. * * Parameters: - * pub: A loaned instance of :c:type:`z_publisher_t` from where to put the data. - * options: The options to apply to the put operation. If ``NULL`` is passed, the default options will be applied. + * pub: Pointer to a :c:type:`z_loaned_publisher_t` from where to put the data. + * payload: Moved :c:type:`z_owned_bytes_t` containing the data to put. + * options: Pointer to a :c:type:`z_publisher_put_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the put operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if put operation successful, ``negative value`` otherwise. */ -int8_t z_publisher_put(const z_publisher_t pub, const uint8_t *payload, size_t len, +int8_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *payload, const z_publisher_put_options_t *options); /** - * Deletes data from the keyexpr associated to the given publisher. + * Deletes data from the keyexpr bound to the given publisher. + * + * Parameters: + * pub: Pointer to a :c:type:`z_loaned_publisher_t` from where to delete the data. + * options: Pointer to a :c:type:`z_publisher_delete_options_t` to configure the delete operation. + * + * Return: + * ``0`` if delete operation successful, ``negative value`` otherwise. + */ +int8_t z_publisher_delete(const z_loaned_publisher_t *pub, const z_publisher_delete_options_t *options); + +/** + * Gets the keyexpr from a publisher. * * Parameters: - * pub: A loaned instance of :c:type:`z_publisher_t` from where to delete the data. - * options: The options to apply to the delete operation. If ``NULL`` is passed, the default options will be applied. + * publisher: Pointer to a :c:type:`z_loaned_publisher_t` to get the keyexpr from. * - * Returns: - * Returns ``0`` if the delete operation is successful, or a ``negative value`` otherwise. + * Return: + * The keyexpr wrapped as a :c:type:`z_loaned_keyexpr_t`. */ -int8_t z_publisher_delete(const z_publisher_t pub, const z_publisher_delete_options_t *options); +const z_loaned_keyexpr_t *z_publisher_keyexpr(const z_loaned_publisher_t *publisher); #endif #if Z_FEATURE_QUERY == 1 /** - * Constructs the default values for the get operation. + * Builds a :c:type:`z_get_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_get_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_get_options_t`. */ -z_get_options_t z_get_options_default(void); +void z_get_options_default(z_get_options_t *options); /** - * Issues a distributed query for a given keyexpr. + * Sends a distributed query for a given keyexpr. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` through where data will be put. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to put. + * zs: Pointer to a :c:type:`z_loaned_session_t` to send the query through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to send the query for. * parameters: Pointer to the parameters as a null-terminated string. - * callback: A moved instance of :c:type:`z_owned_closure_reply_t` containing the callbacks to be called. - * options: The get options to be applied in the distributed query. + * callback: Moved :c:type:`z_owned_closure_reply_t` callback. + * options: Pointer to a :c:type:`z_get_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the put operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if put operation successful, ``negative value`` otherwise. */ -int8_t z_get(z_session_t zs, z_keyexpr_t keyexpr, const char *parameters, z_owned_closure_reply_t *callback, - const z_get_options_t *options); +int8_t z_get(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, const char *parameters, + z_moved_closure_reply_t *callback, z_get_options_t *options); /** - * Checks if the queryable answered with an OK, which allows this value to be treated as a sample. - * - * If this returns ``false``, you should use ``z_check`` before trying to use :c:func:`z_reply_err` if you want to - * process the error that may be here. + * Checks if queryable answered with an OK, which allows this value to be treated as a sample. * * Parameters: - * reply: Pointer to the received query reply. + * reply: Pointer to a :c:type:`z_loaned_reply_t` to check. * - * Returns: - * Returns ``true`` if the queryable answered with an OK, which allows this value to be treated as a sample, or - * ``false`` otherwise. + * Return: + * ``true`` if queryable answered with an OK, ``false`` otherwise. */ -_Bool z_reply_is_ok(const z_owned_reply_t *reply); +_Bool z_reply_is_ok(const z_loaned_reply_t *reply); /** - * Yields the contents of the reply by asserting it indicates a success. + * Gets the content of an OK reply. * * You should always make sure that :c:func:`z_reply_is_ok` returns ``true`` before calling this function. * * Parameters: - * reply: Pointer to the received query reply. + * reply: Pointer to a :c:type:`z_loaned_reply_t` to get content from. * - * Returns: - * Returns the :c:type:`z_sample_t` wrapped in the query reply. + * Return: + * The OK reply content wrapped as a :c:type:`z_loaned_sample_t`. */ -z_sample_t z_reply_ok(const z_owned_reply_t *reply); +const z_loaned_sample_t *z_reply_ok(const z_loaned_reply_t *reply); /** - * Yields the contents of the reply by asserting it indicates a failure. + * Gets the contents of an error reply. * * You should always make sure that :c:func:`z_reply_is_ok` returns ``false`` before calling this function. * * Parameters: - * reply: Pointer to the received query reply. + * reply: Pointer to a :c:type:`z_loaned_reply_t` to get content from. + * + * Return: + * The error reply content wrapped as a :c:type:`z_loaned_reply_err_t`. + */ +const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply); + +/** + * Gets the id of the zenoh instance that answered this Reply. + * + * Parameters: + * reply: Pointer to a :c:type:`z_loaned_reply_t` to get content from. * - * Returns: - * Returns the :c:type:`z_value_t` wrapped in the query reply. + * Return: + * `true` if id is present */ -z_value_t z_reply_err(const z_owned_reply_t *reply); +_Bool z_reply_replier_id(const z_loaned_reply_t *reply, z_id_t *out_id); #endif #if Z_FEATURE_QUERYABLE == 1 /** - * Constructs the default values for the queryable entity. + * Builds a :c:type:`z_queryable_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_queryable_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_queryable_options_t`. */ -z_queryable_options_t z_queryable_options_default(void); +void z_queryable_options_default(z_queryable_options_t *options); /** - * Declares a queryable for the given keyexpr. - * - * Received queries are processed by means of callbacks. - * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_queryable_t` by loaning it using - * ``z_queryable_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_queryable_loan(&val)``. - * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. - * - * To check if ``val`` is still valid, you may use ``z_queryable_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Declares a queryable for a given keyexpr. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to declare the subscriber. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to associate with the subscriber. - * callback: A moved instance of :c:type:`z_owned_closure_query_t` containing the callbacks to be called and the - * context to pass to them. options: The options to apply to the queryable. If ``NULL`` is passed, the default options - * will be applied. + * queryable: Pointer to an uninitialized :c:type:`z_owned_queryable_t` to contain the queryable. + * zs: Pointer to a :c:type:`z_loaned_session_t` to declare the subscriber through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to bind the subscriber with. + * callback: Pointer to a :c:type:`z_owned_closure_query_t` callback. + * options: Pointer to a :c:type:`z_queryable_options_t` to configure the declare. * - * Returns: - * A :c:type:`z_owned_queryable_t` with either a valid queryable or a failing queryable. - * Should the queryable be invalid, ``z_check(val)`` ing the returned value will return ``false``. + * Return: + * ``0`` if declare operation successful, ``negative value`` otherwise. */ -z_owned_queryable_t z_declare_queryable(z_session_t zs, z_keyexpr_t keyexpr, z_owned_closure_query_t *callback, - const z_queryable_options_t *options); +int8_t z_declare_queryable(z_owned_queryable_t *queryable, const z_loaned_session_t *zs, + const z_loaned_keyexpr_t *keyexpr, z_moved_closure_query_t *callback, + const z_queryable_options_t *options); /** - * Undeclares the queryable generated by a call to :c:func:`z_declare_queryable`. + * Undeclares a queryable. * * Parameters: - * queryable: A moved instance of :c:type:`z_owned_queryable_t` to undeclare. + * queryable: Moved :c:type:`z_owned_queryable_t` to undeclare. * - * Returns: - * Returns ``0`` if the undeclare queryable operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if undeclare operation successful, ``negative value`` otherwise. */ -int8_t z_undeclare_queryable(z_owned_queryable_t *queryable); +int8_t z_undeclare_queryable(z_moved_queryable_t *queryable); /** - * Constructs the default values for the query reply operation. + * Builds a :c:type:`z_query_reply_options_t` with default values. * - * Returns: - * Returns the constructed :c:type:`z_query_reply_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_query_reply_options_t`. */ -z_query_reply_options_t z_query_reply_options_default(void); +void z_query_reply_options_default(z_query_reply_options_t *options); /** * Sends a reply to a query. @@ -1073,343 +1916,344 @@ z_query_reply_options_t z_query_reply_options_default(void); * returns. * * Parameters: - * query: Pointer to the received query. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to associate with the subscriber. - * payload: Pointer to the data to put. - * payload_len: The length of the ``payload``. - * options: The options to apply to the send query reply operation. If ``NULL`` is passed, the default options will be - * applied. + * query: Pointer to a :c:type:`z_loaned_query_t` to reply. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to bind the reply with. + * payload: Pointer to the reply data. + * options: Pointer to a :c:type:`z_query_reply_options_t` to configure the reply. * - * Returns: - * Returns ``0`` if the send query reply operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if reply operation successful, ``negative value`` otherwise. */ -int8_t z_query_reply(const z_query_t *query, const z_keyexpr_t keyexpr, const uint8_t *payload, size_t payload_len, +int8_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); -#endif /** - * Creates keyexpr owning string passed to it + * Builds a :c:type:`z_query_reply_del_options_t` with default values. + * + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_query_reply_del_options_t`. */ -z_owned_keyexpr_t z_keyexpr_new(const char *name); +void z_query_reply_del_options_default(z_query_reply_del_options_t *options); /** - * Declares a keyexpr, so that it is internally mapped into into a numerical id. - * - * This numerical id is used on the network to save bandwidth and ease the retrieval of the concerned resource - * in the routing tables. - * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_keyexpr_t` by loaning it using - * ``z_keyexpr_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_keyexpr_loan(&val)``. + * Sends a reply delete to a query. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. - * - * To check if ``val`` is still valid, you may use ``z_keyexpr_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * This function must be called inside of a :c:type:`z_owned_closure_query_t` callback associated to the + * :c:type:`z_owned_queryable_t`, passing the received query as parameters of the callback function. This function can + * be called multiple times to send multiple replies to a query. The reply will be considered complete when the callback + * returns. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to declare the keyexpr. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to declare. + * query: Pointer to a :c:type:`z_loaned_query_t` to reply. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to bind the reply with. + * options: Pointer to a :c:type:`z_query_reply_del_options_t` to configure the reply. * - * Returns: - * A :c:type:`z_owned_keyexpr_t` with either a valid or invalid keyexpr. - * Should the keyexpr be invalid, ``z_check(val)`` ing the returned value will return ``false``. + * Return: + * ``0`` if reply operation successful, ``negative value`` otherwise. */ -z_owned_keyexpr_t z_declare_keyexpr(z_session_t zs, z_keyexpr_t keyexpr); +int8_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); /** - * Undeclares the keyexpr generated by a call to :c:func:`z_declare_keyexpr`. + * Builds a :c:type:`z_query_reply_err_options_t` with default values. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` through where data will be put. - * keyexpr: A moved instance of :c:type:`z_owned_keyexpr_t` to undeclare. - * - * Returns: - * Returns ``0`` if the undeclare keyexpr operation is successful, or a ``negative value`` otherwise. + * options: Pointer to an uninitialized :c:type:`z_query_reply_err_options_t`. */ -int8_t z_undeclare_keyexpr(z_session_t zs, z_owned_keyexpr_t *keyexpr); +void z_query_reply_err_options_default(z_query_reply_err_options_t *options); -#if Z_FEATURE_SUBSCRIPTION == 1 /** - * Constructs the default values for the subscriber entity. + * Sends a reply error to a query. + * + * This function must be called inside of a :c:type:`z_owned_closure_query_t` callback associated to the + * :c:type:`z_owned_queryable_t`, passing the received query as parameters of the callback function. This function can + * be called multiple times to send multiple replies to a query. The reply will be considered complete when the callback + * returns. + * + * Parameters: + * query: Pointer to a :c:type:`z_loaned_query_t` to reply. + * payload: Moved reply error data payload. + * options: Pointer to a :c:type:`z_query_reply_err_options_t` to configure the reply error. * - * Returns: - * Returns the constructed :c:type:`z_subscriber_options_t`. + * Return: + * ``0`` if reply operation successful, ``negative value`` otherwise. */ -z_subscriber_options_t z_subscriber_options_default(void); +int8_t z_query_reply_err(const z_loaned_query_t *query, z_moved_bytes_t *payload, + const z_query_reply_err_options_t *options); + +#endif /** - * Declares a (push) subscriber for the given keyexpr. - * - * Received data is processed by means of callbacks. - * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_subscriber_t` by loaning it using - * ``z_subscriber_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's ``_Generic``, is - * equivalent to writing ``z_subscriber_loan(&val)``. - * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. - * - * To check if ``val`` is still valid, you may use ``z_subscriber_check(&val)`` or ``z_check(val)`` if your compiler - * supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Builds a new keyexpr. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to declare the subscriber. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to associate with the subscriber. - * callback: A moved instance of :c:type:`z_owned_closure_sample_t` containg the callbacks to be called and the - * context to pass to them. options: The options to apply to the subscriber. If ``NULL`` is passed, the default options - * will be applied. + * keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t` to store the keyexpr. + * name: Pointer to the null-terminated string of the keyexpr. * - * Returns: - * A :c:type:`z_owned_subscriber_t` with either a valid subscriber or a failing subscriber. - * Should the subscriber be invalid, ``z_check(val)`` ing the returned value will return ``false``. + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -z_owned_subscriber_t z_declare_subscriber(z_session_t zs, z_keyexpr_t keyexpr, z_owned_closure_sample_t *callback, - const z_subscriber_options_t *options); +int8_t z_keyexpr_from_str(z_owned_keyexpr_t *keyexpr, const char *name); /** - * Undeclares the (push) subscriber generated by a call to :c:func:`z_declare_subscriber`. + * Builds a new keyexpr from a substring. * * Parameters: - * sub: A moved instance of :c:type:`z_owned_subscriber_t` to undeclare. + * keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t` to store the keyexpr. + * name: Pointer to the start of the substring for keyxpr. + * len: Length of the substring to consider. * - * Returns: - * Returns ``0`` if the undeclare (push) subscriber operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -int8_t z_undeclare_subscriber(z_owned_subscriber_t *sub); +int8_t z_keyexpr_from_substr(z_owned_keyexpr_t *keyexpr, const char *name, size_t len); /** - * @brief + * Builds a :c:type:`z_owned_keyexpr_t` from a null-terminated string with auto canonization. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t`. + * name: Pointer to string representation of the keyexpr as a null terminated string. * + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -z_owned_keyexpr_t z_subscriber_keyexpr(z_subscriber_t sub); +int8_t z_keyexpr_from_str_autocanonize(z_owned_keyexpr_t *keyexpr, const char *name); /** - * Constructs the default values for the pull subscriber entity. + * Builds a :c:type:`z_owned_keyexpr_t` from a substring with auto canonization. + * + * Parameters: + * keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t` to store the keyexpr. + * name: Pointer to the start of the substring for keyxpr. + * len: Length of the substring to consider. After the function return it will be equal to the canonized key + * expression string length. * - * Returns: - * Returns the constructed :c:type:`z_pull_subscriber_options_t`. + * Return: + * ``0`` if creation successful, ``negative value`` otherwise. */ -z_pull_subscriber_options_t z_pull_subscriber_options_default(void); +int8_t z_keyexpr_from_substr_autocanonize(z_owned_keyexpr_t *keyexpr, const char *name, size_t *len); /** - * Declares a pull subscriber for the given keyexpr. - * - * Data can be pulled with this subscriber with the help of the - * :c:func:`z_pull` function. Received data is processed by means of callbacks. + * Declares a keyexpr, so that it is mapped on a numerical id. * - * Like most ``z_owned_X_t`` types, you may obtain an instance of :c:type:`z_owned_pull_subscriber_t` by loaning it - * using ``z_pull_subscriber_loan(&val)``. The ``z_loan(val)`` macro, available if your compiler supports C11's - * ``_Generic``, is equivalent to writing ``z_pull_subscriber_loan(&val)``. + * This numerical id is used on the network to save bandwidth and ease the retrieval of the concerned resource + * in the routing tables. * - * Like all ``z_owned_X_t``, an instance will be destroyed by any function which takes a mutable pointer to said - * instance, as this implies the instance's inners were moved. To make this fact more obvious when reading your code, - * consider using ``z_move(val)`` instead of ``&val`` as the argument. After a ``z_move``, ``val`` will still exist, but - * will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your ``val`` - * is valid. + * Parameters: + * declared_keyexpr: Pointer to an uninitialized :c:type:`z_owned_keyexpr_t` to contain the declared keyexpr. + * zs: Pointer to a :c:type:`z_loaned_session_t` to declare the keyexpr through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to bind the keyexpr with. * - * To check if ``val`` is still valid, you may use ``z_pull_subscriber_check(&val)`` or ``z_check(val)`` if your - * compiler supports ``_Generic``, which will return ``true`` if ``val`` is valid, or ``false`` otherwise. + * Return: + * ``0`` if declare successful, ``negative value`` otherwise. + */ +int8_t z_declare_keyexpr(z_owned_keyexpr_t *declared_keyexpr, const z_loaned_session_t *zs, + const z_loaned_keyexpr_t *keyexpr); + +/** + * Undeclares a keyexpr. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to declare the subscriber. - * keyexpr: A loaned instance of :c:type:`z_keyexpr_t` to associate with the subscriber. - * callback: A moved instance of :c:type:`z_owned_closure_sample_t` containing the callbacks to be called and the - * context to pass to them. options: The options to apply to the pull subscriber. If ``NULL`` is passed, the default - * options will be applied. + * keyexpr: Moved :c:type:`z_owned_keyexpr_t` to undeclare. + * zs: Pointer to a :c:type:`z_loaned_session_t` to undeclare the data through. + * + * Return: + * ``0`` if undeclare successful, ``negative value`` otherwise. + */ +int8_t z_undeclare_keyexpr(z_moved_keyexpr_t *keyexpr, const z_loaned_session_t *zs); + +#if Z_FEATURE_SUBSCRIPTION == 1 +/** + * Builds a :c:type:`z_subscriber_options_t` with default values. * - * Returns: - * A :c:type:`z_owned_pull_subscriber_t` with either a valid subscriber or a failing subscriber. - * Should the pull subscriber be invalid, ``z_check(val)`` ing the returned value will return ``false``. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_subscriber_options_t`. */ -z_owned_pull_subscriber_t z_declare_pull_subscriber(z_session_t zs, z_keyexpr_t keyexpr, - z_owned_closure_sample_t *callback, - const z_pull_subscriber_options_t *options); +void z_subscriber_options_default(z_subscriber_options_t *options); /** - * Undeclares the pull subscriber generated by a call to :c:func:`z_declare_pull_subscriber`. + * Declares a subscriber for a given keyexpr. * * Parameters: - * sub: A moved instance of :c:type:`z_owned_pull_subscriber_t` to undeclare. + * sub: Pointer to a :c:type:`z_owned_subscriber_t` to contain the subscriber. + * zs: Pointer to a :c:type:`z_loaned_session_t` to declare the subscriber through. + * keyexpr: Pointer to a :c:type:`z_loaned_keyexpr_t` to bind the subscriber with. + * callback: Pointer to a`z_owned_closure_sample_t` callback. + * options: Pointer to a :c:type:`z_subscriber_options_t` to configure the operation * - * Returns: - * Returns ``0`` if the undeclare pull subscriber operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if declare successful, ``negative value`` otherwise. */ -int8_t z_undeclare_pull_subscriber(z_owned_pull_subscriber_t *sub); +int8_t z_declare_subscriber(z_owned_subscriber_t *sub, const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, + z_moved_closure_sample_t *callback, const z_subscriber_options_t *options); /** - * Pulls data for :c:type:`z_owned_pull_subscriber_t`. The pulled data will be provided - * by calling the **callback** function provided to the :c:func:`z_declare_pull_subscriber` function. + * Undeclares the subscriber. * * Parameters: - * sub: A loaned instance of :c:type:`z_pull_subscriber_t` from where to pull the data. + * sub: Moved :c:type:`z_owned_subscriber_t` to undeclare. * - * Returns: - * Returns ``0`` if the pull operation is successful, or a ``negative value`` otherwise. + * Return: + * ``0`` if undeclare successful, ``negative value`` otherwise. */ -int8_t z_subscriber_pull(const z_pull_subscriber_t sub); -#endif +int8_t z_undeclare_subscriber(z_moved_subscriber_t *sub); /** - * Checks if a given value is valid. + * Gets the keyexpr from a subscriber. * * Parameters: - * value: A loaned instance of :c:type:`z_value_t` to be checked. + * subscriber: Pointer to a :c:type:`z_loaned_subscriber_t` to get the keyexpr from. * - * Returns: - * Returns ``true`` if the value is valid, or ``false`` otherwise. + * Return: + * The keyexpr wrapped as a :c:type:`z_loaned_keyexpr_t`. */ -_Bool z_value_is_initialized(z_value_t *value); +const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *subscriber); +#endif /************* Multi Thread Tasks helpers **************/ /** - * Constructs the default values for the session read task. + * Builds a :c:type:`zp_task_read_options_t` with default value. * - * Returns: - * Returns the constructed :c:type:`zp_task_read_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`zp_task_read_options_t`. */ -zp_task_read_options_t zp_task_read_options_default(void); +void zp_task_read_options_default(zp_task_read_options_t *options); /** - * Start a separate task to read from the network and process the messages as soon as they are received. + * Starts a task to read from the network and process the received messages. * - * Note that the task can be implemented in form of thread, process, etc. and its implementation is platform-dependent. + * Note that the task can be implemented in form of thread, process, etc. and its implementation is + * platform-dependent. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to start the read task. - * options: The options to apply when starting the read task. If ``NULL`` is passed, the default options will be - * applied. + * zs: Pointer to a :c:type:`z_loaned_session_t` to start the task from. + * options: Pointer to a :c:type:`zp_task_read_options_t` to configure the task. * - * Returns: - * Returns ``0`` if the read task started successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if task started successfully, ``negative value`` otherwise. */ -int8_t zp_start_read_task(z_session_t zs, const zp_task_read_options_t *options); +int8_t zp_start_read_task(z_loaned_session_t *zs, const zp_task_read_options_t *options); /** - * Stop the read task. + * Stops the read task. * * This may result in stopping a thread or a process depending on the target platform. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to stop the read task. + * zs: Pointer to a :c:type:`z_loaned_session_t` to stop the task from. * - * Returns: - * Returns ``0`` if the read task stopped successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if task stopped successfully, ``negative value`` otherwise. */ -int8_t zp_stop_read_task(z_session_t zs); +int8_t zp_stop_read_task(z_loaned_session_t *zs); /** - * Constructs the default values for the session lease task. + * Builds a :c:type:`zp_task_lease_options_t` with default value. * - * Returns: - * Returns the constructed :c:type:`zp_task_lease_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`zp_task_lease_options_t`. */ -zp_task_lease_options_t zp_task_lease_options_default(void); +void zp_task_lease_options_default(zp_task_lease_options_t *options); /** - * Start a separate task to handle the session lease. + * Starts a task to handle the session lease. * * This task will send ``KeepAlive`` messages when needed and will close the session when the lease is expired. * When operating over a multicast transport, it also periodically sends the ``Join`` messages. - * Note that the task can be implemented in form of thread, process, etc. and its implementation is platform-dependent. + * Note that the task can be implemented in form of thread, process, etc. and its implementation is + * platform-dependent. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to start the lease task. - * options: The options to apply when starting the lease task. If ``NULL`` is passed, the default options will be - * applied. + * zs: Pointer to a :c:type:`z_loaned_session_t` to start the task from. + * options: Pointer to a :c:type:`zp_task_lease_options_t` to configure the task. * - * Returns: - * Returns ``0`` if the lease task started successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if task started successfully, ``negative value`` otherwise. */ -int8_t zp_start_lease_task(z_session_t zs, const zp_task_lease_options_t *options); +int8_t zp_start_lease_task(z_loaned_session_t *zs, const zp_task_lease_options_t *options); /** - * Stop the lease task. + * Stops the lease task. * * This may result in stopping a thread or a process depending on the target platform. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where to stop the lease task. + * zs: Pointer to a :c:type:`z_loaned_session_t` to stop the task from. * - * Returns: - * Returns ``0`` if the lease task stopped successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if task stopped successfully, ``negative value`` otherwise. */ -int8_t zp_stop_lease_task(z_session_t zs); +int8_t zp_stop_lease_task(z_loaned_session_t *zs); /************* Single Thread helpers **************/ /** - * Constructs the default values for the reading procedure. + * Builds a :c:type:`zp_read_options_t` with default value. * - * Returns: - * Returns the constructed :c:type:`zp_read_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`zp_read_options_t`. */ -zp_read_options_t zp_read_options_default(void); +void zp_read_options_default(zp_read_options_t *options); /** - * Triggers a single execution of reading procedure from the network and processes of any received the message. + * Executes a single read from the network and process received messages. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where trigger the reading procedure. - * options: The options to apply to the read. If ``NULL`` is passed, the default options will be - * applied. + * zs: Pointer to a :c:type:`z_loaned_session_t` to execute the read for. + * options: Pointer to a :c:type:`zp_read_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the reading procedure was executed successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if execution was successful, ``negative value`` otherwise. */ -int8_t zp_read(z_session_t zs, const zp_read_options_t *options); +int8_t zp_read(const z_loaned_session_t *zs, const zp_read_options_t *options); /** - * Constructs the default values for sending the keep alive. + * Builds a :c:type:`zp_send_keep_alive_options_t` with default value. * - * Returns: - * Returns the constructed :c:type:`zp_send_keep_alive_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`zp_send_keep_alive_options_t`. */ -zp_send_keep_alive_options_t zp_send_keep_alive_options_default(void); +void zp_send_keep_alive_options_default(zp_send_keep_alive_options_t *options); /** - * Triggers a single execution of keep alive procedure. - * - * It will send ``KeepAlive`` messages when needed and will close the session when the lease is expired. + * Executes a single send keep alive procedure. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where trigger the leasing procedure. - * options: The options to apply to the send of a ``KeepAlive`` messages. If ``NULL`` is passed, the default options - * will be applied. + * zs: Pointer to a :c:type:`z_loaned_session_t` to execute the send for. + * options: Pointer to a :c:type:`zp_send_keep_alive_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the leasing procedure was executed successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if execution was successful, ``negative value`` otherwise. */ -int8_t zp_send_keep_alive(z_session_t zs, const zp_send_keep_alive_options_t *options); +int8_t zp_send_keep_alive(const z_loaned_session_t *zs, const zp_send_keep_alive_options_t *options); /** - * Constructs the default values for sending the join. + * Builds a :c:type:`zp_send_join_options_t` with default value. * - * Returns: - * Returns the constructed :c:type:`zp_send_join_options_t`. + * Parameters: + * options: Pointer to an uninitialized :c:type:`zp_send_join_options_t`. */ -zp_send_join_options_t zp_send_join_options_default(void); +void zp_send_join_options_default(zp_send_join_options_t *options); /** - * Triggers a single execution of join procedure. + * Builds a :c:type:`z_scout_options_t` with default value. * - * It will send ``Join`` messages. + * Parameters: + * options: Pointer to an uninitialized :c:type:`z_scout_options_t`. + */ +void z_scout_options_default(z_scout_options_t *options); + +/** + * Executes a single send join procedure. * * Parameters: - * zs: A loaned instance of the the :c:type:`z_session_t` where trigger the leasing procedure. - * options: The options to apply to the send of a ``Join`` messages. If ``NULL`` is passed, the default options will - * be applied. + * zs: Pointer to a :c:type:`z_loaned_session_t` to execute the send for. + * options: Pointer to a :c:type:`zp_send_keep_alive_options_t` to configure the operation. * - * Returns: - * Returns ``0`` if the leasing procedure was executed successfully, or a ``negative value`` otherwise. + * Return: + * ``0`` if execution was successful, ``negative value`` otherwise. */ -int8_t zp_send_join(z_session_t zs, const zp_send_join_options_t *options); +int8_t zp_send_join(const z_loaned_session_t *zs, const zp_send_join_options_t *options); #ifdef __cplusplus } diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index dc6fc71aa..1db2306c2 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -11,15 +11,21 @@ // Contributors: // ZettaScale Zenoh Team, // BÅ‚ażej Sowa, - +// #ifndef INCLUDE_ZENOH_PICO_API_TYPES_H #define INCLUDE_ZENOH_PICO_API_TYPES_H +#include "olv_macros.h" #include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/list.h" +#include "zenoh-pico/collections/slice.h" +#include "zenoh-pico/collections/string.h" +#include "zenoh-pico/net/encoding.h" #include "zenoh-pico/net/publish.h" #include "zenoh-pico/net/query.h" +#include "zenoh-pico/net/reply.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/net/session.h" #include "zenoh-pico/net/subscribe.h" #include "zenoh-pico/protocol/core.h" @@ -28,17 +34,6 @@ extern "C" { #endif -/* Owned types */ -#define _OWNED_TYPE_PTR(type, name) \ - typedef struct { \ - type *_value; \ - } z_owned_##name##_t; - -#define _OWNED_TYPE_STR(type, name) \ - typedef struct { \ - type _value; \ - } z_owned_##name##_t; - /** * Represents a variable-length encoding unsigned integer. * @@ -46,6 +41,21 @@ extern "C" { */ typedef _z_zint_t z_zint_t; +/** + * Represents a Zenoh ID. + * + * In general, valid Zenoh IDs are LSB-first 128bit unsigned and non-zero integers. + * + * Members: + * uint8_t id[16]: The array containing the 16 octets of a Zenoh ID. + */ +typedef _z_id_t z_id_t; + +/* + * Represents timestamp value in Zenoh + */ +typedef _z_timestamp_t z_timestamp_t; + /** * Represents an array of bytes. * @@ -53,18 +63,27 @@ typedef _z_zint_t z_zint_t; * size_t len: The length of the bytes array. * uint8_t *start: A pointer to the bytes array. */ -typedef _z_bytes_t z_bytes_t; -_Bool z_bytes_check(const z_bytes_t *v); +_Z_OWNED_TYPE_VALUE(_z_slice_t, slice) /** - * Represents a Zenoh ID. - * - * In general, valid Zenoh IDs are LSB-first 128bit unsigned and non-zero integers. - * - * Members: - * uint8_t id[16]: The array containing the 16 octets of a Zenoh ID. + * Represents a container for slices. */ -typedef _z_id_t z_id_t; +_Z_OWNED_TYPE_VALUE(_z_bytes_t, bytes) + +/** + * Represents a writer for serialized data. + */ +typedef _z_bytes_iterator_writer_t z_bytes_writer_t; + +/** + * An iterator over multi-element serialized data. + */ +typedef _z_bytes_iterator_t z_bytes_iterator_t; + +/** + * A reader for serialized data. + */ +typedef _z_bytes_iterator_t z_bytes_reader_t; /** * Represents a string without null-terminator. @@ -73,204 +92,136 @@ typedef _z_id_t z_id_t; * size_t len: The length of the string. * const char *val: A pointer to the string. */ -typedef _z_string_t z_string_t; - -typedef _z_str_t z_str_t; -_OWNED_TYPE_STR(z_str_t, str) +_Z_OWNED_TYPE_VALUE(_z_string_t, string) +_Z_VIEW_TYPE(_z_string_t, string) /** * Represents a key expression in Zenoh. * - * Operations over :c:type:`z_keyexpr_t` must be done using the provided functions: + * Members are private and operations must be done using the provided functions: * - * - :c:func:`z_keyexpr` - * - :c:func:`z_keyexpr_is_initialized` - * - :c:func:`z_keyexpr_to_string` - * - :c:func:`zp_keyexpr_resolve` + * - :c:func:`z_keyexpr_from_str` + * - :c:func:`z_keyexpr_as_view_string` */ -typedef _z_keyexpr_t z_keyexpr_t; -_OWNED_TYPE_PTR(z_keyexpr_t, keyexpr) +_Z_OWNED_TYPE_VALUE(_z_keyexpr_t, keyexpr) +_Z_VIEW_TYPE(_z_keyexpr_t, keyexpr) /** - * Represents a Zenoh configuration. + * Represents a Zenoh configuration, used to configure Zenoh sessions upon opening. * - * Configurations are usually used to set the parameters of a Zenoh session upon its opening. - * - * Operations over :c:type:`z_config_t` must be done using the provided functions: + * Members are private and operations must be done using the provided functions: * * - :c:func:`z_config_new` * - :c:func:`z_config_default` * - :c:func:`zp_config_get` * - :c:func:`zp_config_insert` */ -typedef struct { - _z_config_t *_val; -} z_config_t; -_OWNED_TYPE_PTR(_z_config_t, config) +_Z_OWNED_TYPE_VALUE(_z_config_t, config) /** - * Represents a scouting configuration. - * - * Configurations are usually used to set the parameters of the scouting procedure. - * - * Operations over :c:type:`z_scouting_config_t` must be done using the provided functions: - * - * - :c:func:`z_scouting_config_default` - * - :c:func:`z_scouting_config_from` - * - :c:func:`zp_scouting_config_get` - * - :c:func:`zp_scouting_config_insert` - */ -typedef struct { - _z_scouting_config_t *_val; -} z_scouting_config_t; -_OWNED_TYPE_PTR(_z_scouting_config_t, scouting_config) - -/** - * Represents a Zenoh session. + * Represents a Zenoh Session. */ -typedef struct { - _z_session_rc_t _val; -} z_session_t; - -typedef struct { - _z_session_rc_t _value; -} z_owned_session_t; +_Z_OWNED_TYPE_RC(_z_session_rc_t, session) /** - * Represents a Zenoh (push) Subscriber entity. + * Represents a Zenoh Subscriber entity. * - * Operations over :c:type:`z_subscriber_t` must be done using the provided functions: + * Members are private and operations must be done using the provided functions: * * - :c:func:`z_declare_subscriber` * - :c:func:`z_undeclare_subscriber` */ -typedef struct { - _z_subscriber_t *_val; -} z_subscriber_t; -_OWNED_TYPE_PTR(_z_subscriber_t, subscriber) - -/** - * Represents a Zenoh Pull Subscriber entity. - * - * Operations over :c:type:`z_pull_subscriber_t` must be done using the provided functions: - * - * - :c:func:`z_declare_pull_subscriber` - * - :c:func:`z_undeclare_pull_subscriber` - * - :c:func:`z_subscriber_pull` - */ -typedef struct { - _z_pull_subscriber_t *_val; -} z_pull_subscriber_t; -_OWNED_TYPE_PTR(_z_pull_subscriber_t, pull_subscriber) +_Z_OWNED_TYPE_VALUE(_z_subscriber_t, subscriber) /** * Represents a Zenoh Publisher entity. * - * Operations over :c:type:`z_publisher_t` must be done using the provided functions: + * Members are private and operations must be done using the provided functions: * * - :c:func:`z_declare_publisher` * - :c:func:`z_undeclare_publisher` * - :c:func:`z_publisher_put` * - :c:func:`z_publisher_delete` */ -typedef struct { - _z_publisher_t *_val; -} z_publisher_t; -_OWNED_TYPE_PTR(_z_publisher_t, publisher) +_Z_OWNED_TYPE_VALUE(_z_publisher_t, publisher) /** * Represents a Zenoh Queryable entity. * - * Operations over :c:type:`z_queryable_t` must be done using the provided functions: + * Members are private and operations must be done using the provided functions: * * - :c:func:`z_declare_queryable` * - :c:func:`z_undeclare_queryable` */ -typedef struct { - _z_queryable_t *_val; -} z_queryable_t; -_OWNED_TYPE_PTR(_z_queryable_t, queryable) +_Z_OWNED_TYPE_VALUE(_z_queryable_t, queryable) /** - * Represents a Zenoh query entity, received by Zenoh Queryable entities. + * Represents a Zenoh Query entity, received by Zenoh Queryable entities. * */ -typedef struct z_query_t { - z_owned_query_t _val; -} z_query_t; +_Z_OWNED_TYPE_RC(_z_query_rc_t, query) /** * Represents the encoding of a payload, in a MIME-like format. * * Members: - * z_encoding_prefix_t prefix: The integer prefix of this encoding. - * z_bytes_t suffix: The suffix of this encoding. It MUST be a valid UTF-8 string. + * uint16_t prefix: The integer prefix of this encoding. + * z_loaned_slice_t* suffix: The suffix of this encoding. It MUST be a valid UTF-8 string. */ -typedef _z_encoding_t z_encoding_t; - -/* - * Represents timestamp value in Zenoh - */ -typedef _z_timestamp_t z_timestamp_t; +_Z_OWNED_TYPE_VALUE(_z_encoding_t, encoding) /** - * Represents a Zenoh value. + * Represents a Zenoh reply error. * * Members: - * z_encoding_t encoding: The encoding of the `payload`. - * z_bytes_t payload: The payload of this zenoh value. + * z_loaned_encoding_t encoding: The encoding of the error `payload`. + * z_loaned_bytes_t* payload: The payload of this zenoh reply error. */ -typedef _z_value_t z_value_t; +_Z_OWNED_TYPE_VALUE(_z_value_t, reply_err) /** - * Represents the set of options that can be applied to a (push) subscriber, - * upon its declaration via :c:func:`z_declare_subscriber`. + * Represents the configuration used to configure a subscriber upon declaration :c:func:`z_declare_subscriber`. * * Members: - * z_reliability_t reliability: The subscription reliability. + * (unstable) z_reliability_t reliability: The subscription reliability value. */ typedef struct { +#ifdef Z_FEATURE_UNSTABLE_API z_reliability_t reliability; +#else + uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior +#endif } z_subscriber_options_t; /** - * Represents the set of options that can be applied to a pull subscriber, - * upon its declaration via :c:func:`z_declare_pull_subscriber`. - * - * Members: - * z_reliability_t reliability: The subscription reliability. - */ -typedef struct { - z_reliability_t reliability; -} z_pull_subscriber_options_t; - -/** - * Represents the replies consolidation to apply on replies to a :c:func:`z_get`. + * Represents the reply consolidation mode to apply on replies to a :c:func:`z_get`. * * Members: - * z_consolidation_mode_t mode: Defines the consolidation mode to apply to the replies. + * z_consolidation_mode_t mode: the consolidation mode, see :c:type:`z_consolidation_mode_t` */ typedef struct { z_consolidation_mode_t mode; } z_query_consolidation_t; /** - * Represents the set of options that can be applied to a publisher, - * upon its declaration via :c:func:`z_declare_publisher`. + * Represents the configuration used to configure a publisher upon declaration with :c:func:`z_declare_publisher`. * * Members: + * z_owned_encoding_t *encoding: Default encoding for messages put by this publisher. * z_congestion_control_t congestion_control: The congestion control to apply when routing messages from this * publisher. * z_priority_t priority: The priority of messages issued by this publisher. + * _Bool is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. */ typedef struct { + z_moved_encoding_t *encoding; z_congestion_control_t congestion_control; z_priority_t priority; + _Bool is_express; } z_publisher_options_t; /** - * Represents the set of options that can be applied to a queryable, - * upon its declaration via :c:func:`z_declare_queryable`. + * Represents the configuration used to configure a queryable upon declaration :c:func:`z_declare_queryable`. * * Members: * _Bool complete: The completeness of the queryable. @@ -280,95 +231,142 @@ typedef struct { } z_queryable_options_t; /** - * Represents the set of options that can be applied to a query reply, - * sent via :c:func:`z_query_reply`. + * Represents the configuration used to configure a query reply sent via :c:func:`z_query_reply. * * Members: - * z_encoding_t encoding: The encoding of the payload. - * z_attachment_t attachment: an attachment to the response. + * z_moved_encoding_t* encoding: The encoding of the payload. + * z_congestion_control_t congestion_control: The congestion control to apply when routing this message. + * z_priority_t priority: The priority of this message when routed. + * z_timestamp_t *timestamp: The API level timestamp (e.g. of the data when it was created). + * _Bool is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. + * z_moved_bytes_t* attachment: An optional attachment to the response. */ typedef struct { - z_encoding_t encoding; -#if Z_FEATURE_ATTACHMENT == 1 - // TODO:ATT z_attachment_t attachment; -#endif + z_moved_encoding_t *encoding; + z_congestion_control_t congestion_control; + z_priority_t priority; + z_timestamp_t *timestamp; + _Bool is_express; + z_moved_bytes_t *attachment; } z_query_reply_options_t; /** - * Represents the set of options that can be applied to the put operation, - * whenever issued via :c:func:`z_put`. + * Represents the configuration used to configure a query reply delete sent via :c:func:`z_query_reply_del. * * Members: - * z_encoding_t encoding: The encoding of the payload. * z_congestion_control_t congestion_control: The congestion control to apply when routing this message. * z_priority_t priority: The priority of this message when routed. + * z_timestamp_t *timestamp: The API level timestamp (e.g. of the data when it was created). + * _Bool is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. + * z_moved_bytes_t* attachment: An optional attachment to the response. */ typedef struct { - z_encoding_t encoding; z_congestion_control_t congestion_control; z_priority_t priority; -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t attachment; -#endif + z_timestamp_t *timestamp; + _Bool is_express; + z_moved_bytes_t *attachment; +} z_query_reply_del_options_t; + +/** + * Represents the configuration used to configure a query reply error sent via :c:func:`z_query_reply_err. + * + * Members: + * z_moved_encoding_t* encoding: The encoding of the payload. + */ +typedef struct { + z_moved_encoding_t *encoding; +} z_query_reply_err_options_t; + +/** + * Represents the configuration used to configure a put operation sent via via :c:func:`z_put`. + * + * Members: + * z_moved_encoding_t* encoding: The encoding of the payload. + * z_congestion_control_t congestion_control: The congestion control to apply when routing this message. + * z_priority_t priority: The priority of this message when routed. + * z_timestamp_t *timestamp: The API level timestamp (e.g. of the data when it was created). + * _Bool is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. + * z_moved_bytes_t* attachment: An optional attachment to the publication. + */ +typedef struct { + z_moved_encoding_t *encoding; + z_congestion_control_t congestion_control; + z_priority_t priority; + z_timestamp_t *timestamp; + _Bool is_express; + z_moved_bytes_t *attachment; } z_put_options_t; /** - * Represents the set of options that can be applied to the delete operation, - * whenever issued via :c:func:`z_delete`. + * Represents the configuration used to configure a delete operation sent via :c:func:`z_delete`. * * Members: * z_congestion_control_t congestion_control: The congestion control to apply when routing this message. * z_priority_t priority: The priority of this message when router. + * _Bool is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. + * z_timestamp_t *timestamp: The API level timestamp (e.g. of the data when it was created). */ typedef struct { z_congestion_control_t congestion_control; z_priority_t priority; + _Bool is_express; + z_timestamp_t *timestamp; } z_delete_options_t; /** - * Represents the set of options that can be applied to the put operation by a previously declared publisher, - * whenever issued via :c:func:`z_publisher_put`. + * Represents the configuration used to configure a put operation by a previously declared publisher, + * sent via :c:func:`z_publisher_put`. * * Members: - * z_encoding_t encoding: The encoding of the payload. + * z_moved_encoding_t* encoding: The encoding of the payload. + * z_timestamp_t *timestamp: The API level timestamp (e.g. of the data when it was created). + * z_moved_bytes_t* attachment: An optional attachment to the publication. */ typedef struct { - z_encoding_t encoding; -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t attachment; -#endif + z_moved_encoding_t *encoding; + z_timestamp_t *timestamp; + z_moved_bytes_t *attachment; } z_publisher_put_options_t; /** - * Represents the set of options that can be applied to the delete operation by a previously declared publisher, - * whenever issued via :c:func:`z_publisher_delete`. + * Represents the configuration used to configure a delete operation by a previously declared publisher, + * sent via :c:func:`z_publisher_delete`. + * + * Members: + * z_timestamp_t *timestamp: The API level timestamp (e.g. of the data when it was created). */ typedef struct { - uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior + z_timestamp_t *timestamp; } z_publisher_delete_options_t; /** - * Represents the set of options that can be applied to the get operation, - * whenever issued via :c:func:`z_get`. + * Represents the configuration used to configure a get operation sent via :c:func:`z_get`. * * Members: - * z_query_target_t target: The queryables that should be targeted by this get. + * z_moved_bytes_t* payload: The payload to include in the query. + * z_moved_encoding_t* encoding: Payload encoding. * z_query_consolidation_t consolidation: The replies consolidation strategy to apply on replies. - * z_value_t value: The payload to include in the query. + * z_congestion_control_t congestion_control: The congestion control to apply when routing the query. + * z_priority_t priority: The priority of the query. + * _Bool is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. + * z_query_target_t target: The queryables that should be targeted by this get. + * z_moved_bytes_t* attachment: An optional attachment to the query. */ typedef struct { - z_value_t value; + z_moved_bytes_t *payload; + z_moved_encoding_t *encoding; z_query_consolidation_t consolidation; + z_congestion_control_t congestion_control; + z_priority_t priority; + _Bool is_express; z_query_target_t target; uint32_t timeout_ms; -#if Z_FEATURE_ATTACHMENT == 1 -// TODO:ATT z_attachment_t attachment; -#endif + z_moved_bytes_t *attachment; } z_get_options_t; /** - * Represents the set of options that can be applied to the read task, - * whenever issued via :c:func:`zp_start_read_task`. + * Represents the configuration used to configure a read task started via :c:func:`zp_start_read_task`. */ typedef struct { #if Z_FEATURE_MULTI_THREAD == 1 @@ -379,8 +377,7 @@ typedef struct { } zp_task_read_options_t; /** - * Represents the set of options that can be applied to the lease task, - * whenever issued via :c:func:`zp_start_lease_task`. + * Represents the configuration used to configure a lease task started via :c:func:`zp_start_lease_task`. */ typedef struct { #if Z_FEATURE_MULTI_THREAD == 1 @@ -391,319 +388,189 @@ typedef struct { } zp_task_lease_options_t; /** - * Represents the set of options that can be applied to the read operation, - * whenever issued via :c:func:`zp_read`. + * Represents the configuration used to configure a read operation started via :c:func:`zp_read`. */ typedef struct { uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior } zp_read_options_t; /** - * Represents the set of options that can be applied to the keep alive send, - * whenever issued via :c:func:`zp_send_keep_alive`. + * Represents the configuration used to configure a send keep alive operation started via :c:func:`zp_send_keep_alive`. */ typedef struct { uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior } zp_send_keep_alive_options_t; /** - * Represents the set of options that can be applied to the join send, - * whenever issued via :c:func:`zp_send_join`. + * Represents the configuration used to configure a send join operation started via :c:func:`zp_send_join`. */ typedef struct { uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior } zp_send_join_options_t; /** - * QoS settings of zenoh message. - */ -typedef _z_qos_t z_qos_t; -/** - * Returns message priority. - */ -static inline z_priority_t z_qos_get_priority(z_qos_t qos) { - z_priority_t ret = _z_n_qos_get_priority(qos); - return ret == _Z_PRIORITY_CONTROL ? Z_PRIORITY_DEFAULT : ret; -} -/** - * Returns message congestion control. - */ -static inline z_congestion_control_t z_qos_get_congestion_control(z_qos_t qos) { - return _z_n_qos_get_congestion_control(qos); -} -/** - * Returns message express flag. If set to true, the message is not batched to reduce the latency. - */ -static inline _Bool z_qos_get_express(z_qos_t qos) { return _z_n_qos_get_express(qos); } -/** - * Returns default qos settings. + * Represents the configuration used to configure a publisher upon declaration with :c:func:`z_declare_publisher`. + * + * Members: + * uint64_t timeout_ms: The maximum duration in ms the scouting can take. + * z_what_t what: Type of entities to scout for. */ -static inline z_qos_t z_qos_default(void) { return _Z_N_QOS_DEFAULT; } +typedef struct { + uint32_t timeout_ms; + z_what_t what; +} z_scout_options_t; /** * Represents a data sample. * - * A sample is the value associated to a given :c:type:`z_keyexpr_t` at a given point in time. + * A sample is the value associated to a given key-expression at a given point in time. * - * Members: - * z_keyexpr_t keyexpr: The keyexpr of this data sample. - * z_bytes_t payload: The value of this data sample. - * z_encoding_t encoding: The encoding of the value of this data sample. - * z_sample_kind_t kind: The kind of this data sample (PUT or DELETE). - * z_timestamp_t timestamp: The timestamp of this data sample. - * z_qos_t qos: Quality of service settings used to deliver this sample. */ -typedef _z_sample_t z_sample_t; +_Z_OWNED_TYPE_VALUE(_z_sample_t, sample) /** * Represents the content of a `hello` message returned by a zenoh entity as a reply to a `scout` message. * * Members: * z_whatami_t whatami: The kind of zenoh entity. - * z_bytes_t zid: The Zenoh ID of the scouted entity (empty if absent). - * z_str_array_t locators: The locators of the scouted entity. - */ -typedef _z_hello_t z_hello_t; -_OWNED_TYPE_PTR(z_hello_t, hello) - -/** - * Represents the content of a reply to a query. - * - * Members: - * z_sample_t sample: The :c:type:`_z_sample_t` containing the key and value of the reply. - * z_bytes_t replier_id: The id of the replier that sent this reply. + * z_loaned_slice_t* zid: The Zenoh ID of the scouted entity (empty if absent). + * z_loaned_string_array_t locators: The locators of the scouted entity. */ -typedef _z_reply_data_t z_reply_data_t; +_Z_OWNED_TYPE_VALUE(_z_hello_t, hello) /** * Represents the reply to a query. - * - * Members: - * z_reply_data_t data: the content of the reply. */ -typedef _z_reply_t z_reply_t; -_OWNED_TYPE_PTR(z_reply_t, reply) +_Z_OWNED_TYPE_VALUE(_z_reply_t, reply) /** - * Represents an array of ``z_str_t``. + * Represents an array of non null-terminated string. * - * Operations over :c:type:`z_str_array_t` must be done using the provided functions: + * Operations over :c:type:`z_loaned_string_array_t` must be done using the provided functions: * - * - ``char *z_str_array_get(z_str_array_t *a, size_t k);`` - * - ``size_t z_str_array_len(z_str_array_t *a);`` - * - ``_Bool z_str_array_array_is_empty(z_str_array_t *a);`` + * - :c:func:`z_string_array_get` + * - :c:func:`z_string_array_len` + * - :c:func:`z_str_array_array_is_empty` */ -typedef _z_str_array_t z_str_array_t; +_Z_OWNED_TYPE_VALUE(_z_string_svec_t, string_array) +_Z_VIEW_TYPE(_z_string_svec_t, string_array) -z_str_t *z_str_array_get(const z_str_array_t *a, size_t k); -size_t z_str_array_len(const z_str_array_t *a); -_Bool z_str_array_is_empty(const z_str_array_t *a); -_OWNED_TYPE_PTR(z_str_array_t, str_array) +const z_loaned_string_t *z_string_array_get(const z_loaned_string_array_t *a, size_t k); +size_t z_string_array_len(const z_loaned_string_array_t *a); +_Bool z_string_array_is_empty(const z_loaned_string_array_t *a); -typedef void (*_z_dropper_handler_t)(void *arg); +typedef void (*z_dropper_handler_t)(void *arg); +typedef _z_data_handler_t z_data_handler_t; +typedef struct { + void *context; + z_data_handler_t call; + z_dropper_handler_t drop; +} _z_closure_sample_t; /** * Represents the sample closure. * * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Members: - * _z_data_handler_t call: `void *call(const struct z_sample_t*, const void *context)` is the callback function. - * _z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. * void *context: a pointer to an arbitrary state. + * z_data_handler_t call: `void *call(const struct z_sample_t*, const void *context)` is the callback function. + * z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. */ -typedef struct { - void *context; - _z_data_handler_t call; - _z_dropper_handler_t drop; -} z_owned_closure_sample_t; +_Z_OWNED_TYPE_VALUE(_z_closure_sample_t, closure_sample) + +void z_closure_sample_call(const z_loaned_closure_sample_t *closure, const z_loaned_sample_t *sample); -void z_closure_sample_call(const z_owned_closure_sample_t *closure, const z_sample_t *sample); +typedef _z_queryable_handler_t z_queryable_handler_t; +typedef struct { + void *context; + z_queryable_handler_t call; + z_dropper_handler_t drop; +} _z_closure_query_t; /** * Represents the query callback closure. * * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Members: + * void *context: a pointer to an arbitrary state. * _z_queryable_handler_t call: `void (*_z_queryable_handler_t)(z_query_t *query, void *arg)` is the * callback function. - * _z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. + * z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. * void *context: a pointer to an arbitrary state. */ -typedef struct { - void *context; - _z_queryable_handler_t call; - _z_dropper_handler_t drop; -} z_owned_closure_query_t; +_Z_OWNED_TYPE_VALUE(_z_closure_query_t, closure_query) -void z_closure_query_call(const z_owned_closure_query_t *closure, const z_query_t *query); +void z_closure_query_call(const z_loaned_closure_query_t *closure, const z_loaned_query_t *query); -typedef void (*z_owned_reply_handler_t)(z_owned_reply_t *reply, void *arg); +typedef _z_reply_handler_t z_reply_handler_t; +typedef struct { + void *context; + z_reply_handler_t call; + z_dropper_handler_t drop; +} _z_closure_reply_t; /** * Represents the query reply callback closure. * * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Members: - * z_owned_reply_handler_t call: `void (*z_owned_reply_handler_t)(z_owned_reply_t reply, void *arg)` is the callback - * function. - * _z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. + * void *context: a pointer to an arbitrary state. + * z_reply_handler_t call: `void (*_z_reply_handler_t)(_z_reply_t *reply, void *arg)` is the + * callback function. + * z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. * void *context: a pointer to an arbitrary state. */ -typedef struct { - void *context; - z_owned_reply_handler_t call; - _z_dropper_handler_t drop; -} z_owned_closure_reply_t; +_Z_OWNED_TYPE_VALUE(_z_closure_reply_t, closure_reply) -void z_closure_reply_call(const z_owned_closure_reply_t *closure, z_owned_reply_t *reply); +void z_closure_reply_call(const z_loaned_closure_reply_t *closure, const z_loaned_reply_t *reply); -typedef void (*z_owned_hello_handler_t)(z_owned_hello_t *hello, void *arg); +typedef void (*z_loaned_hello_handler_t)(const 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_t; /** * Represents the Zenoh ID callback closure. * * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Members: - * z_owned_hello_handler_t call: `void (*z_owned_hello_handler_t)(const z_owned_hello_t *hello, void *arg)` is the + * void *context: a pointer to an arbitrary state. + * z_loaned_hello_handler_t call: `void (*z_loaned_hello_handler_t)(const z_loaned_hello_t *hello, void *arg)` is the * callback function. - * _z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. + * z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. * void *context: a pointer to an arbitrary state. */ -typedef struct { - void *context; - z_owned_hello_handler_t call; - _z_dropper_handler_t drop; -} z_owned_closure_hello_t; +_Z_OWNED_TYPE_VALUE(_z_closure_hello_t, closure_hello) -void z_closure_hello_call(const z_owned_closure_hello_t *closure, z_owned_hello_t *hello); +void z_closure_hello_call(const z_loaned_closure_hello_t *closure, const z_loaned_hello_t *hello); typedef void (*z_id_handler_t)(const z_id_t *id, void *arg); +typedef struct { + void *context; + z_id_handler_t call; + z_dropper_handler_t drop; +} _z_closure_zid_t; /** * Represents the Zenoh ID callback closure. * * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Members: + * void *context: a pointer to an arbitrary state. * z_id_handler_t call: `void (*z_id_handler_t)(const z_id_t *id, void *arg)` is the callback function. - * _z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. + * z_dropper_handler_t drop: `void *drop(void*)` allows the callback's state to be freed. * void *context: a pointer to an arbitrary state. */ -typedef struct { - void *context; - z_id_handler_t call; - _z_dropper_handler_t drop; -} z_owned_closure_zid_t; - -void z_closure_zid_call(const z_owned_closure_zid_t *closure, const z_id_t *id); -#if Z_FEATURE_ATTACHMENT == 1 -struct _z_bytes_pair_t { - _z_bytes_t key; - _z_bytes_t value; -}; - -void _z_bytes_pair_clear(struct _z_bytes_pair_t *this_); - -_Z_ELEM_DEFINE(_z_bytes_pair, struct _z_bytes_pair_t, _z_noop_size, _z_bytes_pair_clear, _z_noop_copy) -_Z_LIST_DEFINE(_z_bytes_pair, struct _z_bytes_pair_t) - -/** - * A map of maybe-owned vector of bytes to maybe-owned vector of bytes. - */ -typedef struct z_owned_bytes_map_t { - _z_bytes_pair_list_t *_inner; -} z_owned_bytes_map_t; - -/** - * Aliases `this` into a generic `z_attachment_t`, allowing it to be passed to corresponding APIs. - */ -z_attachment_t z_bytes_map_as_attachment(const z_owned_bytes_map_t *this_); -/** - * Returns `true` if the map is not in its gravestone state - */ -bool z_bytes_map_check(const z_owned_bytes_map_t *this_); -/** - * Destroys the map, resetting `this` to its gravestone value. - * - * This function is double-free safe, passing a pointer to the gravestone value will have no effect. - */ -void z_bytes_map_drop(z_owned_bytes_map_t *this_); -/** - * Constructs a map from the provided attachment, copying keys and values. - * - * If `this` is at gravestone value, the returned value will also be at gravestone value. - */ -z_owned_bytes_map_t z_bytes_map_from_attachment(z_attachment_t this_); -/** - * Constructs a map from the provided attachment, aliasing the attachment's keys and values. - * - * If `this` is at gravestone value, the returned value will also be at gravestone value. - */ - -z_owned_bytes_map_t z_bytes_map_from_attachment_aliasing(z_attachment_t this_); -/** - * Returns the value associated with `key`, returning a gravestone value if: - * - `this` or `key` is in gravestone state. - * - `this` has no value associated to `key` - */ +_Z_OWNED_TYPE_VALUE(_z_closure_zid_t, closure_zid) -z_bytes_t z_bytes_map_get(const z_owned_bytes_map_t *this_, z_bytes_t key); -/** - * Associates `value` to `key` in the map, aliasing them. - * - * Note that once `key` is aliased, reinserting at the same key may alias the previous instance, or the new instance of - * `key`. - * - * Calling this with `NULL` or the gravestone value is undefined behaviour. - */ - -void z_bytes_map_insert_by_alias(const z_owned_bytes_map_t *this_, z_bytes_t key, z_bytes_t value); -/** - * Associates `value` to `key` in the map, copying them to obtain ownership: `key` and `value` are not aliased past the - * function's return. - * - * Calling this with `NULL` or the gravestone value is undefined behaviour. - */ - -void z_bytes_map_insert_by_copy(const z_owned_bytes_map_t *this_, z_bytes_t key, z_bytes_t value); -/** - * Iterates over the key-value pairs in the map. - * - * `body` will be called once per pair, with `ctx` as its last argument. - * If `body` returns a non-zero value, the iteration will stop immediately and the value will be returned. - * Otherwise, this will return 0 once all pairs have been visited. - * `body` is not given ownership of the key nor value, which alias the pairs in the map. - * It is safe to keep these aliases until existing keys are modified/removed, or the map is destroyed. - * Note that this map is unordered. - * - * Calling this with `NULL` or the gravestone value is undefined behaviour. - */ - -int8_t z_bytes_map_iter(const z_owned_bytes_map_t *this_, z_attachment_iter_body_t body, void *ctx); -/** - * Constructs a new map. - */ -z_owned_bytes_map_t z_bytes_map_new(void); -/** - * Constructs the gravestone value for `z_owned_bytes_map_t` - */ -z_owned_bytes_map_t z_bytes_map_null(void); -#endif - -/** - * Returns a view of `str` using `strlen` (this constructor should not be used on untrusted input). - * - * `str == NULL` will cause this to return `z_bytes_null()` - */ -z_bytes_t z_bytes_from_str(const char *str); -/** - * Returns the gravestone value for `z_bytes_t` - */ -z_bytes_t z_bytes_null(void); +void z_closure_zid_call(const z_loaned_closure_zid_t *closure, const z_id_t *id); #ifdef __cplusplus } diff --git a/include/zenoh-pico/collections/arc_slice.h b/include/zenoh-pico/collections/arc_slice.h new file mode 100644 index 000000000..2e6c1bf67 --- /dev/null +++ b/include/zenoh-pico/collections/arc_slice.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2024 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_COLLECTIONS_ARC_SLICE_H +#define ZENOH_PICO_COLLECTIONS_ARC_SLICE_H + +#include +#include +#include +#include + +#include "refcount.h" +#include "slice.h" +#include "zenoh-pico/system/platform-common.h" + +_Z_REFCOUNT_DEFINE(_z_slice, _z_slice) + +/*-------- ArcSlice --------*/ +/** + * An atomically reference counted subslice. + * + * Members: + * _z_slice_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; + size_t start; + size_t len; +} _z_arc_slice_t; + +_z_arc_slice_t _z_arc_slice_empty(void); +_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_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); +int8_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src); +int8_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src); +int8_t _z_arc_slice_drop(_z_arc_slice_t* s); + +#endif /* ZENOH_PICO_COLLECTIONS_ARC_SLICE_H */ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index 0002bc257..6553fe199 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 ZettaScale Technology +// Copyright (c) 2024 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 @@ -19,35 +19,100 @@ #include #include +#include "arc_slice.h" +#include "vec.h" +#include "zenoh-pico/protocol/iobuf.h" + +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_SVEC_DEFINE(_z_arc_slice, _z_arc_slice_t) + /*-------- Bytes --------*/ /** - * An array of bytes. + * A container for slices. * * Members: - * size_t len: The length of the bytes array. - * uint8_t *val: A pointer to the bytes array. + * _z_slice_vec_t _slices: contents of the container. */ + typedef struct { - size_t len; - const uint8_t *start; - _Bool _is_alloc; + _z_arc_slice_svec_t _slices; } _z_bytes_t; -_z_bytes_t _z_bytes_empty(void); -inline static _Bool _z_bytes_check(_z_bytes_t value) { return value.start != NULL; } -int8_t _z_bytes_init(_z_bytes_t *bs, size_t capacity); -_z_bytes_t _z_bytes_make(size_t capacity); -_z_bytes_t _z_bytes_wrap(const uint8_t *bs, size_t len); -_z_bytes_t _z_bytes_steal(_z_bytes_t *b); - -void _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src); +_Bool _z_bytes_check(const _z_bytes_t *bytes); +_z_bytes_t _z_bytes_null(void); +int8_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src); +int8_t _z_bytes_append_slice(_z_bytes_t *dst, _z_arc_slice_t *s); +int8_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_reset(_z_bytes_t *bs); +void _z_bytes_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); +size_t _z_bytes_len(const _z_bytes_t *bs); _Bool _z_bytes_is_empty(const _z_bytes_t *bs); +int8_t _z_bytes_to_uint8(const _z_bytes_t *bs, uint8_t *u); +int8_t _z_bytes_to_uint16(const _z_bytes_t *bs, uint16_t *u); +int8_t _z_bytes_to_uint32(const _z_bytes_t *bs, uint32_t *u); +int8_t _z_bytes_to_uint64(const _z_bytes_t *bs, uint64_t *u); +int8_t _z_bytes_to_float(const _z_bytes_t *bs, float *f); +int8_t _z_bytes_to_double(const _z_bytes_t *bs, double *d); +int8_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s); +int8_t _z_bytes_from_slice(_z_bytes_t *b, _z_slice_t s); +int8_t _z_bytes_from_uint8(_z_bytes_t *b, uint8_t val); +int8_t _z_bytes_from_uint16(_z_bytes_t *b, uint16_t val); +int8_t _z_bytes_from_uint32(_z_bytes_t *b, uint32_t val); +int8_t _z_bytes_from_uint64(_z_bytes_t *b, uint64_t val); +int8_t _z_bytes_from_float(_z_bytes_t *b, float val); +int8_t _z_bytes_from_double(_z_bytes_t *b, double val); +size_t _z_bytes_to_buf(const _z_bytes_t *bytes, uint8_t *dst, size_t len); +int8_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len); +int8_t _z_bytes_from_pair(_z_bytes_t *out, _z_bytes_t *first, _z_bytes_t *second); +int8_t _z_bytes_deserialize_into_pair(const _z_bytes_t *bs, _z_bytes_t *first_out, _z_bytes_t *second_out); +_z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs); -_Bool _z_bytes_eq(const _z_bytes_t *left, const _z_bytes_t *right); -void _z_bytes_clear(_z_bytes_t *bs); -void _z_bytes_free(_z_bytes_t **bs); +typedef struct { + size_t slice_idx; + size_t in_slice_idx; + size_t byte_idx; + const _z_bytes_t *bytes; +} _z_bytes_reader_t; + +_z_bytes_reader_t _z_bytes_get_reader(const _z_bytes_t *bytes); +int8_t _z_bytes_reader_seek(_z_bytes_reader_t *reader, int64_t offset, int origin); +int64_t _z_bytes_reader_tell(const _z_bytes_reader_t *reader); +int8_t _z_bytes_reader_read_slices(_z_bytes_reader_t *reader, size_t len, _z_bytes_t *out); +size_t _z_bytes_reader_read(_z_bytes_reader_t *reader, uint8_t *buf, size_t len); + +typedef struct { + _z_bytes_reader_t _reader; +} _z_bytes_iterator_t; + +_z_bytes_iterator_t _z_bytes_get_iterator(const _z_bytes_t *bytes); +int8_t _z_bytes_iterator_next(_z_bytes_iterator_t *iter, _z_bytes_t *b); + +typedef struct { + uint8_t *cache; + size_t cache_size; + _z_bytes_t *bytes; +} _z_bytes_writer_t; + +_z_bytes_writer_t _z_bytes_get_writer(_z_bytes_t *bytes, size_t cache_size); +int8_t _z_bytes_writer_write_all(_z_bytes_writer_t *writer, const uint8_t *src, size_t len); +int8_t _z_bytes_writer_append(_z_bytes_writer_t *writer, _z_bytes_t *bytes); +int8_t _z_bytes_writer_ensure_cache(_z_bytes_writer_t *writer); + +typedef struct { + _z_bytes_writer_t writer; +} _z_bytes_iterator_writer_t; +_z_bytes_iterator_writer_t _z_bytes_get_iterator_writer(_z_bytes_t *bytes, size_t cache_size); +int8_t _z_bytes_iterator_writer_write(_z_bytes_iterator_writer_t *writer, _z_bytes_t *bytes); #endif /* ZENOH_PICO_COLLECTIONS_BYTES_H */ diff --git a/include/zenoh-pico/collections/element.h b/include/zenoh-pico/collections/element.h index 96a62e4eb..94a71403d 100644 --- a/include/zenoh-pico/collections/element.h +++ b/include/zenoh-pico/collections/element.h @@ -19,12 +19,14 @@ #include #include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/result.h" /*-------- element functions --------*/ typedef size_t (*z_element_size_f)(void *e); typedef void (*z_element_clear_f)(void *e); typedef void (*z_element_free_f)(void **e); typedef void (*z_element_copy_f)(void *dst, const void *src); +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); @@ -61,8 +63,13 @@ static inline void _z_noop_clear(void *s) { (void)(s); } static inline void _z_noop_free(void **s) { (void)(s); } static inline void _z_noop_copy(void *dst, const void *src) { - (void)(dst); - (void)(src); + _ZP_UNUSED(dst); + _ZP_UNUSED(src); +} + +static inline void _z_noop_move(void *dst, void *src) { + _ZP_UNUSED(dst); + _ZP_UNUSED(src); } _Z_ELEM_DEFINE(_z_noop, _z_noop_t, _z_noop_size, _z_noop_clear, _z_noop_copy) diff --git a/include/zenoh-pico/collections/fifo.h b/include/zenoh-pico/collections/fifo.h new file mode 100644 index 000000000..23562e460 --- /dev/null +++ b/include/zenoh-pico/collections/fifo.h @@ -0,0 +1,63 @@ +// +// 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_COLLECTIONS_FIFO_H +#define ZENOH_PICO_COLLECTIONS_FIFO_H + +#include +#include + +#include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/ring.h" + +/*-------- Fifo Buffer --------*/ +typedef struct { + _z_ring_t _ring; +} _z_fifo_t; + +int8_t _z_fifo_init(_z_fifo_t *fifo, size_t capacity); +_z_fifo_t _z_fifo_make(size_t capacity); + +size_t _z_fifo_capacity(const _z_fifo_t *r); +size_t _z_fifo_len(const _z_fifo_t *r); +_Bool _z_fifo_is_empty(const _z_fifo_t *r); +_Bool _z_fifo_is_full(const _z_fifo_t *r); + +void *_z_fifo_push(_z_fifo_t *r, void *e); +void _z_fifo_push_drop(_z_fifo_t *r, void *e, z_element_free_f f); +void *_z_fifo_pull(_z_fifo_t *r); + +_z_fifo_t *_z_fifo_clone(const _z_fifo_t *xs, z_element_clone_f d_f); + +void _z_fifo_clear(_z_fifo_t *v, z_element_free_f f); +void _z_fifo_free(_z_fifo_t **xs, z_element_free_f f_f); + +#define _Z_FIFO_DEFINE(name, type) \ + typedef _z_fifo_t name##_fifo_t; \ + static inline int8_t name##_fifo_init(name##_fifo_t *fifo, size_t capacity) { \ + return _z_fifo_init(fifo, capacity); \ + } \ + static inline name##_fifo_t name##_fifo_make(size_t capacity) { return _z_fifo_make(capacity); } \ + static inline size_t name##_fifo_capacity(const name##_fifo_t *r) { return _z_fifo_capacity(r); } \ + static inline size_t name##_fifo_len(const name##_fifo_t *r) { return _z_fifo_len(r); } \ + static inline _Bool name##_fifo_is_empty(const name##_fifo_t *r) { return _z_fifo_is_empty(r); } \ + static inline _Bool name##_fifo_is_full(const name##_fifo_t *r) { return _z_fifo_is_full(r); } \ + static inline type *name##_fifo_push(name##_fifo_t *r, type *e) { return _z_fifo_push(r, (void *)e); } \ + static inline void name##_fifo_push_drop(name##_fifo_t *r, type *e) { \ + _z_fifo_push_drop(r, (void *)e, name##_elem_free); \ + } \ + static inline type *name##_fifo_pull(name##_fifo_t *r) { return (type *)_z_fifo_pull(r); } \ + 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); } + +#endif /* ZENOH_PICO_COLLECTIONS_FIFO_H */ diff --git a/include/zenoh-pico/collections/fifo_mt.h b/include/zenoh-pico/collections/fifo_mt.h new file mode 100644 index 000000000..3257c7704 --- /dev/null +++ b/include/zenoh-pico/collections/fifo_mt.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2024 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_COLLECTIONS_FIFO_MT_H +#define ZENOH_PICO_COLLECTIONS_FIFO_MT_H + +#include + +#include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/fifo.h" +#include "zenoh-pico/system/platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*-------- Fifo Buffer Multithreaded --------*/ +typedef struct { + _z_fifo_t _fifo; + _Bool is_closed; +#if Z_FEATURE_MULTI_THREAD == 1 + _z_mutex_t _mutex; + _z_condvar_t _cv_not_full; + _z_condvar_t _cv_not_empty; +#endif +} _z_fifo_mt_t; + +int8_t _z_fifo_mti_init(size_t capacity); +_z_fifo_mt_t *_z_fifo_mt_new(size_t capacity); + +int8_t _z_fifo_mt_close(_z_fifo_mt_t *fifo); +void _z_fifo_mt_clear(_z_fifo_mt_t *fifo, z_element_free_f free_f); +void _z_fifo_mt_free(_z_fifo_mt_t *fifo, z_element_free_f free_f); + +int8_t _z_fifo_mt_push(const void *src, void *context, z_element_free_f element_free); + +int8_t _z_fifo_mt_pull(void *dst, void *context, z_element_move_f element_move); +int8_t _z_fifo_mt_try_pull(void *dst, void *context, z_element_move_f element_move); + +#ifdef __cplusplus +} +#endif + +#endif // ZENOH_PICO_COLLECTIONS_FIFO_MT_H diff --git a/include/zenoh-pico/collections/intmap.h b/include/zenoh-pico/collections/intmap.h index caa54e035..c3c853670 100644 --- a/include/zenoh-pico/collections/intmap.h +++ b/include/zenoh-pico/collections/intmap.h @@ -61,6 +61,9 @@ size_t _z_int_void_map_capacity(const _z_int_void_map_t *map); size_t _z_int_void_map_len(const _z_int_void_map_t *map); _Bool _z_int_void_map_is_empty(const _z_int_void_map_t *map); +int8_t _z_int_void_map_copy(_z_int_void_map_t *dst, const _z_int_void_map_t *src, z_element_clone_f f_c); +_z_int_void_map_t _z_int_void_map_clone(const _z_int_void_map_t *src, z_element_clone_f f_c, z_element_free_f f_f); + void _z_int_void_map_clear(_z_int_void_map_t *map, z_element_free_f f); void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); @@ -74,6 +77,13 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); *e = NULL; \ } \ } \ + static inline void *name##_intmap_entry_elem_clone(const void *e) { \ + const name##_intmap_entry_t *src = (name##_intmap_entry_t *)e; \ + name##_intmap_entry_t *dst = (name##_intmap_entry_t *)z_malloc(sizeof(name##_intmap_entry_t)); \ + dst->_key = src->_key; \ + dst->_val = name##_elem_clone(src->_val); \ + return dst; \ + } \ typedef _z_int_void_map_t name##_intmap_t; \ static inline void name##_intmap_init(name##_intmap_t *m) { \ _z_int_void_map_init(m, _Z_DEFAULT_INT_MAP_CAPACITY); \ @@ -87,6 +97,9 @@ void _z_int_void_map_free(_z_int_void_map_t **map, z_element_free_f f); static inline type *name##_intmap_get(const name##_intmap_t *m, size_t k) { \ return (type *)_z_int_void_map_get(m, k); \ } \ + static inline name##_intmap_t name##_intmap_clone(const name##_intmap_t *m) { \ + return _z_int_void_map_clone(m, name##_intmap_entry_elem_clone, name##_intmap_entry_elem_free); \ + } \ static inline void name##_intmap_remove(name##_intmap_t *m, size_t k) { \ _z_int_void_map_remove(m, k, name##_intmap_entry_elem_free); \ } \ diff --git a/include/zenoh-pico/collections/lifo.h b/include/zenoh-pico/collections/lifo.h new file mode 100644 index 000000000..caba25d18 --- /dev/null +++ b/include/zenoh-pico/collections/lifo.h @@ -0,0 +1,64 @@ +// +// 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_COLLECTIONS_LIFO_H +#define ZENOH_PICO_COLLECTIONS_LIFO_H + +#include +#include + +#include "zenoh-pico/collections/element.h" + +/*-------- Ring Buffer --------*/ +typedef struct { + void **_val; + size_t _capacity; + size_t _len; +} _z_lifo_t; + +int8_t _z_lifo_init(_z_lifo_t *lifo, size_t capacity); +_z_lifo_t _z_lifo_make(size_t capacity); + +size_t _z_lifo_capacity(const _z_lifo_t *r); +size_t _z_lifo_len(const _z_lifo_t *r); +_Bool _z_lifo_is_empty(const _z_lifo_t *r); +_Bool _z_lifo_is_full(const _z_lifo_t *r); + +void *_z_lifo_push(_z_lifo_t *r, void *e); +void _z_lifo_push_drop(_z_lifo_t *r, void *e, z_element_free_f f); +void *_z_lifo_pull(_z_lifo_t *r); + +_z_lifo_t *_z_lifo_clone(const _z_lifo_t *xs, z_element_clone_f d_f); + +void _z_lifo_clear(_z_lifo_t *v, z_element_free_f f); +void _z_lifo_free(_z_lifo_t **xs, z_element_free_f f_f); + +#define _Z_LIFO_DEFINE(name, type) \ + typedef _z_lifo_t name##_lifo_t; \ + static inline int8_t name##_lifo_init(name##_lifo_t *lifo, size_t capacity) { \ + return _z_lifo_init(lifo, capacity); \ + } \ + static inline name##_lifo_t name##_lifo_make(size_t capacity) { return _z_lifo_make(capacity); } \ + static inline size_t name##_lifo_capacity(const name##_lifo_t *r) { return _z_lifo_capacity(r); } \ + static inline size_t name##_lifo_len(const name##_lifo_t *r) { return _z_lifo_len(r); } \ + static inline _Bool name##_lifo_is_empty(const name##_lifo_t *r) { return _z_lifo_is_empty(r); } \ + static inline _Bool name##_lifo_is_full(const name##_lifo_t *r) { return _z_lifo_is_full(r); } \ + static inline type *name##_lifo_push(name##_lifo_t *r, type *e) { return _z_lifo_push(r, (void *)e); } \ + static inline void name##_lifo_push_drop(name##_lifo_t *r, type *e) { \ + _z_lifo_push_drop(r, (void *)e, name##_elem_free); \ + } \ + static inline type *name##_lifo_pull(name##_lifo_t *r) { return (type *)_z_lifo_pull(r); } \ + 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); } + +#endif /* ZENOH_PICO_COLLECTIONS_LIFO_H */ diff --git a/include/zenoh-pico/collections/refcount.h b/include/zenoh-pico/collections/refcount.h index 76e186f74..167ca734a 100644 --- a/include/zenoh-pico/collections/refcount.h +++ b/include/zenoh-pico/collections/refcount.h @@ -14,131 +14,162 @@ #ifndef ZENOH_PICO_COLLECTIONS_REFCOUNT_H #define ZENOH_PICO_COLLECTIONS_REFCOUNT_H - #include +#include #include -#if Z_FEATURE_MULTI_THREAD == 1 -#if ZENOH_C_STANDARD != 99 - -#ifndef __cplusplus -#include -#define _z_atomic(X) _Atomic X -#define _z_atomic_store_explicit atomic_store_explicit -#define _z_atomic_fetch_add_explicit atomic_fetch_add_explicit -#define _z_atomic_fetch_sub_explicit atomic_fetch_sub_explicit -#define _z_memory_order_acquire memory_order_acquire -#define _z_memory_order_release memory_order_release -#define _z_memory_order_relaxed memory_order_relaxed -#else -#include -#define _z_atomic(X) std::atomic -#define _z_atomic_store_explicit std::atomic_store_explicit -#define _z_atomic_fetch_add_explicit std::atomic_fetch_add_explicit -#define _z_atomic_fetch_sub_explicit std::atomic_fetch_sub_explicit -#define _z_memory_order_acquire std::memory_order_acquire -#define _z_memory_order_release std::memory_order_release -#define _z_memory_order_relaxed std::memory_order_relaxed -#endif // __cplusplus - -// c11 atomic variant -#define _ZP_RC_CNT_TYPE _z_atomic(unsigned int) -#define _ZP_RC_OP_INIT_CNT _z_atomic_store_explicit(&p.in->_cnt, (unsigned int)1, _z_memory_order_relaxed); -#define _ZP_RC_OP_INCR_CNT _z_atomic_fetch_add_explicit(&p->in->_cnt, (unsigned int)1, _z_memory_order_relaxed); -#define _ZP_RC_OP_DECR_AND_CMP \ - _z_atomic_fetch_sub_explicit(&p->in->_cnt, (unsigned int)1, _z_memory_order_release) > (unsigned int)1 -#define _ZP_RC_OP_SYNC atomic_thread_fence(_z_memory_order_acquire); - -#else // ZENOH_C_STANDARD == 99 -#ifdef ZENOH_COMPILER_GCC +#include "zenoh-pico/utils/result.h" -// c99 gcc sync builtin variant -#define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT \ - __sync_fetch_and_and(&p.in->_cnt, (unsigned int)0); \ - __sync_fetch_and_add(&p.in->_cnt, (unsigned int)1); -#define _ZP_RC_OP_INCR_CNT __sync_fetch_and_add(&p->in->_cnt, (unsigned int)1); -#define _ZP_RC_OP_DECR_AND_CMP __sync_fetch_and_sub(&p->in->_cnt, (unsigned int)1) > (unsigned int)1 -#define _ZP_RC_OP_SYNC __sync_synchronize(); +#ifdef __cplusplus +extern "C" { +#endif -#else // !ZENOH_COMPILER_GCC +int8_t _z_rc_init(void **cnt); +int8_t _z_rc_increase_strong(void *cnt); +int8_t _z_rc_increase_weak(void *cnt); +_Bool _z_rc_decrease_strong(void **cnt); +_Bool _z_rc_decrease_weak(void **cnt); +int8_t _z_rc_weak_upgrade(void *cnt); -// 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 -#define _ZP_RC_OP_INCR_CNT -#define _ZP_RC_OP_DECR_AND_CMP -#define _ZP_RC_OP_SYNC - -#endif // ZENOH_COMPILER_GCC -#endif // ZENOH_C_STANDARD != 99 -#else // Z_FEATURE_MULTI_THREAD == 0 - -// Single thread variant -#define _ZP_RC_CNT_TYPE unsigned int -#define _ZP_RC_OP_INIT_CNT p.in->_cnt = (unsigned int)1; -#define _ZP_RC_OP_INCR_CNT p->in->_cnt += (unsigned int)1; -#define _ZP_RC_OP_DECR_AND_CMP p->in->_cnt-- > (unsigned int)1 -#define _ZP_RC_OP_SYNC - -#endif // Z_FEATURE_MULTI_THREAD == 1 +size_t _z_rc_weak_count(void *cnt); +size_t _z_rc_strong_count(void *cnt); /*------------------ Internal Array Macros ------------------*/ -#define _Z_REFCOUNT_DEFINE(name, type) \ - typedef struct name##_inner_rc_t { \ - type##_t val; \ - _ZP_RC_CNT_TYPE _cnt; \ - } name##_inner_rc_t; \ - typedef struct name##_rc_t { \ - name##_inner_rc_t *in; \ - } name##_rc_t; \ - static inline name##_rc_t name##_rc_new(void) { \ - name##_rc_t p; \ - p.in = (name##_inner_rc_t *)z_malloc(sizeof(name##_inner_rc_t)); \ - if (p.in != NULL) { \ - memset(&p.in->val, 0, sizeof(type##_t)); \ - _ZP_RC_OP_INIT_CNT \ - } \ - return p; \ - } \ - static inline name##_rc_t name##_rc_new_from_val(type##_t val) { \ - name##_rc_t p; \ - p.in = (name##_inner_rc_t *)z_malloc(sizeof(name##_inner_rc_t)); \ - if (p.in != NULL) { \ - p.in->val = val; \ - _ZP_RC_OP_INIT_CNT \ - } \ - return p; \ - } \ - static inline name##_rc_t name##_rc_clone(name##_rc_t *p) { \ - name##_rc_t c; \ - c.in = p->in; \ - _ZP_RC_OP_INCR_CNT \ - return c; \ - } \ - static inline name##_rc_t *name##_rc_clone_as_ptr(name##_rc_t *p) { \ - name##_rc_t *c = (name##_rc_t *)z_malloc(sizeof(name##_rc_t)); \ - if (c != NULL) { \ - c->in = p->in; \ - _ZP_RC_OP_INCR_CNT \ - } \ - return c; \ - } \ - static inline _Bool name##_rc_eq(const name##_rc_t *left, const name##_rc_t *right) { \ - return (left->in == right->in); \ - } \ - static inline _Bool name##_rc_drop(name##_rc_t *p) { \ - if ((p == NULL) || (p->in == NULL)) { \ - return false; \ - } \ - if (_ZP_RC_OP_DECR_AND_CMP) { \ - return false; \ - } \ - _ZP_RC_OP_SYNC \ - type##_clear(&p->in->val); \ - z_free(p->in); \ - return true; \ +#define _Z_REFCOUNT_DEFINE(name, type) \ + typedef struct name##_rc_t { \ + type##_t *_val; \ + void *_cnt; \ + } name##_rc_t; \ + \ + typedef struct name##_weak_t { \ + type##_t *_val; \ + 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_new(type##_t *val) { \ + name##_rc_t p = name##_rc_null(); \ + if (_z_rc_init(&p._cnt) == _Z_RES_OK) { \ + p._val = val; \ + } \ + return p; \ + } \ + static inline name##_rc_t name##_rc_new_from_val(const type##_t *val) { \ + type##_t *v = (type##_t *)z_malloc(sizeof(type##_t)); \ + if (v == NULL) { \ + return name##_rc_null(); \ + } \ + *v = *val; \ + name##_rc_t p = name##_rc_new(v); \ + if (p._cnt == NULL) { \ + z_free(v); \ + return name##_rc_null(); \ + } \ + 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 c; \ + } \ + 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)); \ + if (c != NULL) { \ + *c = name##_rc_clone(p); \ + if (c->_cnt == NULL) { \ + z_free(c); \ + } \ + } \ + 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 c; \ + } \ + 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)); \ + if (c != NULL) { \ + *c = name##_rc_clone_as_weak(p); \ + if (c->_cnt == NULL) { \ + z_free(c); \ + } \ + } \ + return c; \ + } \ + static inline void name##_rc_copy(name##_rc_t *dst, const name##_rc_t *p) { *dst = name##_rc_clone(p); } \ + static inline _Bool name##_rc_eq(const name##_rc_t *left, const name##_rc_t *right) { \ + return (left->_val == right->_val); \ + } \ + static inline _Bool name##_rc_decr(name##_rc_t *p) { \ + if ((p == NULL) || (p->_cnt == NULL)) { \ + return false; \ + } \ + if (_z_rc_decrease_strong(&p->_cnt)) { \ + return true; \ + } \ + return false; \ + } \ + static inline _Bool name##_rc_drop(name##_rc_t *p) { \ + if (name##_rc_decr(p) && p->_val != NULL) { \ + type##_clear(p->_val); \ + z_free(p->_val); \ + return true; \ + } \ + return false; \ + } \ + 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 c; \ + } \ + 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(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 c; \ + } \ + static inline _Bool name##_weak_eq(const name##_weak_t *left, const name##_weak_t *right) { \ + return (left->_val == right->_val); \ + } \ + static inline _Bool name##_weak_drop(name##_weak_t *p) { \ + if ((p == NULL) || (p->_cnt == NULL)) { \ + return false; \ + } \ + if (_z_rc_decrease_weak(&p->_cnt)) { \ + return true; \ + } \ + return false; \ + } \ + static inline size_t name##_rc_size(name##_rc_t *p) { \ + _ZP_UNUSED(p); \ + return sizeof(name##_rc_t); \ } +#ifdef __cplusplus +} +#endif + #endif /* ZENOH_PICO_COLLECTIONS_REFCOUNT_H */ diff --git a/include/zenoh-pico/collections/ring.h b/include/zenoh-pico/collections/ring.h new file mode 100644 index 000000000..3cdcc057c --- /dev/null +++ b/include/zenoh-pico/collections/ring.h @@ -0,0 +1,68 @@ +// +// 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_COLLECTIONS_RING_H +#define ZENOH_PICO_COLLECTIONS_RING_H + +#include +#include + +#include "zenoh-pico/collections/element.h" + +/*-------- Ring Buffer --------*/ +typedef struct { + void **_val; + size_t _capacity; + size_t _len; + size_t _r_idx; + size_t _w_idx; +} _z_ring_t; + +int8_t _z_ring_init(_z_ring_t *ring, size_t capacity); +_z_ring_t _z_ring_make(size_t capacity); + +size_t _z_ring_capacity(const _z_ring_t *r); +size_t _z_ring_len(const _z_ring_t *r); +bool _z_ring_is_empty(const _z_ring_t *r); +bool _z_ring_is_full(const _z_ring_t *r); + +void *_z_ring_push(_z_ring_t *r, void *e); +void *_z_ring_push_force(_z_ring_t *r, void *e); +void _z_ring_push_force_drop(_z_ring_t *r, void *e, z_element_free_f f); +void *_z_ring_pull(_z_ring_t *r); + +_z_ring_t *_z_ring_clone(const _z_ring_t *xs, z_element_clone_f d_f); + +void _z_ring_clear(_z_ring_t *v, z_element_free_f f); +void _z_ring_free(_z_ring_t **xs, z_element_free_f f_f); + +#define _Z_RING_DEFINE(name, type) \ + typedef _z_ring_t name##_ring_t; \ + static inline int8_t name##_ring_init(name##_ring_t *ring, size_t capacity) { \ + return _z_ring_init(ring, capacity); \ + } \ + static inline name##_ring_t name##_ring_make(size_t capacity) { return _z_ring_make(capacity); } \ + static inline size_t name##_ring_capacity(const name##_ring_t *r) { return _z_ring_capacity(r); } \ + static inline size_t name##_ring_len(const name##_ring_t *r) { return _z_ring_len(r); } \ + static inline bool name##_ring_is_empty(const name##_ring_t *r) { return _z_ring_is_empty(r); } \ + static inline bool name##_ring_is_full(const name##_ring_t *r) { return _z_ring_is_full(r); } \ + static inline type *name##_ring_push(name##_ring_t *r, type *e) { return _z_ring_push(r, (void *)e); } \ + static inline type *name##_ring_push_force(name##_ring_t *r, type *e) { return _z_ring_push_force(r, (void *)e); } \ + static inline void name##_ring_push_force_drop(name##_ring_t *r, type *e) { \ + _z_ring_push_force_drop(r, (void *)e, name##_elem_free); \ + } \ + static inline type *name##_ring_pull(name##_ring_t *r) { return (type *)_z_ring_pull(r); } \ + 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); } + +#endif /* ZENOH_PICO_COLLECTIONS_RING_H */ diff --git a/include/zenoh-pico/collections/ring_mt.h b/include/zenoh-pico/collections/ring_mt.h new file mode 100644 index 000000000..a7702e017 --- /dev/null +++ b/include/zenoh-pico/collections/ring_mt.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2024 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_COLLECTIONS_RING_MT_H +#define ZENOH_PICO_COLLECTIONS_RING_MT_H + +#include + +#include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/fifo.h" +#include "zenoh-pico/system/platform.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/*-------- Ring Buffer Multithreaded --------*/ +typedef struct { + _z_ring_t _ring; + _Bool is_closed; +#if Z_FEATURE_MULTI_THREAD == 1 + _z_mutex_t _mutex; + _z_condvar_t _cv_not_empty; +#endif +} _z_ring_mt_t; + +int8_t _z_ring_mt_init(_z_ring_mt_t *ring, size_t capacity); +_z_ring_mt_t *_z_ring_mt_new(size_t capacity); +int8_t _z_ring_mt_close(_z_ring_mt_t *ring); + +void _z_ring_mt_clear(_z_ring_mt_t *ring, z_element_free_f free_f); +void _z_ring_mt_free(_z_ring_mt_t *ring, z_element_free_f free_f); + +int8_t _z_ring_mt_push(const void *src, void *context, z_element_free_f element_free); + +int8_t _z_ring_mt_pull(void *dst, void *context, z_element_move_f element_move); +int8_t _z_ring_mt_try_pull(void *dst, void *context, z_element_move_f element_move); + +#ifdef __cplusplus +} +#endif + +#endif // ZENOH_PICO_COLLECTIONS_RING_MT_H diff --git a/include/zenoh-pico/collections/slice.h b/include/zenoh-pico/collections/slice.h new file mode 100644 index 000000000..7edd952e8 --- /dev/null +++ b/include/zenoh-pico/collections/slice.h @@ -0,0 +1,68 @@ +// +// 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_COLLECTIONS_SLICE_H +#define ZENOH_PICO_COLLECTIONS_SLICE_H + +#include +#include +#include + +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); +_z_delete_context_t _z_delete_context_default(void); +void _z_delete_context_delete(_z_delete_context_t *c, void *data); + +/*-------- Slice --------*/ +/** + * An array of bytes. + * + * Members: + * size_t len: The length of the bytes array. + * uint8_t *start: A pointer to the bytes array. + * _z_delete_context_t delete_context - context used to delete the data. + */ +typedef struct { + size_t len; + const uint8_t *start; + _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; } +int8_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); +int8_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src); +int8_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); + +#endif /* ZENOH_PICO_COLLECTIONS_SLICE_H */ diff --git a/include/zenoh-pico/collections/string.h b/include/zenoh-pico/collections/string.h index 38fe3d334..4d6268bb6 100644 --- a/include/zenoh-pico/collections/string.h +++ b/include/zenoh-pico/collections/string.h @@ -15,16 +15,17 @@ #define ZENOH_PICO_COLLECTIONS_STRING_H #include "zenoh-pico/collections/array.h" -#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/intmap.h" #include "zenoh-pico/collections/list.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" /*-------- str --------*/ typedef char *_z_str_t; char *_z_str_clone(const char *src); +char *_z_str_n_clone(const char *src, size_t len); void _z_str_clear(char *src); void _z_str_free(char **src); _Bool _z_str_eq(const char *left, const char *right); @@ -33,10 +34,7 @@ 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_ARRAY_DEFINE(_z_str, char *) -// This is here for reference on why -// the _z_str_array_t was not defined using this macro -// but instead manually as find below + _Z_VEC_DEFINE(_z_str, char) _Z_LIST_DEFINE(_z_str, char) _Z_INT_MAP_DEFINE(_z_str, char) @@ -63,46 +61,43 @@ int8_t _z_str_intmap_from_strn(_z_str_intmap_t *strint, const char *s, uint8_t a /** * A string with no terminator. * - * Members: - * size_t len: The length of the string. - * const char *val: A pointer to the string. */ typedef struct { - size_t len; - char *val; + _z_slice_t _slice; } _z_string_t; -_z_string_t _z_string_make(const char *value); -void _z_string_copy(_z_string_t *dst, const _z_string_t *src); +_z_string_t _z_string_null(void); +_Bool _z_string_check(const _z_string_t *value); +_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_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); +_Bool _z_string_is_empty(const _z_string_t *s); +const char *_z_string_rchr(_z_string_t *str, char filter); +char *_z_string_pbrk(_z_string_t *str, const char *filter); + +size_t _z_string_len(const _z_string_t *s); +const char *_z_string_data(const _z_string_t *s); +int8_t _z_string_copy(_z_string_t *dst, const _z_string_t *src); +int8_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); -_z_string_t _z_string_from_bytes(const _z_bytes_t *bs); +_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_preallocate(const size_t len); -/*-------- str_array --------*/ -/** - * An array of NULL terminated strings. - * - * Members: - * size_t len: The length of the array. - * char **_val: A pointer to the array. - */ -typedef struct { - size_t len; - char **val; -} _z_str_array_t; - -_z_str_array_t _z_str_array_empty(void); -_z_str_array_t _z_str_array_make(size_t len); -void _z_str_array_init(_z_str_array_t *sa, size_t len); -char **_z_str_array_get(const _z_str_array_t *sa, size_t pos); -size_t _z_str_array_len(const _z_str_array_t *sa); -_Bool _z_str_array_is_empty(const _z_str_array_t *sa); -void _z_str_array_copy(_z_str_array_t *dst, const _z_str_array_t *src); -void _z_str_array_move(_z_str_array_t *dst, _z_str_array_t *src); -void _z_str_array_clear(_z_str_array_t *sa); -void _z_str_array_free(_z_str_array_t **sa); +_Z_ELEM_DEFINE(_z_string, _z_string_t, _z_string_len, _z_string_clear, _z_string_copy) + +static inline void _z_string_elem_move(void *dst, void *src) { _z_string_move((_z_string_t *)dst, (_z_string_t *)src); } +_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) #endif /* ZENOH_PICO_COLLECTIONS_STRING_H */ diff --git a/include/zenoh-pico/collections/vec.h b/include/zenoh-pico/collections/vec.h index a6bcdb71d..066b72cbb 100644 --- a/include/zenoh-pico/collections/vec.h +++ b/include/zenoh-pico/collections/vec.h @@ -21,7 +21,7 @@ /*-------- Dynamically allocated vector --------*/ /** - * A dynamically allocate vector. + * A dynamically allocated vector. Elements are stored as pointers. */ typedef struct { size_t _capacity; @@ -43,6 +43,7 @@ void _z_vec_remove(_z_vec_t *sv, size_t pos, z_element_free_f f); void _z_vec_reset(_z_vec_t *v, z_element_free_f f); void _z_vec_clear(_z_vec_t *v, z_element_free_f f); void _z_vec_free(_z_vec_t **v, z_element_free_f f); +void _z_vec_release(_z_vec_t *v); #define _Z_VEC_DEFINE(name, type) \ typedef _z_vec_t name##_vec_t; \ @@ -60,6 +61,57 @@ void _z_vec_free(_z_vec_t **v, z_element_free_f f); } \ 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); } + static inline void name##_vec_free(name##_vec_t **v) { _z_vec_free(v, name##_elem_free); } \ + static inline void name##_vec_release(name##_vec_t *v) { _z_vec_release(v); } + +/*-------- Dynamically allocated sized vector --------*/ +/** + * A dynamically allocated vector. Elements are stored by value. + */ +typedef struct { + size_t _capacity; + size_t _len; + void *_val; +} _z_svec_t; + +_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); + +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); +void *_z_svec_get(const _z_svec_t *v, size_t pos, 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_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)); } \ + static inline void name##_svec_free(name##_svec_t **v) { _z_svec_free(v, name##_elem_clear, sizeof(type)); } #endif /* ZENOH_PICO_COLLECTIONS_VECTOR_H */ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 041f3a36b..de3cb138e 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -15,6 +15,33 @@ #ifndef INCLUDE_ZENOH_PICO_CONFIG_H #define INCLUDE_ZENOH_PICO_CONFIG_H +/*--- CMake generated config; pass values to CMake to change the following tokens ---*/ +#define Z_FRAG_MAX_SIZE 300000 +#define Z_BATCH_UNICAST_SIZE 65535 +#define Z_BATCH_MULTICAST_SIZE 8096 +#define Z_CONFIG_SOCKET_TIMEOUT 100 + +#define Z_FEATURE_MULTI_THREAD 1 +#define Z_FEATURE_PUBLICATION 1 +#define Z_FEATURE_SUBSCRIPTION 1 +#define Z_FEATURE_QUERY 1 +#define Z_FEATURE_QUERYABLE 1 +#define Z_FEATURE_RAWETH_TRANSPORT 0 +#define Z_FEATURE_INTEREST 1 +#define Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION 0 +#define Z_FEATURE_LINK_TCP 1 +#define Z_FEATURE_LINK_BLUETOOTH 0 +#define Z_FEATURE_LINK_WS 0 +#define Z_FEATURE_LINK_SERIAL 0 +#define Z_FEATURE_SCOUTING_UDP 1 +#define Z_FEATURE_LINK_UDP_MULTICAST 1 +#define Z_FEATURE_LINK_UDP_UNICAST 1 +#define Z_FEATURE_MULTICAST_TRANSPORT 1 +#define Z_FEATURE_UNICAST_TRANSPORT 1 +#define Z_FEATURE_FRAGMENTATION 1 +#define Z_FEATURE_ENCODING_VALUES 1 +// End of CMake generation + /*------------------ Runtime configuration properties ------------------*/ /** * The library mode. @@ -75,10 +102,10 @@ /** * In client mode, the period dedicated to scouting a router before failing. * Accepted values : ``. - * Default value : `"3000"`. + * Default value : `"1000"`. */ #define Z_CONFIG_SCOUTING_TIMEOUT_KEY 0x47 -#define Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT "3000" +#define Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT "1000" /** * The entities to find in the multicast scouting, defined as a bitwise value. @@ -102,239 +129,51 @@ #define Z_CONFIG_ADD_TIMESTAMP_KEY 0x4A #define Z_CONFIG_ADD_TIMESTAMP_DEFAULT "false" -/*------------------ Compile-time feature configuration ------------------*/ -// WARNING: Default values may always be overridden by CMake/make values - -/** - * Enable multi-thread support. - */ -#ifndef Z_FEATURE_MULTI_THREAD -#define Z_FEATURE_MULTI_THREAD 1 -#endif - -/** - * Enable dynamic memory allocation. - */ -#ifndef Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION -#define Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION 0 -#endif - -/** - * Enable queryables - */ -#ifndef Z_FEATURE_QUERYABLE -#define Z_FEATURE_QUERYABLE 1 -#endif - -/** - * Enable queries - */ -#ifndef Z_FEATURE_QUERY -#define Z_FEATURE_QUERY 1 -#endif - -/** - * Enable subscription on this node - */ -#ifndef Z_FEATURE_SUBSCRIPTION -#define Z_FEATURE_SUBSCRIPTION 1 -#endif - -/** - * Enable publication - */ -#ifndef Z_FEATURE_PUBLICATION -#define Z_FEATURE_PUBLICATION 1 -#endif - -/** - * Enable TCP links. - */ -#ifndef Z_FEATURE_LINK_TCP -#define Z_FEATURE_LINK_TCP 1 -#endif - -/** - * Enable Bluetooth links. - */ -#ifndef Z_FEATURE_LINK_BLUETOOTH -#define Z_FEATURE_LINK_BLUETOOTH 0 -#endif - -/** - * Enable WebSocket links. - */ -#ifndef Z_FEATURE_LINK_WS -#define Z_FEATURE_LINK_WS 0 -#endif - -/** - * Enable Serial links. - */ -#ifndef Z_FEATURE_LINK_SERIAL -#define Z_FEATURE_LINK_SERIAL 0 -#endif - -/** - * Enable UDP Scouting. - */ -#ifndef Z_FEATURE_SCOUTING_UDP -#define Z_FEATURE_SCOUTING_UDP 1 -#endif - -/** - * Enable UDP Multicast links. - */ -#ifndef Z_FEATURE_LINK_UDP_MULTICAST -#define Z_FEATURE_LINK_UDP_MULTICAST 1 -#endif - -/** - * Enable UDP Unicast links. - */ -#ifndef Z_FEATURE_LINK_UDP_UNICAST -#define Z_FEATURE_LINK_UDP_UNICAST 1 -#endif - -/** - * Enable Multicast Transport. - */ -#ifndef Z_FEATURE_MULTICAST_TRANSPORT -#if Z_FEATURE_SCOUTING_UDP == 0 && Z_FEATURE_LINK_BLUETOOTH == 0 && Z_FEATURE_LINK_UDP_MULTICAST == 0 -#define Z_FEATURE_MULTICAST_TRANSPORT 0 -#else -#define Z_FEATURE_MULTICAST_TRANSPORT 1 -#endif -#endif - -/** - * Enable Unicast Transport. - */ -#ifndef Z_FEATURE_UNICAST_TRANSPORT -#if Z_FEATURE_LINK_TCP == 0 && Z_FEATURE_LINK_UDP_UNICAST == 0 && Z_FEATURE_LINK_SERIAL == 0 && Z_FEATURE_LINK_WS == 0 -#define Z_FEATURE_UNICAST_TRANSPORT 0 -#else -#define Z_FEATURE_UNICAST_TRANSPORT 1 -#endif -#endif - -/** - * Enable raweth transport/link. - */ -#ifndef Z_FEATURE_RAWETH_TRANSPORT -#define Z_FEATURE_RAWETH_TRANSPORT 0 -#endif - -/** - * Enable message fragmentation. - */ -#ifndef Z_FEATURE_FRAGMENTATION -#define Z_FEATURE_FRAGMENTATION 1 -#endif - -/** - * Enable attachments. - */ -#ifndef Z_FEATURE_ATTACHMENT -#define Z_FEATURE_ATTACHMENT 1 -#endif - /*------------------ Compile-time configuration properties ------------------*/ /** * Default length for Zenoh ID. Maximum size is 16 bytes. * This configuration will only be applied to Zenoh IDs generated by Zenoh-Pico. */ -#ifndef Z_ZID_LENGTH #define Z_ZID_LENGTH 16 -#endif - -#ifndef Z_TSID_LENGTH #define Z_TSID_LENGTH 16 -#endif /** * Protocol version identifier. * Do not change this value. */ -#ifndef Z_PROTO_VERSION -#define Z_PROTO_VERSION 0x08 -#endif +#define Z_PROTO_VERSION 0x09 /** * Default session lease in milliseconds. */ -#ifndef Z_TRANSPORT_LEASE #define Z_TRANSPORT_LEASE 10000 -#endif /** * Default session lease expire factor. */ -#ifndef Z_TRANSPORT_LEASE_EXPIRE_FACTOR -#define Z_TRANSPORT_LEASE_EXPIRE_FACTOR 3.5 -#endif +#define Z_TRANSPORT_LEASE_EXPIRE_FACTOR 3 /** * Default multicast session join interval in milliseconds. */ -#ifndef Z_JOIN_INTERVAL #define Z_JOIN_INTERVAL 2500 -#endif -/** - * Default socket timeout in milliseconds. - */ -#ifndef Z_CONFIG_SOCKET_TIMEOUT -#define Z_CONFIG_SOCKET_TIMEOUT 100 -#endif - -#ifndef Z_SN_RESOLUTION #define Z_SN_RESOLUTION 0x02 -#endif - -#ifndef Z_REQ_RESOLUTION #define Z_REQ_RESOLUTION 0x02 -#endif /** * Default size for an IO slice. */ -#ifndef Z_IOSLICE_SIZE #define Z_IOSLICE_SIZE 128 -#endif /** - * Default maximum batch size possible to be received or sent. - */ -#ifndef Z_BATCH_UNICAST_SIZE -#define Z_BATCH_UNICAST_SIZE 65535 -#endif -/** - * Default maximum batch size possible to be received or sent. - */ -#ifndef Z_BATCH_MULTICAST_SIZE -#define Z_BATCH_MULTICAST_SIZE 8192 -#endif - -/** - * Default maximum size for fragmented messages. + * Default get timeout in milliseconds. */ -#ifndef Z_FRAG_MAX_SIZE -#define Z_FRAG_MAX_SIZE 300000 -#endif +#define Z_GET_TIMEOUT_DEFAULT 10000 /** * Default "nop" instruction */ -#ifndef ZP_ASM_NOP #define ZP_ASM_NOP __asm__("nop") -#endif - -/** - * Default get timeout in milliseconds. - */ -#ifndef Z_GET_TIMEOUT_DEFAULT -#define Z_GET_TIMEOUT_DEFAULT 10000 -#endif #endif /* INCLUDE_ZENOH_PICO_CONFIG_H */ diff --git a/include/zenoh-pico/config.h.in b/include/zenoh-pico/config.h.in new file mode 100644 index 000000000..b4577f1fe --- /dev/null +++ b/include/zenoh-pico/config.h.in @@ -0,0 +1,179 @@ +// +// 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 INCLUDE_ZENOH_PICO_CONFIG_H +#define INCLUDE_ZENOH_PICO_CONFIG_H + +/*--- CMake generated config; pass values to CMake to change the following tokens ---*/ +#define Z_FRAG_MAX_SIZE @FRAG_MAX_SIZE@ +#define Z_BATCH_UNICAST_SIZE @BATCH_UNICAST_SIZE@ +#define Z_BATCH_MULTICAST_SIZE @BATCH_MULTICAST_SIZE@ +#define Z_CONFIG_SOCKET_TIMEOUT @Z_CONFIG_SOCKET_TIMEOUT@ + +#define Z_FEATURE_MULTI_THREAD @Z_FEATURE_MULTI_THREAD@ +#define Z_FEATURE_PUBLICATION @Z_FEATURE_PUBLICATION@ +#define Z_FEATURE_SUBSCRIPTION @Z_FEATURE_SUBSCRIPTION@ +#define Z_FEATURE_QUERY @Z_FEATURE_QUERY@ +#define Z_FEATURE_QUERYABLE @Z_FEATURE_QUERYABLE@ +#define Z_FEATURE_RAWETH_TRANSPORT @Z_FEATURE_RAWETH_TRANSPORT@ +#define Z_FEATURE_INTEREST @Z_FEATURE_INTEREST@ +#define Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION @Z_FEATURE_DYNAMIC_MEMORY_ALLOCATION@ +#define Z_FEATURE_LINK_TCP @Z_FEATURE_LINK_TCP@ +#define Z_FEATURE_LINK_BLUETOOTH @Z_FEATURE_LINK_BLUETOOTH@ +#define Z_FEATURE_LINK_WS @Z_FEATURE_LINK_WS@ +#define Z_FEATURE_LINK_SERIAL @Z_FEATURE_LINK_SERIAL@ +#define Z_FEATURE_SCOUTING_UDP @Z_FEATURE_SCOUTING_UDP@ +#define Z_FEATURE_LINK_UDP_MULTICAST @Z_FEATURE_LINK_UDP_MULTICAST@ +#define Z_FEATURE_LINK_UDP_UNICAST @Z_FEATURE_LINK_UDP_UNICAST@ +#define Z_FEATURE_MULTICAST_TRANSPORT @Z_FEATURE_MULTICAST_TRANSPORT@ +#define Z_FEATURE_UNICAST_TRANSPORT @Z_FEATURE_UNICAST_TRANSPORT@ +#define Z_FEATURE_FRAGMENTATION @Z_FEATURE_FRAGMENTATION@ +#define Z_FEATURE_ENCODING_VALUES @Z_FEATURE_ENCODING_VALUES@ +// End of CMake generation + +/*------------------ Runtime configuration properties ------------------*/ +/** + * The library mode. + * Accepted values : `"client"`, `"peer"`. + * Default value : `"client"`. + */ +#define Z_CONFIG_MODE_KEY 0x40 +#define Z_CONFIG_MODE_CLIENT "client" +#define Z_CONFIG_MODE_PEER "peer" +#define Z_CONFIG_MODE_DEFAULT Z_CONFIG_MODE_CLIENT + +/** + * The locator of a peer to connect to. + * Accepted values : `` (ex: `"tcp/10.10.10.10:7447"`). + * Default value : None. + * Multiple values are not accepted in zenoh-pico. + */ +#define Z_CONFIG_CONNECT_KEY 0x41 + +/** + * A locator to listen on. + * Accepted values : `` (ex: `"tcp/10.10.10.10:7447"`). + * Default value : None. + * Multiple values accepted. + */ +#define Z_CONFIG_LISTEN_KEY 0x42 + +/** + * The user name to use for authentication. + * Accepted values : ``. + * Default value : None. + */ +#define Z_CONFIG_USER_KEY 0x43 + +/** + * The password to use for authentication. + * Accepted values : ``. + * Default value : None. + */ +#define Z_CONFIG_PASSWORD_KEY 0x44 + +/** + * Activates/Deactivates multicast scouting. + * Accepted values : `false`, `true`. + * Default value : `true`. + */ +#define Z_CONFIG_MULTICAST_SCOUTING_KEY 0x45 +#define Z_CONFIG_MULTICAST_SCOUTING_DEFAULT "true" + +/** + * The multicast address and ports to use for multicast scouting. + * Accepted values : `:`. + * Default value : `"224.0.0.224:7446"`. + */ +#define Z_CONFIG_MULTICAST_LOCATOR_KEY 0x46 +#define Z_CONFIG_MULTICAST_LOCATOR_DEFAULT "udp/224.0.0.224:7446" + +/** + * In client mode, the period dedicated to scouting a router before failing. + * Accepted values : ``. + * Default value : `"1000"`. + */ +#define Z_CONFIG_SCOUTING_TIMEOUT_KEY 0x47 +#define Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT "1000" + +/** + * The entities to find in the multicast scouting, defined as a bitwise value. + * Accepted values : [0-7]. Bitwise value are defined in :c:enum:`z_whatami_t`. + * Default value : `3`. + */ +#define Z_CONFIG_SCOUTING_WHAT_KEY 0x48 +#define Z_CONFIG_SCOUTING_WHAT_DEFAULT "3" + +/** + * A configurable and static Zenoh ID to be used on Zenoh Sessions. + * Accepted values : ``. + */ +#define Z_CONFIG_SESSION_ZID_KEY 0x49 + +/** + * Indicates if data messages should be timestamped. + * Accepted values : `false`, `true`. + * Default value : `false`. + */ +#define Z_CONFIG_ADD_TIMESTAMP_KEY 0x4A +#define Z_CONFIG_ADD_TIMESTAMP_DEFAULT "false" + +/*------------------ Compile-time configuration properties ------------------*/ +/** + * Default length for Zenoh ID. Maximum size is 16 bytes. + * This configuration will only be applied to Zenoh IDs generated by Zenoh-Pico. + */ +#define Z_ZID_LENGTH 16 +#define Z_TSID_LENGTH 16 + +/** + * Protocol version identifier. + * Do not change this value. + */ +#define Z_PROTO_VERSION 0x09 + +/** + * Default session lease in milliseconds. + */ +#define Z_TRANSPORT_LEASE 10000 + +/** + * Default session lease expire factor. + */ +#define Z_TRANSPORT_LEASE_EXPIRE_FACTOR 3 + +/** + * Default multicast session join interval in milliseconds. + */ +#define Z_JOIN_INTERVAL 2500 + +#define Z_SN_RESOLUTION 0x02 +#define Z_REQ_RESOLUTION 0x02 + +/** + * Default size for an IO slice. + */ +#define Z_IOSLICE_SIZE 128 + +/** + * Default get timeout in milliseconds. + */ +#define Z_GET_TIMEOUT_DEFAULT 10000 + +/** + * Default "nop" instruction + */ +#define ZP_ASM_NOP __asm__("nop") + +#endif /* INCLUDE_ZENOH_PICO_CONFIG_H */ diff --git a/include/zenoh-pico/deprecated/platform.h b/include/zenoh-pico/deprecated/platform.h deleted file mode 100644 index 5e47d65c6..000000000 --- a/include/zenoh-pico/deprecated/platform.h +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright (c) 2024 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_DEPRECATED_PLATFORM_H -#define ZENOH_PICO_DEPRECATED_PLATFORM_H - -#include - -#include "zenoh-pico/config.h" -#include "zenoh-pico/system/platform-common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/*------------------ Random ------------------*/ -uint8_t zp_random_u8(void); -uint16_t zp_random_u16(void); -uint32_t zp_random_u32(void); -uint64_t zp_random_u64(void); -void zp_random_fill(void *buf, size_t len); - -/*------------------ Memory ------------------*/ -void *zp_malloc(size_t size); -void *zp_realloc(void *ptr, size_t size); -void zp_free(void *ptr); - -#if Z_FEATURE_MULTI_THREAD == 1 -/*------------------ Thread ------------------*/ -typedef z_task_t zp_task_t; -typedef z_task_attr_t zp_task_attr_t; - -int8_t zp_task_init(zp_task_t *task, zp_task_attr_t *attr, void *(*fun)(void *), void *arg); -int8_t zp_task_join(zp_task_t *task); -void zp_task_free(zp_task_t **task); - -/*------------------ Mutex ------------------*/ -typedef z_mutex_t zp_mutex_t; -int8_t zp_mutex_init(zp_mutex_t *m); -int8_t zp_mutex_free(zp_mutex_t *m); - -int8_t zp_mutex_lock(zp_mutex_t *m); -int8_t zp_mutex_trylock(zp_mutex_t *m); -int8_t zp_mutex_unlock(zp_mutex_t *m); - -/*------------------ CondVar ------------------*/ -typedef z_condvar_t zp_condvar_t; -int8_t zp_condvar_init(zp_condvar_t *cv); -int8_t zp_condvar_free(zp_condvar_t *cv); - -int8_t zp_condvar_signal(zp_condvar_t *cv); -int8_t zp_condvar_wait(zp_condvar_t *cv, zp_mutex_t *m); -#endif // Z_FEATURE_MULTI_THREAD == 1 - -/*------------------ Sleep ------------------*/ -int zp_sleep_us(size_t time); -int zp_sleep_ms(size_t time); -int zp_sleep_s(size_t time); - -/*------------------ Clock ------------------*/ -typedef z_clock_t zp_clock_t; -zp_clock_t zp_clock_now(void); -unsigned long zp_clock_elapsed_us(zp_clock_t *time); -unsigned long zp_clock_elapsed_ms(zp_clock_t *time); -unsigned long zp_clock_elapsed_s(zp_clock_t *time); - -/*------------------ Time ------------------*/ -typedef z_time_t zp_time_t; -zp_time_t zp_time_now(void); -const char *zp_time_now_as_str(char *const buf, unsigned long buflen); -unsigned long zp_time_elapsed_us(zp_time_t *time); -unsigned long zp_time_elapsed_ms(zp_time_t *time); -unsigned long zp_time_elapsed_s(zp_time_t *time); - -#ifdef __cplusplus -} -#endif - -#endif /* ZENOH_PICO_DEPRECATED_PLATFORM_H */ diff --git a/include/zenoh-pico/link/config/bt.h b/include/zenoh-pico/link/config/bt.h index 0a68898b0..9910e9886 100644 --- a/include/zenoh-pico/link/config/bt.h +++ b/include/zenoh-pico/link/config/bt.h @@ -50,4 +50,4 @@ int8_t _z_bt_config_from_str(_z_str_intmap_t *strint, const char *s); int8_t _z_bt_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif -#endif /* ZENOH_PICO_LINK_CONFIG_BT_H */ \ No newline at end of file +#endif /* ZENOH_PICO_LINK_CONFIG_BT_H */ diff --git a/include/zenoh-pico/link/config/serial.h b/include/zenoh-pico/link/config/serial.h index 7eb4408ba..6960d2ea6 100644 --- a/include/zenoh-pico/link/config/serial.h +++ b/include/zenoh-pico/link/config/serial.h @@ -66,4 +66,4 @@ int8_t _z_serial_config_from_str(_z_str_intmap_t *strint, const char *s); int8_t _z_serial_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif -#endif /* ZENOH_PICO_LINK_CONFIG_SERIAL_H */ \ No newline at end of file +#endif /* ZENOH_PICO_LINK_CONFIG_SERIAL_H */ diff --git a/include/zenoh-pico/link/endpoint.h b/include/zenoh-pico/link/endpoint.h index bd7c8cbc3..f9dd2efa3 100644 --- a/include/zenoh-pico/link/endpoint.h +++ b/include/zenoh-pico/link/endpoint.h @@ -42,15 +42,15 @@ #define LOCATOR_METADATA_SEPARATOR '?' typedef struct { _z_str_intmap_t _metadata; - char *_protocol; - char *_address; + _z_string_t _protocol; + _z_string_t _address; } _z_locator_t; _Bool _z_locator_eq(const _z_locator_t *left, const _z_locator_t *right); void _z_locator_init(_z_locator_t *locator); -char *_z_locator_to_str(const _z_locator_t *l); -int8_t _z_locator_from_str(_z_locator_t *lc, const char *s); +_z_string_t _z_locator_to_string(const _z_locator_t *loc); +int8_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); @@ -67,8 +67,8 @@ typedef struct { _z_str_intmap_t _config; } _z_endpoint_t; -char *_z_endpoint_to_str(const _z_endpoint_t *e); -int8_t _z_endpoint_from_str(_z_endpoint_t *ep, const char *s); +_z_string_t _z_endpoint_to_string(const _z_endpoint_t *e); +int8_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); diff --git a/include/zenoh-pico/link/link.h b/include/zenoh-pico/link/link.h index 75e2a02a7..e4c83d78a 100644 --- a/include/zenoh-pico/link/link.h +++ b/include/zenoh-pico/link/link.h @@ -94,8 +94,8 @@ typedef int8_t (*_z_f_link_listen)(struct _z_link_t *self); typedef void (*_z_f_link_close)(struct _z_link_t *self); typedef size_t (*_z_f_link_write)(const struct _z_link_t *self, const uint8_t *ptr, size_t len); typedef size_t (*_z_f_link_write_all)(const struct _z_link_t *self, const uint8_t *ptr, size_t len); -typedef size_t (*_z_f_link_read)(const struct _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr); -typedef size_t (*_z_f_link_read_exact)(const struct _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr); +typedef size_t (*_z_f_link_read)(const struct _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr); +typedef size_t (*_z_f_link_read_exact)(const struct _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr); typedef void (*_z_f_link_free)(struct _z_link_t *self); typedef struct _z_link_t { @@ -137,11 +137,11 @@ typedef struct _z_link_t { void _z_link_clear(_z_link_t *zl); void _z_link_free(_z_link_t **zl); -int8_t _z_open_link(_z_link_t *zl, const char *locator); -int8_t _z_listen_link(_z_link_t *zl, const char *locator); +int8_t _z_open_link(_z_link_t *zl, _z_string_t *locator); +int8_t _z_listen_link(_z_link_t *zl, _z_string_t *locator); int8_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_bytes_t *addr); -size_t _z_link_recv_exact_zbuf(const _z_link_t *zl, _z_zbuf_t *zbf, size_t len, _z_bytes_t *addr); +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); #endif /* ZENOH_PICO_LINK_H */ diff --git a/include/zenoh-pico/net/config.h b/include/zenoh-pico/net/config.h index ba94a122e..24418c730 100644 --- a/include/zenoh-pico/net/config.h +++ b/include/zenoh-pico/net/config.h @@ -24,25 +24,30 @@ * Returns: * A :c:type:`_z_config_t` containing an empty configuration. */ -_z_config_t *_z_config_empty(void); +_z_config_t _z_config_empty(void); /** * Create a default set of properties for zenoh-net session configuration. * + * Parameters: + * config: A :c:type:`_z_config_t` where a default configuration for client mode will be constructed. + * * Returns: - * A :c:type:`_z_config_t` containing a default configuration. + * `0`` in case of success, or a ``negative value`` otherwise. */ -_z_config_t *_z_config_default(void); +int8_t _z_config_default(_z_config_t *config); /** * Create a default set of properties for client mode zenoh-net session configuration. * If peer is not null, it is added to the configuration as remote peer. * * Parameters: + * config: A :c:type:`_z_config_t` where a default configuration for client mode will be constructed. * locator: An optional peer locator. The caller keeps its ownership. + * * Returns: - * A :c:type:`_z_config_t` containing a default configuration for client mode. + * `0`` in case of success, or a ``negative value`` otherwise. */ -_z_config_t *_z_config_client(const char *locator); +int8_t _z_config_client(_z_config_t *config, const char *locator); #endif /* ZENOH_PICO_CONFIG_NETAPI_H */ diff --git a/include/zenoh-pico/net/encoding.h b/include/zenoh-pico/net/encoding.h new file mode 100644 index 000000000..acd9061ec --- /dev/null +++ b/include/zenoh-pico/net/encoding.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2024 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_ENCODING_NETAPI_H +#define ZENOH_PICO_ENCODING_NETAPI_H + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/collections/string.h" + +#define _Z_ENCODING_ID_DEFAULT 0 + +/** + * A zenoh encoding. + */ +typedef struct _z_encoding_t { + _z_string_t schema; + uint16_t id; +} _z_encoding_t; + +int8_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len); +_z_encoding_t _z_encoding_wrap(uint16_t id, const char *schema); +_z_encoding_t _z_encoding_null(void); +void _z_encoding_clear(_z_encoding_t *encoding); +_Bool _z_encoding_check(const _z_encoding_t *encoding); +int8_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); + +#endif /* ZENOH_PICO_ENCODING_NETAPI_H */ diff --git a/include/zenoh-pico/net/filtering.h b/include/zenoh-pico/net/filtering.h new file mode 100644 index 000000000..57e12c01a --- /dev/null +++ b/include/zenoh-pico/net/filtering.h @@ -0,0 +1,48 @@ +// +// 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_FILTERING_NETAPI_H +#define ZENOH_PICO_FILTERING_NETAPI_H + +#include + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/net/session.h" +#include "zenoh-pico/protocol/core.h" + +typedef enum { + WRITE_FILTER_INIT = 0, + WRITE_FILTER_ACTIVE = 1, + WRITE_FILTER_OFF = 2, +} _z_write_filter_state_t; + +typedef struct { + uint32_t decl_id; + uint8_t state; +} _z_writer_filter_ctx_t; + +/** + * Return type when declaring a queryable. + */ +typedef struct _z_write_filter_t { + uint32_t _interest_id; + _z_writer_filter_ctx_t *ctx; +} _z_write_filter_t; + +typedef struct _z_publisher_t _z_publisher_t; + +int8_t _z_write_filter_create(_z_publisher_t *pub); +int8_t _z_write_filter_destroy(const _z_publisher_t *pub); +_Bool _z_write_filter_active(const _z_publisher_t *pub); + +#endif /* ZENOH_PICO_FILTERING_NETAPI_H */ diff --git a/include/zenoh-pico/net/memory.h b/include/zenoh-pico/net/memory.h deleted file mode 100644 index 750bcff4d..000000000 --- a/include/zenoh-pico/net/memory.h +++ /dev/null @@ -1,30 +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_MEMORY_NETAPI_H -#define ZENOH_PICO_MEMORY_NETAPI_H - -#include "zenoh-pico/protocol/core.h" -#include "zenoh-pico/session/session.h" - -/** - * Free a :c:type:`_z_sample_t`, including its internal fields. - * - * Parameters: - * sample: The :c:type:`_z_sample_t` to free. - */ -void _z_sample_move(_z_sample_t *dst, _z_sample_t *src); -void _z_sample_clear(_z_sample_t *sample); -void _z_sample_free(_z_sample_t **sample); - -#endif /* ZENOH_PICO_MEMORY_NETAPI_H */ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index 8deeec549..c3d610d11 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -18,6 +18,7 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/collections/string.h" +#include "zenoh-pico/net/encoding.h" #include "zenoh-pico/net/publish.h" #include "zenoh-pico/net/query.h" #include "zenoh-pico/net/session.h" @@ -36,7 +37,7 @@ * locator: The locator where to scout. * 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, const char *locator, const uint32_t timeout, +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); /*------------------ Declarations ------------------*/ @@ -82,12 +83,13 @@ int8_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid); * zn: The zenoh-net session. The caller keeps its ownership. * keyexpr: The resource key to publish. The callee gets the ownership * of any allocated value. + * encoding: The optional default encoding to use during put. The callee gets the ownership. * * Returns: - * The created :c:type:`_z_publisher_t` or null if the declaration failed. + * The created :c:type:`_z_publisher_t` (in null state if the declaration failed).. */ -_z_publisher_t *_z_declare_publisher(_z_session_rc_t *zn, _z_keyexpr_t keyexpr, - z_congestion_control_t congestion_control, z_priority_t priority); +_z_publisher_t _z_declare_publisher(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_encoding_t *encoding, + z_congestion_control_t congestion_control, z_priority_t priority, _Bool is_express); /** * Undeclare a :c:type:`_z_publisher_t`. @@ -107,24 +109,21 @@ int8_t _z_undeclare_publisher(_z_publisher_t *pub); * Parameters: * zn: The zenoh-net session. The caller keeps its ownership. * keyexpr: The resource key to write. The caller keeps its ownership. - * payload: The value to write. - * len: The length of the value to write. + * payload: The data to write. * encoding: The encoding of the payload. The callee gets the ownership of * any allocated value. * kind: The kind of the value. * cong_ctrl: The congestion control of this write. Possible values defined * in :c:type:`_z_congestion_control_t`. + * is_express: If true, Zenoh will not wait to batch this operation with others to reduce the bandwidth. + * timestamp: The timestamp of this write. The API level timestamp (e.g. of the data when it was created). + * attachment: An optional attachment to this write. * Returns: * ``0`` in case of success, ``-1`` in case of failure. */ -int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, const size_t len, - const _z_encoding_t encoding, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, - z_priority_t priority -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t attachment -#endif -); +int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, _z_bytes_t payload, const _z_encoding_t *encoding, + const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, z_priority_t priority, + _Bool is_express, const _z_timestamp_t *timestamp, const _z_bytes_t attachment); #endif #if Z_FEATURE_SUBSCRIPTION == 1 @@ -141,10 +140,10 @@ int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *pay * received. arg: A pointer that will be passed to the **callback** on each call. * * Returns: - * The created :c:type:`_z_subscriber_t` or null if the declaration failed. + * The created :c:type:`_z_subscriber_t` (in null state if the declaration failed). */ -_z_subscriber_t *_z_declare_subscriber(_z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_subinfo_t sub_info, - _z_data_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_subinfo_t sub_info, + _z_data_handler_t callback, _z_drop_handler_t dropper, void *arg); /** * Undeclare a :c:type:`_z_subscriber_t`. @@ -156,17 +155,6 @@ _z_subscriber_t *_z_declare_subscriber(_z_session_rc_t *zn, _z_keyexpr_t keyexpr * 0 if success, or a negative value identifying the error. */ int8_t _z_undeclare_subscriber(_z_subscriber_t *sub); - -/** - * Pull data for a pull mode :c:type:`_z_subscriber_t`. The pulled data will be provided - * by calling the **callback** function provided to the :c:func:`_z_declare_subscriber` function. - * - * Parameters: - * sub: The :c:type:`_z_subscriber_t` to pull from. - * Returns: - * ``0`` in case of success, ``-1`` in case of failure. - */ -int8_t _z_subscriber_pull(const _z_subscriber_t *sub); #endif #if Z_FEATURE_QUERYABLE == 1 @@ -182,10 +170,10 @@ int8_t _z_subscriber_pull(const _z_subscriber_t *sub); * arg: A pointer that will be passed to the **callback** on each call. * * Returns: - * The created :c:type:`_z_queryable_t` or null if the declaration failed. + * The created :c:type:`_z_queryable_t` (in null state if the declaration failed).. */ -_z_queryable_t *_z_declare_queryable(_z_session_rc_t *zn, _z_keyexpr_t keyexpr, _Bool complete, - _z_queryable_handler_t callback, _z_drop_handler_t dropper, void *arg); +_z_queryable_t _z_declare_queryable(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _Bool complete, + _z_queryable_handler_t callback, _z_drop_handler_t dropper, void *arg); /** * Undeclare a :c:type:`_z_queryable_t`. @@ -210,8 +198,27 @@ int8_t _z_undeclare_queryable(_z_queryable_t *qle); * query: The query to reply to. The caller keeps its ownership. * key: The resource key of this reply. The caller keeps the ownership. * payload: The value of this reply, the caller keeps ownership. + * kind: The type of operation. + * attachment: An optional attachment to the reply. */ -int8_t _z_send_reply(const _z_query_t *query, const _z_keyexpr_t keyexpr, const _z_value_t payload); +int8_t _z_send_reply(const _z_query_t *query, const _z_session_rc_t *zsrc, const _z_keyexpr_t keyexpr, + const _z_value_t payload, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, + z_priority_t priority, _Bool is_express, const _z_timestamp_t *timestamp, + const _z_bytes_t attachment); +/** + * Send a reply error to a query. + * + * This function must be called inside of a Queryable callback passing the + * query received as parameters of the callback function. This function can + * be called multiple times to send multiple replies to a query. The reply + * will be considered complete when the Queryable callback returns. + * + * Parameters: + * query: The query to reply to. The caller keeps its ownership. + * key: The resource key of this reply. The caller keeps the ownership. + * payload: The value of this reply, the caller keeps ownership. + */ +int8_t _z_send_reply_err(const _z_query_t *query, const _z_session_rc_t *zsrc, const _z_value_t payload); #endif #if Z_FEATURE_QUERY == 1 @@ -227,18 +234,24 @@ int8_t _z_send_reply(const _z_query_t *query, const _z_keyexpr_t keyexpr, const * consolidation: The kind of consolidation that should be applied on replies. * value: The payload of the query. * callback: The callback function that will be called on reception of replies for this query. - * arg_call: A pointer that will be passed to the **callback** on each call. * dropper: The callback function that will be called on upon completion of the callback. - * arg_drop: A pointer that will be passed to the **dropper** on each call. + * arg: A pointer that will be passed to the **callback** on each call. + * timeout_ms: The timeout value of this query. + * attachment: An optional attachment to this query. + * cong_ctrl: The congestion control to apply when routing the query. + * priority: The priority of the query. + * */ int8_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, - void *arg_call, _z_drop_handler_t dropper, void *arg_drop, uint32_t timeout_ms -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t attachment + _z_drop_handler_t dropper, void *arg, uint32_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 +uint32_t _z_add_interest(_z_session_t *zn, _z_keyexpr_t keyexpr, _z_interest_handler_t callback, uint8_t flags, + void *arg); +int8_t _z_remove_interest(_z_session_t *zn, uint32_t interest_id); #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 75ebad8d1..f7f44686e 100644 --- a/include/zenoh-pico/net/publish.h +++ b/include/zenoh-pico/net/publish.h @@ -15,23 +15,31 @@ #ifndef INCLUDE_ZENOH_PICO_NET_PUBLISH_H #define INCLUDE_ZENOH_PICO_NET_PUBLISH_H +#include "zenoh-pico/net/filtering.h" #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" /** * Return type when declaring a publisher. */ -typedef struct { +typedef struct _z_publisher_t { _z_keyexpr_t _key; _z_zint_t _id; _z_session_rc_t _zn; + _z_encoding_t _encoding; z_congestion_control_t _congestion_control; z_priority_t _priority; + _Bool _is_express; +#if Z_FEATURE_INTEREST == 1 + _z_write_filter_t _filter; +#endif } _z_publisher_t; #if Z_FEATURE_PUBLICATION == 1 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 #endif /* INCLUDE_ZENOH_PICO_NET_PUBLISH_H */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 0dafb9f4d..d55af1c26 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -17,6 +17,7 @@ #include #include "zenoh-pico/api/constants.h" +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" @@ -27,20 +28,18 @@ typedef struct _z_query_t { _z_value_t _value; _z_keyexpr_t _key; uint32_t _request_id; - _z_session_t *_zn; + _z_session_weak_t _zn; // Can't be an rc because of cross referencing + _z_bytes_t attachment; char *_parameters; _Bool _anyke; } _z_query_t; +_z_query_t _z_query_null(void); void _z_query_clear(_z_query_t *q); -_Z_REFCOUNT_DEFINE(_z_query, _z_query) +int8_t _z_query_copy(_z_query_t *dst, const _z_query_t *src); +void _z_query_free(_z_query_t **query); -/** - * Container for an owned query rc - */ -typedef struct { - _z_query_rc_t _rc; -} z_owned_query_t; +_Z_REFCOUNT_DEFINE(_z_query, _z_query) /** * Return type when declaring a queryable. @@ -51,10 +50,12 @@ typedef struct { } _z_queryable_t; #if Z_FEATURE_QUERYABLE == 1 -_z_query_t _z_query_create(const _z_value_t *value, const _z_keyexpr_t *key, const _z_bytes_t *parameters, - _z_session_t *zn, uint32_t request_id); +_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); 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 #endif /* ZENOH_PICO_QUERY_NETAPI_H */ diff --git a/include/zenoh-pico/net/reply.h b/include/zenoh-pico/net/reply.h new file mode 100644 index 000000000..b40658d3c --- /dev/null +++ b/include/zenoh-pico/net/reply.h @@ -0,0 +1,100 @@ +// +// 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_REPLY_NETAPI_H +#define ZENOH_PICO_REPLY_NETAPI_H + +#include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/list.h" +#include "zenoh-pico/collections/refcount.h" +#include "zenoh-pico/collections/string.h" +#include "zenoh-pico/net/encoding.h" +#include "zenoh-pico/net/sample.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/session.h" + +/** + * Reply tag values. + * + * Enumerators: + * _Z_REPLY_TAG_DATA: Tag identifying that the reply contains some data. + * _Z_REPLY_TAG_FINAL: Tag identifying that the reply does not contain any data and that there will be no more + * replies for this query. + * _Z_REPLY_TAG_ERROR: Tag identifying that the reply contains error. + * _Z_REPLY_TAG_NONE: Tag identifying empty reply. + */ +typedef enum { + _Z_REPLY_TAG_DATA = 0, + _Z_REPLY_TAG_FINAL = 1, + _Z_REPLY_TAG_ERROR = 2, + _Z_REPLY_TAG_NONE = 3 +} _z_reply_tag_t; + +/** + * An reply to a :c:func:`z_query`. + * + * Members: + * _z_sample_t data: a :c:type:`_z_sample_t` containing the key and value of the reply. + * _z_slice_t replier_id: The id of the replier that sent this reply. + * + */ +typedef struct _z_reply_data_t { + union { + _z_value_t error; + _z_sample_t sample; + } _result; + _z_id_t replier_id; + _z_reply_tag_t _tag; +} _z_reply_data_t; + +void _z_reply_data_clear(_z_reply_data_t *rd); +int8_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_LIST_DEFINE(_z_reply_data, _z_reply_data_t) + +/** + * An reply to a :c:func:`z_query`. + * + * Members: + * _z_reply_t_Tag tag: Indicates if the reply contains data or if it's a FINAL reply. + * _z_reply_data_t data: The reply data if :c:member:`_z_reply_t.tag` equals + * :c:member:`_z_reply_t_Tag._Z_REPLY_TAG_DATA`. + * + */ +typedef struct _z_reply_t { + _z_reply_data_t data; +} _z_reply_t; + +_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); +int8_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; + _z_timestamp_t _tstamp; +} _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_LIST_DEFINE(_z_pending_reply, _z_pending_reply_t) + +#endif /* ZENOH_PICO_REPLY_NETAPI_H */ diff --git a/include/zenoh-pico/net/sample.h b/include/zenoh-pico/net/sample.h new file mode 100644 index 000000000..9cd33fc82 --- /dev/null +++ b/include/zenoh-pico/net/sample.h @@ -0,0 +1,61 @@ +// +// 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_SAMPLE_NETAPI_H +#define ZENOH_PICO_SAMPLE_NETAPI_H + +#include "zenoh-pico/net/encoding.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/session.h" + +/** + * A zenoh-net data sample. + * + * A sample is the value associated to a given resource at a given point in time. + * + * Members: + * _z_keyexpr_t key: The resource key of this data sample. + * _z_slice_t value: The value of this data sample. + * _z_encoding_t encoding: The encoding for the value of this data sample. + */ +typedef struct _z_sample_t { + _z_keyexpr_t keyexpr; + _z_bytes_t payload; + _z_timestamp_t timestamp; + _z_encoding_t encoding; + z_sample_kind_t kind; + _z_qos_t qos; + _z_bytes_t attachment; +} _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); +void _z_sample_move(_z_sample_t *dst, _z_sample_t *src); + +/** + * Free a :c:type:`_z_sample_t`, including its internal fields. + * + * Parameters: + * sample: The :c:type:`_z_sample_t` to free. + */ +void _z_sample_free(_z_sample_t **sample); + +int8_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); + +#endif /* ZENOH_PICO_SAMPLE_NETAPI_H */ diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index 6662edf74..541e762e5 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -29,7 +29,7 @@ */ typedef struct _z_session_t { #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_t _mutex_inner; + _z_mutex_t _mutex_inner; #endif // Z_FEATURE_MULTI_THREAD == 1 // Zenoh-pico is considering a single transport per session. @@ -41,7 +41,6 @@ typedef struct _z_session_t { // Session counters uint16_t _resource_id; uint32_t _entity_id; - _z_zint_t _pull_id; _z_zint_t _query_id; _z_zint_t _interest_id; @@ -62,9 +61,15 @@ typedef struct _z_session_t { #if Z_FEATURE_QUERY == 1 _z_pending_query_list_t *_pending_queries; #endif + + // Session interests +#if Z_FEATURE_INTEREST == 1 + _z_session_interest_rc_list_t *_local_interests; + _z_declare_data_list_t *_remote_declares; +#endif } _z_session_t; -extern void _z_session_clear(_z_session_t *zn); // Forward type declaration to avoid cyclical include +extern void _z_session_clear(_z_session_t *zn); // Forward declaration to avoid cyclical include _Z_REFCOUNT_DEFINE(_z_session, _z_session) @@ -79,7 +84,7 @@ _Z_REFCOUNT_DEFINE(_z_session, _z_session) * ``0`` in case of success, or a ``negative value`` in case of failure. * */ -int8_t _z_open(_z_session_t *zn, _z_config_t *config); +int8_t _z_open(_z_session_rc_t *zn, _z_config_t *config); /** * Close a zenoh-net session. diff --git a/include/zenoh-pico/net/subscribe.h b/include/zenoh-pico/net/subscribe.h index e2aafe540..9aaf60a42 100644 --- a/include/zenoh-pico/net/subscribe.h +++ b/include/zenoh-pico/net/subscribe.h @@ -28,8 +28,6 @@ typedef struct { _z_session_rc_t _zn; } _z_subscriber_t; -typedef _z_subscriber_t _z_pull_subscriber_t; - #if Z_FEATURE_SUBSCRIPTION == 1 /** * Create a default subscription info for a push subscriber. @@ -37,18 +35,12 @@ typedef _z_subscriber_t _z_pull_subscriber_t; * Returns: * A :c:type:`_z_subinfo_t` containing the created subscription info. */ -_z_subinfo_t _z_subinfo_push_default(void); - -/** - * Create a default subscription info for a pull subscriber. - * - * Returns: - * A :c:type:`_z_subinfo_t` containing the created subscription info. - */ -_z_subinfo_t _z_subinfo_pull_default(void); +_z_subinfo_t _z_subinfo_default(void); 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 #endif /* ZENOH_PICO_SUBSCRIBE_NETAPI_H */ diff --git a/include/zenoh-pico/net/zenoh-pico.h b/include/zenoh-pico/net/zenoh-pico.h index b90fcf05a..ee4614ce5 100644 --- a/include/zenoh-pico/net/zenoh-pico.h +++ b/include/zenoh-pico/net/zenoh-pico.h @@ -16,10 +16,10 @@ #include "zenoh-pico/net/config.h" #include "zenoh-pico/net/logger.h" -#include "zenoh-pico/net/memory.h" #include "zenoh-pico/net/primitives.h" #include "zenoh-pico/net/publish.h" #include "zenoh-pico/net/query.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/net/session.h" #include "zenoh-pico/net/subscribe.h" diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h index 13725f8d9..53857ba00 100644 --- a/include/zenoh-pico/protocol/codec/core.h +++ b/include/zenoh-pico/protocol/codec/core.h @@ -18,31 +18,14 @@ #include #include +#include "zenoh-pico/net/encoding.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/utils/config.h" #include "zenoh-pico/utils/result.h" -#define _Z_RETURN_IF_ERR(expr) \ - { \ - int8_t __res = expr; \ - if (__res != _Z_RES_OK) { \ - return __res; \ - } \ - } - -#define _Z_CLEAN_RETURN_IF_ERR(base_expr, clean_expr) \ - { \ - int8_t __res = base_expr; \ - if (__res != _Z_RES_OK) { \ - clean_expr; \ - return __res; \ - } \ - } - +typedef int8_t (*__z_single_byte_reader_t)(uint8_t *, void *context); /*------------------ Internal Zenoh-net Macros ------------------*/ -int8_t _z_encoding_prefix_encode(_z_wbuf_t *wbf, z_encoding_prefix_t en); -int8_t _z_encoding_prefix_decode(z_encoding_prefix_t *en, _z_zbuf_t *zbf); int8_t _z_consolidation_mode_encode(_z_wbuf_t *wbf, z_consolidation_mode_t en); int8_t _z_consolidation_mode_decode(z_consolidation_mode_t *en, _z_zbuf_t *zbf); int8_t _z_query_target_encode(_z_wbuf_t *wbf, z_query_target_t en); @@ -50,8 +33,8 @@ int8_t _z_query_target_decode(z_query_target_t *en, _z_zbuf_t *zbf); int8_t _z_whatami_encode(_z_wbuf_t *wbf, z_whatami_t en); int8_t _z_whatami_decode(z_whatami_t *en, _z_zbuf_t *zbf); -int8_t _z_uint_encode(_z_wbuf_t *buf, unsigned int v); -int8_t _z_uint_decode(unsigned int *u, _z_zbuf_t *buf); +uint8_t _z_whatami_to_uint8(z_whatami_t whatami); +z_whatami_t _z_whatami_from_uint8(uint8_t b); int8_t _z_uint8_encode(_z_wbuf_t *buf, uint8_t v); int8_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *buf); @@ -59,32 +42,40 @@ int8_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *buf); int8_t _z_uint16_encode(_z_wbuf_t *buf, uint16_t v); int8_t _z_uint16_decode(uint16_t *u16, _z_zbuf_t *buf); -int8_t _z_uint64_encode(_z_wbuf_t *buf, uint64_t v); -int8_t _z_uint64_decode(uint64_t *u64, _z_zbuf_t *buf); +uint8_t _z_zint_len(uint64_t v); +uint8_t _z_zint64_encode_buf(uint8_t *buf, uint64_t v); +static inline uint8_t _z_zsize_encode_buf(uint8_t *buf, _z_zint_t v) { return _z_zint64_encode_buf(buf, (uint64_t)v); } -uint8_t _z_zint_len(_z_zint_t v); -int8_t _z_zint_encode(_z_wbuf_t *buf, _z_zint_t v); +int8_t _z_zsize_encode(_z_wbuf_t *buf, _z_zint_t v); int8_t _z_zint64_encode(_z_wbuf_t *buf, uint64_t v); int8_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *buf); int8_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *buf); int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *buf); -int8_t _z_zint_decode(_z_zint_t *zint, _z_zbuf_t *buf); - -int8_t _z_bytes_val_encode(_z_wbuf_t *buf, const _z_bytes_t *bs); -int8_t _z_bytes_val_decode(_z_bytes_t *bs, _z_zbuf_t *buf); -int8_t _z_bytes_val_decode_na(_z_bytes_t *bs, _z_zbuf_t *zbf); - -int8_t _z_bytes_encode(_z_wbuf_t *buf, const _z_bytes_t *bs); -size_t _z_bytes_encode_len(const _z_bytes_t *bs); -int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *buf); +int8_t _z_zint64_decode_with_reader(uint64_t *zint, __z_single_byte_reader_t reader, void *context); +int8_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t reader, void *context); +int8_t _z_zsize_decode(_z_zint_t *zint, _z_zbuf_t *buf); + +int8_t _z_slice_val_encode(_z_wbuf_t *buf, const _z_slice_t *bs); +int8_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *buf); +int8_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf); + +int8_t _z_slice_encode(_z_wbuf_t *buf, const _z_slice_t *bs); +int8_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *buf); +int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf); +int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs); int8_t _z_zbuf_read_exact(_z_zbuf_t *zbf, uint8_t *dest, size_t length); int8_t _z_str_encode(_z_wbuf_t *buf, const char *s); int8_t _z_str_decode(char **str, _z_zbuf_t *buf); +int8_t _z_string_encode(_z_wbuf_t *wbf, const _z_string_t *s); +int8_t _z_string_decode(_z_string_t *str, _z_zbuf_t *zbf); + +size_t _z_encoding_len(const _z_encoding_t *en); +int8_t _z_encoding_encode(_z_wbuf_t *wbf, const _z_encoding_t *en); +int8_t _z_encoding_decode(_z_encoding_t *en, _z_zbuf_t *zbf); -int8_t _z_period_encode(_z_wbuf_t *wbf, const _z_period_t *m); -int8_t _z_period_decode(_z_period_t *p, _z_zbuf_t *zbf); -int8_t _z_period_decode_na(_z_period_t *p, _z_zbuf_t *zbf); +int8_t _z_value_encode(_z_wbuf_t *wbf, const _z_value_t *en); +int8_t _z_value_decode(_z_value_t *en, _z_zbuf_t *zbf); int8_t _z_keyexpr_encode(_z_wbuf_t *buf, _Bool has_suffix, const _z_keyexpr_t *ke); int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *buf, _Bool has_suffix); diff --git a/include/zenoh-pico/protocol/codec/declarations.h b/include/zenoh-pico/protocol/codec/declarations.h index 1e4ffa631..d41f875b7 100644 --- a/include/zenoh-pico/protocol/codec/declarations.h +++ b/include/zenoh-pico/protocol/codec/declarations.h @@ -28,9 +28,8 @@ #define _Z_UNDECL_QUERYABLE_MID 5 #define _Z_DECL_TOKEN_MID 6 #define _Z_UNDECL_TOKEN_MID 7 -#define _Z_DECL_INTEREST_MID 8 -#define _Z_FINAL_INTEREST_MID 9 -#define _Z_UNDECL_INTEREST_MID 10 +#define _Z_DECL_FINAL_MID 0x1a + int8_t _z_decl_kexpr_encode(_z_wbuf_t *wbf, const _z_decl_kexpr_t *decl); int8_t _z_decl_kexpr_decode(_z_decl_kexpr_t *decl, _z_zbuf_t *zbf, uint8_t header); int8_t _z_undecl_kexpr_encode(_z_wbuf_t *wbf, const _z_undecl_kexpr_t *decl); @@ -47,12 +46,6 @@ int8_t _z_decl_token_encode(_z_wbuf_t *wbf, const _z_decl_token_t *decl); int8_t _z_decl_token_decode(_z_decl_token_t *decl, _z_zbuf_t *zbf, uint8_t header); int8_t _z_undecl_token_encode(_z_wbuf_t *wbf, const _z_undecl_token_t *decl); int8_t _z_undecl_token_decode(_z_undecl_token_t *decl, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_decl_interest_encode(_z_wbuf_t *wbf, const _z_decl_interest_t *decl); -int8_t _z_decl_interest_decode(_z_decl_interest_t *decl, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_final_interest_encode(_z_wbuf_t *wbf, const _z_final_interest_t *decl); -int8_t _z_final_interest_decode(_z_final_interest_t *decl, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_undecl_interest_encode(_z_wbuf_t *wbf, const _z_undecl_interest_t *decl); -int8_t _z_undecl_interest_decode(_z_undecl_interest_t *decl, _z_zbuf_t *zbf, uint8_t header); int8_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl); int8_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf); diff --git a/include/zenoh-pico/protocol/codec/interest.h b/include/zenoh-pico/protocol/codec/interest.h new file mode 100644 index 000000000..239144870 --- /dev/null +++ b/include/zenoh-pico/protocol/codec/interest.h @@ -0,0 +1,24 @@ +// +// Copyright (c) 2024 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 INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_INTEREST_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_INTEREST_H + +#include "zenoh-pico/protocol/definitions/interest.h" +#include "zenoh-pico/protocol/iobuf.h" + +int8_t _z_interest_encode(_z_wbuf_t *wbf, const _z_interest_t *interest, _Bool is_final); +int8_t _z_interest_decode(_z_interest_t *decl, _z_zbuf_t *zbf, _Bool is_final, _Bool has_ext); + +#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 89080475a..1ad2de4ba 100644 --- a/include/zenoh-pico/protocol/codec/message.h +++ b/include/zenoh-pico/protocol/codec/message.h @@ -18,27 +18,18 @@ #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/iobuf.h" -int8_t _z_push_body_encode(_z_wbuf_t *buf, const _z_push_body_t *ts); -int8_t _z_push_body_decode(_z_push_body_t *ts, _z_zbuf_t *buf, uint8_t header); +int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb); +int8_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header); int8_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *query); int8_t _z_query_decode(_z_msg_query_t *query, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_pull_encode(_z_wbuf_t *wbf, const _z_msg_pull_t *pull); -int8_t _z_pull_decode(_z_msg_pull_t *pull, _z_zbuf_t *zbf, uint8_t header); - int8_t _z_reply_encode(_z_wbuf_t *wbf, const _z_msg_reply_t *reply); int8_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header); int8_t _z_err_encode(_z_wbuf_t *wbf, const _z_msg_err_t *err); int8_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_ack_encode(_z_wbuf_t *wbf, const _z_msg_ack_t *ack); -int8_t _z_ack_decode(_z_msg_ack_t *ack, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb); -int8_t _z_push_body_decode(_z_push_body_t *body, _z_zbuf_t *zbf, uint8_t header); - int8_t _z_put_encode(_z_wbuf_t *wbf, const _z_msg_put_t *put); int8_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header); diff --git a/include/zenoh-pico/protocol/codec/network.h b/include/zenoh-pico/protocol/codec/network.h index ef42cc991..100bb2bd9 100644 --- a/include/zenoh-pico/protocol/codec/network.h +++ b/include/zenoh-pico/protocol/codec/network.h @@ -29,6 +29,8 @@ int8_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_final_t int8_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, uint8_t header); int8_t _z_declare_encode(_z_wbuf_t *wbf, const _z_n_msg_declare_t *decl); int8_t _z_declare_decode(_z_n_msg_declare_t *decl, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_n_interest_encode(_z_wbuf_t *wbf, const _z_n_msg_interest_t *interest); +int8_t _z_n_interest_decode(_z_n_msg_interest_t *interest, _z_zbuf_t *zbf, uint8_t header); int8_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg); int8_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf); diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index d7d2dc3f2..78be5e3a7 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -22,8 +22,11 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/refcount.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/net/encoding.h" #include "zenoh-pico/system/platform.h" #define _Z_OPTIONAL @@ -55,14 +58,6 @@ uint8_t _z_id_len(_z_id_t id); _Bool _z_id_check(_z_id_t id); _z_id_t _z_id_empty(void); -/** - * A zenoh encoding. - */ -typedef struct { - _z_bytes_t suffix; - z_encoding_prefix_t prefix; -} _z_encoding_t; - /** * A zenoh timestamp. */ @@ -71,69 +66,11 @@ typedef struct { uint64_t time; } _z_timestamp_t; -#if Z_FEATURE_ATTACHMENT == 1 -/** - * The body of a loop over an attachment's key-value pairs. - * - * `key` and `value` are loaned to the body for the duration of a single call. - * `context` is passed transparently through the iteration driver. - * - * Returning `0` is treated as `continue`. - * Returning any other value is treated as `break`. - */ -typedef int8_t (*z_attachment_iter_body_t)(_z_bytes_t key, _z_bytes_t value, void *context); -/** - * The driver of a loop over an attachment's key-value pairs. - * - * This function is expected to call `loop_body` once for each key-value pair - * within `iterator`, passing `context`, and returning any non-zero value immediately (breaking iteration). - */ -typedef int8_t (*z_attachment_iter_driver_t)(const void *iterator, z_attachment_iter_body_t loop_body, void *context); -/** - * The v-table for an attachment. - */ -typedef struct z_attachment_vtable_t { - /** - * See `z_attachment_iteration_driver_t`'s documentation. - */ - z_attachment_iter_driver_t iteration_driver; -} z_attachment_vtable_t; - -/** - * A v-table based map of byte slice to byte slice. - * - * `vtable == NULL` marks the gravestone value, as this type is often optional. - * Users are encouraged to use `z_attachment_null` and `z_attachment_check` to interact. - */ -typedef struct z_attachment_t { - const void *data; - z_attachment_iter_driver_t iteration_driver; -} z_attachment_t; - -z_attachment_t z_attachment_null(void); -_Bool z_attachment_check(const z_attachment_t *attachment); -int8_t z_attachment_iterate(z_attachment_t this_, z_attachment_iter_body_t body, void *ctx); -_z_bytes_t z_attachment_get(z_attachment_t this_, _z_bytes_t key); - -typedef struct { - union { - z_attachment_t decoded; - _z_bytes_t encoded; - } body; - _Bool is_encoded; -} _z_owned_encoded_attachment_t; -/** - * Estimate the length of an attachment once encoded. - */ -size_t _z_attachment_estimate_length(z_attachment_t att); -z_attachment_t _z_encoded_as_attachment(const _z_owned_encoded_attachment_t *att); -void _z_encoded_attachment_drop(_z_owned_encoded_attachment_t *att); -#endif - _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); +uint64_t _z_timestamp_ntp64_from_time(uint32_t seconds, uint32_t nanos); /** * The product of: @@ -150,25 +87,26 @@ typedef struct { #define _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE 0x7fff /** - * A zenoh-net resource key. + * A zenoh key-expression. * * Members: - * _z_zint_t: The resource ID. - * char *val: A pointer to the string containing the resource name. + * uint16_t _id: The resource ID of the ke. + * _z_mapping_t _mapping: The resource mapping of the ke. + * _z_string_t _suffix: The string value of the ke. */ typedef struct { uint16_t _id; _z_mapping_t _mapping; - char *_suffix; + _z_string_t _suffix; } _z_keyexpr_t; -static inline _Bool _z_keyexpr_owns_suffix(const _z_keyexpr_t *key) { return (key->_mapping._val & 0x8000) != 0; } + static inline uint16_t _z_keyexpr_mapping_id(const _z_keyexpr_t *key) { return key->_mapping._val & 0x7fff; } static inline _Bool _z_keyexpr_is_local(const _z_keyexpr_t *key) { return (key->_mapping._val & 0x7fff) == _Z_KEYEXPR_MAPPING_LOCAL; } -static inline _z_mapping_t _z_keyexpr_mapping(uint16_t id, _Bool owns_suffix) { +static inline _z_mapping_t _z_keyexpr_mapping(uint16_t id) { assert(id <= _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); - _z_mapping_t mapping = {(uint16_t)((owns_suffix ? 0x8000 : 0) | id)}; + _z_mapping_t mapping = {id}; return mapping; } static inline void _z_keyexpr_set_mapping(_z_keyexpr_t *ke, uint16_t id) { @@ -181,12 +119,8 @@ static inline void _z_keyexpr_fix_mapping(_z_keyexpr_t *ke, uint16_t id) { _z_keyexpr_set_mapping(ke, id); } } -static inline void _z_keyexpr_set_owns_suffix(_z_keyexpr_t *ke, _Bool owns_suffix) { - ke->_mapping._val &= 0x7fff; - ke->_mapping._val |= owns_suffix ? 0x8000 : 0; -} -static inline _Bool _z_keyexpr_has_suffix(_z_keyexpr_t ke) { return (ke._suffix != NULL) && (ke._suffix[0] != 0); } -static inline _Bool _z_keyexpr_check(_z_keyexpr_t ke) { return (ke._id != 0) || _z_keyexpr_has_suffix(ke); } +static inline _Bool _z_keyexpr_has_suffix(const _z_keyexpr_t *ke) { return _z_string_check(&ke->_suffix); } +static inline _Bool _z_keyexpr_check(const _z_keyexpr_t *ke) { return (ke->_id != 0) || _z_keyexpr_has_suffix(ke); } /** * Create a resource key from a resource name. @@ -218,34 +152,12 @@ typedef struct { uint8_t _val; } _z_qos_t; -/** - * A zenoh-net data sample. - * - * A sample is the value associated to a given resource at a given point in time. - * - * Members: - * _z_keyexpr_t key: The resource key of this data sample. - * _z_bytes_t value: The value of this data sample. - * _z_encoding_t encoding: The encoding for the value of this data sample. - */ -typedef struct { - _z_keyexpr_t keyexpr; - _z_bytes_t payload; - _z_timestamp_t timestamp; - _z_encoding_t encoding; - z_sample_kind_t kind; - _z_qos_t qos; -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t attachment; -#endif -} _z_sample_t; - /** * Represents a Zenoh value. * * Members: - * _z_encoding_t encoding: The encoding of the `payload`. * _z_bytes_t payload: The payload of this zenoh value. + * _z_encoding_t encoding: The encoding of the `payload`. */ typedef struct { _z_bytes_t payload; @@ -253,7 +165,8 @@ typedef struct { } _z_value_t; _z_value_t _z_value_null(void); _z_value_t _z_value_steal(_z_value_t *value); -void _z_value_copy(_z_value_t *dst, const _z_value_t *src); +int8_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); void _z_value_clear(_z_value_t *src); void _z_value_free(_z_value_t **hello); @@ -261,18 +174,22 @@ void _z_value_free(_z_value_t **hello); * A hello message returned by a zenoh entity to a scout message sent with :c:func:`_z_scout`. * * Members: - * _z_bytes_t zid: The Zenoh ID of the scouted entity (empty if absent). - * _z_str_array_t locators: The locators of the scouted entity. + * _z_slice_t zid: The Zenoh ID of the scouted entity (empty if absent). + * _z_string_vec_t locators: The locators of the scouted entity. * z_whatami_t whatami: The kind of zenoh entity. */ typedef struct { - _z_id_t zid; - _z_str_array_t locators; - z_whatami_t whatami; - uint8_t version; + _z_id_t _zid; + _z_string_svec_t _locators; + z_whatami_t _whatami; + uint8_t _version; } _z_hello_t; void _z_hello_clear(_z_hello_t *src); void _z_hello_free(_z_hello_t **hello); +int8_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_LIST_DEFINE(_z_hello, _z_hello_t) @@ -280,33 +197,15 @@ typedef struct { _z_zint_t n; } _z_target_complete_body_t; -/** - * The subscription period. - * - * Members: - * unsigned int origin: - * unsigned int period: - * unsigned int duration: - */ -typedef struct { - unsigned int origin; - unsigned int period; - unsigned int duration; -} _z_period_t; - /** * Informations to be passed to :c:func:`_z_declare_subscriber` to configure the created * :c:type:`_z_subscription_rc_t`. * * Members: - * _z_period_t *period: The subscription period. * z_reliability_t reliability: The subscription reliability. - * _z_submode_t mode: The subscription mode. */ typedef struct { - _z_period_t period; z_reliability_t reliability; - z_submode_t mode; } _z_subinfo_t; typedef struct { diff --git a/include/zenoh-pico/protocol/definitions/core.h b/include/zenoh-pico/protocol/definitions/core.h index 58d16a430..5d98e4baf 100644 --- a/include/zenoh-pico/protocol/definitions/core.h +++ b/include/zenoh-pico/protocol/definitions/core.h @@ -44,5 +44,6 @@ #define _Z_FLAGS(h) (_Z_FLAGS_MASK & (h)) #define _Z_HAS_FLAG(h, f) (((h) & (f)) != 0) #define _Z_SET_FLAG(h, f) (h |= f) +#define _Z_CLEAR_FLAG(h, f) (h &= (uint8_t)(~(f))) #endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_CORE_H */ diff --git a/include/zenoh-pico/protocol/definitions/declarations.h b/include/zenoh-pico/protocol/definitions/declarations.h index 8a3c8e597..cba210a77 100644 --- a/include/zenoh-pico/protocol/definitions/declarations.h +++ b/include/zenoh-pico/protocol/definitions/declarations.h @@ -34,7 +34,6 @@ typedef struct { _z_keyexpr_t _keyexpr; uint32_t _id; struct { - _Bool _pull_mode; _Bool _reliable; } _ext_subinfo; } _z_decl_subscriber_t; @@ -49,8 +48,8 @@ typedef struct { _z_keyexpr_t _keyexpr; uint32_t _id; struct { - uint8_t _complete; - uint32_t _distance; + _Bool _complete; + uint16_t _distance; } _ext_queryable_info; } _z_decl_queryable_t; _z_decl_queryable_t _z_decl_queryable_null(void); @@ -71,28 +70,10 @@ typedef struct { } _z_undecl_token_t; _z_undecl_token_t _z_undecl_token_null(void); -#define _Z_INTEREST_FLAG_KEYEXPRS (1) -#define _Z_INTEREST_FLAG_SUBSCRIBERS (1 << 1) -#define _Z_INTEREST_FLAG_QUERYABLES (1 << 2) -#define _Z_INTEREST_FLAG_TOKENS (1 << 3) -#define _Z_INTEREST_FLAG_CURRENT (1 << 5) -#define _Z_INTEREST_FLAG_FUTURE (1 << 6) -#define _Z_INTEREST_FLAG_AGGREGATE (1 << 7) typedef struct { - _z_keyexpr_t _keyexpr; - uint32_t _id; - uint8_t interest_flags; -} _z_decl_interest_t; -_z_decl_interest_t _z_decl_interest_null(void); -typedef struct { - uint32_t _id; -} _z_final_interest_t; -_z_final_interest_t _z_final_interest_null(void); -typedef struct { - uint32_t _id; - _z_keyexpr_t _ext_keyexpr; -} _z_undecl_interest_t; -_z_undecl_interest_t _z_undecl_interest_null(void); + _Bool _placeholder; // In case we add extensions +} _z_decl_final_t; +_z_decl_final_t _z_decl_final_null(void); typedef struct { enum { @@ -104,9 +85,7 @@ typedef struct { _Z_UNDECL_QUERYABLE, _Z_DECL_TOKEN, _Z_UNDECL_TOKEN, - _Z_DECL_INTEREST, - _Z_FINAL_INTEREST, - _Z_UNDECL_INTEREST, + _Z_DECL_FINAL, } _tag; union { _z_decl_kexpr_t _decl_kexpr; @@ -117,9 +96,7 @@ typedef struct { _z_undecl_queryable_t _undecl_queryable; _z_decl_token_t _decl_token; _z_undecl_token_t _undecl_token; - _z_decl_interest_t _decl_interest; - _z_final_interest_t _final_interest; - _z_undecl_interest_t _undecl_interest; + _z_decl_final_t _decl_final; } _body; } _z_declaration_t; void _z_declaration_clear(_z_declaration_t* decl); @@ -128,17 +105,15 @@ void _z_decl_fix_mapping(_z_declaration_t* msg, uint16_t mapping); _z_declaration_t _z_make_decl_keyexpr(uint16_t id, _Z_MOVE(_z_keyexpr_t) key); _z_declaration_t _z_make_undecl_keyexpr(uint16_t id); -_z_declaration_t _z_make_decl_subscriber(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, _Bool reliable, _Bool pull_mode); +_z_declaration_t _z_make_decl_subscriber(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, _Bool reliable); _z_declaration_t _z_make_undecl_subscriber(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t* key); -_z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint32_t distance, uint8_t complete); +_z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint16_t distance, _Bool complete); _z_declaration_t _z_make_undecl_queryable(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t* key); _z_declaration_t _z_make_decl_token(_Z_MOVE(_z_keyexpr_t) key, uint32_t id); _z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t* key); -_z_declaration_t _z_make_decl_interest(_Z_MOVE(_z_keyexpr_t) key, uint32_t id); -_z_declaration_t _z_make_undecl_interest(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t* key); -_z_declaration_t _z_make_final_decl(uint32_t id); +_z_declaration_t _z_make_decl_final(void); #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 new file mode 100644 index 000000000..ca2900874 --- /dev/null +++ b/include/zenoh-pico/protocol/definitions/interest.h @@ -0,0 +1,46 @@ +// +// Copyright (c) 2024 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 INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_INTEREST_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_INTEREST_H + +#include + +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/keyexpr.h" + +#define _Z_INTEREST_FLAG_KEYEXPRS (1) +#define _Z_INTEREST_FLAG_SUBSCRIBERS (1 << 1) +#define _Z_INTEREST_FLAG_QUERYABLES (1 << 2) +#define _Z_INTEREST_FLAG_TOKENS (1 << 3) +#define _Z_INTEREST_FLAG_RESTRICTED (1 << 4) +#define _Z_INTEREST_FLAG_CURRENT (1 << 5) +#define _Z_INTEREST_FLAG_FUTURE (1 << 6) +#define _Z_INTEREST_FLAG_AGGREGATE (1 << 7) + +#define _Z_INTEREST_NOT_FINAL_MASK (_Z_INTEREST_FLAG_CURRENT | _Z_INTEREST_FLAG_FUTURE) + +typedef struct { + _z_keyexpr_t _keyexpr; + uint32_t _id; + uint8_t flags; +} _z_interest_t; +_z_interest_t _z_interest_null(void); + +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); + +#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 503483c89..d58ec38f9 100644 --- a/include/zenoh-pico/protocol/definitions/message.h +++ b/include/zenoh-pico/protocol/definitions/message.h @@ -15,6 +15,7 @@ #ifndef INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_MESSAGE_H #define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_MESSAGE_H +#include "zenoh-pico/net/encoding.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/core.h" /* Zenoh Messages */ @@ -24,120 +25,40 @@ #define _Z_MID_Z_QUERY 0x03 #define _Z_MID_Z_REPLY 0x04 #define _Z_MID_Z_ERR 0x05 -#define _Z_MID_Z_ACK 0x06 -#define _Z_MID_Z_PULL 0x07 -#define _Z_MID_Z_LINK_STATE_LIST 0x10 /* Zenoh message flags */ #define _Z_FLAG_Z_Z 0x80 -#define _Z_FLAG_Z_B 0x40 // 1 << 6 | QueryPayload if B==1 then QueryPayload is present #define _Z_FLAG_Z_D 0x20 // 1 << 5 | Dropping if D==1 then the message can be dropped -#define _Z_FLAG_Z_F \ - 0x20 // 1 << 5 | Final if F==1 then this is the final message (e.g., ReplyContext, Pull) -#define _Z_FLAG_Z_I 0x40 // 1 << 6 | DataInfo if I==1 then DataInfo is present #define _Z_FLAG_Z_K 0x80 // 1 << 7 | ResourceKey if K==1 then keyexpr is string -#define _Z_FLAG_Z_N 0x40 // 1 << 6 | MaxSamples if N==1 then the MaxSamples is indicated -#define _Z_FLAG_Z_P 0x20 // 1 << 7 | Period if P==1 then a period is present -#define _Z_FLAG_Z_Q 0x40 // 1 << 6 | QueryableKind if Q==1 then the queryable kind is present #define _Z_FLAG_Z_R \ 0x20 // 1 << 5 | Reliable if R==1 then it concerns the reliable channel, best-effort otherwise -#define _Z_FLAG_Z_S 0x40 // 1 << 6 | SubMode if S==1 then the declaration SubMode is indicated -#define _Z_FLAG_Z_T 0x20 // 1 << 5 | QueryTarget if T==1 then the query target is present #define _Z_FLAG_Z_X 0x00 // Unused flags are set to zero #define _Z_FRAG_BUFF_BASE_SIZE 128 // Arbitrary base size of the buffer to encode a fragment message header // Flags: -// - T: Timestamp If T==1 then the timestamp if present +// - X: Reserved // - E: Encoding If E==1 then the encoding is present // - Z: Extension If Z==1 then at least one extension is present // // 7 6 5 4 3 2 1 0 // +-+-+-+-+-+-+-+-+ -// |Z|E|T| REPLY | +// |Z|E|X| ERR | // +-+-+-+---------+ -// ~ ts: ~ if T==1 -// +---------------+ -// ~ encoding ~ if E==1 -// +---------------+ -// ~ [repl_exts] ~ if Z==1 -// +---------------+ -// ~ pl: ~ -- Payload -// +---------------+ -typedef struct { - _z_timestamp_t _timestamp; - _z_value_t _value; - _z_source_info_t _ext_source_info; - z_consolidation_mode_t _ext_consolidation; -#if Z_FEATURE_ATTACHMENT == 1 - _z_owned_encoded_attachment_t _ext_attachment; -#endif -} _z_msg_reply_t; -void _z_msg_reply_clear(_z_msg_reply_t *msg); -#define _Z_FLAG_Z_R_T 0x20 -#define _Z_FLAG_Z_R_E 0x40 - -// Flags: -// - T: Timestamp If T==1 then the timestamp if present -// - I: Infrastructure If I==1 then the error is related to the infrastructure else to the user -// - Z: Extension If Z==1 then at least one extension is present -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |Z|I|T| ERR | -// +-+-+-+---------+ -// % code:z16 % -// +---------------+ -// ~ ts: ~ if T==1 +// % encoding % // +---------------+ // ~ [err_exts] ~ if Z==1 // +---------------+ -#define _Z_FLAG_Z_E_T 0x20 -#define _Z_FLAG_Z_E_I 0x40 +/// ~ pl: ~ Payload +/// +---------------+ +#define _Z_FLAG_Z_E_E 0x40 typedef struct { - uint16_t _code; - _Bool _is_infrastructure; - _z_timestamp_t _timestamp; + _z_encoding_t _encoding; _z_source_info_t _ext_source_info; - _z_value_t _ext_value; + _z_bytes_t _payload; } _z_msg_err_t; void _z_msg_err_clear(_z_msg_err_t *err); -/// Flags: -/// - T: Timestamp If T==1 then the timestamp if present -/// - X: Reserved -/// - Z: Extension If Z==1 then at least one extension is present -/// -/// 7 6 5 4 3 2 1 0 -/// +-+-+-+-+-+-+-+-+ -/// |Z|X|T| ACK | -/// +-+-+-+---------+ -/// ~ ts: ~ if T==1 -/// +---------------+ -/// ~ [err_exts] ~ if Z==1 -/// +---------------+ -typedef struct { - _z_timestamp_t _timestamp; - _z_source_info_t _ext_source_info; -} _z_msg_ack_t; -#define _Z_FLAG_Z_A_T 0x20 - -/// Flags: -/// - T: Timestamp If T==1 then the timestamp if present -/// - X: Reserved -/// - Z: Extension If Z==1 then at least one extension is present -/// -/// 7 6 5 4 3 2 1 0 -/// +-+-+-+-+-+-+-+-+ -/// |Z|X|X| PULL | -/// +---------------+ -/// ~ [pull_exts] ~ if Z==1 -/// +---------------+ -typedef struct { - _z_source_info_t _ext_source_info; -} _z_msg_pull_t; -static inline void _z_msg_pull_clear(_z_msg_pull_t *pull) { (void)pull; } - typedef struct { _z_timestamp_t _timestamp; _z_source_info_t _source_info; @@ -145,6 +66,7 @@ typedef struct { typedef struct { _z_m_push_commons_t _commons; + _z_bytes_t _attachment; } _z_msg_del_t; static inline void _z_msg_del_clear(_z_msg_del_t *del) { (void)del; } #define _Z_M_DEL_ID 0x02 @@ -154,9 +76,7 @@ typedef struct { _z_m_push_commons_t _commons; _z_bytes_t _payload; _z_encoding_t _encoding; -#if Z_FEATURE_ATTACHMENT == 1 - _z_owned_encoded_attachment_t _attachment; -#endif + _z_bytes_t _attachment; } _z_msg_put_t; void _z_msg_put_clear(_z_msg_put_t *); #define _Z_M_PUT_ID 0x01 @@ -166,31 +86,58 @@ void _z_msg_put_clear(_z_msg_put_t *); /*------------------ Query Message ------------------*/ // 7 6 5 4 3 2 1 0 // +-+-+-+-+-+-+-+-+ -// |Z|C|P| QUERY | +// |Z|P|C| QUERY | // +-+-+-+---------+ -// ~ params ~ if P==1 -- -// +---------------+ // ~ consolidation ~ if C==1 -- u8 // +---------------+ +// ~ params ~ if P==1 -- +// +---------------+ // ~ [qry_exts] ~ if Z==1 // +---------------+ -#define _Z_FLAG_Z_Q_P 0x20 // 1 << 6 | Period if P==1 then a period is present +#define _Z_FLAG_Z_Q_C 0x20 // 1 << 5 | Consolidation if C==1 then consolidation is present +#define _Z_FLAG_Z_Q_P 0x40 // 1 << 6 | Params if P==1 then parameters are present typedef struct { - _z_bytes_t _parameters; + _z_slice_t _parameters; _z_source_info_t _ext_info; _z_value_t _ext_value; - z_consolidation_mode_t _ext_consolidation; -#if Z_FEATURE_ATTACHMENT == 1 - _z_owned_encoded_attachment_t _ext_attachment; -#endif + z_consolidation_mode_t _consolidation; + _z_bytes_t _ext_attachment; } _z_msg_query_t; typedef struct { _Bool info; _Bool body; - _Bool consolidation; _Bool attachment; } _z_msg_query_reqexts_t; _z_msg_query_reqexts_t _z_msg_query_required_extensions(const _z_msg_query_t *msg); void _z_msg_query_clear(_z_msg_query_t *msg); +typedef struct { + _Bool _is_put; + union { + _z_msg_del_t _del; + _z_msg_put_t _put; + } _body; +} _z_reply_body_t; +// Flags: +// - C: Consolidation If C==1 then consolidation is present +// - X: Reserved +// - Z: Extension If Z==1 then at least one extension is present +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|X|C| REPLY | +// +-+-+-+---------+ +// ~ consolidation ~ if C==1 +// +---------------+ +// ~ [repl_exts] ~ if Z==1 +// +---------------+ +// ~ ReplyBody ~ -- Payload +// +---------------+ +typedef struct { + z_consolidation_mode_t _consolidation; + _z_reply_body_t _body; +} _z_msg_reply_t; +void _z_msg_reply_clear(_z_msg_reply_t *msg); +#define _Z_FLAG_Z_R_C 0x20 + #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 642ff7b58..023959cce 100644 --- a/include/zenoh-pico/protocol/definitions/network.h +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -18,9 +18,10 @@ #include #include "zenoh-pico/api/constants.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/declarations.h" +#include "zenoh-pico/protocol/definitions/interest.h" #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/keyexpr.h" @@ -31,12 +32,26 @@ #define _Z_MID_N_REQUEST 0x1c #define _Z_MID_N_RESPONSE 0x1b #define _Z_MID_N_RESPONSE_FINAL 0x1a +#define _Z_MID_N_INTEREST 0x19 /*=============================*/ /* Network flags */ /*=============================*/ #define _Z_FLAG_N_Z 0x80 // 1 << 7 +// DECLARE message flags: +// - I: Interest If I==1 then the declare is in a response to an Interest with future==false +// - X: Reserved +// - Z: Extension If Z==1 then Zenoh extensions are present +#define _Z_FLAG_N_DECLARE_I 0x20 // 1 << 5 + +// INTEREST message flags: +// - C: Current If C==1 then interest concerns current declarations +// - F: Future If F==1 then interest concerns future declarations +// - Z: Extension If Z==1 then Zenoh extensions are present +#define _Z_FLAG_N_INTEREST_CURRENT 0x20 // 1 << 5 +#define _Z_FLAG_N_INTEREST_FUTURE 0x40 // 1 << 6 + // PUSH message flags: // N Named if N==1 then the key expr has name/suffix // M Mapping if M==1 then keyexpr mapping is the one declared by the sender, otherwise by the receiver @@ -112,12 +127,15 @@ typedef struct { z_query_target_t _ext_target; uint32_t _ext_budget; uint32_t _ext_timeout_ms; - enum { _Z_REQUEST_QUERY, _Z_REQUEST_PUT, _Z_REQUEST_DEL, _Z_REQUEST_PULL } _tag; + enum { + _Z_REQUEST_QUERY, + _Z_REQUEST_PUT, + _Z_REQUEST_DEL, + } _tag; union { _z_msg_query_t _query; _z_msg_put_t _put; _z_msg_del_t _del; - _z_msg_pull_t _pull; } _body; } _z_n_msg_request_t; typedef struct { @@ -131,13 +149,7 @@ typedef struct { _z_n_msg_request_exts_t _z_n_msg_request_needed_exts(const _z_n_msg_request_t *msg); void _z_n_msg_request_clear(_z_n_msg_request_t *msg); -typedef struct { - _Bool _is_put; - union { - _z_msg_del_t _del; - _z_msg_put_t _put; - } _body; -} _z_push_body_t; +typedef _z_reply_body_t _z_push_body_t; _z_push_body_t _z_push_body_null(void); _z_push_body_t _z_push_body_steal(_z_push_body_t *msg); void _z_push_body_clear(_z_push_body_t *msg); @@ -199,27 +211,64 @@ typedef struct { enum { _Z_RESPONSE_BODY_REPLY, _Z_RESPONSE_BODY_ERR, - _Z_RESPONSE_BODY_ACK, - _Z_RESPONSE_BODY_PUT, - _Z_RESPONSE_BODY_DEL, } _tag; union { _z_msg_reply_t _reply; _z_msg_err_t _err; - _z_msg_ack_t _ack; - _z_msg_put_t _put; - _z_msg_del_t _del; } _body; } _z_n_msg_response_t; void _z_n_msg_response_clear(_z_n_msg_response_t *msg); +/*------------------ Declare Message ------------------*/ + typedef struct { _z_declaration_t _decl; _z_timestamp_t _ext_timestamp; _z_n_qos_t _ext_qos; + uint32_t _interest_id; + _Bool has_interest_id; } _z_n_msg_declare_t; static inline void _z_n_msg_declare_clear(_z_n_msg_declare_t *msg) { _z_declaration_clear(&msg->_decl); } +/*------------------ Interest Message ------------------*/ + +/// Flags: +/// - C: Current If C==1 then interest concerns current declarations +/// - F: Future If F==1 then interest concerns future declarations +/// - Z: Extension If Z==1 then Zenoh extensions are present +/// If C==0 and F==0, then interest is final +/// +/// 7 6 5 4 3 2 1 0 +/// +-+-+-+-+-+-+-+-+ +/// |Z|F|C|INTEREST | +/// +-+-+-+---------+ +/// ~ id:z32 ~ +/// +---------------+ +/// |A|M|N|R|T|Q|S|K| (*) if interest is not final +/// +---------------+ +/// ~ key_scope:z16 ~ if interest is not final && R==1 +/// +---------------+ +/// ~ key_suffix ~ if interest is not final && R==1 && N==1 -- +/// +---------------+ +/// ~ [int_exts] ~ if Z==1 +/// +---------------+ +/// +/// (*) - if K==1 then the interest refers to key expressions +/// - if S==1 then the interest refers to subscribers +/// - if Q==1 then the interest refers to queryables +/// - if T==1 then the interest refers to tokens +/// - if R==1 then the interest is restricted to the matching key expression, else it is for all key expressions. +/// - if N==1 then the key expr has name/suffix. If R==0 then N should be set to 0. +/// - if M==1 then key expr mapping is the one declared by the sender, else it is the one declared by the receiver. +/// If R==0 then M should be set to 0. +/// - if A==1 then the replies SHOULD be aggregated +/// ``` + +typedef struct { + _z_interest_t _interest; +} _z_n_msg_interest_t; +static inline void _z_n_msg_interest_clear(_z_n_msg_interest_t *msg) { _z_interest_clear(&msg->_interest); } + /*------------------ Zenoh Message ------------------*/ typedef union { _z_n_msg_declare_t _declare; @@ -227,9 +276,10 @@ typedef union { _z_n_msg_request_t _request; _z_n_msg_response_t _response; _z_n_msg_response_final_t _response_final; + _z_n_msg_interest_t _interest; } _z_network_body_t; typedef struct { - enum { _Z_N_DECLARE, _Z_N_PUSH, _Z_N_REQUEST, _Z_N_RESPONSE, _Z_N_RESPONSE_FINAL } _tag; + enum { _Z_N_DECLARE, _Z_N_PUSH, _Z_N_REQUEST, _Z_N_RESPONSE, _Z_N_RESPONSE_FINAL, _Z_N_INTEREST } _tag; _z_network_body_t _body; } _z_network_message_t; typedef _z_network_message_t _z_zenoh_message_t; @@ -241,19 +291,14 @@ _Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_ _Z_VEC_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_pull(_z_keyexpr_t key, _z_zint_t pull_id); -_z_network_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_bytes_t) parameters, _z_zint_t qid, +_z_network_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_slice_t) parameters, _z_zint_t qid, z_consolidation_mode_t consolidation, _Z_MOVE(_z_value_t) value, - uint32_t timeout_ms -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t attachment -#endif -); -_z_network_message_t _z_n_msg_make_reply(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_value_t) value); -_z_network_message_t _z_n_msg_make_ack(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key); + uint32_t timeout_ms, _z_bytes_t attachment, z_congestion_control_t cong_ctrl, + z_priority_t priority, _Bool is_express); +_z_network_message_t _z_n_msg_make_reply(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_push_body_t) body); _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); +_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); #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 df0b5cecd..74f4de973 100644 --- a/include/zenoh-pico/protocol/definitions/transport.h +++ b/include/zenoh-pico/protocol/definitions/transport.h @@ -305,7 +305,7 @@ void _z_t_msg_join_clear(_z_t_msg_join_t *msg); // typedef struct { _z_id_t _zid; - _z_bytes_t _cookie; + _z_slice_t _cookie; uint16_t _batch_size; z_whatami_t _whatami; uint8_t _req_id_res; @@ -348,7 +348,7 @@ void _z_t_msg_init_clear(_z_t_msg_init_t *msg); typedef struct { _z_zint_t _lease; _z_zint_t _initial_sn; - _z_bytes_t _cookie; + _z_slice_t _cookie; } _z_t_msg_open_t; void _z_t_msg_open_clear(_z_t_msg_open_t *msg); @@ -472,7 +472,7 @@ void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg); // +---------------+ // typedef struct { - _z_bytes_t _payload; + _z_slice_t _payload; _z_zint_t _sn; } _z_t_msg_fragment_t; void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg); @@ -500,8 +500,8 @@ void _z_t_msg_clear(_z_transport_message_t *msg); _z_transport_message_t _z_t_msg_make_join(z_whatami_t whatami, _z_zint_t lease, _z_id_t zid, _z_conduit_sn_list_t next_sn); _z_transport_message_t _z_t_msg_make_init_syn(z_whatami_t whatami, _z_id_t zid); -_z_transport_message_t _z_t_msg_make_init_ack(z_whatami_t whatami, _z_id_t zid, _z_bytes_t cookie); -_z_transport_message_t _z_t_msg_make_open_syn(_z_zint_t lease, _z_zint_t initial_sn, _z_bytes_t cookie); +_z_transport_message_t _z_t_msg_make_init_ack(z_whatami_t whatami, _z_id_t zid, _z_slice_t cookie); +_z_transport_message_t _z_t_msg_make_open_syn(_z_zint_t lease, _z_zint_t initial_sn, _z_slice_t cookie); _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); @@ -509,7 +509,7 @@ _z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_ 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); -_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_bytes_t messages, z_reliability_t reliability, +_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_slice_t messages, z_reliability_t reliability, _Bool is_last); /*------------------ Copy ------------------*/ diff --git a/include/zenoh-pico/protocol/ext.h b/include/zenoh-pico/protocol/ext.h index 118c1ed14..cba1ab55d 100644 --- a/include/zenoh-pico/protocol/ext.h +++ b/include/zenoh-pico/protocol/ext.h @@ -68,7 +68,7 @@ void _z_msg_ext_clear_zint(_z_msg_ext_zint_t *ext); /*------------------ Unknown Extension ------------------*/ typedef struct { - _z_bytes_t _val; + _z_slice_t _val; } _z_msg_ext_zbuf_t; void _z_msg_ext_clear_zbuf(_z_msg_ext_zbuf_t *ext); @@ -88,7 +88,7 @@ void _z_msg_ext_clear(_z_msg_ext_t *ext); /*------------------ Builders ------------------*/ _z_msg_ext_t _z_msg_ext_make_unit(uint8_t id); _z_msg_ext_t _z_msg_ext_make_zint(uint8_t id, _z_zint_t zid); -_z_msg_ext_t _z_msg_ext_make_zbuf(uint8_t id, _z_bytes_t zbuf); +_z_msg_ext_t _z_msg_ext_make_zbuf(uint8_t id, _z_slice_t zbuf); /*------------------ Copy ------------------*/ void _z_msg_ext_copy(_z_msg_ext_t *clone, const _z_msg_ext_t *ext); diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index 90af275fe..1f29a9b56 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -19,8 +19,8 @@ #include #include -#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/vec.h" /*------------------ IOSli ------------------*/ @@ -48,7 +48,7 @@ void _z_iosli_write_bytes(_z_iosli_t *ios, const uint8_t *bs, size_t offset, siz void _z_iosli_put(_z_iosli_t *ios, uint8_t b, size_t pos); void _z_iosli_reset(_z_iosli_t *ios); -_z_bytes_t _z_iosli_to_bytes(const _z_iosli_t *ios); +_z_slice_t _z_iosli_to_bytes(const _z_iosli_t *ios); size_t _z_iosli_size(const _z_iosli_t *ios); void _z_iosli_clear(_z_iosli_t *ios); @@ -67,7 +67,7 @@ typedef struct { _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` -_z_zbuf_t _z_zbytes_as_zbuf(_z_bytes_t slice); +_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); diff --git a/include/zenoh-pico/protocol/keyexpr.h b/include/zenoh-pico/protocol/keyexpr.h index 193d3b54e..e475f8761 100644 --- a/include/zenoh-pico/protocol/keyexpr.h +++ b/include/zenoh-pico/protocol/keyexpr.h @@ -21,19 +21,27 @@ 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_includes(const char *lstart, const size_t llen, const char *rstart, const size_t rlen); -_Bool _z_keyexpr_intersects(const char *lstart, const size_t llen, const char *rstart, const size_t rlen); +_Bool _z_keyexpr_suffix_includes(const _z_keyexpr_t *left, const _z_keyexpr_t *right); +_Bool _z_keyexpr_suffix_intersects(const _z_keyexpr_t *left, const _z_keyexpr_t *right); +_Bool _z_keyexpr_suffix_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right); /*------------------ clone/Copy/Free helpers ------------------*/ -void _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src); +_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); +int8_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_to_owned(_z_keyexpr_t src); _z_keyexpr_t _z_keyexpr_alias(_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}, NULL}; + _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); diff --git a/include/zenoh-pico/session/interest.h b/include/zenoh-pico/session/interest.h new file mode 100644 index 000000000..7114fea1b --- /dev/null +++ b/include/zenoh-pico/session/interest.h @@ -0,0 +1,35 @@ +// +// 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_SESSION_INTEREST_H +#define ZENOH_PICO_SESSION_INTEREST_H + +#include + +#include "zenoh-pico/net/session.h" + +#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); +void _z_unregister_interest(_z_session_t *zn, _z_session_interest_rc_t *intr); +#endif // Z_FEATURE_INTEREST == 1 + +void _z_flush_interest(_z_session_t *zn); +int8_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t *decl); +int8_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration_t *decl); +int8_t _z_interest_process_declare_final(_z_session_t *zn, uint32_t id); +int8_t _z_interest_process_interest_final(_z_session_t *zn, uint32_t id); +int8_t _z_interest_process_interest(_z_session_t *zn, _z_keyexpr_t key, uint32_t id, uint8_t flags); + +#endif /* ZENOH_PICO_SESSION_INTEREST_H */ diff --git a/include/zenoh-pico/session/push.h b/include/zenoh-pico/session/push.h index 583746c15..76c02b2f1 100644 --- a/include/zenoh-pico/session/push.h +++ b/include/zenoh-pico/session/push.h @@ -23,4 +23,4 @@ int8_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push); -#endif /* ZENOH_PICO_SESSION_PUSH_H */ \ No newline at end of file +#endif /* ZENOH_PICO_SESSION_PUSH_H */ diff --git a/include/zenoh-pico/session/query.h b/include/zenoh-pico/session/query.h index 86d03bb6f..acdc3a6b3 100644 --- a/include/zenoh-pico/session/query.h +++ b/include/zenoh-pico/session/query.h @@ -26,8 +26,8 @@ _z_pending_query_t *_z_get_pending_query_by_id(_z_session_t *zn, const _z_zint_t int8_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pq); int8_t _z_trigger_query_reply_partial(_z_session_t *zn, _z_zint_t reply_context, const _z_keyexpr_t keyexpr, - const _z_bytes_t payload, const _z_encoding_t encoding, const _z_zint_t kind, - const _z_timestamp_t timestamp); + _z_msg_put_t *msg, z_sample_kind_t kind); +int8_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg); int8_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id); void _z_unregister_pending_query(_z_session_t *zn, _z_pending_query_t *pq); void _z_flush_pending_queries(_z_session_t *zn); diff --git a/include/zenoh-pico/session/queryable.h b/include/zenoh-pico/session/queryable.h index b51a0c90d..400af55f8 100644 --- a/include/zenoh-pico/session/queryable.h +++ b/include/zenoh-pico/session/queryable.h @@ -28,7 +28,8 @@ _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, cons _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); -int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *query, const _z_keyexpr_t q_key, uint32_t qid); +int8_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); 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 e84fa5c7e..719b2fee1 100644 --- a/include/zenoh-pico/session/reply.h +++ b/include/zenoh-pico/session/reply.h @@ -24,6 +24,8 @@ int8_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t key, _z_msg_reply_t *reply); +int8_t _z_trigger_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *error); + int8_t _z_trigger_reply_final(_z_session_t *zn, _z_n_msg_response_final_t *final); -#endif /* ZENOH_PICO_SESSION_REPLY_H */ \ No newline at end of file +#endif /* ZENOH_PICO_SESSION_REPLY_H */ diff --git a/include/zenoh-pico/session/resource.h b/include/zenoh-pico/session/resource.h index 7c6ef0cc1..3702a86cd 100644 --- a/include/zenoh-pico/session/resource.h +++ b/include/zenoh-pico/session/resource.h @@ -27,7 +27,7 @@ uint16_t _z_get_resource_id(_z_session_t *zn); _z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t rid); _z_resource_t *_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); -int16_t _z_register_resource(_z_session_t *zn, const _z_keyexpr_t key, uint16_t id, uint16_t register_to_mapping); +uint16_t _z_register_resource(_z_session_t *zn, const _z_keyexpr_t key, uint16_t id, uint16_t register_to_mapping); 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); diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index 997848080..de91d28fd 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -34,40 +34,6 @@ typedef void (*_z_drop_handler_t)(void *arg); #define _Z_RESOURCE_IS_REMOTE 0 #define _Z_RESOURCE_IS_LOCAL 1 -/** - * An reply to a :c:func:`z_query`. - * - * Members: - * _z_sample_t data: a :c:type:`_z_sample_t` containing the key and value of the reply. - * _z_bytes_t replier_id: The id of the replier that sent this reply. - * - */ -typedef struct { - _z_sample_t sample; - _z_id_t replier_id; -} _z_reply_data_t; - -void _z_reply_data_clear(_z_reply_data_t *rd); - -_Z_ELEM_DEFINE(_z_reply_data, _z_reply_data_t, _z_noop_size, _z_reply_data_clear, _z_noop_copy) -_Z_LIST_DEFINE(_z_reply_data, _z_reply_data_t) - -/** - * An reply to a :c:func:`z_query`. - * - * Members: - * _z_reply_t_Tag tag: Indicates if the reply contains data or if it's a FINAL reply. - * _z_reply_data_t data: The reply data if :c:member:`_z_reply_t.tag` equals - * :c:member:`_z_reply_t_Tag.Z_REPLY_TAG_DATA`. - * - */ -typedef struct { - _z_reply_data_t data; - z_reply_tag_t _tag; -} _z_reply_t; -void _z_reply_clear(_z_reply_t *src); -void _z_reply_free(_z_reply_t **hello); - typedef struct { _z_keyexpr_t _key; uint16_t _id; @@ -76,11 +42,15 @@ typedef struct { _Bool _z_resource_eq(const _z_resource_t *one, const _z_resource_t *two); 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_noop_copy) +_Z_ELEM_DEFINE(_z_resource, _z_resource_t, _z_noop_size, _z_resource_clear, _z_resource_copy) _Z_LIST_DEFINE(_z_resource, _z_resource_t) +// Forward declaration to avoid cyclical include +typedef struct _z_sample_t _z_sample_t; + /** * The callback signature of the functions handling data messages. */ @@ -101,7 +71,8 @@ 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_subscription_rc, _z_subscription_rc_t, _z_noop_size, _z_subscription_rc_drop, _z_noop_copy) +_Z_ELEM_DEFINE(_z_subscription_rc, _z_subscription_rc_t, _z_subscription_rc_size, _z_subscription_rc_drop, + _z_subscription_rc_copy) _Z_LIST_DEFINE(_z_subscription_rc, _z_subscription_rc_t) typedef struct { @@ -109,11 +80,13 @@ typedef struct { uint32_t _id; } _z_publication_t; -typedef struct z_query_t z_query_t; // Forward type declaration to avoid cyclical include +// Forward type declaration to avoid cyclical include +typedef struct _z_query_rc_t _z_query_rc_t; + /** * The callback signature of the functions handling query messages. */ -typedef void (*_z_queryable_handler_t)(const z_query_t *query, void *arg); +typedef void (*_z_queryable_handler_t)(const _z_query_rc_t *query, void *arg); typedef struct { _z_keyexpr_t _key; @@ -133,31 +106,23 @@ _Z_ELEM_DEFINE(_z_session_queryable_rc, _z_session_queryable_rc_t, _z_noop_size, _z_noop_copy) _Z_LIST_DEFINE(_z_session_queryable_rc, _z_session_queryable_rc_t) -typedef struct { - _z_reply_t _reply; - _z_timestamp_t _tstamp; -} _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_LIST_DEFINE(_z_pending_reply, _z_pending_reply_t) +// Forward declaration to avoid cyclical includes +typedef struct _z_reply_t _z_reply_t; +typedef _z_list_t _z_reply_data_list_t; +typedef _z_list_t _z_pending_reply_list_t; +typedef struct _z_reply_t _z_reply_t; -struct __z_reply_handler_wrapper_t; // Forward declaration to be used in _z_reply_handler_t /** * The callback signature of the functions handling query replies. */ -typedef void (*_z_reply_handler_t)(_z_reply_t *reply, struct __z_reply_handler_wrapper_t *arg); +typedef void (*_z_reply_handler_t)(const _z_reply_t *reply, void *arg); typedef struct { _z_keyexpr_t _key; _z_zint_t _id; _z_reply_handler_t _callback; _z_drop_handler_t _dropper; - void *_call_arg; // TODO[API-NET]: These two can be merged into one, when API and NET are a single layer - void *_drop_arg; // TODO[API-NET]: These two can be merged into one, when API and NET are a single layer - char *_parameters; + void *_arg; _z_pending_reply_list_t *_pending_replies; z_query_target_t _target; z_consolidation_mode_t _consolidation; @@ -172,8 +137,8 @@ _Z_LIST_DEFINE(_z_pending_query, _z_pending_query_t) typedef struct { #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_t _mutex; - z_condvar_t _cond_var; + _z_mutex_t _mutex; + _z_condvar_t _cond_var; #endif // Z_FEATURE_MULTI_THREAD == 1 _z_reply_data_list_t *_replies; } _z_pending_query_collect_t; @@ -186,4 +151,57 @@ typedef void (*_z_hello_handler_t)(_z_hello_t *hello, struct __z_hello_handler_w int8_t _z_session_generate_zid(_z_id_t *bs, uint8_t size); +typedef enum { + _Z_INTEREST_MSG_TYPE_FINAL = 0, + _Z_INTEREST_MSG_TYPE_DECL_SUBSCRIBER = 1, + _Z_INTEREST_MSG_TYPE_DECL_QUERYABLE = 2, + _Z_INTEREST_MSG_TYPE_DECL_TOKEN = 3, + _Z_INTEREST_MSG_TYPE_UNDECL_SUBSCRIBER = 4, + _Z_INTEREST_MSG_TYPE_UNDECL_QUERYABLE = 5, + _Z_INTEREST_MSG_TYPE_UNDECL_TOKEN = 6, +} _z_interest_msg_type_t; + +typedef struct _z_interest_msg_t { + uint8_t type; + uint32_t id; +} _z_interest_msg_t; + +/** + * The callback signature of the functions handling interest messages. + */ +typedef void (*_z_interest_handler_t)(const _z_interest_msg_t *msg, void *arg); + +typedef struct { + _z_keyexpr_t _key; + uint32_t _id; + _z_interest_handler_t _callback; + void *_arg; + uint8_t _flags; +} _z_session_interest_t; + +_Bool _z_session_interest_eq(const _z_session_interest_t *one, const _z_session_interest_t *two); +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_rc, _z_session_interest_rc_t, _z_noop_size, _z_session_interest_rc_drop, + _z_noop_copy) +_Z_LIST_DEFINE(_z_session_interest_rc, _z_session_interest_rc_t) + +typedef enum { + _Z_DECLARE_TYPE_SUBSCRIBER = 0, + _Z_DECLARE_TYPE_QUERYABLE = 1, + _Z_DECLARE_TYPE_TOKEN = 2, +} _z_declare_type_t; + +typedef struct { + _z_keyexpr_t _key; + uint32_t _id; + uint8_t _type; +} _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_LIST_DEFINE(_z_declare_data, _z_declare_data_t) + #endif /* INCLUDE_ZENOH_PICO_SESSION_SESSION_H */ diff --git a/include/zenoh-pico/session/subscription.h b/include/zenoh-pico/session/subscription.h index 77fb05af7..bade6d1ce 100644 --- a/include/zenoh-pico/session/subscription.h +++ b/include/zenoh-pico/session/subscription.h @@ -15,34 +15,24 @@ #ifndef INCLUDE_ZENOH_PICO_SESSION_SUBSCRIPTION_H #define INCLUDE_ZENOH_PICO_SESSION_SUBSCRIPTION_H +#include "zenoh-pico/net/encoding.h" #include "zenoh-pico/net/session.h" -#if Z_FEATURE_SUBSCRIPTION == 1 /*------------------ Subscription ------------------*/ +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, + _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, + const _z_bytes_t attachment); + +#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); _z_subscription_rc_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *sub); -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, - _z_zint_t payload_len, _z_n_qos_t qos -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t att -#endif -); int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, - const _z_encoding_t encoding, const _z_zint_t kind, const _z_timestamp_t timestamp, - const _z_n_qos_t qos -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t att -#endif -); + _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); 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); - -/*------------------ Pull ------------------*/ -_z_zint_t _z_get_pull_id(_z_session_t *zn); #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 39491ba4d..5e125556a 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -23,15 +23,18 @@ #include "zenoh-pico/protocol/core.h" /*------------------ Session ------------------*/ -_z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t id, const char *locator, const uint32_t timeout, +_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); -int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid); +int8_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid); void _z_session_clear(_z_session_t *zn); int8_t _z_session_close(_z_session_t *zn, uint8_t reason); -int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *z_msg, uint16_t local_peer_id); +int8_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t *z_msg, uint16_t local_peer_id); int8_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); + #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 6ac5523d8..af725a12b 100644 --- a/include/zenoh-pico/system/link/raweth.h +++ b/include/zenoh-pico/system/link/raweth.h @@ -32,7 +32,7 @@ // Max frame size #define _ZP_MAX_ETH_FRAME_SIZE 1514 -// Endpoing config types +// Endpoint config types typedef struct { _z_keyexpr_t _keyexpr; uint16_t _vlan; // vlan tag (pcp + dei + id), big endian @@ -82,14 +82,13 @@ typedef struct { _Bool _has_vlan; } _z_raweth_socket_t; -int8_t _z_get_smac_raweth(_z_raweth_socket_t *resock); int8_t _z_open_raweth(_z_sys_net_socket_t *sock, const char *interface); size_t _z_send_raweth(const _z_sys_net_socket_t *sock, const void *buff, size_t buff_len); -size_t _z_receive_raweth(const _z_sys_net_socket_t *sock, void *buff, size_t buff_len, _z_bytes_t *addr, +size_t _z_receive_raweth(const _z_sys_net_socket_t *sock, void *buff, size_t buff_len, _z_slice_t *addr, const _zp_raweth_whitelist_array_t *whitelist); int8_t _z_close_raweth(_z_sys_net_socket_t *sock); -size_t _z_raweth_ntohs(size_t val); -size_t _z_raweth_htons(size_t val); +uint16_t _z_raweth_ntohs(uint16_t val); +uint16_t _z_raweth_htons(uint16_t val); #endif diff --git a/include/zenoh-pico/system/link/udp.h b/include/zenoh-pico/system/link/udp.h index 794cff091..e9f17acb9 100644 --- a/include/zenoh-pico/system/link/udp.h +++ b/include/zenoh-pico/system/link/udp.h @@ -49,9 +49,9 @@ int8_t _z_listen_udp_multicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpo void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t *socksend, const _z_sys_net_endpoint_t rep, const _z_sys_net_endpoint_t lep); size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *ep); + const _z_sys_net_endpoint_t lep, _z_slice_t *ep); size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *ep); + _z_slice_t *ep); size_t _z_send_udp_multicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t rep); #endif diff --git a/include/zenoh-pico/system/platform-common.h b/include/zenoh-pico/system/platform-common.h index 081a5a9c4..15f2440aa 100644 --- a/include/zenoh-pico/system/platform-common.h +++ b/include/zenoh-pico/system/platform-common.h @@ -15,9 +15,12 @@ #ifndef ZENOH_PICO_SYSTEM_PLATFORM_COMMON_H #define ZENOH_PICO_SYSTEM_PLATFORM_COMMON_H +#include #include +#include "zenoh-pico/api/olv_macros.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/utils/result.h" #if defined(ZENOH_LINUX) || defined(ZENOH_MACOS) || defined(ZENOH_BSD) #include "zenoh-pico/system/platform/unix.h" @@ -48,6 +51,18 @@ extern "C" { #endif +void _z_report_system_error(int errcode); + +#define _Z_CHECK_SYS_ERR(expr) \ + do { \ + int __res = expr; \ + if (__res != 0) { \ + _z_report_system_error(__res); \ + return _Z_ERR_SYSTEM_GENERIC; \ + } \ + return _Z_RES_OK; \ + } while (false) + /*------------------ Random ------------------*/ uint8_t z_random_u8(void); uint16_t z_random_u16(void); @@ -60,28 +75,60 @@ void *z_malloc(size_t size); void *z_realloc(void *ptr, size_t size); void z_free(void *ptr); -#if Z_FEATURE_MULTI_THREAD == 1 +#if Z_FEATURE_MULTI_THREAD == 0 +// dummy types for correct macros work +typedef void *_z_task_t; +typedef void *_z_mutex_t; +typedef void *_z_condvar_t; +typedef void *z_task_attr_t; +#endif + /*------------------ Thread ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg); -int8_t z_task_join(z_task_t *task); -int8_t zp_task_cancel(z_task_t *task); -void z_task_free(z_task_t **task); +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg); +int8_t _z_task_join(_z_task_t *task); +int8_t _z_task_cancel(_z_task_t *task); +void _z_task_free(_z_task_t **task); + +_Z_OWNED_TYPE_VALUE(_z_task_t, task) +_Z_OWNED_FUNCTIONS_SYSTEM_DEF(task) + +int8_t z_task_init(z_owned_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg); +int8_t z_task_join(z_owned_task_t *task); /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m); -int8_t z_mutex_free(z_mutex_t *m); +int8_t _z_mutex_init(_z_mutex_t *m); +int8_t _z_mutex_drop(_z_mutex_t *m); + +int8_t _z_mutex_lock(_z_mutex_t *m); +int8_t _z_mutex_try_lock(_z_mutex_t *m); +int8_t _z_mutex_unlock(_z_mutex_t *m); -int8_t z_mutex_lock(z_mutex_t *m); -int8_t z_mutex_trylock(z_mutex_t *m); -int8_t z_mutex_unlock(z_mutex_t *m); +_Z_OWNED_TYPE_VALUE(_z_mutex_t, mutex) +_Z_OWNED_FUNCTIONS_SYSTEM_DEF(mutex) + +int8_t z_mutex_init(z_owned_mutex_t *m); +int8_t z_mutex_drop(z_moved_mutex_t *m); + +int8_t z_mutex_lock(z_loaned_mutex_t *m); +int8_t z_mutex_try_lock(z_loaned_mutex_t *m); +int8_t z_mutex_unlock(z_loaned_mutex_t *m); /*------------------ CondVar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv); -int8_t z_condvar_free(z_condvar_t *cv); +int8_t _z_condvar_init(_z_condvar_t *cv); +int8_t _z_condvar_drop(_z_condvar_t *cv); + +int8_t _z_condvar_signal(_z_condvar_t *cv); +int8_t _z_condvar_signal_all(_z_condvar_t *cv); +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m); -int8_t z_condvar_signal(z_condvar_t *cv); -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m); -#endif // Z_FEATURE_MULTI_THREAD == 1 +_Z_OWNED_TYPE_VALUE(_z_condvar_t, condvar) +_Z_OWNED_FUNCTIONS_SYSTEM_DEF(condvar) + +int8_t z_condvar_init(z_owned_condvar_t *cv); +int8_t z_condvar_drop(z_moved_condvar_t *cv); + +int8_t z_condvar_signal(z_loaned_condvar_t *cv); +int8_t z_condvar_wait(z_loaned_condvar_t *cv, z_loaned_mutex_t *m); /*------------------ Sleep ------------------*/ int z_sleep_us(size_t time); @@ -101,6 +148,12 @@ unsigned long z_time_elapsed_us(z_time_t *time); unsigned long z_time_elapsed_ms(z_time_t *time); unsigned long z_time_elapsed_s(z_time_t *time); +typedef struct { + uint32_t secs; + uint32_t nanos; +} zp_time_since_epoch; + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t); #ifdef __cplusplus } #endif diff --git a/include/zenoh-pico/system/platform.h b/include/zenoh-pico/system/platform.h index 4fe70198d..a0bf54990 100644 --- a/include/zenoh-pico/system/platform.h +++ b/include/zenoh-pico/system/platform.h @@ -18,7 +18,6 @@ #include #include "zenoh-pico/config.h" -#include "zenoh-pico/deprecated/platform.h" #include "zenoh-pico/system/platform-common.h" #endif /* ZENOH_PICO_SYSTEM_PLATFORM_H */ diff --git a/include/zenoh-pico/system/platform/arduino/esp32.h b/include/zenoh-pico/system/platform/arduino/esp32.h index abdc37f67..9f8c34da9 100644 --- a/include/zenoh-pico/system/platform/arduino/esp32.h +++ b/include/zenoh-pico/system/platform/arduino/esp32.h @@ -24,10 +24,10 @@ #endif // Z_FEATURE_MULTI_THREAD == 1 #if Z_FEATURE_MULTI_THREAD == 1 -typedef TaskHandle_t z_task_t; +typedef TaskHandle_t _z_task_t; typedef void *z_task_attr_t; // Not used in ESP32 -typedef pthread_mutex_t z_mutex_t; -typedef pthread_cond_t z_condvar_t; +typedef pthread_mutex_t _z_mutex_t; +typedef pthread_cond_t _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef struct timespec z_clock_t; diff --git a/include/zenoh-pico/system/platform/arduino/opencr.h b/include/zenoh-pico/system/platform/arduino/opencr.h index af16ce60b..44b0f4a8f 100644 --- a/include/zenoh-pico/system/platform/arduino/opencr.h +++ b/include/zenoh-pico/system/platform/arduino/opencr.h @@ -21,10 +21,10 @@ #include "zenoh-pico/config.h" #if Z_FEATURE_MULTI_THREAD == 1 -typedef void *z_task_t; +typedef void *_z_task_t; typedef void *z_task_attr_t; -typedef void *z_mutex_t; -typedef void *z_condvar_t; +typedef void *_z_mutex_t; +typedef void *_z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef struct timespec z_clock_t; diff --git a/include/zenoh-pico/system/platform/emscripten.h b/include/zenoh-pico/system/platform/emscripten.h index b89921197..edb9c6b44 100644 --- a/include/zenoh-pico/system/platform/emscripten.h +++ b/include/zenoh-pico/system/platform/emscripten.h @@ -22,10 +22,10 @@ #if Z_FEATURE_MULTI_THREAD == 1 #include -typedef pthread_t z_task_t; +typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; -typedef pthread_mutex_t z_mutex_t; -typedef pthread_cond_t z_condvar_t; +typedef pthread_mutex_t _z_mutex_t; +typedef pthread_cond_t _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef double z_clock_t; diff --git a/include/zenoh-pico/system/platform/espidf.h b/include/zenoh-pico/system/platform/espidf.h index b7353b561..aa09362b4 100644 --- a/include/zenoh-pico/system/platform/espidf.h +++ b/include/zenoh-pico/system/platform/espidf.h @@ -38,9 +38,9 @@ typedef struct { typedef struct { TaskHandle_t handle; EventGroupHandle_t join_event; -} z_task_t; -typedef pthread_mutex_t z_mutex_t; -typedef pthread_cond_t z_condvar_t; +} _z_task_t; +typedef pthread_mutex_t _z_mutex_t; +typedef pthread_cond_t _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef struct timespec z_clock_t; diff --git a/include/zenoh-pico/system/platform/flipper.h b/include/zenoh-pico/system/platform/flipper.h index 124714afe..4a51074f6 100644 --- a/include/zenoh-pico/system/platform/flipper.h +++ b/include/zenoh-pico/system/platform/flipper.h @@ -27,10 +27,10 @@ #define FLIPPER_SERIAL_TIMEOUT_MS 200 #if Z_FEATURE_MULTI_THREAD == 1 -typedef FuriThread* z_task_t; +typedef FuriThread* _z_task_t; typedef uint32_t z_task_attr_t; -typedef FuriMutex* z_mutex_t; -typedef void* z_condvar_t; +typedef FuriMutex* _z_mutex_t; +typedef void* _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef struct timespec z_clock_t; diff --git a/include/zenoh-pico/system/platform/freertos_plus_tcp.h b/include/zenoh-pico/system/platform/freertos_plus_tcp.h index f85269dab..81ea0389a 100644 --- a/include/zenoh-pico/system/platform/freertos_plus_tcp.h +++ b/include/zenoh-pico/system/platform/freertos_plus_tcp.h @@ -33,10 +33,10 @@ typedef struct { typedef struct { TaskHandle_t handle; EventGroupHandle_t join_event; -} z_task_t; +} _z_task_t; -typedef SemaphoreHandle_t z_mutex_t; -typedef void *z_condvar_t; +typedef SemaphoreHandle_t _z_mutex_t; +typedef void *_z_condvar_t; #endif // Z_MULTI_THREAD == 1 typedef TickType_t z_clock_t; diff --git a/include/zenoh-pico/system/platform/mbed.h b/include/zenoh-pico/system/platform/mbed.h index 170b230f3..e444dc930 100644 --- a/include/zenoh-pico/system/platform/mbed.h +++ b/include/zenoh-pico/system/platform/mbed.h @@ -23,10 +23,10 @@ typedef int _z_socket_t; #if Z_FEATURE_MULTI_THREAD == 1 -typedef void *z_task_t; // Workaround as MBED is a C++ library +typedef void *_z_task_t; // Workaround as MBED is a C++ library typedef void *z_task_attr_t; // Workaround as MBED is a C++ library -typedef void *z_mutex_t; // Workaround as MBED is a C++ library -typedef void *z_condvar_t; // Workaround as MBED is a C++ library +typedef void *_z_mutex_t; // Workaround as MBED is a C++ library +typedef void *_z_condvar_t; // Workaround as MBED is a C++ library #endif // Z_FEATURE_MULTI_THREAD == 1 typedef void *z_clock_t; // Not defined diff --git a/include/zenoh-pico/system/platform/unix.h b/include/zenoh-pico/system/platform/unix.h index 8fd10421e..cea7b5868 100644 --- a/include/zenoh-pico/system/platform/unix.h +++ b/include/zenoh-pico/system/platform/unix.h @@ -25,10 +25,10 @@ #if Z_FEATURE_MULTI_THREAD == 1 #include -typedef pthread_t z_task_t; +typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; -typedef pthread_mutex_t z_mutex_t; -typedef pthread_cond_t z_condvar_t; +typedef pthread_mutex_t _z_mutex_t; +typedef pthread_cond_t _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef struct timespec z_clock_t; diff --git a/include/zenoh-pico/system/platform/void.h b/include/zenoh-pico/system/platform/void.h index b6fc1dd99..cda1b50ab 100644 --- a/include/zenoh-pico/system/platform/void.h +++ b/include/zenoh-pico/system/platform/void.h @@ -18,10 +18,10 @@ #include "zenoh-pico/config.h" #if Z_FEATURE_MULTI_THREAD == 1 -typedef void *z_task_t; +typedef void *_z_task_t; typedef void *z_task_attr_t; -typedef void *z_mutex_t; -typedef void *z_condvar_t; +typedef void *_z_mutex_t; +typedef void *_z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef void *z_clock_t; diff --git a/include/zenoh-pico/system/platform/windows.h b/include/zenoh-pico/system/platform/windows.h index d003be987..57513e20a 100644 --- a/include/zenoh-pico/system/platform/windows.h +++ b/include/zenoh-pico/system/platform/windows.h @@ -21,10 +21,10 @@ #include "zenoh-pico/config.h" #if Z_FEATURE_MULTI_THREAD == 1 -typedef HANDLE *z_task_t; +typedef HANDLE *_z_task_t; typedef void *z_task_attr_t; // Not used in Windows -typedef SRWLOCK z_mutex_t; -typedef CONDITION_VARIABLE z_condvar_t; +typedef SRWLOCK _z_mutex_t; +typedef CONDITION_VARIABLE _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef LARGE_INTEGER z_clock_t; diff --git a/include/zenoh-pico/system/platform/zephyr.h b/include/zenoh-pico/system/platform/zephyr.h index da7b41997..966edaa52 100644 --- a/include/zenoh-pico/system/platform/zephyr.h +++ b/include/zenoh-pico/system/platform/zephyr.h @@ -31,10 +31,10 @@ #include "zenoh-pico/config.h" #if Z_FEATURE_MULTI_THREAD == 1 -typedef pthread_t z_task_t; +typedef pthread_t _z_task_t; typedef pthread_attr_t z_task_attr_t; -typedef pthread_mutex_t z_mutex_t; -typedef pthread_cond_t z_condvar_t; +typedef pthread_mutex_t _z_mutex_t; +typedef pthread_cond_t _z_condvar_t; #endif // Z_FEATURE_MULTI_THREAD == 1 typedef struct timespec z_clock_t; diff --git a/include/zenoh-pico/transport/common/rx.h b/include/zenoh-pico/transport/common/rx.h index 950f9dcb1..11e6cc1fe 100644 --- a/include/zenoh-pico/transport/common/rx.h +++ b/include/zenoh-pico/transport/common/rx.h @@ -19,6 +19,7 @@ #include "zenoh-pico/transport/transport.h" /*------------------ Transmission and Reception helpers ------------------*/ +size_t _z_read_stream_size(_z_zbuf_t *zbuf); int8_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl); #endif /* ZENOH_PICO_TRANSPORT_RX_H */ diff --git a/include/zenoh-pico/transport/manager.h b/include/zenoh-pico/transport/manager.h index faac8c25e..6a6a7ad48 100644 --- a/include/zenoh-pico/transport/manager.h +++ b/include/zenoh-pico/transport/manager.h @@ -15,11 +15,11 @@ #ifndef INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H #define INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/link/manager.h" #include "zenoh-pico/transport/transport.h" -int8_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, char *locator, z_whatami_t mode); +int8_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode); void _z_free_transport(_z_transport_t **zt); #endif /* INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H */ diff --git a/include/zenoh-pico/transport/multicast.h b/include/zenoh-pico/transport/multicast.h index fa1c873b6..487ef6dae 100644 --- a/include/zenoh-pico/transport/multicast.h +++ b/include/zenoh-pico/transport/multicast.h @@ -17,7 +17,7 @@ #include "zenoh-pico/api/types.h" -void _zp_multicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *callback); +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); #endif /* ZENOH_PICO_MULTICAST_H */ diff --git a/include/zenoh-pico/transport/multicast/lease.h b/include/zenoh-pico/transport/multicast/lease.h index 628eaa088..e9202aa11 100644 --- a/include/zenoh-pico/transport/multicast/lease.h +++ b/include/zenoh-pico/transport/multicast/lease.h @@ -23,7 +23,7 @@ int8_t _zp_multicast_stop_lease_task(_z_transport_multicast_t *ztm); void *_zp_multicast_lease_task(void *ztm_arg); // The argument is void* to avoid incompatible pointer types in tasks #if Z_FEATURE_MULTI_THREAD == 1 && (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) -int8_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_attr_t *attr, z_task_t *task); +int8_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_attr_t *attr, _z_task_t *task); #else int8_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) */ diff --git a/include/zenoh-pico/transport/multicast/read.h b/include/zenoh-pico/transport/multicast/read.h index 67b046397..5a0fda213 100644 --- a/include/zenoh-pico/transport/multicast/read.h +++ b/include/zenoh-pico/transport/multicast/read.h @@ -22,7 +22,7 @@ int8_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 #if Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_MULTICAST_TRANSPORT == 1 -int8_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task); +int8_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task); #else int8_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 */ diff --git a/include/zenoh-pico/transport/multicast/rx.h b/include/zenoh-pico/transport/multicast/rx.h index 5a74d11cf..8357e8291 100644 --- a/include/zenoh-pico/transport/multicast/rx.h +++ b/include/zenoh-pico/transport/multicast/rx.h @@ -17,8 +17,8 @@ #include "zenoh-pico/transport/transport.h" -int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr); +int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, - _z_bytes_t *addr); + _z_slice_t *addr); #endif /* ZENOH_PICO_TRANSPORT_LINK_RX_H */ diff --git a/include/zenoh-pico/transport/raweth/read.h b/include/zenoh-pico/transport/raweth/read.h index 3df0d2979..7c98e1c87 100644 --- a/include/zenoh-pico/transport/raweth/read.h +++ b/include/zenoh-pico/transport/raweth/read.h @@ -22,7 +22,7 @@ int8_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 #if Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_RAWETH_TRANSPORT == 1 -int8_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task); +int8_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task); #else int8_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 */ diff --git a/include/zenoh-pico/transport/raweth/rx.h b/include/zenoh-pico/transport/raweth/rx.h index a8f281369..4484a2e43 100644 --- a/include/zenoh-pico/transport/raweth/rx.h +++ b/include/zenoh-pico/transport/raweth/rx.h @@ -17,7 +17,7 @@ #include "zenoh-pico/transport/transport.h" -int8_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr); -int8_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr); +int8_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); +int8_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr); #endif /* ZENOH_PICO_RAWETH_RX_H */ diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index 76921bd9c..0e5163b6d 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -18,8 +18,8 @@ #include #include -#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" #include "zenoh-pico/protocol/core.h" @@ -33,7 +33,7 @@ typedef struct { #endif _z_id_t _remote_zid; - _z_bytes_t _remote_addr; + _z_slice_t _remote_addr; _z_conduit_sn_list_t _sn_rx_sns; // SN numbers @@ -56,7 +56,7 @@ _z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport _z_transport_peer_entry_t *entry); // Forward type declaration to avoid cyclical include -typedef struct _z_session_t _z_session_t; +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; @@ -65,12 +65,12 @@ typedef int8_t (*_zp_f_send_tmsg)(_z_transport_multicast_t *self, const _z_trans typedef struct { // Session associated to the transport - _z_session_t *_session; + _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; + _z_mutex_t _mutex_rx; + _z_mutex_t _mutex_tx; #endif // Z_FEATURE_MULTI_THREAD == 1 _z_link_t _link; @@ -96,8 +96,8 @@ typedef struct { volatile _z_zint_t _lease; #if Z_FEATURE_MULTI_THREAD == 1 - z_task_t *_read_task; - z_task_t *_lease_task; + _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 @@ -108,15 +108,15 @@ typedef struct { typedef struct _z_transport_multicast_t { // Session associated to the transport - _z_session_t *_session; + _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; + _z_mutex_t _mutex_rx; + _z_mutex_t _mutex_tx; // Peer list mutex - z_mutex_t _mutex_peer; + _z_mutex_t _mutex_peer; #endif // Z_FEATURE_MULTI_THREAD == 1 _z_link_t _link; @@ -138,8 +138,8 @@ typedef struct _z_transport_multicast_t { _zp_f_send_tmsg _send_f; #if Z_FEATURE_MULTI_THREAD == 1 - z_task_t *_read_task; - z_task_t *_lease_task; + _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 diff --git a/include/zenoh-pico/transport/unicast.h b/include/zenoh-pico/transport/unicast.h index bcfbcc1ef..652384e47 100644 --- a/include/zenoh-pico/transport/unicast.h +++ b/include/zenoh-pico/transport/unicast.h @@ -17,7 +17,7 @@ #include "zenoh-pico/api/types.h" -void _zp_unicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *callback); +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); #endif /* ZENOH_PICO_UNICAST_H */ diff --git a/include/zenoh-pico/transport/unicast/lease.h b/include/zenoh-pico/transport/unicast/lease.h index 8ccad0e7b..17361c32e 100644 --- a/include/zenoh-pico/transport/unicast/lease.h +++ b/include/zenoh-pico/transport/unicast/lease.h @@ -22,7 +22,7 @@ int8_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 #if Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_UNICAST_TRANSPORT == 1 -int8_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task); +int8_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task); #else int8_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 */ diff --git a/include/zenoh-pico/transport/unicast/read.h b/include/zenoh-pico/transport/unicast/read.h index c3c17bc05..91c7b9356 100644 --- a/include/zenoh-pico/transport/unicast/read.h +++ b/include/zenoh-pico/transport/unicast/read.h @@ -22,7 +22,7 @@ int8_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 #if Z_FEATURE_MULTI_THREAD == 1 && Z_FEATURE_UNICAST_TRANSPORT == 1 -int8_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task); +int8_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, _z_task_t *task); #else int8_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 */ diff --git a/include/zenoh-pico/utils/config.h b/include/zenoh-pico/utils/config.h index e6ec4e934..0a538e7d0 100644 --- a/include/zenoh-pico/utils/config.h +++ b/include/zenoh-pico/utils/config.h @@ -30,7 +30,6 @@ * Zenoh-net properties are represented as int-string map. */ typedef _z_str_intmap_t _z_config_t; -typedef _z_str_intmap_t _z_scouting_config_t; /** * Initialize a new empty map of properties. @@ -46,7 +45,7 @@ int8_t _z_config_init(_z_config_t *ps); * key: The key of the property to add. * value: The value of the property to add. */ -int8_t _zp_config_insert(_z_config_t *ps, uint8_t key, _z_string_t value); +int8_t _zp_config_insert(_z_config_t *ps, uint8_t key, const char *value); /** * Get the property with the given key from a properties map. @@ -71,6 +70,17 @@ char *_z_config_get(const _z_config_t *ps, uint8_t key); */ #define _z_config_len _z_str_intmap_len +/** + * Clone a config. + * + * Parameters: + * m: A pointer to the config to clone. + * + * Returns: + * The clone of the config. + */ +#define _z_config_clone _z_str_intmap_clone + /** * Get the length of the given properties map. * @@ -98,6 +108,5 @@ char *_z_config_get(const _z_config_t *ps, uint8_t key); * */ #define _z_config_free _z_str_intmap_free -#define _z_scouting_config_free _z_str_intmap_free #endif /* ZENOH_PICO_UTILS_PROPERTY_H */ diff --git a/include/zenoh-pico/utils/endianness.h b/include/zenoh-pico/utils/endianness.h new file mode 100644 index 000000000..5a29bbf93 --- /dev/null +++ b/include/zenoh-pico/utils/endianness.h @@ -0,0 +1,51 @@ +// +// 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_UTILS_ENDIANNESS_H +#define ZENOH_PICO_UTILS_ENDIANNESS_H + +#include +#include + +// Load int from memory with specified endianness +uint16_t _z_le_load16(const uint8_t *src); +uint32_t _z_le_load32(const uint8_t *src); +uint64_t _z_le_load64(const uint8_t *src); +uint16_t _z_be_load16(const uint8_t *src); +uint32_t _z_be_load32(const uint8_t *src); +uint64_t _z_be_load64(const uint8_t *src); + +// Store int to memory with specified endianness +size_t _z_le_store16(uint16_t val, uint8_t *dest); +size_t _z_le_store32(uint32_t val, uint8_t *dest); +size_t _z_le_store64(uint64_t val, uint8_t *dest); +size_t _z_be_store16(uint16_t val, uint8_t *dest); +size_t _z_be_store32(uint32_t val, uint8_t *dest); +size_t _z_be_store64(uint64_t val, uint8_t *dest); + +// Load little-endian int from memory to host order +uint16_t _z_host_le_load16(const uint8_t *src); +uint32_t _z_host_le_load32(const uint8_t *src); +uint64_t _z_host_le_load64(const uint8_t *src); + +// Store little-endian int to memory from host order +size_t _z_host_le_store16(const uint16_t val, uint8_t *dst); +size_t _z_host_le_store32(const uint32_t val, uint8_t *dst); +size_t _z_host_le_store64(const uint64_t val, uint8_t *dst); + +// Return u16 individual bytes +uint8_t _z_get_u16_lsb(uint_fast16_t val); +uint8_t _z_get_u16_msb(uint_fast16_t val); + +#endif /* ZENOH_PICO_UTILS_ENDIANNESS_H */ diff --git a/include/zenoh-pico/utils/logging.h b/include/zenoh-pico/utils/logging.h index f6e3304ef..c440d1774 100644 --- a/include/zenoh-pico/utils/logging.h +++ b/include/zenoh-pico/utils/logging.h @@ -17,6 +17,8 @@ #include +#include "zenoh-pico/system/platform-common.h" + // Logging values #define _Z_LOG_LVL_ERROR 1 #define _Z_LOG_LVL_INFO 2 diff --git a/include/zenoh-pico/utils/result.h b/include/zenoh-pico/utils/result.h index a3ff7c1d6..87ff8308f 100644 --- a/include/zenoh-pico/utils/result.h +++ b/include/zenoh-pico/utils/result.h @@ -26,9 +26,15 @@ #define _Z_ERR_SYSTEM_MASK 0xb0 #define _Z_ERR_GENERIC_MASK 0xb8 +typedef int8_t z_result_t; /*------------------ Result Enums ------------------*/ typedef enum { _Z_RES_OK = 0, + Z_OK = 0, + _Z_RES_CHANNEL_CLOSED = 1, + Z_CHANNEL_DISCONNECTED = 1, + _Z_RES_CHANNEL_NODATA = 2, + Z_CHANNEL_NODATA = 2, _Z_ERR_MESSAGE_DESERIALIZATION_FAILED = -119, _Z_ERR_MESSAGE_SERIALIZATION_FAILED = -118, @@ -62,12 +68,38 @@ typedef enum { _Z_ERR_SCOUT_NO_RESULTS = -87, + _Z_ERR_SYSTEM_GENERIC = -80, _Z_ERR_SYSTEM_TASK_FAILED = -79, _Z_ERR_SYSTEM_OUT_OF_MEMORY = -78, _Z_ERR_CONNECTION_CLOSED = -77, + _Z_ERR_DID_NOT_READ = -76, + _Z_ERR_INVALID = -75, + Z_EINVAL = -75, + _Z_ERR_OVERFLOW = -74, + _Z_ERR_GENERIC = -128 } _z_res_t; +#define _Z_RETURN_IF_ERR(expr) \ + { \ + int8_t __res = expr; \ + if (__res != _Z_RES_OK) { \ + return __res; \ + } \ + } + +#define _Z_CLEAN_RETURN_IF_ERR(base_expr, clean_expr) \ + { \ + int8_t __res = base_expr; \ + if (__res != _Z_RES_OK) { \ + clean_expr; \ + return __res; \ + } \ + } + +#define _Z_IS_OK(expr) (expr == _Z_RES_OK) +#define _Z_IS_ERR(expr) (expr != _Z_RES_OK) + #endif /* ZENOH_PICO_UTILS_RESULT_H */ diff --git a/include/zenoh-pico/utils/uuid.h b/include/zenoh-pico/utils/uuid.h index b0e487235..4bd581a91 100644 --- a/include/zenoh-pico/utils/uuid.h +++ b/include/zenoh-pico/utils/uuid.h @@ -22,14 +22,3 @@ * uuid_str: A valid UUID string. */ void _z_uuid_to_bytes(uint8_t *bytes, const char *uuid_str); - -/** - * Converts a byte array representing an UUID to its string representation. - * - * Parameters: - * bytes: Pointer to the byte array containing the UUID. - * - * Returns: - * The `char *` of the UUID in string format. - */ -char *_z_bytes_to_uuid(const uint8_t *uuid); diff --git a/library.json b/library.json index 5197887b1..b1328cdf6 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "zenoh-pico", - "version": "0.11.0.0", + "version": "1.0.0.0", "description": "The Eclipse Zenoh: Zero Overhead Pub/sub, Store/Query and Compute. It unifies data in motion, data in-use, 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-Pico is the implementation able to scale down to extremely constrainded devices and networks.", "keywords": [ "pubsub", diff --git a/library.json.in b/library.json.in new file mode 100644 index 000000000..873b996b5 --- /dev/null +++ b/library.json.in @@ -0,0 +1,43 @@ +{ + "name": "zenoh-pico", + "version": "@ZENOH_PICO_MAJOR@.@ZENOH_PICO_MINOR@.@ZENOH_PICO_PATCH@.@ZENOH_PICO_TWEAK@", + "description": "The Eclipse Zenoh: Zero Overhead Pub/sub, Store/Query and Compute. It unifies data in motion, data in-use, 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-Pico is the implementation able to scale down to extremely constrainded devices and networks.", + "keywords": [ + "pubsub", + "publish", + "subscribe", + "query", + "distributed data distribution" + ], + "homepage": "https://zenoh.io/", + "repository": { + "type": "git", + "url": "https://github.com/eclipse-zenoh/zenoh-pico" + }, + "authors": { + "name": "ZettaScale Technology Zenoh Team", + "email": "zenoh@zettascale.tech", + "url": "https://www.zettascale.tech/", + "maintainer": true + }, + "license": "Apache-2.0 OR EPL-2.0", + "frameworks": [ + "arduino", + "espidf", + "mbed", + "zephyr" + ], + "headers": [ + "zenoh-pico.h" + ], + "examples": [ + "examples" + ], + "dependencies": { + "BluetoothSerial": "0.16.1", + "FreeRTOS": "1.0.0" + }, + "build": { + "extraScript": "extra_script.py" + } +} diff --git a/src/api/api.c b/src/api/api.c index 95ba8fbea..105ff350a 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -18,14 +18,17 @@ #include #include +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/api/olv_macros.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/config.h" #include "zenoh-pico/net/config.h" +#include "zenoh-pico/net/filtering.h" #include "zenoh-pico/net/logger.h" -#include "zenoh-pico/net/memory.h" #include "zenoh-pico/net/primitives.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" @@ -33,243 +36,639 @@ #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/system/platform-common.h" #include "zenoh-pico/system/platform.h" #include "zenoh-pico/transport/multicast.h" #include "zenoh-pico/transport/unicast.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" #include "zenoh-pico/utils/uuid.h" /********* Data Types Handlers *********/ -_Bool z_bytes_check(const z_bytes_t *v) { return v->start != NULL; } -z_string_t z_string_make(const char *value) { return _z_string_make(value); } +int8_t z_view_string_from_str(z_view_string_t *str, const char *value) { + str->_val = _z_string_alias_str((char *)value); + return _Z_RES_OK; +} -z_str_t *z_str_array_get(const z_str_array_t *a, size_t k) { return _z_str_array_get(a, k); } -size_t z_str_array_len(const z_str_array_t *a) { return _z_str_array_len(a); } -_Bool z_str_array_is_empty(const z_str_array_t *a) { return _z_str_array_is_empty(a); } +const z_loaned_string_t *z_string_array_get(const z_loaned_string_array_t *a, size_t k) { + return _z_string_svec_get(a, k); +} -z_keyexpr_t z_keyexpr(const char *name) { return _z_rname(name); } +size_t z_string_array_len(const z_loaned_string_array_t *a) { return _z_string_svec_len(a); } -z_keyexpr_t z_keyexpr_unchecked(const char *name) { return _z_rname(name); } +_Bool z_string_array_is_empty(const z_loaned_string_array_t *a) { return _z_string_svec_is_empty(a); } -z_owned_str_t z_keyexpr_to_string(z_keyexpr_t keyexpr) { - z_owned_str_t ret = {._value = NULL}; +int8_t z_keyexpr_is_canon(const char *start, size_t len) { return _z_keyexpr_is_canon(start, len); } - if (keyexpr._id == Z_RESOURCE_ID_NONE) { - size_t ke_len = _z_str_size(keyexpr._suffix); +int8_t z_keyexpr_canonize(char *start, size_t *len) { return _z_keyexpr_canonize(start, len); } - ret._value = (char *)z_malloc(ke_len); - if (ret._value != NULL) { - _z_str_n_copy(ret._value, keyexpr._suffix, ke_len); - } +void z_view_keyexpr_from_str_unchecked(z_view_keyexpr_t *keyexpr, const char *name) { keyexpr->_val = _z_rname(name); } + +z_result_t z_view_keyexpr_from_substr(z_view_keyexpr_t *keyexpr, const char *name, size_t len) { + if (_z_keyexpr_is_canon(name, len) != Z_KEYEXPR_CANON_SUCCESS) { + return Z_EINVAL; } + keyexpr->_val = _z_keyexpr_from_substr(0, name, len); + return _Z_RES_OK; +} - return ret; +int8_t z_view_keyexpr_from_str(z_view_keyexpr_t *keyexpr, const char *name) { + size_t name_len = strlen(name); + return z_view_keyexpr_from_substr(keyexpr, name, name_len); } -z_bytes_t z_keyexpr_as_bytes(z_keyexpr_t keyexpr) { - if (keyexpr._id == Z_RESOURCE_ID_NONE) { - z_bytes_t ret = {.start = (const uint8_t *)keyexpr._suffix, .len = strlen(keyexpr._suffix), ._is_alloc = false}; - return ret; - } else { - z_bytes_t ret = {.start = NULL, .len = 0, ._is_alloc = false}; - return ret; - } +z_result_t z_view_keyexpr_from_substr_autocanonize(z_view_keyexpr_t *keyexpr, char *name, size_t *len) { + _Z_RETURN_IF_ERR(z_keyexpr_canonize(name, len)); + keyexpr->_val = _z_keyexpr_from_substr(0, name, *len); + return _Z_RES_OK; } -_Bool zp_keyexpr_was_declared(const z_keyexpr_t *keyexpr) { - _Bool ret = false; - if (keyexpr->_id != Z_RESOURCE_ID_NONE) { - ret = true; - } - return ret; +int8_t z_view_keyexpr_from_str_autocanonize(z_view_keyexpr_t *keyexpr, char *name) { + size_t name_len = strlen(name); + return z_view_keyexpr_from_substr_autocanonize(keyexpr, name, &name_len); } -z_owned_str_t zp_keyexpr_resolve(z_session_t zs, z_keyexpr_t keyexpr) { - z_owned_str_t ret = {._value = NULL}; +void z_view_keyexpr_from_substr_unchecked(z_view_keyexpr_t *keyexpr, const char *name, size_t len) { + keyexpr->_val = _z_keyexpr_from_substr(0, name, len); +} - _z_keyexpr_t ekey = _z_get_expanded_key_from_key(&zs._val.in->val, &keyexpr); - ret._value = (char *)ekey._suffix; // ekey will be out of scope so - // - suffix can be safely casted as non-const - // - suffix does not need to be copied - return ret; +int8_t z_keyexpr_as_view_string(const z_loaned_keyexpr_t *keyexpr, z_view_string_t *s) { + s->_val = _z_string_alias(&keyexpr->_suffix); + return _Z_RES_OK; } -_Bool z_keyexpr_is_initialized(const z_keyexpr_t *keyexpr) { - _Bool ret = false; +int8_t z_keyexpr_concat(z_owned_keyexpr_t *key, const z_loaned_keyexpr_t *left, const char *right, size_t len) { + z_internal_keyexpr_null(key); + if (len == 0) { + return z_keyexpr_clone(key, left); + } else if (right == NULL) { + return _Z_ERR_INVALID; + } + size_t left_len = _z_string_len(&left->_suffix); + if (left_len == 0) { + return _Z_ERR_INVALID; + } + const char *left_data = _z_string_data(&left->_suffix); - if ((keyexpr->_id != Z_RESOURCE_ID_NONE) || (keyexpr->_suffix != NULL)) { - ret = true; + if (left_data[left_len - 1] == '*' && right[0] == '*') { + return _Z_ERR_INVALID; } - return ret; + key->_val._suffix = _z_string_preallocate(left_len + len); + if (!_z_keyexpr_has_suffix(&key->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Copy data + uint8_t *curr_ptr = (uint8_t *)_z_string_data(&key->_val._suffix); + memcpy(curr_ptr, _z_string_data(&left->_suffix), left_len); + memcpy(curr_ptr + left_len, right, len); + return _Z_RES_OK; } -int8_t z_keyexpr_is_canon(const char *start, size_t len) { return _z_keyexpr_is_canon(start, len); } +int8_t z_keyexpr_join(z_owned_keyexpr_t *key, const z_loaned_keyexpr_t *left, const z_loaned_keyexpr_t *right) { + z_internal_keyexpr_null(key); -int8_t zp_keyexpr_is_canon_null_terminated(const char *start) { return _z_keyexpr_is_canon(start, strlen(start)); } + size_t left_len = _z_string_len(&left->_suffix); + size_t right_len = _z_string_len(&right->_suffix); -int8_t z_keyexpr_canonize(char *start, size_t *len) { return _z_keyexpr_canonize(start, len); } - -int8_t zp_keyexpr_canonize_null_terminated(char *start) { - zp_keyexpr_canon_status_t ret = Z_KEYEXPR_CANON_SUCCESS; + key->_val._suffix = _z_string_preallocate(left_len + right_len + 1); + if (!_z_keyexpr_has_suffix(&key->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Copy data + uint8_t *curr_ptr = (uint8_t *)_z_string_data(&key->_val._suffix); + memcpy(curr_ptr, _z_string_data(&left->_suffix), left_len); + curr_ptr[left_len] = '/'; + memcpy(curr_ptr + left_len + 1, _z_string_data(&right->_suffix), right_len); + _Z_CLEAN_RETURN_IF_ERR(z_keyexpr_canonize((char *)curr_ptr, &key->_val._suffix._slice.len), z_free(curr_ptr)); + return _Z_RES_OK; +} - size_t len = strlen(start); - size_t newlen = len; - ret = _z_keyexpr_canonize(start, &newlen); - if (newlen < len) { - start[newlen] = '\0'; +z_keyexpr_intersection_level_t z_keyexpr_relation_to(const z_loaned_keyexpr_t *left, const z_loaned_keyexpr_t *right) { + if (z_keyexpr_equals(left, right)) { + return Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS; + } else if (z_keyexpr_includes(left, right)) { + return Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES; + } else if (z_keyexpr_intersects(left, right)) { + return Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS; } + return Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT; +} - return ret; +_Bool z_keyexpr_includes(const z_loaned_keyexpr_t *l, const z_loaned_keyexpr_t *r) { + return _z_keyexpr_suffix_includes(l, r); } -int8_t z_keyexpr_includes(z_keyexpr_t l, z_keyexpr_t r) { - int8_t ret = 0; +_Bool z_keyexpr_intersects(const z_loaned_keyexpr_t *l, const z_loaned_keyexpr_t *r) { + return _z_keyexpr_suffix_intersects(l, r); +} - if ((l._id == Z_RESOURCE_ID_NONE) && (r._id == Z_RESOURCE_ID_NONE)) { - ret = zp_keyexpr_includes_null_terminated(l._suffix, r._suffix); - } else { - ret = _Z_ERR_GENERIC; +_Bool z_keyexpr_equals(const z_loaned_keyexpr_t *l, const z_loaned_keyexpr_t *r) { + return _z_keyexpr_suffix_equals(l, r); +} + +void z_config_new(z_owned_config_t *config) { config->_val = _z_config_empty(); } + +int8_t z_config_default(z_owned_config_t *config) { return _z_config_default(&config->_val); } + +void z_config_clone(z_owned_config_t *config, const z_loaned_config_t *src) { config->_val = _z_config_clone(src); } + +int8_t z_config_client(z_owned_config_t *config, const char *locator) { + return _z_config_client(&config->_val, locator); +} + +int8_t z_config_peer(z_owned_config_t *config, const char *locator) { + if (locator == NULL) { + return _Z_ERR_INVALID; } + _Z_RETURN_IF_ERR(z_config_default(config)); + _Z_CLEAN_RETURN_IF_ERR(zp_config_insert(&config->_val, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_PEER), + z_config_drop(z_config_move(config))); + _Z_CLEAN_RETURN_IF_ERR(zp_config_insert(&config->_val, Z_CONFIG_CONNECT_KEY, locator), + z_config_drop(z_config_move(config))); + return _Z_RES_OK; +} - return ret; +const char *zp_config_get(const z_loaned_config_t *config, uint8_t key) { return _z_config_get(config, key); } + +int8_t zp_config_insert(z_loaned_config_t *config, uint8_t key, const char *value) { + return _zp_config_insert(config, key, value); +} + +#if Z_FEATURE_ENCODING_VALUES == 1 +#define ENCODING_SCHEMA_SEPARATOR ';' + +const char *ENCODING_VALUES_ID_TO_STR[] = { + "zenoh/bytes", + "zenoh/int8", + "zenoh/int16", + "zenoh/int32", + "zenoh/int64", + "zenoh/int128", + "zenoh/uint8", + "zenoh/uint16", + "zenoh/uint32", + "zenoh/uint64", + "zenoh/uint128", + "zenoh/float32", + "zenoh/float64", + "zenoh/bool", + "zenoh/string", + "zenoh/error", + "application/octet-stream", + "text/plain", + "application/json", + "text/json", + "application/cdr", + "application/cbor", + "application/yaml", + "text/yaml", + "text/json5", + "application/python-serialized-object", + "application/protobuf", + "application/java-serialized-object", + "application/openmetrics-text", + "image/png", + "image/jpeg", + "image/gif", + "image/bmp", + "image/webp", + "application/xml", + "application/x-www-form-urlencoded", + "text/html", + "text/xml", + "text/css", + "text/javascript", + "text/markdown", + "text/csv", + "application/sql", + "application/coap-payload", + "application/json-patch+json", + "application/json-seq", + "application/jsonpath", + "application/jwt", + "application/mp4", + "application/soap+xml", + "application/yang", + "audio/aac", + "audio/flac", + "audio/mp4", + "audio/ogg", + "audio/vorbis", + "video/h261", + "video/h263", + "video/h264", + "video/h265", + "video/h266", + "video/mp4", + "video/ogg", + "video/raw", + "video/vp8", + "video/vp9", +}; + +static uint16_t _z_encoding_values_str_to_int(const char *schema, size_t len) { + for (size_t i = 0; i < _ZP_ARRAY_SIZE(ENCODING_VALUES_ID_TO_STR); i++) { + if (strncmp(schema, ENCODING_VALUES_ID_TO_STR[i], len) == 0) { + return (uint16_t)i; + } + } + return UINT16_MAX; } -int8_t zp_keyexpr_includes_null_terminated(const char *l, const char *r) { - int8_t ret = 0; +static int8_t _z_encoding_convert_from_substr(z_owned_encoding_t *encoding, const char *s, size_t len) { + size_t pos = 0; + for (; pos < len; ++pos) { + if (s[pos] == ENCODING_SCHEMA_SEPARATOR) break; + } - if (l != NULL && r != NULL) { - ret = _z_keyexpr_includes(l, strlen(l), r, strlen(r)) == true ? 0 : -1; - } else { - ret = _Z_ERR_GENERIC; + // Check id_end value + corner cases + if ((pos != len) && (pos != 0)) { + uint16_t id = _z_encoding_values_str_to_int(s, pos); + // Check id + if (id != UINT16_MAX) { + const char *ptr = (pos + 1 == len) ? NULL : s + pos + 1; + return _z_encoding_make(&encoding->_val, id, ptr, len - pos - 1); + } } + // By default store the string as schema + return _z_encoding_make(&encoding->_val, _Z_ENCODING_ID_DEFAULT, s, len); +} - return ret; +static int8_t _z_encoding_convert_into_string(const z_loaned_encoding_t *encoding, z_owned_string_t *s) { + const char *prefix = NULL; + size_t prefix_len = 0; + // Convert id + if (encoding->id < _ZP_ARRAY_SIZE(ENCODING_VALUES_ID_TO_STR)) { + prefix = ENCODING_VALUES_ID_TO_STR[encoding->id]; + prefix_len = strlen(prefix); + } + _Bool has_schema = _z_string_len(&encoding->schema) > 0; + // Size include null terminator + size_t total_len = prefix_len + _z_string_len(&encoding->schema) + 1; + // Check for schema separator + if (has_schema) { + total_len += 1; + } + // Allocate string + char *value = (char *)z_malloc(sizeof(char) * total_len); + memset(value, 0, total_len); + if (value == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + // Copy prefix + char sep = ENCODING_SCHEMA_SEPARATOR; + (void)strncpy(value, prefix, prefix_len); + // Copy schema and separator + if (has_schema) { + (void)strncat(value, &sep, 1); + (void)strncat(value, _z_string_data(&encoding->schema), _z_string_len(&encoding->schema)); + } + // Fill container + s->_val = _z_string_alias_str(value); + return _Z_RES_OK; } -int8_t z_keyexpr_intersects(z_keyexpr_t l, z_keyexpr_t r) { - int8_t ret = 0; +#else +static int8_t _z_encoding_convert_from_substr(z_owned_encoding_t *encoding, const char *s, size_t len) { + return _z_encoding_make(encoding->_val, _Z_ENCODING_ID_DEFAULT, s, len); +} - if ((l._id == Z_RESOURCE_ID_NONE) && (r._id == Z_RESOURCE_ID_NONE)) { - ret = zp_keyexpr_intersect_null_terminated(l._suffix, r._suffix); - } else { - ret = _Z_ERR_GENERIC; +static int8_t _z_encoding_convert_into_string(const z_loaned_encoding_t *encoding, z_owned_string_t *s) { + _z_string_copy(s->_val, &encoding->schema); + return _Z_RES_OK; +} + +#endif + +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_encoding_t, encoding, _z_encoding_check, _z_encoding_null, _z_encoding_copy, + _z_encoding_clear) + +int8_t z_encoding_from_str(z_owned_encoding_t *encoding, const char *s) { + // Init owned encoding + z_internal_encoding_null(encoding); + // Convert string to encoding + if (s != NULL) { + return _z_encoding_convert_from_substr(encoding, s, strlen(s)); } + return _Z_RES_OK; +} - return ret; +int8_t z_encoding_from_substr(z_owned_encoding_t *encoding, const char *s, size_t len) { + // Init owned encoding + z_internal_encoding_null(encoding); + // Convert string to encoding + if (s != NULL) { + return _z_encoding_convert_from_substr(encoding, s, len); + } + return _Z_RES_OK; +} +int8_t z_encoding_set_schema_from_str(z_loaned_encoding_t *encoding, const char *schema) { + return z_encoding_set_schema_from_substr(encoding, schema, strlen(schema)); } -int8_t zp_keyexpr_intersect_null_terminated(const char *l, const char *r) { - int8_t ret = -1; +int8_t z_encoding_set_schema_from_substr(z_loaned_encoding_t *encoding, const char *schema, size_t len) { + _z_string_clear(&encoding->schema); + if (schema == NULL && len > 0) { + return _Z_ERR_INVALID; + } + encoding->schema = _z_string_copy_from_substr(schema, len); + if (_z_string_len(&encoding->schema) != len) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _Z_RES_OK; +} - if (l != NULL && r != NULL) { - ret = (_z_keyexpr_intersects(l, strlen(l), r, strlen(r)) == true) ? 0 : -1; +int8_t z_encoding_to_string(const z_loaned_encoding_t *encoding, z_owned_string_t *s) { + // Init owned string + z_internal_string_null(s); + // Convert encoding to string + _z_encoding_convert_into_string(encoding, s); + return _Z_RES_OK; +} + +int8_t z_slice_copy_from_buf(z_owned_slice_t *slice, const uint8_t *data, size_t len) { + slice->_val = _z_slice_copy_from_buf(data, len); + if (slice->_val.start == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } else { - ret = _Z_ERR_GENERIC; + return _Z_RES_OK; } +} - return ret; +int8_t z_slice_from_buf(z_owned_slice_t *slice, uint8_t *data, size_t len, void (*deleter)(void *data, void *context), + void *context) { + slice->_val = _z_slice_from_buf_custom_deleter(data, len, _z_delete_context_create(deleter, context)); + return _Z_RES_OK; } -int8_t z_keyexpr_equals(z_keyexpr_t l, z_keyexpr_t r) { - int8_t ret = 0; +const uint8_t *z_slice_data(const z_loaned_slice_t *slice) { return slice->start; } - if ((l._id == Z_RESOURCE_ID_NONE) && (r._id == Z_RESOURCE_ID_NONE)) { - ret = zp_keyexpr_equals_null_terminated(l._suffix, r._suffix); - } else { - ret = _Z_ERR_GENERIC; - } +size_t z_slice_len(const z_loaned_slice_t *slice) { return slice->len; } - return ret; +void z_slice_empty(z_owned_slice_t *slice) { slice->_val = _z_slice_empty(); } + +bool z_slice_is_empty(const z_loaned_slice_t *slice) { return _z_slice_is_empty(slice); } + +int8_t z_bytes_deserialize_into_int8(const z_loaned_bytes_t *bytes, int8_t *dst) { + return _z_bytes_to_uint8(bytes, (uint8_t *)dst); } -int8_t zp_keyexpr_equals_null_terminated(const char *l, const char *r) { - int8_t ret = -1; +int8_t z_bytes_deserialize_into_int16(const z_loaned_bytes_t *bytes, int16_t *dst) { + return _z_bytes_to_uint16(bytes, (uint16_t *)dst); +} - if (l != NULL && r != NULL) { - size_t llen = strlen(l); - if (llen == strlen(r)) { - if (strncmp(l, r, llen) == 0) { - ret = 0; - } - } - } else { - ret = _Z_ERR_GENERIC; - } +int8_t z_bytes_deserialize_into_int32(const z_loaned_bytes_t *bytes, int32_t *dst) { + return _z_bytes_to_uint32(bytes, (uint32_t *)dst); +} - return ret; +int8_t z_bytes_deserialize_into_int64(const z_loaned_bytes_t *bytes, int64_t *dst) { + return _z_bytes_to_uint64(bytes, (uint64_t *)dst); +} + +int8_t z_bytes_deserialize_into_uint8(const z_loaned_bytes_t *bytes, uint8_t *dst) { + return _z_bytes_to_uint8(bytes, dst); +} + +int8_t z_bytes_deserialize_into_uint16(const z_loaned_bytes_t *bytes, uint16_t *dst) { + return _z_bytes_to_uint16(bytes, dst); } -z_owned_config_t z_config_new(void) { return (z_owned_config_t){._value = _z_config_empty()}; } +int8_t z_bytes_deserialize_into_uint32(const z_loaned_bytes_t *bytes, uint32_t *dst) { + return _z_bytes_to_uint32(bytes, dst); +} -z_owned_config_t z_config_default(void) { return (z_owned_config_t){._value = _z_config_default()}; } +int8_t z_bytes_deserialize_into_uint64(const z_loaned_bytes_t *bytes, uint64_t *dst) { + return _z_bytes_to_uint64(bytes, dst); +} -const char *zp_config_get(z_config_t config, uint8_t key) { return _z_config_get(config._val, key); } +int8_t z_bytes_deserialize_into_float(const z_loaned_bytes_t *bytes, float *dst) { + return _z_bytes_to_float(bytes, dst); +} -int8_t zp_config_insert(z_config_t config, uint8_t key, z_string_t value) { - return _zp_config_insert(config._val, key, value); +int8_t z_bytes_deserialize_into_double(const z_loaned_bytes_t *bytes, double *dst) { + return _z_bytes_to_double(bytes, dst); } -z_owned_scouting_config_t z_scouting_config_default(void) { - _z_scouting_config_t *sc = _z_config_empty(); +int8_t z_bytes_deserialize_into_slice(const z_loaned_bytes_t *bytes, z_owned_slice_t *dst) { + dst->_val = _z_slice_empty(); + return _z_bytes_to_slice(bytes, &dst->_val); +} - _zp_config_insert(sc, Z_CONFIG_MULTICAST_LOCATOR_KEY, _z_string_make(Z_CONFIG_MULTICAST_LOCATOR_DEFAULT)); - _zp_config_insert(sc, Z_CONFIG_SCOUTING_TIMEOUT_KEY, _z_string_make(Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT)); - _zp_config_insert(sc, Z_CONFIG_SCOUTING_WHAT_KEY, _z_string_make(Z_CONFIG_SCOUTING_WHAT_DEFAULT)); +int8_t z_bytes_deserialize_into_string(const z_loaned_bytes_t *bytes, z_owned_string_t *s) { + // Init owned string + z_internal_string_null(s); + // Convert bytes to string + size_t len = _z_bytes_len(bytes); + s->_val = _z_string_preallocate(len); + if (_z_string_len(&s->_val) != len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + _z_bytes_to_buf(bytes, (uint8_t *)_z_string_data(&s->_val), len); + return _Z_RES_OK; +} - return (z_owned_scouting_config_t){._value = sc}; +int8_t z_bytes_deserialize_into_pair(const z_loaned_bytes_t *bytes, z_owned_bytes_t *first, z_owned_bytes_t *second) { + // Init pair of owned bytes + z_bytes_empty(first); + z_bytes_empty(second); + return _z_bytes_deserialize_into_pair(bytes, &first->_val, &second->_val); } -z_owned_scouting_config_t z_scouting_config_from(z_config_t c) { - _z_scouting_config_t *sc = _z_config_empty(); +int8_t z_bytes_serialize_from_int8(z_owned_bytes_t *bytes, int8_t val) { + return z_bytes_serialize_from_uint8(bytes, (uint8_t)val); +} - char *opt; - opt = _z_config_get(c._val, Z_CONFIG_MULTICAST_LOCATOR_KEY); - if (opt == NULL) { - _zp_config_insert(sc, Z_CONFIG_MULTICAST_LOCATOR_KEY, _z_string_make(Z_CONFIG_MULTICAST_LOCATOR_DEFAULT)); - } else { - _zp_config_insert(sc, Z_CONFIG_MULTICAST_LOCATOR_KEY, _z_string_make(opt)); - } +int8_t z_bytes_serialize_from_int16(z_owned_bytes_t *bytes, int16_t val) { + return z_bytes_serialize_from_uint16(bytes, (uint16_t)val); +} - opt = _z_config_get(c._val, Z_CONFIG_SCOUTING_TIMEOUT_KEY); - if (opt == NULL) { - _zp_config_insert(sc, Z_CONFIG_SCOUTING_TIMEOUT_KEY, _z_string_make(Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT)); - } else { - _zp_config_insert(sc, Z_CONFIG_SCOUTING_TIMEOUT_KEY, _z_string_make(opt)); - } +int8_t z_bytes_serialize_from_int32(z_owned_bytes_t *bytes, int32_t val) { + return z_bytes_serialize_from_uint32(bytes, (uint32_t)val); +} - opt = _z_config_get(c._val, Z_CONFIG_SCOUTING_WHAT_KEY); - if (opt == NULL) { - _zp_config_insert(sc, Z_CONFIG_SCOUTING_WHAT_KEY, _z_string_make(Z_CONFIG_SCOUTING_WHAT_DEFAULT)); - } else { - _zp_config_insert(sc, Z_CONFIG_SCOUTING_WHAT_KEY, _z_string_make(opt)); +int8_t z_bytes_serialize_from_int64(z_owned_bytes_t *bytes, int64_t val) { + return z_bytes_serialize_from_uint64(bytes, (uint64_t)val); +} + +int8_t z_bytes_serialize_from_uint8(z_owned_bytes_t *bytes, uint8_t val) { + z_bytes_empty(bytes); + return _z_bytes_from_uint8(&bytes->_val, val); +} + +int8_t z_bytes_serialize_from_uint16(z_owned_bytes_t *bytes, uint16_t val) { + z_bytes_empty(bytes); + return _z_bytes_from_uint16(&bytes->_val, val); +} + +int8_t z_bytes_serialize_from_uint32(z_owned_bytes_t *bytes, uint32_t val) { + z_bytes_empty(bytes); + return _z_bytes_from_uint32(&bytes->_val, val); +} + +int8_t z_bytes_serialize_from_uint64(z_owned_bytes_t *bytes, uint64_t val) { + z_bytes_empty(bytes); + return _z_bytes_from_uint64(&bytes->_val, val); +} + +int8_t z_bytes_serialize_from_float(z_owned_bytes_t *bytes, float val) { + z_bytes_empty(bytes); + return _z_bytes_from_float(&bytes->_val, val); +} + +int8_t z_bytes_serialize_from_double(z_owned_bytes_t *bytes, double val) { + z_bytes_empty(bytes); + return _z_bytes_from_double(&bytes->_val, val); +} + +int8_t z_bytes_from_slice(z_owned_bytes_t *bytes, z_moved_slice_t *slice) { + z_bytes_empty(bytes); + _z_slice_t s = _z_slice_steal(&slice->_this._val); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_from_slice(&bytes->_val, s), _z_slice_clear(&s)); + return _Z_RES_OK; +} + +int8_t z_bytes_serialize_from_slice(z_owned_bytes_t *bytes, const z_loaned_slice_t *slice) { + z_owned_slice_t s; + _Z_RETURN_IF_ERR(z_slice_clone(&s, slice)); + return z_bytes_from_slice(bytes, z_slice_move(&s)); +} + +int8_t z_bytes_from_buf(z_owned_bytes_t *bytes, uint8_t *data, size_t len, void (*deleter)(void *data, void *context), + void *context) { + z_owned_slice_t s; + s._val = _z_slice_from_buf_custom_deleter(data, len, _z_delete_context_create(deleter, context)); + return z_bytes_from_slice(bytes, z_slice_move(&s)); +} + +int8_t z_bytes_from_static_buf(z_owned_bytes_t *bytes, const uint8_t *data, size_t len) { + z_owned_slice_t s; + s._val = _z_slice_alias_buf(data, len); + return z_bytes_from_slice(bytes, z_slice_move(&s)); +} + +int8_t z_bytes_serialize_from_buf(z_owned_bytes_t *bytes, const uint8_t *data, size_t len) { + z_owned_slice_t s; + _Z_RETURN_IF_ERR(z_slice_copy_from_buf(&s, data, len)); + return z_bytes_from_slice(bytes, z_slice_move(&s)); +} + +int8_t z_bytes_from_string(z_owned_bytes_t *bytes, z_moved_string_t *s) { + // TODO, verify that string is a valid UTF-8 ? + z_owned_slice_t slice; + size_t str_len = _z_string_len(&s->_this._val); + slice._val = _z_slice_steal(&s->_this._val._slice); + slice._val.len = str_len; + return z_bytes_from_slice(bytes, z_slice_move(&slice)); +} + +int8_t z_bytes_serialize_from_string(z_owned_bytes_t *bytes, const z_loaned_string_t *s) { + z_owned_string_t s_copy; + _Z_RETURN_IF_ERR(z_string_clone(&s_copy, s)); + return z_bytes_from_string(bytes, z_string_move(&s_copy)); +} + +int8_t z_bytes_from_str(z_owned_bytes_t *bytes, char *value, void (*deleter)(void *value, void *context), + void *context) { + z_owned_string_t s; + s._val = _z_string_from_str_custom_deleter(value, _z_delete_context_create(deleter, context)); + return z_bytes_from_string(bytes, z_string_move(&s)); +} + +int8_t z_bytes_from_static_str(z_owned_bytes_t *bytes, const char *value) { + z_owned_string_t s; + s._val = _z_string_alias_str(value); + return z_bytes_from_string(bytes, z_string_move(&s)); +} + +int8_t z_bytes_serialize_from_str(z_owned_bytes_t *bytes, const char *value) { + z_owned_string_t s; + _Z_RETURN_IF_ERR(z_string_copy_from_str(&s, value)); + return z_bytes_from_string(bytes, z_string_move(&s)); +} + +int8_t z_bytes_from_iter(z_owned_bytes_t *bytes, _Bool (*iterator_body)(z_owned_bytes_t *data, void *context), + void *context) { + z_bytes_empty(bytes); + z_owned_bytes_t data; + _z_bytes_iterator_writer_t iter_writer = _z_bytes_get_iterator_writer(&bytes->_val, 0); + while (iterator_body(&data, context)) { + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_iterator_writer_write(&iter_writer, &data._val), + z_bytes_drop(z_bytes_move(bytes))); } + return _Z_RES_OK; +} - return (z_owned_scouting_config_t){._value = sc}; +int8_t z_bytes_from_pair(z_owned_bytes_t *bytes, z_moved_bytes_t *first, z_moved_bytes_t *second) { + z_bytes_empty(bytes); + return _z_bytes_from_pair(&bytes->_val, &first->_this._val, &second->_this._val); } -const char *zp_scouting_config_get(z_scouting_config_t sc, uint8_t key) { return _z_config_get(sc._val, key); } +void z_bytes_empty(z_owned_bytes_t *bytes) { bytes->_val = _z_bytes_null(); } + +size_t z_bytes_len(const z_loaned_bytes_t *bytes) { return _z_bytes_len(bytes); } + +_Bool z_bytes_is_empty(const z_loaned_bytes_t *bytes) { return _z_bytes_is_empty(bytes); } + +z_bytes_reader_t z_bytes_get_reader(const z_loaned_bytes_t *bytes) { return _z_bytes_get_iterator(bytes); } -int8_t zp_scouting_config_insert(z_scouting_config_t sc, uint8_t key, z_string_t value) { - return _zp_config_insert(sc._val, key, value); +size_t z_bytes_reader_read(z_bytes_reader_t *reader, uint8_t *dst, size_t len) { + return _z_bytes_reader_read(&reader->_reader, dst, len); } -z_encoding_t z_encoding(z_encoding_prefix_t prefix, const char *suffix) { - return (_z_encoding_t){ - .prefix = prefix, - .suffix = _z_bytes_wrap((const uint8_t *)suffix, (suffix == NULL) ? (size_t)0 : strlen(suffix))}; +int8_t z_bytes_reader_read_bounded(z_bytes_reader_t *reader, z_owned_bytes_t *dst) { + return _z_bytes_iterator_next(reader, &dst->_val); } -z_encoding_t z_encoding_default(void) { return z_encoding(Z_ENCODING_PREFIX_DEFAULT, NULL); } +int8_t z_bytes_reader_seek(z_bytes_reader_t *reader, int64_t offset, int origin) { + return _z_bytes_reader_seek(&reader->_reader, offset, origin); +} -_Bool z_timestamp_check(z_timestamp_t ts) { return _z_timestamp_check(&ts); } +int64_t z_bytes_reader_tell(z_bytes_reader_t *reader) { return _z_bytes_reader_tell(&reader->_reader); } + +z_bytes_iterator_t z_bytes_get_iterator(const z_loaned_bytes_t *bytes) { return _z_bytes_get_iterator(bytes); } + +_Bool z_bytes_iterator_next(z_bytes_iterator_t *iter, z_owned_bytes_t *bytes) { + z_bytes_empty(bytes); + if (_z_bytes_iterator_next(iter, &bytes->_val) != _Z_RES_OK) { + z_bytes_drop(z_bytes_move(bytes)); + return false; + } + return true; +} + +z_bytes_writer_t z_bytes_get_writer(z_loaned_bytes_t *bytes) { + return _z_bytes_get_iterator_writer(bytes, Z_IOSLICE_SIZE); +} -z_value_t z_value(const char *payload, size_t payload_len, z_encoding_t encoding) { - return (z_value_t){.payload = {.start = (const uint8_t *)payload, .len = payload_len}, .encoding = encoding}; +int8_t z_bytes_writer_write_all(z_bytes_writer_t *writer, const uint8_t *src, size_t len) { + return _z_bytes_writer_write_all(&writer->writer, src, len); } +int8_t z_bytes_writer_append(z_bytes_writer_t *writer, z_moved_bytes_t *bytes) { + return _z_bytes_writer_append(&writer->writer, &bytes->_this._val); +} + +int8_t z_bytes_writer_append_bounded(z_bytes_writer_t *writer, z_moved_bytes_t *bytes) { + return _z_bytes_iterator_writer_write(writer, &bytes->_this._val); +} + +int8_t z_timestamp_new(z_timestamp_t *ts, const z_loaned_session_t *zs) { + *ts = _z_timestamp_null(); + zp_time_since_epoch t; + _Z_RETURN_IF_ERR(zp_get_time_since_epoch(&t)); + ts->time = _z_timestamp_ntp64_from_time(t.secs, t.nanos); + ts->id = _Z_RC_IN_VAL(zs)->_local_zid; + return _Z_RES_OK; +} + +uint64_t z_timestamp_ntp64_time(const z_timestamp_t *ts) { return ts->time; } + +z_id_t z_timestamp_id(const z_timestamp_t *ts) { return ts->id; } + +_Bool z_timestamp_check(z_timestamp_t ts) { return _z_timestamp_check(&ts); } + z_query_target_t z_query_target_default(void) { return Z_QUERY_TARGET_DEFAULT; } z_query_consolidation_t z_query_consolidation_auto(void) { @@ -290,532 +689,577 @@ z_query_consolidation_t z_query_consolidation_none(void) { z_query_consolidation_t z_query_consolidation_default(void) { return z_query_consolidation_auto(); } -z_bytes_t z_query_parameters(const z_query_t *query) { - z_bytes_t parameters = - _z_bytes_wrap((uint8_t *)query->_val._rc.in->val._parameters, strlen(query->_val._rc.in->val._parameters)); - return parameters; +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); } -z_value_t z_query_value(const z_query_t *query) { return query->_val._rc.in->val._value; } - -z_keyexpr_t z_query_keyexpr(const z_query_t *query) { return query->_val._rc.in->val._key; } +const z_loaned_bytes_t *z_query_attachment(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->attachment; } -_Bool z_value_is_initialized(z_value_t *value) { - _Bool ret = false; +const z_loaned_keyexpr_t *z_query_keyexpr(const z_loaned_query_t *query) { return &_Z_RC_IN_VAL(query)->_key; } - if ((value->payload.start != NULL)) { - ret = true; - } - - return ret; +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; } -void z_closure_sample_call(const z_owned_closure_sample_t *closure, const z_sample_t *sample) { - if (closure->call) { +void z_closure_sample_call(const z_loaned_closure_sample_t *closure, const z_loaned_sample_t *sample) { + if (closure->call != NULL) { (closure->call)(sample, closure->context); } } -void z_closure_query_call(const z_owned_closure_query_t *closure, const z_query_t *query) { - if (closure->call) { +void z_closure_query_call(const z_loaned_closure_query_t *closure, const z_loaned_query_t *query) { + if (closure->call != NULL) { (closure->call)(query, closure->context); } } -void z_closure_reply_call(const z_owned_closure_reply_t *closure, z_owned_reply_t *reply) { - if (closure->call) { +void z_closure_reply_call(const z_loaned_closure_reply_t *closure, const z_loaned_reply_t *reply) { + if (closure->call != NULL) { (closure->call)(reply, closure->context); } } -void z_closure_hello_call(const z_owned_closure_hello_t *closure, z_owned_hello_t *hello) { - if (closure->call) { +void z_closure_hello_call(const z_loaned_closure_hello_t *closure, const z_loaned_hello_t *hello) { + if (closure->call != NULL) { (closure->call)(hello, closure->context); } } -void z_closure_zid_call(const z_owned_closure_zid_t *closure, const z_id_t *id) { - if (closure->call) { +void z_closure_zid_call(const z_loaned_closure_zid_t *closure, const z_id_t *id) { + if (closure->call != NULL) { (closure->call)(id, closure->context); } } -/**************** Loans ****************/ -#define OWNED_FUNCTIONS_PTR_INTERNAL(type, ownedtype, name, f_free, f_copy) \ - _Bool z_##name##_check(const ownedtype *val) { return val->_value != NULL; } \ - type z_##name##_loan(const ownedtype *val) { return *val->_value; } \ - ownedtype z_##name##_null(void) { return (ownedtype){._value = NULL}; } \ - ownedtype *z_##name##_move(ownedtype *val) { return val; } \ - ownedtype z_##name##_clone(ownedtype *val) { \ - ownedtype ret; \ - ret._value = (type *)z_malloc(sizeof(type)); \ - if (ret._value != NULL) { \ - f_copy(ret._value, val->_value); \ - } \ - return ret; \ - } \ - void z_##name##_drop(ownedtype *val) { \ - if (val->_value != NULL) { \ - f_free(&val->_value); \ - } \ - } - -#define OWNED_FUNCTIONS_PTR_COMMON(type, ownedtype, name) \ - _Bool z_##name##_check(const ownedtype *val) { return val->_value != NULL; } \ - type z_##name##_loan(const ownedtype *val) { return (type){._val = val->_value}; } \ - ownedtype z_##name##_null(void) { return (ownedtype){._value = NULL}; } \ - ownedtype *z_##name##_move(ownedtype *val) { return val; } - -#define OWNED_FUNCTIONS_PTR_CLONE(type, ownedtype, name, f_copy) \ - ownedtype z_##name##_clone(ownedtype *val) { \ - ownedtype ret; \ - ret._value = (_##type *)z_malloc(sizeof(_##type)); \ - if (ret._value != NULL) { \ - f_copy(ret._value, val->_value); \ - } \ - return ret; \ - } - -#define OWNED_FUNCTIONS_PTR_DROP(type, ownedtype, name, f_free) \ - void z_##name##_drop(ownedtype *val) { \ - if (val->_value != NULL) { \ - f_free(&val->_value); \ - } \ - } - -#define OWNED_FUNCTIONS_STR(type, ownedtype, name, f_free, f_copy) \ - _Bool z_##name##_check(const ownedtype *val) { return val->_value != NULL; } \ - type z_##name##_loan(const ownedtype *val) { return val->_value; } \ - ownedtype z_##name##_null(void) { return (ownedtype){._value = NULL}; }; \ - ownedtype *z_##name##_move(ownedtype *val) { return val; } \ - ownedtype z_##name##_clone(ownedtype *val) { \ - ownedtype ret; \ - size_t size = _z_str_size(val->_value); \ - ret._value = (_##type)z_malloc(size); \ - if (ret._value != NULL) { \ - f_copy(ret._value, val->_value, size); \ - } \ - return ret; \ - } \ - void z_##name##_drop(ownedtype *val) { \ - if (val->_value != NULL) { \ - f_free(&val->_value); \ - } \ - } - -static inline void _z_owner_noop_copy(void *dst, const void *src) { - (void)(dst); - (void)(src); -} - -OWNED_FUNCTIONS_STR(z_str_t, z_owned_str_t, str, _z_str_free, _z_str_n_copy) - -OWNED_FUNCTIONS_PTR_COMMON(z_config_t, z_owned_config_t, config) -OWNED_FUNCTIONS_PTR_CLONE(z_config_t, z_owned_config_t, config, _z_owner_noop_copy) -OWNED_FUNCTIONS_PTR_DROP(z_config_t, z_owned_config_t, config, _z_config_free) - -OWNED_FUNCTIONS_PTR_COMMON(z_scouting_config_t, z_owned_scouting_config_t, scouting_config) -OWNED_FUNCTIONS_PTR_CLONE(z_scouting_config_t, z_owned_scouting_config_t, scouting_config, _z_owner_noop_copy) -OWNED_FUNCTIONS_PTR_DROP(z_scouting_config_t, z_owned_scouting_config_t, scouting_config, _z_scouting_config_free) - -OWNED_FUNCTIONS_PTR_INTERNAL(z_keyexpr_t, z_owned_keyexpr_t, keyexpr, _z_keyexpr_free, _z_keyexpr_copy) -OWNED_FUNCTIONS_PTR_INTERNAL(z_hello_t, z_owned_hello_t, hello, _z_hello_free, _z_owner_noop_copy) -OWNED_FUNCTIONS_PTR_INTERNAL(z_str_array_t, z_owned_str_array_t, str_array, _z_str_array_free, _z_owner_noop_copy) - -_Bool z_session_check(const z_owned_session_t *val) { return val->_value.in != NULL; } -z_session_t z_session_loan(const z_owned_session_t *val) { return (z_session_t){._val = val->_value}; } -z_owned_session_t z_session_null(void) { return (z_owned_session_t){._value = {.in = NULL}}; } -z_owned_session_t *z_session_move(z_owned_session_t *val) { return val; } -z_owned_session_t z_session_clone(z_owned_session_t *val) { - z_owned_session_t ret; - ret._value = _z_session_rc_clone(&val->_value); - return ret; -} -void z_session_drop(z_owned_session_t *val) { z_close(val); } +_Bool _z_config_check(const _z_config_t *config) { return !_z_str_intmap_is_empty(config); } +_z_config_t _z_config_null(void) { return _z_str_intmap_make(); } +void _z_config_drop(_z_config_t *config) { _z_str_intmap_clear(config); } +_Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_config_t, config, _z_config_check, _z_config_null, _z_config_drop) -#define OWNED_FUNCTIONS_CLOSURE(ownedtype, name) \ - _Bool z_##name##_check(const ownedtype *val) { return val->call != NULL; } \ - ownedtype *z_##name##_move(ownedtype *val) { return val; } \ - void z_##name##_drop(ownedtype *val) { \ - if (val->drop != NULL) { \ - (val->drop)(val->context); \ - val->drop = NULL; \ - } \ - val->call = NULL; \ - val->context = NULL; \ - } \ - ownedtype z_##name##_null(void) { \ - ownedtype v = {.call = NULL, .drop = NULL, .context = NULL}; \ - return v; \ - } +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_string_t, string, _z_string_check, _z_string_null, _z_string_copy, _z_string_clear) -z_owned_closure_sample_t z_closure_sample(_z_data_handler_t call, _z_dropper_handler_t drop, void *context) { - return (z_owned_closure_sample_t){.call = call, .drop = drop, .context = context}; +_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_OWNED_FUNCTIONS_VALUE_IMPL(_z_hello_t, hello, _z_hello_check, _z_hello_null, _z_hello_copy, _z_hello_clear) -z_owned_closure_query_t z_closure_query(_z_queryable_handler_t call, _z_dropper_handler_t drop, void *context) { - return (z_owned_closure_query_t){.call = call, .drop = drop, .context = context}; +z_id_t z_hello_zid(const z_loaned_hello_t *hello) { return hello->_zid; } + +z_whatami_t z_hello_whatami(const z_loaned_hello_t *hello) { return hello->_whatami; } + +const z_loaned_string_array_t *z_hello_locators(const z_loaned_hello_t *hello) { return &hello->_locators; } + +static const char *WHAT_AM_I_TO_STRING_MAP[8] = { + "Other", // 0 + "Router", // 0b1 + "Peer", // 0b01 + "Router|Peer", // 0b11, + "Client", // 0b100 + "Router|Client", // 0b101 + "Peer|Client", // 0b110 + "Router|Peer|Client" // 0b111 +}; + +int8_t z_whatami_to_view_string(z_whatami_t whatami, z_view_string_t *str_out) { + uint8_t idx = (uint8_t)whatami; + if (idx >= _ZP_ARRAY_SIZE(WHAT_AM_I_TO_STRING_MAP) || idx == 0) { + z_view_string_from_str(str_out, WHAT_AM_I_TO_STRING_MAP[0]); + return _Z_ERR_INVALID; + } else { + z_view_string_from_str(str_out, WHAT_AM_I_TO_STRING_MAP[idx]); + } + return _Z_RES_OK; } -z_owned_closure_reply_t z_closure_reply(z_owned_reply_handler_t call, _z_dropper_handler_t drop, void *context) { - return (z_owned_closure_reply_t){.call = call, .drop = drop, .context = context}; +_Bool _z_string_array_check(const _z_string_svec_t *val) { return !_z_string_svec_is_empty(val); } +int8_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; } +_z_string_svec_t _z_string_array_null(void) { return _z_string_svec_make(0); } +_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_bytes_t, bytes, _z_bytes_check, _z_bytes_null, _z_bytes_copy, _z_bytes_drop) -z_owned_closure_hello_t z_closure_hello(z_owned_hello_handler_t call, _z_dropper_handler_t drop, void *context) { - return (z_owned_closure_hello_t){.call = call, .drop = drop, .context = context}; +#if Z_FEATURE_PUBLICATION == 1 || Z_FEATURE_QUERYABLE == 1 || Z_FEATURE_QUERY == 1 +// Convert a user owned bytes payload to an internal bytes payload, returning an empty one if value invalid +static _z_bytes_t _z_bytes_from_owned_bytes(z_owned_bytes_t *bytes) { + if ((bytes != NULL)) { + return bytes->_val; + } else { + return _z_bytes_null(); + } } +#endif -z_owned_closure_zid_t z_closure_zid(z_id_handler_t call, _z_dropper_handler_t drop, void *context) { - return (z_owned_closure_zid_t){.call = call, .drop = drop, .context = context}; +#if Z_FEATURE_QUERYABLE == 1 || Z_FEATURE_QUERY == 1 +// Convert a user owned encoding to an internal encoding, return default encoding if value invalid +static _z_encoding_t _z_encoding_from_owned(const z_owned_encoding_t *encoding) { + if (encoding == NULL) { + return _z_encoding_null(); + } + return encoding->_val; } +#endif -OWNED_FUNCTIONS_CLOSURE(z_owned_closure_sample_t, closure_sample) -OWNED_FUNCTIONS_CLOSURE(z_owned_closure_query_t, closure_query) -OWNED_FUNCTIONS_CLOSURE(z_owned_closure_reply_t, closure_reply) -OWNED_FUNCTIONS_CLOSURE(z_owned_closure_hello_t, closure_hello) -OWNED_FUNCTIONS_CLOSURE(z_owned_closure_zid_t, closure_zid) +_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_data_handler_t, z_dropper_handler_t) +_Z_OWNED_FUNCTIONS_CLOSURE_IMPL(closure_query, _z_queryable_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_id_handler_t, z_dropper_handler_t) /************* Primitives **************/ typedef struct __z_hello_handler_wrapper_t { - z_owned_hello_handler_t user_call; + z_loaned_hello_handler_t user_call; void *ctx; } __z_hello_handler_wrapper_t; void __z_hello_handler(_z_hello_t *hello, __z_hello_handler_wrapper_t *wrapped_ctx) { - z_owned_hello_t ohello = {._value = hello}; - wrapped_ctx->user_call(&ohello, wrapped_ctx->ctx); + wrapped_ctx->user_call(hello, wrapped_ctx->ctx); } -int8_t z_scout(z_owned_scouting_config_t *config, z_owned_closure_hello_t *callback) { +int8_t z_scout(z_moved_config_t *config, z_moved_closure_hello_t *callback, const z_scout_options_t *options) { int8_t ret = _Z_RES_OK; - void *ctx = callback->context; - callback->context = NULL; + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; // TODO[API-NET]: When API and NET are a single layer, there is no wrap the user callback and args // to enclose the z_reply_t into a z_owned_reply_t. __z_hello_handler_wrapper_t *wrapped_ctx = (__z_hello_handler_wrapper_t *)z_malloc(sizeof(__z_hello_handler_wrapper_t)); if (wrapped_ctx != NULL) { - wrapped_ctx->user_call = callback->call; + wrapped_ctx->user_call = callback->_this._val.call; wrapped_ctx->ctx = ctx; - char *opt_as_str = _z_config_get(config->_value, Z_CONFIG_SCOUTING_WHAT_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_SCOUTING_WHAT_DEFAULT; + z_what_t what; + if (options != NULL) { + what = options->what; + } else { + char *opt_as_str = _z_config_get(&config->_this._val, Z_CONFIG_SCOUTING_WHAT_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_SCOUTING_WHAT_DEFAULT; + } + what = strtol(opt_as_str, NULL, 10); } - z_what_t what = strtol(opt_as_str, NULL, 10); - opt_as_str = _z_config_get(config->_value, Z_CONFIG_MULTICAST_LOCATOR_KEY); + char *opt_as_str = _z_config_get(&config->_this._val, Z_CONFIG_MULTICAST_LOCATOR_KEY); if (opt_as_str == NULL) { opt_as_str = (char *)Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; } - char *mcast_locator = opt_as_str; + _z_string_t mcast_locator = _z_string_alias_str(opt_as_str); - opt_as_str = _z_config_get(config->_value, Z_CONFIG_SCOUTING_TIMEOUT_KEY); - if (opt_as_str == NULL) { - opt_as_str = (char *)Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; + uint32_t timeout; + if (options != NULL) { + timeout = options->timeout_ms; + } else { + opt_as_str = _z_config_get(&config->_this._val, Z_CONFIG_SCOUTING_TIMEOUT_KEY); + if (opt_as_str == NULL) { + opt_as_str = (char *)Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; + } + timeout = (uint32_t)strtoul(opt_as_str, NULL, 10); } - uint32_t timeout = strtoul(opt_as_str, NULL, 10); _z_id_t zid = _z_id_empty(); - char *zid_str = _z_config_get(config->_value, Z_CONFIG_SESSION_ZID_KEY); + char *zid_str = _z_config_get(&config->_this._val, Z_CONFIG_SESSION_ZID_KEY); if (zid_str != NULL) { _z_uuid_to_bytes(zid.id, zid_str); } - _z_scout(what, zid, mcast_locator, timeout, __z_hello_handler, wrapped_ctx, callback->drop, ctx); + _z_scout(what, zid, &mcast_locator, timeout, __z_hello_handler, wrapped_ctx, callback->_this._val.drop, ctx); z_free(wrapped_ctx); - z_scouting_config_drop(config); + z_config_drop(config); } else { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; } + z_internal_closure_hello_null(&callback->_this); return ret; } -z_owned_session_t z_open(z_owned_config_t *config) { - z_owned_session_t zs = {._value = {.in = NULL}}; - +int8_t z_open(z_owned_session_t *zs, z_moved_config_t *config) { + z_internal_session_null(zs); + _z_session_t *s = z_malloc(sizeof(_z_session_t)); + if (s == NULL) { + z_config_drop(config); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + memset(s, 0, sizeof(_z_session_t)); // Create rc - _z_session_rc_t zsrc = _z_session_rc_new(); - if (zsrc.in == NULL) { + _z_session_rc_t zsrc = _z_session_rc_new(s); + if (zsrc._cnt == NULL) { + z_free(s); z_config_drop(config); - return zs; + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } + zs->_rc = zsrc; // Open session - if (_z_open(&zsrc.in->val, config->_value) != _Z_RES_OK) { - _z_session_rc_drop(&zsrc); + int8_t ret = _z_open(&zs->_rc, &config->_this._val); + if (ret != _Z_RES_OK) { + _z_session_rc_decr(&zs->_rc); + z_internal_session_null(zs); z_config_drop(config); - return zs; + return ret; } - // Store rc in session - zs._value = zsrc; + // Clean up z_config_drop(config); - return zs; + return _Z_RES_OK; } -int8_t z_close(z_owned_session_t *zs) { - if ((zs == NULL) || (zs->_value.in == NULL)) { +int8_t z_close(z_moved_session_t *zs) { + if (zs == NULL || !z_internal_session_check(&zs->_this)) { return _Z_RES_OK; } - _z_close(&zs->_value.in->val); - _z_session_rc_drop(&zs->_value); - zs->_value.in = NULL; + z_session_drop(zs); return _Z_RES_OK; } -int8_t z_info_peers_zid(const z_session_t zs, z_owned_closure_zid_t *callback) { +int8_t z_info_peers_zid(const z_loaned_session_t *zs, z_moved_closure_zid_t *callback) { // Call transport function - switch (zs._val.in->val._tp._type) { + switch (_Z_RC_IN_VAL(zs)->_tp._type) { case _Z_TRANSPORT_MULTICAST_TYPE: case _Z_TRANSPORT_RAWETH_TYPE: - _zp_multicast_fetch_zid(&zs._val.in->val._tp, callback); + _zp_multicast_fetch_zid(&(_Z_RC_IN_VAL(zs)->_tp), &callback->_this._val); break; default: break; } // Note and clear context - void *ctx = callback->context; - callback->context = NULL; + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; // Drop if needed - if (callback->drop != NULL) { - callback->drop(ctx); + if (callback->_this._val.drop != NULL) { + callback->_this._val.drop(ctx); } + z_internal_closure_zid_null(&callback->_this); return 0; } -int8_t z_info_routers_zid(const z_session_t zs, z_owned_closure_zid_t *callback) { +int8_t z_info_routers_zid(const z_loaned_session_t *zs, z_moved_closure_zid_t *callback) { // Call transport function - switch (zs._val.in->val._tp._type) { + switch (_Z_RC_IN_VAL(zs)->_tp._type) { case _Z_TRANSPORT_UNICAST_TYPE: - _zp_unicast_fetch_zid(&zs._val.in->val._tp, callback); + _zp_unicast_fetch_zid(&(_Z_RC_IN_VAL(zs)->_tp), &callback->_this._val); break; default: break; } // Note and clear context - void *ctx = callback->context; - callback->context = NULL; + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; // Drop if needed - if (callback->drop != NULL) { - callback->drop(ctx); + if (callback->_this._val.drop != NULL) { + callback->_this._val.drop(ctx); } + z_internal_closure_zid_null(&callback->_this); return 0; } -z_id_t z_info_zid(const z_session_t zs) { return zs._val.in->val._local_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(z_owned_string_t *str, z_id_t *id) { + _z_slice_t buf = _z_slice_alias_buf(id->id, sizeof(id->id)); + str->_val = _z_string_convert_bytes(&buf); + if (!_z_string_check(&str->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _Z_RES_OK; +} + +const z_loaned_keyexpr_t *z_sample_keyexpr(const z_loaned_sample_t *sample) { return &sample->keyexpr; } +z_sample_kind_t z_sample_kind(const z_loaned_sample_t *sample) { return sample->kind; } +const z_loaned_bytes_t *z_sample_payload(const z_loaned_sample_t *sample) { return &sample->payload; } +const z_timestamp_t *z_sample_timestamp(const z_loaned_sample_t *sample) { + if (_z_timestamp_check(&sample->timestamp)) { + return &sample->timestamp; + } else { + return NULL; + } +} +const z_loaned_encoding_t *z_sample_encoding(const z_loaned_sample_t *sample) { return &sample->encoding; } +const z_loaned_bytes_t *z_sample_attachment(const z_loaned_sample_t *sample) { return &sample->attachment; } +z_congestion_control_t z_sample_congestion_control(const z_loaned_sample_t *sample) { + return _z_n_qos_get_congestion_control(sample->qos); +} +bool z_sample_express(const z_loaned_sample_t *sample) { return _z_n_qos_get_express(sample->qos); } +z_priority_t z_sample_priority(const z_loaned_sample_t *sample) { return _z_n_qos_get_priority(sample->qos); } + +const z_loaned_bytes_t *z_reply_err_payload(const z_loaned_reply_err_t *reply_err) { return &reply_err->payload; } +const z_loaned_encoding_t *z_reply_err_encoding(const z_loaned_reply_err_t *reply_err) { return &reply_err->encoding; } + +const char *z_string_data(const z_loaned_string_t *str) { return _z_string_data(str); } +size_t z_string_len(const z_loaned_string_t *str) { return _z_string_len(str); } + +int8_t z_string_copy_from_str(z_owned_string_t *str, const char *value) { + str->_val = _z_string_copy_from_str(value); + if (str->_val._slice.start == NULL && value != NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _Z_RES_OK; +} + +int8_t z_string_from_str(z_owned_string_t *str, char *value, void (*deleter)(void *value, void *context), + void *context) { + str->_val = _z_string_from_str_custom_deleter(value, _z_delete_context_create(deleter, context)); + return _Z_RES_OK; +} + +void z_string_empty(z_owned_string_t *str) { str->_val = _z_string_null(); } + +int8_t z_string_copy_from_substr(z_owned_string_t *str, const char *value, size_t len) { + str->_val = _z_string_copy_from_substr(value, len); + return _Z_RES_OK; +} + +bool z_string_is_empty(const z_loaned_string_t *str) { return _z_string_is_empty(str); } #if Z_FEATURE_PUBLICATION == 1 -OWNED_FUNCTIONS_PTR_COMMON(z_publisher_t, z_owned_publisher_t, publisher) -OWNED_FUNCTIONS_PTR_CLONE(z_publisher_t, z_owned_publisher_t, publisher, _z_owner_noop_copy) -void z_publisher_drop(z_owned_publisher_t *val) { z_undeclare_publisher(val); } - -z_put_options_t z_put_options_default(void) { - return (z_put_options_t) { - .encoding = z_encoding_default(), .congestion_control = Z_CONGESTION_CONTROL_DEFAULT, - .priority = Z_PRIORITY_DEFAULT, -#if Z_FEATURE_ATTACHMENT == 1 - .attachment = z_attachment_null() -#endif - }; +int8_t _z_undeclare_and_clear_publisher(_z_publisher_t *pub) { + int8_t ret = _Z_RES_OK; + ret = _z_undeclare_publisher(pub); + _z_publisher_clear(pub); + return ret; } -z_delete_options_t z_delete_options_default(void) { - return (z_delete_options_t){.congestion_control = Z_CONGESTION_CONTROL_DEFAULT, .priority = Z_PRIORITY_DEFAULT}; +void _z_publisher_drop(_z_publisher_t *pub) { _z_undeclare_and_clear_publisher(pub); } + +_Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_publisher_t, publisher, _z_publisher_check, _z_publisher_null, + _z_publisher_drop) + +void z_put_options_default(z_put_options_t *options) { + options->congestion_control = Z_CONGESTION_CONTROL_DEFAULT; + options->priority = Z_PRIORITY_DEFAULT; + options->encoding = NULL; + options->is_express = false; + options->timestamp = NULL; + options->attachment = NULL; +} + +void z_delete_options_default(z_delete_options_t *options) { + options->congestion_control = Z_CONGESTION_CONTROL_DEFAULT; + options->is_express = false; + options->timestamp = NULL; + options->priority = Z_PRIORITY_DEFAULT; } -int8_t z_put(z_session_t zs, z_keyexpr_t keyexpr, const uint8_t *payload, z_zint_t payload_len, +int8_t z_put(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, z_moved_bytes_t *payload, const z_put_options_t *options) { int8_t ret = 0; - z_put_options_t opt = z_put_options_default(); + z_put_options_t opt; + z_put_options_default(&opt); if (options != NULL) { opt.congestion_control = options->congestion_control; opt.encoding = options->encoding; opt.priority = options->priority; -#if Z_FEATURE_ATTACHMENT == 1 + opt.is_express = options->is_express; + opt.timestamp = options->timestamp; opt.attachment = options->attachment; -#endif } - ret = _z_write(&zs._val.in->val, keyexpr, (const uint8_t *)payload, payload_len, opt.encoding, Z_SAMPLE_KIND_PUT, - opt.congestion_control, opt.priority -#if Z_FEATURE_ATTACHMENT == 1 - , - opt.attachment -#endif - ); - // Trigger local subscriptions - _z_trigger_local_subscriptions(&zs._val.in->val, keyexpr, payload, payload_len, - _z_n_qos_make(0, opt.congestion_control == Z_CONGESTION_CONTROL_BLOCK, opt.priority) -#if Z_FEATURE_ATTACHMENT == 1 - , - opt.attachment -#endif - ); + _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), + 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)); + // Trigger local subscriptions + _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_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)); + // Clean-up + z_encoding_drop(opt.encoding); + z_bytes_drop(opt.attachment); + z_bytes_drop(payload); return ret; } -int8_t z_delete(z_session_t zs, z_keyexpr_t keyexpr, const z_delete_options_t *options) { +int8_t z_delete(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, const z_delete_options_t *options) { int8_t ret = 0; - z_delete_options_t opt = z_delete_options_default(); + z_delete_options_t opt; + z_delete_options_default(&opt); if (options != NULL) { opt.congestion_control = options->congestion_control; opt.priority = options->priority; + opt.is_express = options->is_express; + opt.timestamp = options->timestamp; } - ret = _z_write(&zs._val.in->val, keyexpr, NULL, 0, z_encoding_default(), Z_SAMPLE_KIND_DELETE, - opt.congestion_control, opt.priority -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_null() -#endif - ); + ret = _z_write(_Z_RC_IN_VAL(zs), *keyexpr, _z_bytes_null(), NULL, Z_SAMPLE_KIND_DELETE, opt.congestion_control, + opt.priority, opt.is_express, opt.timestamp, _z_bytes_null()); return ret; } -z_publisher_options_t z_publisher_options_default(void) { - return (z_publisher_options_t){.congestion_control = Z_CONGESTION_CONTROL_DEFAULT, .priority = Z_PRIORITY_DEFAULT}; +void z_publisher_options_default(z_publisher_options_t *options) { + options->encoding = NULL; + options->congestion_control = Z_CONGESTION_CONTROL_DEFAULT; + options->priority = Z_PRIORITY_DEFAULT; + options->is_express = false; } -z_owned_publisher_t z_declare_publisher(z_session_t zs, z_keyexpr_t keyexpr, const z_publisher_options_t *options) { - z_keyexpr_t key = keyexpr; +int8_t z_declare_publisher(z_owned_publisher_t *pub, const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, + const z_publisher_options_t *options) { + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); + _z_keyexpr_t key = keyexpr_aliased; + pub->_val = _z_publisher_null(); // TODO: Currently, if resource declarations are done over multicast transports, the current protocol definition // lacks a way to convey them to later-joining nodes. Thus, in the current version automatic // resource declarations are only performed on unicast transports. - if (zs._val.in->val._tp._type == _Z_TRANSPORT_UNICAST_TYPE) { - _z_resource_t *r = _z_get_resource_by_key(&zs._val.in->val, &keyexpr); + if (_Z_RC_IN_VAL(zs)->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + _z_resource_t *r = _z_get_resource_by_key(_Z_RC_IN_VAL(zs), &keyexpr_aliased); if (r == NULL) { - uint16_t id = _z_declare_resource(&zs._val.in->val, keyexpr); - key = _z_rid_with_suffix(id, NULL); + uint16_t id = _z_declare_resource(_Z_RC_IN_VAL(zs), keyexpr_aliased); + key = _z_keyexpr_from_string(id, &keyexpr_aliased._suffix); } } - - z_publisher_options_t opt = z_publisher_options_default(); + // Set options + z_publisher_options_t opt; + z_publisher_options_default(&opt); if (options != NULL) { - opt.congestion_control = options->congestion_control; - opt.priority = options->priority; + opt = *options; } - - return (z_owned_publisher_t){._value = _z_declare_publisher(&zs._val, key, opt.congestion_control, opt.priority)}; + // Set publisher + _z_publisher_t int_pub = _z_declare_publisher(zs, key, opt.encoding == NULL ? NULL : &opt.encoding->_this._val, + opt.congestion_control, opt.priority, opt.is_express); + // Create write filter + int8_t res = _z_write_filter_create(&int_pub); + if (res != _Z_RES_OK) { + if (key._id != Z_RESOURCE_ID_NONE) { + _z_undeclare_resource(_Z_RC_IN_VAL(zs), key._id); + } + return res; + } + pub->_val = int_pub; + return _Z_RES_OK; } -int8_t z_undeclare_publisher(z_owned_publisher_t *pub) { - int8_t ret = _Z_RES_OK; - - ret = _z_undeclare_publisher(pub->_value); - _z_publisher_free(&pub->_value); +int8_t z_undeclare_publisher(z_moved_publisher_t *pub) { return _z_undeclare_and_clear_publisher(&pub->_this._val); } - return ret; +void z_publisher_put_options_default(z_publisher_put_options_t *options) { + options->encoding = NULL; + options->attachment = NULL; + options->timestamp = NULL; } -z_publisher_put_options_t z_publisher_put_options_default(void) { - return (z_publisher_put_options_t) { - .encoding = z_encoding_default(), -#if Z_FEATURE_ATTACHMENT == 1 - .attachment = z_attachment_null() -#endif - }; -} - -z_publisher_delete_options_t z_publisher_delete_options_default(void) { - return (z_publisher_delete_options_t){.__dummy = 0}; -} +void z_publisher_delete_options_default(z_publisher_delete_options_t *options) { options->timestamp = NULL; } -int8_t z_publisher_put(const z_publisher_t pub, const uint8_t *payload, size_t len, +int8_t z_publisher_put(const z_loaned_publisher_t *pub, z_moved_bytes_t *payload, const z_publisher_put_options_t *options) { - int8_t ret = _Z_RES_OK; - - z_publisher_put_options_t opt = z_publisher_put_options_default(); + int8_t ret = 0; + // Build options + z_publisher_put_options_t opt; + z_publisher_put_options_default(&opt); if (options != NULL) { opt.encoding = options->encoding; -#if Z_FEATURE_ATTACHMENT == 1 + opt.timestamp = options->timestamp; opt.attachment = options->attachment; -#endif } - - ret = _z_write(&pub._val->_zn.in->val, pub._val->_key, payload, len, opt.encoding, Z_SAMPLE_KIND_PUT, - pub._val->_congestion_control, pub._val->_priority -#if Z_FEATURE_ATTACHMENT == 1 - , - opt.attachment -#endif - ); - + _z_encoding_t encoding; + if (opt.encoding == NULL) { + _Z_RETURN_IF_ERR(_z_encoding_copy(&encoding, &pub->_encoding)); + } else { + encoding = _z_encoding_steal(&opt.encoding->_this._val); + } + // Remove potentially redundant ke suffix + _z_keyexpr_t pub_keyexpr = _z_keyexpr_alias_from_user_defined(pub->_key, true); + + // Check if write filter is active before writing + if (!_z_write_filter_active(pub)) { + // Write value + ret = _z_write(_Z_RC_IN_VAL(&pub->_zn), 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)); + } // Trigger local subscriptions - _z_trigger_local_subscriptions(&pub._val->_zn.in->val, pub._val->_key, payload, len, _Z_N_QOS_DEFAULT -#if Z_FEATURE_ATTACHMENT == 1 - , - opt.attachment -#endif - ); - + _z_trigger_local_subscriptions( + _Z_RC_IN_VAL(&pub->_zn), pub_keyexpr, _z_bytes_from_owned_bytes(&payload->_this), &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)); + // Clean-up + _z_encoding_clear(&encoding); + z_bytes_drop(opt.attachment); + z_bytes_drop(payload); return ret; } -int8_t z_publisher_delete(const z_publisher_t pub, const z_publisher_delete_options_t *options) { - (void)(options); - return _z_write(&pub._val->_zn.in->val, pub._val->_key, NULL, 0, z_encoding_default(), Z_SAMPLE_KIND_DELETE, - pub._val->_congestion_control, pub._val->_priority -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_null() -#endif - ); +int8_t z_publisher_delete(const z_loaned_publisher_t *pub, const z_publisher_delete_options_t *options) { + // Build options + z_publisher_delete_options_t opt; + z_publisher_delete_options_default(&opt); + if (options != NULL) { + opt.timestamp = options->timestamp; + } + // Remove potentially redundant ke suffix + _z_keyexpr_t pub_keyexpr = _z_keyexpr_alias_from_user_defined(pub->_key, true); + + return _z_write(_Z_RC_IN_VAL(&pub->_zn), pub_keyexpr, _z_bytes_null(), NULL, Z_SAMPLE_KIND_DELETE, + pub->_congestion_control, pub->_priority, pub->_is_express, opt.timestamp, _z_bytes_null()); } -z_owned_keyexpr_t z_publisher_keyexpr(z_publisher_t publisher) { - z_owned_keyexpr_t ret = {._value = z_malloc(sizeof(_z_keyexpr_t))}; - if (ret._value != NULL && publisher._val != NULL) { - *ret._value = _z_keyexpr_duplicate(publisher._val->_key); - } - return ret; +const z_loaned_keyexpr_t *z_publisher_keyexpr(const z_loaned_publisher_t *publisher) { + return (const z_loaned_keyexpr_t *)&publisher->_key; } #endif #if Z_FEATURE_QUERY == 1 -OWNED_FUNCTIONS_PTR_INTERNAL(z_reply_t, z_owned_reply_t, reply, _z_reply_free, _z_owner_noop_copy) - -z_get_options_t z_get_options_default(void) { - return (z_get_options_t) { - .target = z_query_target_default(), .consolidation = z_query_consolidation_default(), - .value = {.encoding = z_encoding_default(), .payload = _z_bytes_empty()}, -#if Z_FEATURE_ATTACHMENT == 1 - // TODO:ATT.attachment = z_attachment_null() -#endif - .timeout_ms = Z_GET_TIMEOUT_DEFAULT - }; +_Bool _z_reply_check(const _z_reply_t *reply) { + if (reply->data._tag == _Z_REPLY_TAG_DATA) { + return _z_sample_check(&reply->data._result.sample); + } else if (reply->data._tag == _Z_REPLY_TAG_ERROR) { + return _z_value_check(&reply->data._result.error); + } + return false; } +_Z_OWNED_FUNCTIONS_VALUE_IMPL(_z_reply_t, reply, _z_reply_check, _z_reply_null, _z_reply_copy, _z_reply_clear) -typedef struct __z_reply_handler_wrapper_t { - z_owned_reply_handler_t user_call; - void *ctx; -} __z_reply_handler_wrapper_t; - -void __z_reply_handler(_z_reply_t *reply, __z_reply_handler_wrapper_t *wrapped_ctx) { - z_owned_reply_t oreply = {._value = reply}; - - wrapped_ctx->user_call(&oreply, wrapped_ctx->ctx); - z_reply_drop(&oreply); // user_call is allowed to take ownership of the reply by setting oreply._value to NULL +void z_get_options_default(z_get_options_t *options) { + options->target = z_query_target_default(); + options->consolidation = z_query_consolidation_default(); + options->congestion_control = Z_CONGESTION_CONTROL_DEFAULT; + options->priority = Z_PRIORITY_DEFAULT; + options->is_express = false; + options->encoding = NULL; + options->payload = NULL; + options->attachment = NULL; + options->timeout_ms = Z_GET_TIMEOUT_DEFAULT; } -int8_t z_get(z_session_t zs, z_keyexpr_t keyexpr, const char *parameters, z_owned_closure_reply_t *callback, - const z_get_options_t *options) { +int8_t z_get(const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, const char *parameters, + z_moved_closure_reply_t *callback, z_get_options_t *options) { int8_t ret = _Z_RES_OK; - void *ctx = callback->context; - callback->context = NULL; + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; + + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); - z_get_options_t opt = z_get_options_default(); + z_get_options_t opt; + z_get_options_default(&opt); if (options != NULL) { opt.consolidation = options->consolidation; opt.target = options->target; - opt.value = options->value; + 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; } if (opt.consolidation.mode == Z_CONSOLIDATION_MODE_AUTO) { @@ -826,465 +1270,431 @@ int8_t z_get(z_session_t zs, z_keyexpr_t keyexpr, const char *parameters, z_owne opt.consolidation.mode = Z_CONSOLIDATION_MODE_LATEST; } } - - // TODO[API-NET]: When API and NET are a single layer, there is no wrap the user callback and args - // to enclose the z_reply_t into a z_owned_reply_t. - __z_reply_handler_wrapper_t *wrapped_ctx = - (__z_reply_handler_wrapper_t *)z_malloc(sizeof(__z_reply_handler_wrapper_t)); - if (wrapped_ctx != NULL) { - wrapped_ctx->user_call = callback->call; - wrapped_ctx->ctx = ctx; - } - - ret = _z_query(&zs._val.in->val, keyexpr, parameters, opt.target, opt.consolidation.mode, opt.value, - __z_reply_handler, wrapped_ctx, callback->drop, ctx, opt.timeout_ms -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_null() - // TODO:ATT opt.attachment -#endif - ); + // Set value + _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&opt.payload->_this), + .encoding = _z_encoding_from_owned(&opt.encoding->_this)}; + + ret = _z_query(_Z_RC_IN_VAL(zs), keyexpr_aliased, parameters, opt.target, opt.consolidation.mode, value, + callback->_this._val.call, callback->_this._val.drop, ctx, opt.timeout_ms, + _z_bytes_from_owned_bytes(&opt.attachment->_this), opt.congestion_control, opt.priority, + opt.is_express); + // Clean-up + z_bytes_drop(opt.payload); + z_encoding_drop(opt.encoding); + z_bytes_drop(opt.attachment); + z_internal_closure_reply_null( + &callback->_this); // call and drop passed to _z_query, so we nullify the closure here return ret; } -_Bool z_reply_is_ok(const z_owned_reply_t *reply) { - (void)(reply); - // For the moment always return TRUE. - // The support for reply errors will come in the next release. - return true; -} +_Bool z_reply_is_ok(const z_loaned_reply_t *reply) { return reply->data._tag != _Z_REPLY_TAG_ERROR; } + +const z_loaned_sample_t *z_reply_ok(const z_loaned_reply_t *reply) { return &reply->data._result.sample; } -z_sample_t z_reply_ok(const z_owned_reply_t *reply) { return reply->_value->data.sample; } +const z_loaned_reply_err_t *z_reply_err(const z_loaned_reply_t *reply) { return &reply->data._result.error; } -z_value_t z_reply_err(const z_owned_reply_t *reply) { - (void)(reply); - return (z_value_t){.payload = _z_bytes_empty(), .encoding = z_encoding_default()}; +_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; + return true; + } + return false; } #endif #if Z_FEATURE_QUERYABLE == 1 -OWNED_FUNCTIONS_PTR_COMMON(z_queryable_t, z_owned_queryable_t, queryable) -OWNED_FUNCTIONS_PTR_CLONE(z_queryable_t, z_owned_queryable_t, queryable, _z_owner_noop_copy) -void z_queryable_drop(z_owned_queryable_t *val) { z_undeclare_queryable(val); } +_Z_OWNED_FUNCTIONS_RC_IMPL(query) -z_queryable_options_t z_queryable_options_default(void) { - return (z_queryable_options_t){.complete = _Z_QUERYABLE_COMPLETE_DEFAULT}; +int8_t _z_undeclare_and_clear_queryable(_z_queryable_t *queryable) { + int8_t ret = _Z_RES_OK; + + ret = _z_undeclare_queryable(queryable); + _z_queryable_clear(queryable); + return ret; } -z_owned_queryable_t z_declare_queryable(z_session_t zs, z_keyexpr_t keyexpr, z_owned_closure_query_t *callback, - const z_queryable_options_t *options) { - void *ctx = callback->context; - callback->context = NULL; +void _z_queryable_drop(_z_queryable_t *queryable) { _z_undeclare_and_clear_queryable(queryable); } - z_keyexpr_t key = keyexpr; +_Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_queryable_t, queryable, _z_queryable_check, _z_queryable_null, + _z_queryable_drop) + +void z_queryable_options_default(z_queryable_options_t *options) { options->complete = _Z_QUERYABLE_COMPLETE_DEFAULT; } + +int8_t z_declare_queryable(z_owned_queryable_t *queryable, const z_loaned_session_t *zs, + const z_loaned_keyexpr_t *keyexpr, z_moved_closure_query_t *callback, + const z_queryable_options_t *options) { + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; + + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); + _z_keyexpr_t key = keyexpr_aliased; // TODO: Currently, if resource declarations are done over multicast transports, the current protocol definition // lacks a way to convey them to later-joining nodes. Thus, in the current version automatic // resource declarations are only performed on unicast transports. - if (zs._val.in->val._tp._type == _Z_TRANSPORT_UNICAST_TYPE) { - _z_resource_t *r = _z_get_resource_by_key(&zs._val.in->val, &keyexpr); + if (_Z_RC_IN_VAL(zs)->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + _z_resource_t *r = _z_get_resource_by_key(_Z_RC_IN_VAL(zs), &keyexpr_aliased); if (r == NULL) { - uint16_t id = _z_declare_resource(&zs._val.in->val, keyexpr); + uint16_t id = _z_declare_resource(_Z_RC_IN_VAL(zs), keyexpr_aliased); key = _z_rid_with_suffix(id, NULL); } } - z_queryable_options_t opt = z_queryable_options_default(); + z_queryable_options_t opt; + z_queryable_options_default(&opt); if (options != NULL) { opt.complete = options->complete; } - return (z_owned_queryable_t){ - ._value = _z_declare_queryable(&zs._val, key, opt.complete, callback->call, callback->drop, ctx)}; + queryable->_val = + _z_declare_queryable(zs, key, opt.complete, callback->_this._val.call, callback->_this._val.drop, ctx); + + z_internal_closure_query_null(&callback->_this); + return _Z_RES_OK; } -int8_t z_undeclare_queryable(z_owned_queryable_t *queryable) { - int8_t ret = _Z_RES_OK; +int8_t z_undeclare_queryable(z_moved_queryable_t *queryable) { + return _z_undeclare_and_clear_queryable(&queryable->_this._val); +} - ret = _z_undeclare_queryable(queryable->_value); - _z_queryable_free(&queryable->_value); +void z_query_reply_options_default(z_query_reply_options_t *options) { + options->encoding = NULL; + options->congestion_control = Z_CONGESTION_CONTROL_DEFAULT; + options->priority = Z_PRIORITY_DEFAULT; + options->timestamp = NULL; + options->is_express = false; + options->attachment = NULL; +} + +int8_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(&_Z_RC_IN_VAL(query)->_zn); + if (_Z_RC_IS_NULL(&sess_rc)) { + return _Z_ERR_CONNECTION_CLOSED; + } + // Set options + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); + z_query_reply_options_t opts; + if (options == NULL) { + z_query_reply_options_default(&opts); + } else { + opts = *options; + } + // Set value + _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&payload->_this), + .encoding = _z_encoding_from_owned(&opts.encoding->_this)}; + + int8_t ret = _z_send_reply(_Z_RC_IN_VAL(query), &sess_rc, 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; } -z_query_reply_options_t z_query_reply_options_default(void) { - return (z_query_reply_options_t){.encoding = z_encoding_default()}; +void z_query_reply_del_options_default(z_query_reply_del_options_t *options) { + options->congestion_control = Z_CONGESTION_CONTROL_DEFAULT; + options->priority = Z_PRIORITY_DEFAULT; + options->timestamp = NULL; + options->is_express = false; + options->attachment = NULL; } -int8_t z_query_reply(const z_query_t *query, const z_keyexpr_t keyexpr, const uint8_t *payload, size_t payload_len, - const z_query_reply_options_t *options) { - z_query_reply_options_t opts = options == NULL ? z_query_reply_options_default() : *options; - _z_value_t value = {.payload = - { - .start = payload, - ._is_alloc = false, - .len = payload_len, - }, - .encoding = {.prefix = opts.encoding.prefix, .suffix = opts.encoding.suffix}}; - return _z_send_reply(&query->_val._rc.in->val, keyexpr, value); - return _Z_ERR_GENERIC; +int8_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(&_Z_RC_IN_VAL(query)->_zn); + if (_Z_RC_IS_NULL(&sess_rc)) { + return _Z_ERR_CONNECTION_CLOSED; + } + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); + z_query_reply_del_options_t opts; + if (options == NULL) { + z_query_reply_del_options_default(&opts); + } else { + opts = *options; + } + + _z_value_t value = {.payload = _z_bytes_null(), .encoding = _z_encoding_null()}; + + int8_t ret = _z_send_reply(_Z_RC_IN_VAL(query), &sess_rc, 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; } -#endif -z_owned_keyexpr_t z_keyexpr_new(const char *name) { - z_owned_keyexpr_t key; +void z_query_reply_err_options_default(z_query_reply_err_options_t *options) { options->encoding = NULL; } - key._value = name ? (z_keyexpr_t *)z_malloc(sizeof(z_keyexpr_t)) : NULL; - if (key._value != NULL) { - *key._value = _z_rid_with_suffix(Z_RESOURCE_ID_NONE, name); +int8_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(&_Z_RC_IN_VAL(query)->_zn); + if (_Z_RC_IS_NULL(&sess_rc)) { + return _Z_ERR_CONNECTION_CLOSED; + } + z_query_reply_err_options_t opts; + if (options == NULL) { + z_query_reply_err_options_default(&opts); + } else { + opts = *options; } + // Set value + _z_value_t value = {.payload = _z_bytes_from_owned_bytes(&payload->_this), + .encoding = _z_encoding_from_owned(&opts.encoding->_this)}; + + int8_t ret = _z_send_reply_err(_Z_RC_IN_VAL(query), &sess_rc, value); + z_bytes_drop(payload); + // Clean-up + z_encoding_drop(opts.encoding); + return ret; +} +#endif - return key; +int8_t z_keyexpr_from_str_autocanonize(z_owned_keyexpr_t *key, const char *name) { + size_t len = strlen(name); + return z_keyexpr_from_substr_autocanonize(key, name, &len); } -z_owned_keyexpr_t z_declare_keyexpr(z_session_t zs, z_keyexpr_t keyexpr) { - z_owned_keyexpr_t key; +int8_t z_keyexpr_from_substr_autocanonize(z_owned_keyexpr_t *key, const char *name, size_t *len) { + z_internal_keyexpr_null(key); - key._value = (z_keyexpr_t *)z_malloc(sizeof(z_keyexpr_t)); - if (key._value != NULL) { - uint16_t id = _z_declare_resource(&zs._val.in->val, keyexpr); - *key._value = _z_rid_with_suffix(id, NULL); + // Copy the suffix + key->_val._suffix = _z_string_preallocate(*len); + if (!_z_keyexpr_has_suffix(&key->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } + memcpy((char *)_z_string_data(&key->_val._suffix), name, _z_string_len(&key->_val._suffix)); + // Canonize the suffix + _Z_CLEAN_RETURN_IF_ERR( + z_keyexpr_canonize((char *)_z_string_data(&key->_val._suffix), &key->_val._suffix._slice.len), + _z_keyexpr_clear(&key->_val)); + *len = _z_string_len(&key->_val._suffix); + return _Z_RES_OK; +} - return key; +int8_t z_keyexpr_from_str(z_owned_keyexpr_t *key, const char *name) { + return z_keyexpr_from_substr(key, name, strlen(name)); } -int8_t z_undeclare_keyexpr(z_session_t zs, z_owned_keyexpr_t *keyexpr) { +int8_t z_keyexpr_from_substr(z_owned_keyexpr_t *key, const char *name, size_t len) { + z_internal_keyexpr_null(key); + key->_val._suffix = _z_string_preallocate(len); + if (!_z_keyexpr_has_suffix(&key->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + memcpy((char *)_z_string_data(&key->_val._suffix), name, _z_string_len(&key->_val._suffix)); + return _Z_RES_OK; +} + +int8_t z_declare_keyexpr(z_owned_keyexpr_t *key, const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr) { + _z_keyexpr_t k = _z_keyexpr_alias_from_user_defined(*keyexpr, false); + uint16_t id = _z_declare_resource(_Z_RC_IN_VAL(zs), k); + key->_val = _z_rid_with_suffix(id, NULL); + // we still need to store the original suffix, for user needs + // (for example to compare keys or perform other operations on their string representation). + // Generally this breaks internal keyexpr representation, but is ok for user-defined keyexprs + // since they consist of 2 disjoint sets: either they have a non-nul suffix or non-trivial id/mapping. + // The resulting keyexpr can be separated later into valid internal keys using _z_keyexpr_alias_from_user_defined. + if (_z_keyexpr_has_suffix(keyexpr)) { + _Z_RETURN_IF_ERR(_z_string_copy(&key->_val._suffix, &keyexpr->_suffix)); + } + return _Z_RES_OK; +} + +int8_t z_undeclare_keyexpr(z_moved_keyexpr_t *keyexpr, const z_loaned_session_t *zs) { int8_t ret = _Z_RES_OK; - ret = _z_undeclare_resource(&zs._val.in->val, keyexpr->_value->_id); + ret = _z_undeclare_resource(_Z_RC_IN_VAL(zs), keyexpr->_this._val._id); z_keyexpr_drop(keyexpr); return ret; } #if Z_FEATURE_SUBSCRIPTION == 1 -OWNED_FUNCTIONS_PTR_COMMON(z_subscriber_t, z_owned_subscriber_t, subscriber) -OWNED_FUNCTIONS_PTR_CLONE(z_subscriber_t, z_owned_subscriber_t, subscriber, _z_owner_noop_copy) -void z_subscriber_drop(z_owned_subscriber_t *val) { z_undeclare_subscriber(val); } +int8_t _z_undeclare_and_clear_subscriber(_z_subscriber_t *sub) { + int8_t ret = _Z_RES_OK; + ret = _z_undeclare_subscriber(sub); + _z_subscriber_clear(sub); + return ret; +} -OWNED_FUNCTIONS_PTR_COMMON(z_pull_subscriber_t, z_owned_pull_subscriber_t, pull_subscriber) -OWNED_FUNCTIONS_PTR_CLONE(z_pull_subscriber_t, z_owned_pull_subscriber_t, pull_subscriber, _z_owner_noop_copy) -void z_pull_subscriber_drop(z_owned_pull_subscriber_t *val) { z_undeclare_pull_subscriber(val); } +void _z_subscriber_drop(_z_subscriber_t *sub) { _z_undeclare_and_clear_subscriber(sub); } -z_subscriber_options_t z_subscriber_options_default(void) { - return (z_subscriber_options_t){.reliability = Z_RELIABILITY_DEFAULT}; -} +_Z_OWNED_FUNCTIONS_VALUE_NO_COPY_IMPL(_z_subscriber_t, subscriber, _z_subscriber_check, _z_subscriber_null, + _z_subscriber_drop) -z_pull_subscriber_options_t z_pull_subscriber_options_default(void) { - return (z_pull_subscriber_options_t){.reliability = Z_RELIABILITY_DEFAULT}; +void z_subscriber_options_default(z_subscriber_options_t *options) { +#if Z_FEATURE_UNSTABLE_API == 1 + options->reliability = Z_RELIABILITY_DEFAULT; +#else + options->__dummy = 0; +#endif } -z_owned_subscriber_t z_declare_subscriber(z_session_t zs, z_keyexpr_t keyexpr, z_owned_closure_sample_t *callback, - const z_subscriber_options_t *options) { - void *ctx = callback->context; - callback->context = NULL; - char *suffix = NULL; +int8_t z_declare_subscriber(z_owned_subscriber_t *sub, const z_loaned_session_t *zs, const z_loaned_keyexpr_t *keyexpr, + z_moved_closure_sample_t *callback, const z_subscriber_options_t *options) { + void *ctx = callback->_this._val.context; + callback->_this._val.context = NULL; + + _z_keyexpr_t keyexpr_aliased = _z_keyexpr_alias_from_user_defined(*keyexpr, true); + _z_keyexpr_t key = _z_keyexpr_alias(keyexpr_aliased); - z_keyexpr_t key = keyexpr; // TODO: Currently, if resource declarations are done over multicast transports, the current protocol definition // lacks a way to convey them to later-joining nodes. Thus, in the current version automatic // resource declarations are only performed on unicast transports. - if (zs._val.in->val._tp._type == _Z_TRANSPORT_UNICAST_TYPE) { - _z_resource_t *r = _z_get_resource_by_key(&zs._val.in->val, &keyexpr); + if (_Z_RC_IN_VAL(zs)->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + _z_resource_t *r = _z_get_resource_by_key(_Z_RC_IN_VAL(zs), &keyexpr_aliased); if (r == NULL) { - char *wild = strpbrk(keyexpr._suffix, "*$"); _Bool do_keydecl = true; - if (wild != NULL && wild != keyexpr._suffix) { - wild -= 1; - size_t len = wild - keyexpr._suffix; - suffix = z_malloc(len + 1); - if (suffix != NULL) { - memcpy(suffix, keyexpr._suffix, len); - suffix[len] = 0; - keyexpr._suffix = suffix; - _z_keyexpr_set_owns_suffix(&keyexpr, false); - } else { - do_keydecl = false; + _z_keyexpr_t resource_key = _z_keyexpr_alias(keyexpr_aliased); + // Remove wild + char *wild = _z_string_pbrk(&keyexpr_aliased._suffix, "*$"); + if ((wild != NULL) && _z_keyexpr_has_suffix(&keyexpr_aliased)) { + wild = _z_ptr_char_offset(wild, -1); + size_t len = _z_ptr_char_diff(wild, _z_string_data(&keyexpr_aliased._suffix)); + resource_key._suffix = _z_string_preallocate(len); + + if (!_z_keyexpr_has_suffix(&resource_key)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } + memcpy((char *)_z_string_data(&resource_key._suffix), _z_string_data(&keyexpr_aliased._suffix), len); } + // Declare resource if (do_keydecl) { - uint16_t id = _z_declare_resource(&zs._val.in->val, keyexpr); + uint16_t id = _z_declare_resource(_Z_RC_IN_VAL(zs), resource_key); key = _z_rid_with_suffix(id, wild); } + _z_keyexpr_clear(&resource_key); } } - _z_subinfo_t subinfo = _z_subinfo_push_default(); + _z_subinfo_t subinfo = _z_subinfo_default(); if (options != NULL) { +#if Z_FEATURE_UNSTABLE_API == 1 subinfo.reliability = options->reliability; +#else + subinfo.reliability = Z_RELIABILITY_DEFAULT; +#endif } - _z_subscriber_t *sub = _z_declare_subscriber(&zs._val, key, subinfo, callback->call, callback->drop, ctx); - if (suffix != NULL) { - z_free(suffix); - } - - return (z_owned_subscriber_t){._value = sub}; -} + _z_subscriber_t int_sub = + _z_declare_subscriber(zs, key, subinfo, callback->_this._val.call, callback->_this._val.drop, ctx); -z_owned_pull_subscriber_t z_declare_pull_subscriber(z_session_t zs, z_keyexpr_t keyexpr, - z_owned_closure_sample_t *callback, - const z_pull_subscriber_options_t *options) { - (void)(options); - - void *ctx = callback->context; - callback->context = NULL; + z_internal_closure_sample_null(&callback->_this); + sub->_val = int_sub; - z_keyexpr_t key = keyexpr; - _z_resource_t *r = _z_get_resource_by_key(&zs._val.in->val, &keyexpr); - if (r == NULL) { - uint16_t id = _z_declare_resource(&zs._val.in->val, keyexpr); - key = _z_rid_with_suffix(id, NULL); - } - - _z_subinfo_t subinfo = _z_subinfo_pull_default(); - if (options != NULL) { - subinfo.reliability = options->reliability; + if (!_z_subscriber_check(&sub->_val)) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } else { + return _Z_RES_OK; } - - return (z_owned_pull_subscriber_t){ - ._value = _z_declare_subscriber(&zs._val, key, subinfo, callback->call, callback->drop, ctx)}; } -int8_t z_undeclare_subscriber(z_owned_subscriber_t *sub) { - int8_t ret = _Z_RES_OK; - - _z_undeclare_subscriber(sub->_value); - _z_subscriber_free(&sub->_value); - - return ret; -} - -int8_t z_undeclare_pull_subscriber(z_owned_pull_subscriber_t *sub) { - int8_t ret = _Z_RES_OK; +int8_t z_undeclare_subscriber(z_moved_subscriber_t *sub) { return _z_undeclare_and_clear_subscriber(&sub->_this._val); } - _z_undeclare_subscriber(sub->_value); - _z_subscriber_free(&sub->_value); - - return ret; -} - -int8_t z_subscriber_pull(const z_pull_subscriber_t sub) { return _z_subscriber_pull(sub._val); } - -z_owned_keyexpr_t z_subscriber_keyexpr(z_subscriber_t sub) { - z_owned_keyexpr_t ret = z_keyexpr_null(); - uint32_t lookup = sub._val->_entity_id; - if (sub._val != NULL) { - _z_subscription_rc_list_t *tail = sub._val->_zn.in->val._local_subscriptions; - while (tail != NULL && !z_keyexpr_check(&ret)) { - _z_subscription_rc_t *head = _z_subscription_rc_list_head(tail); - if (head->in->val._id == lookup) { - _z_keyexpr_t key = _z_keyexpr_duplicate(head->in->val._key); - ret = (z_owned_keyexpr_t){._value = z_malloc(sizeof(_z_keyexpr_t))}; - if (ret._value != NULL) { - *ret._value = key; - } else { - _z_keyexpr_clear(&key); - } - } - tail = _z_subscription_rc_list_tail(tail); +const z_loaned_keyexpr_t *z_subscriber_keyexpr(const z_loaned_subscriber_t *sub) { + // Retrieve keyexpr from session + uint32_t lookup = sub->_entity_id; + _z_subscription_rc_list_t *tail = _Z_RC_IN_VAL(&sub->_zn)->_local_subscriptions; + while (tail != NULL) { + _z_subscription_rc_t *head = _z_subscription_rc_list_head(tail); + if (_Z_RC_IN_VAL(head)->_id == lookup) { + return (const z_loaned_keyexpr_t *)&_Z_RC_IN_VAL(head)->_key; } + tail = _z_subscription_rc_list_tail(tail); } - return ret; + return NULL; } #endif /**************** Tasks ****************/ -zp_task_read_options_t zp_task_read_options_default(void) { - return (zp_task_read_options_t) { +void zp_task_read_options_default(zp_task_read_options_t *options) { #if Z_FEATURE_MULTI_THREAD == 1 - .task_attributes = NULL + options->task_attributes = NULL; #else - .__dummy = 0 + options->__dummy = 0; #endif - }; } -int8_t zp_start_read_task(z_session_t zs, const zp_task_read_options_t *options) { +int8_t zp_start_read_task(z_loaned_session_t *zs, const zp_task_read_options_t *options) { (void)(options); #if Z_FEATURE_MULTI_THREAD == 1 - zp_task_read_options_t opt = zp_task_read_options_default(); + zp_task_read_options_t opt; + zp_task_read_options_default(&opt); if (options != NULL) { opt.task_attributes = options->task_attributes; } - return _zp_start_read_task(&zs._val.in->val, opt.task_attributes); + return _zp_start_read_task(_Z_RC_IN_VAL(zs), opt.task_attributes); #else (void)(zs); return -1; #endif } -int8_t zp_stop_read_task(z_session_t zs) { +int8_t zp_stop_read_task(z_loaned_session_t *zs) { #if Z_FEATURE_MULTI_THREAD == 1 - return _zp_stop_read_task(&zs._val.in->val); + return _zp_stop_read_task(_Z_RC_IN_VAL(zs)); #else (void)(zs); return -1; #endif } -zp_task_lease_options_t zp_task_lease_options_default(void) { - return (zp_task_lease_options_t) { +void zp_task_lease_options_default(zp_task_lease_options_t *options) { #if Z_FEATURE_MULTI_THREAD == 1 - .task_attributes = NULL + options->task_attributes = NULL; #else - .__dummy = 0 + options->__dummy = 0; #endif - }; } -int8_t zp_start_lease_task(z_session_t zs, const zp_task_lease_options_t *options) { +int8_t zp_start_lease_task(z_loaned_session_t *zs, const zp_task_lease_options_t *options) { (void)(options); #if Z_FEATURE_MULTI_THREAD == 1 - zp_task_lease_options_t opt = zp_task_lease_options_default(); + zp_task_lease_options_t opt; + zp_task_lease_options_default(&opt); if (options != NULL) { opt.task_attributes = options->task_attributes; } - return _zp_start_lease_task(&zs._val.in->val, opt.task_attributes); + return _zp_start_lease_task(_Z_RC_IN_VAL(zs), opt.task_attributes); #else (void)(zs); return -1; #endif } -int8_t zp_stop_lease_task(z_session_t zs) { +int8_t zp_stop_lease_task(z_loaned_session_t *zs) { #if Z_FEATURE_MULTI_THREAD == 1 - return _zp_stop_lease_task(&zs._val.in->val); + return _zp_stop_lease_task(_Z_RC_IN_VAL(zs)); #else (void)(zs); return -1; #endif } -zp_read_options_t zp_read_options_default(void) { return (zp_read_options_t){.__dummy = 0}; } +void zp_read_options_default(zp_read_options_t *options) { options->__dummy = 0; } -int8_t zp_read(z_session_t zs, const zp_read_options_t *options) { +int8_t zp_read(const z_loaned_session_t *zs, const zp_read_options_t *options) { (void)(options); - return _zp_read(&zs._val.in->val); + return _zp_read(_Z_RC_IN_VAL(zs)); } -zp_send_keep_alive_options_t zp_send_keep_alive_options_default(void) { - return (zp_send_keep_alive_options_t){.__dummy = 0}; -} +void zp_send_keep_alive_options_default(zp_send_keep_alive_options_t *options) { options->__dummy = 0; } -int8_t zp_send_keep_alive(z_session_t zs, const zp_send_keep_alive_options_t *options) { +int8_t zp_send_keep_alive(const z_loaned_session_t *zs, const zp_send_keep_alive_options_t *options) { (void)(options); - return _zp_send_keep_alive(&zs._val.in->val); + return _zp_send_keep_alive(_Z_RC_IN_VAL(zs)); } -zp_send_join_options_t zp_send_join_options_default(void) { return (zp_send_join_options_t){.__dummy = 0}; } +void zp_send_join_options_default(zp_send_join_options_t *options) { options->__dummy = 0; } -int8_t zp_send_join(z_session_t zs, const zp_send_join_options_t *options) { +int8_t zp_send_join(const z_loaned_session_t *zs, const zp_send_join_options_t *options) { (void)(options); - return _zp_send_join(&zs._val.in->val); -} -#if Z_FEATURE_ATTACHMENT == 1 -void _z_bytes_pair_clear(struct _z_bytes_pair_t *this_) { - _z_bytes_clear(&this_->key); - _z_bytes_clear(&this_->value); -} - -z_attachment_t z_bytes_map_as_attachment(const z_owned_bytes_map_t *this_) { - if (!z_bytes_map_check(this_)) { - return z_attachment_null(); - } - return (z_attachment_t){.data = this_, .iteration_driver = (z_attachment_iter_driver_t)z_bytes_map_iter}; + return _zp_send_join(_Z_RC_IN_VAL(zs)); } -bool z_bytes_map_check(const z_owned_bytes_map_t *this_) { return this_->_inner != NULL; } -void z_bytes_map_drop(z_owned_bytes_map_t *this_) { _z_bytes_pair_list_free(&this_->_inner); } - -int8_t _z_bytes_map_insert_by_alias(z_bytes_t key, z_bytes_t value, void *this_) { - z_bytes_map_insert_by_alias((z_owned_bytes_map_t *)this_, key, value); - return 0; -} -int8_t _z_bytes_map_insert_by_copy(z_bytes_t key, z_bytes_t value, void *this_) { - z_bytes_map_insert_by_copy((z_owned_bytes_map_t *)this_, key, value); - return 0; -} -z_owned_bytes_map_t z_bytes_map_from_attachment(z_attachment_t this_) { - if (!z_attachment_check(&this_)) { - return z_bytes_map_null(); - } - z_owned_bytes_map_t map = z_bytes_map_new(); - z_attachment_iterate(this_, _z_bytes_map_insert_by_copy, &map); - return map; -} -z_owned_bytes_map_t z_bytes_map_from_attachment_aliasing(z_attachment_t this_) { - if (!z_attachment_check(&this_)) { - return z_bytes_map_null(); - } - z_owned_bytes_map_t map = z_bytes_map_new(); - z_attachment_iterate(this_, _z_bytes_map_insert_by_alias, &map); - return map; -} -z_bytes_t z_bytes_map_get(const z_owned_bytes_map_t *this_, z_bytes_t key) { - _z_bytes_pair_list_t *current = this_->_inner; - while (current) { - struct _z_bytes_pair_t *head = _z_bytes_pair_list_head(current); - if (_z_bytes_eq(&key, &head->key)) { - return _z_bytes_wrap(head->value.start, head->value.len); - } - } - return z_bytes_null(); -} -void z_bytes_map_insert_by_alias(const z_owned_bytes_map_t *this_, z_bytes_t key, z_bytes_t value) { - _z_bytes_pair_list_t *current = this_->_inner; - while (current) { - struct _z_bytes_pair_t *head = _z_bytes_pair_list_head(current); - if (_z_bytes_eq(&key, &head->key)) { - break; - } - current = _z_bytes_pair_list_tail(current); - } - if (current) { - struct _z_bytes_pair_t *head = _z_bytes_pair_list_head(current); - _z_bytes_clear(&head->value); - head->value = _z_bytes_wrap(value.start, value.len); - } else { - struct _z_bytes_pair_t *insert = z_malloc(sizeof(struct _z_bytes_pair_t)); - memset(insert, 0, sizeof(struct _z_bytes_pair_t)); - insert->key = _z_bytes_wrap(key.start, key.len); - insert->value = _z_bytes_wrap(value.start, value.len); - ((z_owned_bytes_map_t *)this_)->_inner = _z_bytes_pair_list_push(this_->_inner, insert); - } -} -void z_bytes_map_insert_by_copy(const z_owned_bytes_map_t *this_, z_bytes_t key, z_bytes_t value) { - _z_bytes_pair_list_t *current = this_->_inner; - while (current) { - struct _z_bytes_pair_t *head = _z_bytes_pair_list_head(current); - if (_z_bytes_eq(&key, &head->key)) { - break; - } - current = _z_bytes_pair_list_tail(current); - } - if (current) { - struct _z_bytes_pair_t *head = _z_bytes_pair_list_head(current); - _z_bytes_clear(&head->value); - _z_bytes_copy(&head->value, &value); - if (!head->key._is_alloc) { - _z_bytes_copy(&head->key, &key); - } - } else { - struct _z_bytes_pair_t *insert = z_malloc(sizeof(struct _z_bytes_pair_t)); - memset(insert, 0, sizeof(struct _z_bytes_pair_t)); - _z_bytes_copy(&insert->key, &key); - _z_bytes_copy(&insert->value, &value); - ((z_owned_bytes_map_t *)this_)->_inner = _z_bytes_pair_list_push(this_->_inner, insert); - } -} -int8_t z_bytes_map_iter(const z_owned_bytes_map_t *this_, z_attachment_iter_body_t body, void *ctx) { - _z_bytes_pair_list_t *current = this_->_inner; - while (current) { - struct _z_bytes_pair_t *head = _z_bytes_pair_list_head(current); - int8_t ret = body(head->key, head->value, ctx); - if (ret) { - return ret; - } - current = _z_bytes_pair_list_tail(current); - } - return 0; -} -z_owned_bytes_map_t z_bytes_map_new(void) { return (z_owned_bytes_map_t){._inner = _z_bytes_pair_list_new()}; } -z_owned_bytes_map_t z_bytes_map_null(void) { return (z_owned_bytes_map_t){._inner = NULL}; } -z_bytes_t z_bytes_from_str(const char *str) { return z_bytes_wrap((const uint8_t *)str, strlen(str)); } -z_bytes_t z_bytes_null(void) { return (z_bytes_t){.len = 0, ._is_alloc = false, .start = NULL}; } -#endif diff --git a/src/collections/arc_slice.c b/src/collections/arc_slice.c new file mode 100644 index 000000000..08a569edf --- /dev/null +++ b/src/collections/arc_slice.c @@ -0,0 +1,84 @@ +// +// Copyright (c) 2024 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/collections/arc_slice.h" + +#include +#include +#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); + if (_Z_RC_IS_NULL(&arc_s.slice)) { + return _z_arc_slice_empty(); + } + 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)); + + if (_Z_RC_IS_NULL(&s->slice)) { + return _z_arc_slice_empty(); + } + _z_arc_slice_t out; + out.slice = _z_slice_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; } + +int8_t _z_arc_slice_copy(_z_arc_slice_t* dst, const _z_arc_slice_t* src) { + _z_slice_rc_copy(&dst->slice, &src->slice); + dst->len = src->len; + dst->start = src->start; + return _Z_RES_OK; +} + +int8_t _z_arc_slice_move(_z_arc_slice_t* dst, _z_arc_slice_t* src) { + dst->slice = src->slice; + dst->len = src->len; + dst->start = src->start; + src->len = 0; + src->start = 0; + src->slice = _z_slice_rc_null(); + return _Z_RES_OK; +} + +int8_t _z_arc_slice_drop(_z_arc_slice_t* s) { + _z_slice_rc_drop(&s->slice); + *s = _z_arc_slice_empty(); + return _Z_RES_OK; +} diff --git a/src/collections/bytes.c b/src/collections/bytes.c index 40e67bd36..5c1759242 100644 --- a/src/collections/bytes.c +++ b/src/collections/bytes.c @@ -1,5 +1,5 @@ // -// Copyright (c) 2022 ZettaScale Technology +// Copyright (c) 2024 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 @@ -15,96 +15,481 @@ #include "zenoh-pico/collections/bytes.h" #include +#include #include +#include "zenoh-pico/api/olv_macros.h" +#include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/result.h" -/*-------- bytes --------*/ -_z_bytes_t _z_bytes_empty(void) { return (_z_bytes_t){.start = NULL, .len = 0, ._is_alloc = false}; } +/*-------- Bytes --------*/ +_Bool _z_bytes_check(const _z_bytes_t *bytes) { return !_z_bytes_is_empty(bytes); } -int8_t _z_bytes_init(_z_bytes_t *bs, size_t capacity) { - int8_t ret = _Z_RES_OK; +_z_bytes_t _z_bytes_null(void) { + _z_bytes_t b; + b._slices = _z_arc_slice_svec_make(0); + return b; +} - bs->start = (uint8_t *)z_malloc(capacity); - if (bs->start != NULL) { - bs->len = capacity; - bs->_is_alloc = true; +int8_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 { - bs->len = 0; - bs->_is_alloc = false; - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - - return ret; } -_z_bytes_t _z_bytes_make(size_t capacity) { - _z_bytes_t bs; - (void)_z_bytes_init(&bs, capacity); - return bs; +_z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { + _z_bytes_t dst = _z_bytes_null(); + _z_bytes_copy(&dst, src); + return dst; } -_z_bytes_t _z_bytes_wrap(const uint8_t *p, size_t len) { - _z_bytes_t bs; - bs.start = p; - bs.len = len; - bs._is_alloc = false; - return bs; +size_t _z_bytes_len(const _z_bytes_t *bs) { + size_t len = 0; + for (size_t i = 0; i < _z_arc_slice_svec_len(&bs->_slices); ++i) { + const _z_arc_slice_t *s = _z_arc_slice_svec_get(&bs->_slices, i); + len += _z_arc_slice_len(s); + } + return len; } -void _z_bytes_reset(_z_bytes_t *bs) { - bs->start = NULL; - bs->len = 0; - bs->_is_alloc = false; +_Bool _z_bytes_is_empty(const _z_bytes_t *bs) { + for (size_t i = 0; i < _z_arc_slice_svec_len(&bs->_slices); i++) { + const _z_arc_slice_t *s = _z_arc_slice_svec_get(&bs->_slices, i); + if (_z_arc_slice_len(s) > 0) return false; + } + return true; } -void _z_bytes_clear(_z_bytes_t *bs) { - if ((bs->_is_alloc == true) && (bs->start != NULL)) { - z_free((uint8_t *)bs->start); - } - _z_bytes_reset(bs); +size_t _z_bytes_num_slices(const _z_bytes_t *bs) { return _z_arc_slice_svec_len(&bs->_slices); } + +_z_arc_slice_t *_z_bytes_get_slice(const _z_bytes_t *bs, size_t i) { + if (i >= _z_bytes_num_slices(bs)) return NULL; + return _z_arc_slice_svec_get(&bs->_slices, i); } +void _z_bytes_drop(_z_bytes_t *bytes) { _z_arc_slice_svec_clear(&bytes->_slices); } + void _z_bytes_free(_z_bytes_t **bs) { _z_bytes_t *ptr = *bs; if (ptr != NULL) { - _z_bytes_clear(ptr); + _z_bytes_drop(ptr); z_free(ptr); *bs = NULL; } } -void _z_bytes_copy(_z_bytes_t *dst, const _z_bytes_t *src) { - int8_t ret = - _z_bytes_init(dst, src->len); // FIXME: it should check if dst is already initialized. Otherwise it will leak - if (ret == _Z_RES_OK) { - (void)memcpy((uint8_t *)dst->start, src->start, src->len); +size_t _z_bytes_to_buf(const _z_bytes_t *bytes, uint8_t *dst, size_t len) { + uint8_t *start = dst; + size_t remaining = len; + for (size_t i = 0; i < _z_bytes_num_slices(bytes) && remaining > 0; ++i) { + // Recopy data + _z_arc_slice_t *s = _z_bytes_get_slice(bytes, i); + size_t s_len = _z_arc_slice_len(s); + size_t len_to_copy = remaining >= s_len ? s_len : remaining; + memcpy(start, _z_arc_slice_data(s), len_to_copy); + start += len_to_copy; + remaining -= len_to_copy; + } + + return len - remaining; +} +int8_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; +} + +int8_t _z_bytes_from_buf(_z_bytes_t *b, const uint8_t *src, size_t len) { + *b = _z_bytes_null(); + _z_slice_t s = _z_slice_copy_from_buf(src, len); + if (s.len != len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + return _z_bytes_from_slice(b, s); +} + +int8_t _z_bytes_to_slice(const _z_bytes_t *bytes, _z_slice_t *s) { + // Allocate slice + size_t len = _z_bytes_len(bytes); + *s = _z_slice_make(len); + if (!_z_slice_check(s) && len > 0) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + uint8_t *start = (uint8_t *)s->start; + for (size_t i = 0; i < _z_bytes_num_slices(bytes); ++i) { + // Recopy data + _z_arc_slice_t *arc_s = _z_bytes_get_slice(bytes, i); + size_t s_len = _z_arc_slice_len(arc_s); + memcpy(start, _z_arc_slice_data(arc_s), s_len); + start += s_len; + } + + return _Z_RES_OK; +} + +int8_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; +} + +int8_t _z_bytes_append_bytes(_z_bytes_t *dst, _z_bytes_t *src) { + int8_t res = _Z_RES_OK; + for (size_t i = 0; i < _z_bytes_num_slices(src); ++i) { + _z_arc_slice_t s; + _z_arc_slice_move(&s, _z_bytes_get_slice(src, i)); + res = _z_bytes_append_slice(dst, &s); + if (res != _Z_RES_OK) { + break; + } + } + + _z_bytes_drop(src); + return res; +} + +int8_t _z_bytes_from_pair(_z_bytes_t *out, _z_bytes_t *first, _z_bytes_t *second) { + *out = _z_bytes_null(); + _z_bytes_iterator_writer_t writer = _z_bytes_get_iterator_writer(out, 0); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_iterator_writer_write(&writer, first), _z_bytes_drop(second)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_iterator_writer_write(&writer, second), _z_bytes_drop(out)); + + return _Z_RES_OK; +} + +int8_t _z_bytes_deserialize_into_pair(const _z_bytes_t *bs, _z_bytes_t *first_out, _z_bytes_t *second_out) { + _z_bytes_iterator_t iter = _z_bytes_get_iterator(bs); + int8_t res = _z_bytes_iterator_next(&iter, first_out); + if (res != _Z_RES_OK) return res; + res = _z_bytes_iterator_next(&iter, second_out); + if (res != _Z_RES_OK) { + _z_bytes_drop(first_out); + }; + return res; +} + +int8_t _z_bytes_to_uint8(const _z_bytes_t *bs, uint8_t *val) { + *val = 0; + return _z_bytes_to_buf(bs, val, sizeof(uint8_t)) == sizeof(uint8_t) ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_to_uint16(const _z_bytes_t *bs, uint16_t *val) { + *val = 0; + uint8_t buf[sizeof(uint16_t)] = {0}; + if (_z_bytes_to_buf(bs, buf, sizeof(uint16_t)) == 0) { + return _Z_ERR_DID_NOT_READ; + } + *val = _z_host_le_load16(buf); + return _Z_RES_OK; +} + +int8_t _z_bytes_to_uint32(const _z_bytes_t *bs, uint32_t *val) { + *val = 0; + uint8_t buf[sizeof(uint32_t)] = {0}; + if (_z_bytes_to_buf(bs, buf, sizeof(uint32_t)) == 0) { + return _Z_ERR_DID_NOT_READ; + } + *val = _z_host_le_load32(buf); + return _Z_RES_OK; +} + +int8_t _z_bytes_to_uint64(const _z_bytes_t *bs, uint64_t *val) { + *val = 0; + uint8_t buf[sizeof(uint64_t)] = {0}; + if (_z_bytes_to_buf(bs, buf, sizeof(uint64_t)) == 0) { + return _Z_ERR_DID_NOT_READ; + } + *val = _z_host_le_load64(buf); + return _Z_RES_OK; +} + +int8_t _z_bytes_to_float(const _z_bytes_t *bs, float *val) { + *val = 0; + return _z_bytes_to_buf(bs, (uint8_t *)val, sizeof(float)) == sizeof(float) ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_to_double(const _z_bytes_t *bs, double *val) { + *val = 0; + return _z_bytes_to_buf(bs, (uint8_t *)val, sizeof(double)) == sizeof(double) ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_from_uint8(_z_bytes_t *b, uint8_t val) { return _z_bytes_from_buf(b, &val, sizeof(val)); } + +int8_t _z_bytes_from_uint16(_z_bytes_t *b, uint16_t val) { + uint8_t buf[sizeof(uint16_t)]; + size_t len = _z_host_le_store16(val, buf); + return _z_bytes_from_buf(b, buf, len); +} + +int8_t _z_bytes_from_uint32(_z_bytes_t *b, uint32_t val) { + uint8_t buf[sizeof(uint32_t)]; + size_t len = _z_host_le_store32(val, buf); + return _z_bytes_from_buf(b, buf, len); +} + +int8_t _z_bytes_from_uint64(_z_bytes_t *b, uint64_t val) { + uint8_t buf[sizeof(uint64_t)]; + size_t len = _z_host_le_store64(val, buf); + return _z_bytes_from_buf(b, buf, len); +} + +int8_t _z_bytes_from_float(_z_bytes_t *b, float val) { return _z_bytes_from_buf(b, (uint8_t *)&val, sizeof(val)); } + +int8_t _z_bytes_from_double(_z_bytes_t *b, double val) { return _z_bytes_from_buf(b, (uint8_t *)&val, sizeof(val)); } + +_z_slice_t _z_bytes_try_get_contiguous(const _z_bytes_t *bs) { + if (_z_bytes_num_slices(bs) == 1) { + _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(); } void _z_bytes_move(_z_bytes_t *dst, _z_bytes_t *src) { - dst->start = src->start; - dst->len = src->len; - dst->_is_alloc = src->_is_alloc; + dst->_slices = src->_slices; + *src = _z_bytes_null(); +} - _z_bytes_reset(src); +_z_bytes_reader_t _z_bytes_get_reader(const _z_bytes_t *bytes) { + _z_bytes_reader_t r; + r.bytes = bytes; + r.slice_idx = 0; + r.byte_idx = 0; + r.in_slice_idx = 0; + return r; } -_z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { - _z_bytes_t dst; - _z_bytes_copy(&dst, src); - return dst; +int8_t _z_bytes_reader_seek_forward(_z_bytes_reader_t *reader, size_t offset) { + size_t start_slice = reader->slice_idx; + for (size_t i = start_slice; i < _z_bytes_num_slices(reader->bytes); ++i) { + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, i); + size_t remaining = _z_arc_slice_len(s) - reader->in_slice_idx; + if (offset >= remaining) { + reader->slice_idx += 1; + reader->in_slice_idx = 0; + reader->byte_idx += remaining; + offset -= remaining; + } else { + reader->in_slice_idx += offset; + reader->byte_idx += offset; + offset = 0; + } + if (offset == 0) break; + } + + if (offset > 0) return _Z_ERR_DID_NOT_READ; + return _Z_RES_OK; +} + +int8_t _z_bytes_reader_seek_backward(_z_bytes_reader_t *reader, size_t offset) { + while (offset != 0) { + if (reader->in_slice_idx == 0) { + if (reader->slice_idx == 0) return _Z_ERR_DID_NOT_READ; + reader->slice_idx--; + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, reader->slice_idx); + reader->in_slice_idx = _z_arc_slice_len(s); + } + + if (offset > reader->in_slice_idx) { + offset -= reader->in_slice_idx; + reader->byte_idx -= reader->in_slice_idx; + reader->in_slice_idx = 0; + } else { + reader->byte_idx -= offset; + reader->in_slice_idx -= offset; + offset = 0; + } + } + return _Z_RES_OK; +} + +int8_t _z_bytes_reader_seek(_z_bytes_reader_t *reader, int64_t offset, int origin) { + switch (origin) { + case SEEK_SET: { + reader->byte_idx = 0; + reader->in_slice_idx = 0; + reader->slice_idx = 0; + if (offset < 0) return _Z_ERR_DID_NOT_READ; + return _z_bytes_reader_seek_forward(reader, (size_t)offset); + } + case SEEK_CUR: { + if (offset >= 0) + return _z_bytes_reader_seek_forward(reader, (size_t)offset); + else + return _z_bytes_reader_seek_backward(reader, (size_t)(-offset)); + } + case SEEK_END: { + reader->byte_idx = _z_bytes_len(reader->bytes); + reader->in_slice_idx = 0; + reader->slice_idx = _z_bytes_num_slices(reader->bytes); + if (offset > 0) + return _Z_ERR_DID_NOT_READ; + else + return _z_bytes_reader_seek_backward(reader, (size_t)(-offset)); + } + default: + return _Z_ERR_GENERIC; + } +} + +int64_t _z_bytes_reader_tell(const _z_bytes_reader_t *reader) { return (int64_t)reader->byte_idx; } + +size_t _z_bytes_reader_read(_z_bytes_reader_t *reader, uint8_t *buf, size_t len) { + uint8_t *buf_start = buf; + size_t to_read = len; + for (size_t i = reader->slice_idx; i < _z_bytes_num_slices(reader->bytes); ++i) { + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, i); + size_t remaining = _z_arc_slice_len(s) - reader->in_slice_idx; + if (len >= remaining) { + memcpy(buf_start, _z_arc_slice_data(s) + reader->in_slice_idx, remaining); + reader->slice_idx += 1; + reader->in_slice_idx = 0; + reader->byte_idx += remaining; + len -= remaining; + buf_start += remaining; + } else { + memcpy(buf_start, _z_arc_slice_data(s) + reader->in_slice_idx, len); + reader->in_slice_idx += len; + reader->byte_idx += len; + len = 0; + } + if (len == 0) break; + } + + return to_read - len; +} + +int8_t __read_single_byte(uint8_t *b, void *context) { + _z_bytes_reader_t *reader = (_z_bytes_reader_t *)context; + return _z_bytes_reader_read(reader, b, 1) == 1 ? _Z_RES_OK : _Z_ERR_DID_NOT_READ; +} + +int8_t _z_bytes_reader_read_zint(_z_bytes_reader_t *reader, _z_zint_t *zint) { + return _z_zsize_decode_with_reader(zint, __read_single_byte, reader); +} + +int8_t _z_bytes_reader_read_slices(_z_bytes_reader_t *reader, size_t len, _z_bytes_t *out) { + *out = _z_bytes_null(); + int8_t res = _Z_RES_OK; + + for (size_t i = reader->slice_idx; i < _z_bytes_num_slices(reader->bytes) && len > 0; ++i) { + _z_arc_slice_t *s = _z_bytes_get_slice(reader->bytes, i); + size_t s_len = _z_arc_slice_len(s); + + size_t remaining = s_len - reader->in_slice_idx; + size_t len_to_copy = remaining > len ? len : remaining; + _z_arc_slice_t ss = _z_arc_slice_get_subslice(s, reader->in_slice_idx, len_to_copy); + reader->in_slice_idx += len_to_copy; + reader->byte_idx += len_to_copy; + if (reader->in_slice_idx == s_len) { + reader->slice_idx++; + reader->in_slice_idx = 0; + } + + if (_Z_RC_IS_NULL(&ss.slice)) { + res = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + break; + } + + res = _z_bytes_append_slice(out, &ss); + if (res != _Z_RES_OK) { + _z_arc_slice_drop(&ss); + break; + } + len -= len_to_copy; + } + + if (len > 0 && res == _Z_RES_OK) res = _Z_ERR_DID_NOT_READ; + if (res != _Z_RES_OK) _z_bytes_drop(out); + + return res; } -_Bool _z_bytes_is_empty(const _z_bytes_t *bs) { return bs->len == 0; } -_z_bytes_t _z_bytes_steal(_z_bytes_t *b) { - _z_bytes_t ret = *b; - *b = _z_bytes_empty(); - return ret; +_z_bytes_iterator_t _z_bytes_get_iterator(const _z_bytes_t *bytes) { + return (_z_bytes_iterator_t){._reader = _z_bytes_get_reader(bytes)}; } -_Bool _z_bytes_eq(const _z_bytes_t *left, const _z_bytes_t *right) { - return left->len == right->len && memcmp(left->start, right->start, left->len) == 0; + +int8_t _z_bytes_iterator_next(_z_bytes_iterator_t *iter, _z_bytes_t *b) { + *b = _z_bytes_null(); + _z_zint_t len; + if (_z_bytes_reader_read_zint(&iter->_reader, &len) != _Z_RES_OK) { + return _Z_ERR_DID_NOT_READ; + } + return _z_bytes_reader_read_slices(&iter->_reader, len, b); +} + +_z_bytes_writer_t _z_bytes_get_writer(_z_bytes_t *bytes, size_t cache_size) { + return (_z_bytes_writer_t){.cache = NULL, .cache_size = cache_size, .bytes = bytes}; +} + +int8_t _z_bytes_writer_ensure_cache(_z_bytes_writer_t *writer) { + // first we check if cache stayed untouched since previous write operation + if (writer->cache != NULL) { + _z_arc_slice_t *arc_s = _z_bytes_get_slice(writer->bytes, _z_bytes_num_slices(writer->bytes) - 1); + if (_Z_RC_IN_VAL(&arc_s->slice)->start + arc_s->len == writer->cache) { + if (_Z_RC_IN_VAL(&arc_s->slice)->len > arc_s->len) return _Z_RES_OK; + } + } + // otherwise we allocate a new cache + assert(writer->cache_size > 0); + _z_slice_t s = _z_slice_make(writer->cache_size); + if (s.start == NULL) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + _z_arc_slice_t cache = _z_arc_slice_wrap(s, 0, 0); + if (_Z_RC_IS_NULL(&cache.slice)) { + _z_slice_clear(&s); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_append_slice(writer->bytes, &cache), _z_arc_slice_drop(&cache)); + writer->cache = (uint8_t *)_Z_RC_IN_VAL(&cache.slice)->start; + return _Z_RES_OK; +} + +int8_t _z_bytes_writer_write_all(_z_bytes_writer_t *writer, const uint8_t *src, size_t len) { + if (writer->cache_size == 0) { // no cache - append data as a single slice + _z_slice_t s = _z_slice_copy_from_buf(src, len); + if (s.len != len) return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + _z_arc_slice_t arc_s = _z_arc_slice_wrap(s, 0, len); + if (_Z_RC_IS_NULL(&arc_s.slice)) { + _z_slice_clear(&s); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + return _z_bytes_append_slice(writer->bytes, &arc_s); + } + + while (len > 0) { + _Z_RETURN_IF_ERR(_z_bytes_writer_ensure_cache(writer)); + _z_arc_slice_t *arc_s = _z_bytes_get_slice(writer->bytes, _z_bytes_num_slices(writer->bytes) - 1); + size_t remaining_in_cache = _Z_RC_IN_VAL(&arc_s->slice)->len - arc_s->len; + size_t to_copy = remaining_in_cache < len ? remaining_in_cache : len; + memcpy(writer->cache, src, to_copy); + len -= to_copy; + arc_s->len += to_copy; + src += to_copy; + writer->cache += to_copy; + } + return _Z_RES_OK; +} + +int8_t _z_bytes_writer_append(_z_bytes_writer_t *writer, _z_bytes_t *src) { + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_append_bytes(writer->bytes, src), _z_bytes_drop(src)); + writer->cache = NULL; + return _Z_RES_OK; +} + +_z_bytes_iterator_writer_t _z_bytes_get_iterator_writer(_z_bytes_t *bytes, size_t cache_size) { + return (_z_bytes_iterator_writer_t){.writer = _z_bytes_get_writer(bytes, cache_size)}; +} + +int8_t _z_bytes_iterator_writer_write(_z_bytes_iterator_writer_t *writer, _z_bytes_t *src) { + uint8_t l_buf[16]; + size_t l_len = _z_zsize_encode_buf(l_buf, _z_bytes_len(src)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_writer_write_all(&writer->writer, l_buf, l_len), _z_bytes_drop(src)); + return _z_bytes_writer_append(&writer->writer, src); } diff --git a/src/collections/fifo.c b/src/collections/fifo.c new file mode 100644 index 000000000..914cf2752 --- /dev/null +++ b/src/collections/fifo.c @@ -0,0 +1,53 @@ +// +// 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/collections/fifo.h" + +#include +#include +#include + +/*-------- fifo --------*/ +int8_t _z_fifo_init(_z_fifo_t *r, size_t capacity) { + _z_ring_init(&r->_ring, capacity); + return 0; +} + +_z_fifo_t _z_fifo_make(size_t capacity) { + _z_fifo_t v; + _z_fifo_init(&v, capacity); + return v; +} + +size_t _z_fifo_capacity(const _z_fifo_t *r) { return _z_ring_capacity(&r->_ring); } +size_t _z_fifo_len(const _z_fifo_t *r) { return _z_ring_len(&r->_ring); } +bool _z_fifo_is_empty(const _z_fifo_t *r) { return _z_ring_is_empty(&r->_ring); } +bool _z_fifo_is_full(const _z_fifo_t *r) { return _z_fifo_len(r) == _z_fifo_capacity(r); } + +void *_z_fifo_push(_z_fifo_t *r, void *e) { return _z_ring_push(&r->_ring, e); } +void _z_fifo_push_drop(_z_fifo_t *r, void *e, z_element_free_f free_f) { + void *ret = _z_fifo_push(r, e); + if (ret != NULL) { + free_f(&ret); + } +} +void *_z_fifo_pull(_z_fifo_t *r) { return _z_ring_pull(&r->_ring); } +void _z_fifo_clear(_z_fifo_t *r, z_element_free_f free_f) { _z_ring_clear(&r->_ring, free_f); } +void _z_fifo_free(_z_fifo_t **r, z_element_free_f free_f) { + _z_fifo_t *ptr = (_z_fifo_t *)*r; + if (ptr != NULL) { + _z_fifo_clear(ptr, free_f); + z_free(ptr); + *r = NULL; + } +} diff --git a/src/collections/fifo_mt.c b/src/collections/fifo_mt.c new file mode 100644 index 000000000..a7377d91c --- /dev/null +++ b/src/collections/fifo_mt.c @@ -0,0 +1,159 @@ +// +// Copyright (c) 2024 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/collections/fifo_mt.h" + +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/utils/logging.h" + +/*-------- Fifo Buffer Multithreaded --------*/ +int8_t _z_fifo_mt_init(_z_fifo_mt_t *fifo, size_t capacity) { + _Z_RETURN_IF_ERR(_z_fifo_init(&fifo->_fifo, capacity)) + fifo->is_closed = false; + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_init(&fifo->_mutex)) + _Z_RETURN_IF_ERR(_z_condvar_init(&fifo->_cv_not_full)) + _Z_RETURN_IF_ERR(_z_condvar_init(&fifo->_cv_not_empty)) +#endif + + return _Z_RES_OK; +} + +_z_fifo_mt_t *_z_fifo_mt_new(size_t capacity) { + _z_fifo_mt_t *fifo = (_z_fifo_mt_t *)z_malloc(sizeof(_z_fifo_mt_t)); + if (fifo == NULL) { + _Z_ERROR("z_malloc failed"); + return NULL; + } + + int8_t ret = _z_fifo_mt_init(fifo, capacity); + if (ret != _Z_RES_OK) { + _Z_ERROR("_z_fifo_mt_init failed: %i", ret); + z_free(fifo); + return NULL; + } + + return fifo; +} + +void _z_fifo_mt_clear(_z_fifo_mt_t *fifo, z_element_free_f free_f) { +#if Z_FEATURE_MULTI_THREAD == 1 + _z_mutex_drop(&fifo->_mutex); + _z_condvar_drop(&fifo->_cv_not_full); + _z_condvar_drop(&fifo->_cv_not_empty); +#endif + + _z_fifo_clear(&fifo->_fifo, free_f); +} + +void _z_fifo_mt_free(_z_fifo_mt_t *fifo, z_element_free_f free_f) { + _z_fifo_mt_clear(fifo, free_f); + z_free(fifo); +} + +int8_t _z_fifo_mt_push(const void *elem, void *context, z_element_free_f element_free) { + _ZP_UNUSED(element_free); + if (elem == NULL || context == NULL) { + return _Z_ERR_GENERIC; + } + + _z_fifo_mt_t *f = (_z_fifo_mt_t *)context; + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_lock(&f->_mutex)) + while (elem != NULL) { + elem = _z_fifo_push(&f->_fifo, (void *)elem); + if (elem != NULL) { + _Z_RETURN_IF_ERR(_z_condvar_wait(&f->_cv_not_full, &f->_mutex)) + } else { + _Z_RETURN_IF_ERR(_z_condvar_signal(&f->_cv_not_empty)) + } + } + _Z_RETURN_IF_ERR(_z_mutex_unlock(&f->_mutex)) +#else // Z_FEATURE_MULTI_THREAD == 1 + _z_fifo_push_drop(&f->_fifo, (void *)elem, element_free); +#endif // Z_FEATURE_MULTI_THREAD == 1 + + return _Z_RES_OK; +} + +int8_t _z_fifo_mt_close(_z_fifo_mt_t *fifo) { +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_lock(&fifo->_mutex)) + fifo->is_closed = true; + _Z_RETURN_IF_ERR(_z_condvar_signal_all(&fifo->_cv_not_empty)) + _Z_RETURN_IF_ERR(_z_mutex_unlock(&fifo->_mutex)) +#else + fifo->is_closed = true; +#endif + return _Z_RES_OK; +} + +int8_t _z_fifo_mt_pull(void *dst, void *context, z_element_move_f element_move) { + _z_fifo_mt_t *f = (_z_fifo_mt_t *)context; + +#if Z_FEATURE_MULTI_THREAD == 1 + void *src = NULL; + _Z_RETURN_IF_ERR(_z_mutex_lock(&f->_mutex)) + while (src == NULL) { + src = _z_fifo_pull(&f->_fifo); + if (src == NULL) { + if (f->is_closed) break; + _Z_RETURN_IF_ERR(_z_condvar_wait(&f->_cv_not_empty, &f->_mutex)) + } else { + _Z_RETURN_IF_ERR(_z_condvar_signal(&f->_cv_not_full)) + } + } + _Z_RETURN_IF_ERR(_z_mutex_unlock(&f->_mutex)) + if (f->is_closed && src == NULL) return _Z_RES_CHANNEL_CLOSED; + element_move(dst, src); +#else // Z_FEATURE_MULTI_THREAD == 1 + void *src = _z_fifo_pull(&f->_fifo); + if (src != NULL) { + element_move(dst, src); + } else if (f->is_closed) { + return _Z_RES_CHANNEL_CLOSED; + } +#endif // Z_FEATURE_MULTI_THREAD == 1 + + return _Z_RES_OK; +} + +int8_t _z_fifo_mt_try_pull(void *dst, void *context, z_element_move_f element_move) { + _z_fifo_mt_t *f = (_z_fifo_mt_t *)context; + +#if Z_FEATURE_MULTI_THREAD == 1 + void *src = NULL; + _Z_RETURN_IF_ERR(_z_mutex_lock(&f->_mutex)) + src = _z_fifo_pull(&f->_fifo); + if (src != NULL) { + _Z_RETURN_IF_ERR(_z_condvar_signal(&f->_cv_not_full)) + } + _Z_RETURN_IF_ERR(_z_mutex_unlock(&f->_mutex)) +#else // Z_FEATURE_MULTI_THREAD == 1 + void *src = _z_fifo_pull(&f->_fifo); +#endif // Z_FEATURE_MULTI_THREAD == 1 + + if (src != NULL) { + element_move(dst, src); + } else if (f->is_closed) { + return _Z_RES_CHANNEL_CLOSED; + } else { + return _Z_RES_CHANNEL_NODATA; + } + + return _Z_RES_OK; +} diff --git a/src/collections/intmap.c b/src/collections/intmap.c index 5abeab4f7..5e78dee3e 100644 --- a/src/collections/intmap.c +++ b/src/collections/intmap.c @@ -14,6 +14,7 @@ #include "zenoh-pico/collections/intmap.h" +#include #include #include @@ -49,6 +50,39 @@ size_t _z_int_void_map_len(const _z_int_void_map_t *map) { return len; } +int8_t _z_int_void_map_copy(_z_int_void_map_t *dst, const _z_int_void_map_t *src, z_element_clone_f f_c) { + assert((dst != NULL) && (src != NULL) && (dst->_capacity == src->_capacity)); + for (size_t idx = 0; idx < src->_capacity; idx++) { + const _z_list_t *src_list = src->_vals[idx]; + if (src_list == NULL) { + continue; + } + // Allocate entry + dst->_vals[idx] = _z_list_clone(src_list, f_c); + if (dst->_vals[idx] == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + } + return _Z_RES_OK; +} + +_z_int_void_map_t _z_int_void_map_clone(const _z_int_void_map_t *src, z_element_clone_f f_c, z_element_free_f f_f) { + _z_int_void_map_t dst = {._capacity = src->_capacity, ._vals = NULL}; + // Lazily allocate and initialize to NULL all the pointers + size_t len = dst._capacity * sizeof(_z_list_t *); + dst._vals = (_z_list_t **)z_malloc(len); + if (dst._vals == NULL) { + return dst; + } + (void)memset(dst._vals, 0, len); + // Copy elements + if (_z_int_void_map_copy(&dst, src, f_c) != _Z_RES_OK) { + // Free the map + _z_int_void_map_clear(&dst, f_f); + } + return dst; +} + _Bool _z_int_void_map_is_empty(const _z_int_void_map_t *map) { return _z_int_void_map_len(map) == (size_t)0; } void _z_int_void_map_remove(_z_int_void_map_t *map, size_t k, z_element_free_f f) { diff --git a/src/collections/lifo.c b/src/collections/lifo.c new file mode 100644 index 000000000..4f31a22cf --- /dev/null +++ b/src/collections/lifo.c @@ -0,0 +1,90 @@ +// +// 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/collections/lifo.h" + +#include +#include +#include + +/*-------- lifo --------*/ +int8_t _z_lifo_init(_z_lifo_t *r, size_t capacity) { + memset(r, 0, sizeof(_z_lifo_t)); + if (capacity != (size_t)0) { + r->_val = (void **)z_malloc(sizeof(void *) * capacity); + } + if (r->_val != NULL) { + memset(r->_val, 0, capacity); + r->_capacity = capacity; + } + return 0; +} + +_z_lifo_t _z_lifo_make(size_t capacity) { + _z_lifo_t v; + _z_lifo_init(&v, capacity); + return v; +} + +size_t _z_lifo_capacity(const _z_lifo_t *r) { return r->_capacity; } +size_t _z_lifo_len(const _z_lifo_t *r) { return r->_len; } +_Bool _z_lifo_is_empty(const _z_lifo_t *r) { return r->_len == 0; } +_Bool _z_lifo_is_full(const _z_lifo_t *r) { return r->_len == r->_capacity; } + +void *_z_lifo_push(_z_lifo_t *r, void *e) { + void *ret = e; + if (!_z_lifo_is_full(r)) { + r->_val[r->_len] = e; + r->_len++; + ret = NULL; + } + return ret; +} + +void _z_lifo_push_drop(_z_lifo_t *r, void *e, z_element_free_f free_f) { + void *ret = _z_lifo_push(r, e); + if (ret != NULL) { + free_f(&ret); + } +} + +void *_z_lifo_pull(_z_lifo_t *r) { + void *ret = NULL; + if (!_z_lifo_is_empty(r)) { + r->_len--; + ret = r->_val[r->_len]; + } + return ret; +} + +void _z_lifo_clear(_z_lifo_t *r, z_element_free_f free_f) { + void *e = _z_lifo_pull(r); + while (e != NULL) { + free_f(&e); + e = _z_lifo_pull(r); + } + z_free(r->_val); + + r->_val = NULL; + r->_capacity = (size_t)0; + r->_len = (size_t)0; +} + +void _z_lifo_free(_z_lifo_t **r, z_element_free_f free_f) { + _z_lifo_t *ptr = (_z_lifo_t *)*r; + if (ptr != NULL) { + _z_lifo_clear(ptr, free_f); + z_free(ptr); + *r = NULL; + } +} diff --git a/src/collections/refcount.c b/src/collections/refcount.c new file mode 100644 index 000000000..d7e44f548 --- /dev/null +++ b/src/collections/refcount.c @@ -0,0 +1,221 @@ +// +// Copyright (c) 2024 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/collections/refcount.h" + +#include "zenoh-pico/utils/logging.h" + +#define _Z_RC_MAX_COUNT INT32_MAX // Based on Rust lazy overflow check + +#if Z_FEATURE_MULTI_THREAD == 1 +#if ZENOH_C_STANDARD != 99 + +#ifndef __cplusplus +#include +#define _z_atomic(X) _Atomic X +#define _z_atomic_store_explicit atomic_store_explicit +#define _z_atomic_fetch_add_explicit atomic_fetch_add_explicit +#define _z_atomic_fetch_sub_explicit atomic_fetch_sub_explicit +#define _z_atomic_load_explicit atomic_load_explicit +#define _z_atomic_compare_exchange_strong atomic_compare_exchange_strong +#define _z_atomic_compare_exchange_weak_explicit atomic_compare_exchange_weak_explicit +#define _z_memory_order_acquire memory_order_acquire +#define _z_memory_order_release memory_order_release +#define _z_memory_order_relaxed memory_order_relaxed +#else +#include +#define _z_atomic(X) std::atomic +#define _z_atomic_store_explicit std::atomic_store_explicit +#define _z_atomic_fetch_add_explicit std::atomic_fetch_add_explicit +#define _z_atomic_fetch_sub_explicit std::atomic_fetch_sub_explicit +#define _z_atomic_load_explicit std::atomic_load_explicit +#define _z_atomic_compare_exchange_strong std::atomic_compare_exchange_strong +#define _z_atomic_compare_exchange_weak_explicit std::atomic_compare_exchange_weak_explicit +#define _z_memory_order_acquire std::memory_order_acquire +#define _z_memory_order_release std::memory_order_release +#define _z_memory_order_relaxed std::memory_order_relaxed +#endif // __cplusplus + +// 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_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) \ + _z_atomic_fetch_add_explicit(&(p)->_weak_cnt, (unsigned int)1, _z_memory_order_relaxed) >= x +#define _ZP_RC_OP_DECR_AND_CMP_STRONG(p, x) \ + _z_atomic_fetch_sub_explicit(&(p)->_strong_cnt, (unsigned int)1, _z_memory_order_release) > (unsigned int)x +#define _ZP_RC_OP_DECR_AND_CMP_WEAK(p, x) \ + _z_atomic_fetch_sub_explicit(&(p)->_weak_cnt, (unsigned int)1, _z_memory_order_release) > (unsigned int)x +#define _ZP_RC_OP_CHECK_STRONG_CNT(p, x) _z_atomic_compare_exchange_strong(&(p)->_strong_cnt, &x, x) +#define _ZP_RC_OP_SYNC atomic_thread_fence(_z_memory_order_acquire); +#define _ZP_RC_OP_UPGRADE_CAS_LOOP \ + int8_t _upgrade(_z_inner_rc_t* cnt) { \ + unsigned int prev = _z_atomic_load_explicit(&cnt->_strong_cnt, _z_memory_order_relaxed); \ + while ((prev != 0) && (prev < _Z_RC_MAX_COUNT)) { \ + if (_z_atomic_compare_exchange_weak_explicit(&cnt->_strong_cnt, &prev, prev + 1, _z_memory_order_acquire, \ + _z_memory_order_relaxed)) { \ + if (_ZP_RC_OP_INCR_AND_CMP_WEAK(cnt, _Z_RC_MAX_COUNT)) { \ + _Z_ERROR("Rc weak count overflow"); \ + return _Z_ERR_OVERFLOW; \ + } \ + return _Z_RES_OK; \ + } \ + } \ + return _Z_ERR_INVALID; \ + } + +#else // ZENOH_C_STANDARD == 99 +#ifdef ZENOH_COMPILER_GCC + +// c99 gcc sync builtin variant +#define _ZP_RC_CNT_TYPE unsigned int +#define _ZP_RC_OP_INIT_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)->_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 +#define _ZP_RC_OP_DECR_AND_CMP_STRONG(p, x) __sync_fetch_and_sub(&(p)->_strong_cnt, (unsigned int)1) > (unsigned int)x +#define _ZP_RC_OP_DECR_AND_CMP_WEAK(p, x) __sync_fetch_and_sub(&(p)->_weak_cnt, (unsigned int)1) > (unsigned int)x +#define _ZP_RC_OP_CHECK_STRONG_CNT(p, x) __sync_bool_compare_and_swap(&(p)->_strong_cnt, x, x) +#define _ZP_RC_OP_SYNC __sync_synchronize(); +#define _ZP_RC_OP_UPGRADE_CAS_LOOP \ + int8_t _upgrade(_z_inner_rc_t* cnt) { \ + unsigned int prev = __sync_fetch_and_add(&cnt->_strong_cnt, (unsigned int)0); \ + while ((prev != 0) && (prev < _Z_RC_MAX_COUNT)) { \ + if (__sync_bool_compare_and_swap(&cnt->_strong_cnt, prev, prev + 1)) { \ + if (_ZP_RC_OP_INCR_AND_CMP_WEAK(cnt, _Z_RC_MAX_COUNT)) { \ + _Z_ERROR("Rc weak count overflow"); \ + return _Z_ERR_OVERFLOW; \ + } \ + \ + return _Z_RES_OK; \ + } else { \ + prev = __sync_fetch_and_add(&cnt->_strong_cnt, (unsigned int)0); \ + } \ + } \ + return _Z_ERR_INVALID; \ + } + +#else // !ZENOH_COMPILER_GCC + +// 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_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) +#define _ZP_RC_OP_DECR_AND_CMP_WEAK(p, x) (x == 0) +#define _ZP_RC_OP_CHECK_STRONG_CNT(p, x) (x == 0) && (p != NULL) +#define _ZP_RC_OP_SYNC +#define _ZP_RC_OP_UPGRADE_CAS_LOOP \ + int8_t _upgrade(_z_inner_rc_t* cnt) { \ + (void)cnt; \ + return _Z_ERR_INVALID; \ + } + +#endif // ZENOH_COMPILER_GCC +#endif // ZENOH_C_STANDARD != 99 +#else // Z_FEATURE_MULTI_THREAD == 0 + +// 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_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 +#define _ZP_RC_OP_DECR_AND_CMP_WEAK(p, x) p->_weak_cnt-- > (unsigned int)x +#define _ZP_RC_OP_CHECK_STRONG_CNT(p, x) (p->_strong_cnt == x) +#define _ZP_RC_OP_SYNC +#define _ZP_RC_OP_UPGRADE_CAS_LOOP \ + int8_t _upgrade(_z_inner_rc_t* cnt) { \ + if ((cnt->_strong_cnt != 0) && (cnt->_strong_cnt < _Z_RC_MAX_COUNT)) { \ + if (_ZP_RC_OP_INCR_AND_CMP_WEAK(cnt, _Z_RC_MAX_COUNT)) { \ + _Z_ERROR("Rc weak count overflow"); \ + return _Z_ERR_OVERFLOW; \ + } \ + _ZP_RC_OP_INCR_STRONG_CNT(cnt) \ + return _Z_RES_OK; \ + } \ + return _Z_ERR_OVERFLOW; \ + } + +#endif // Z_FEATURE_MULTI_THREAD == 1 + +typedef struct { + _ZP_RC_CNT_TYPE _strong_cnt; + _ZP_RC_CNT_TYPE _weak_cnt; +} _z_inner_rc_t; + +int8_t _z_rc_init(void** cnt) { + *cnt = z_malloc(sizeof(_z_inner_rc_t)); + if ((*cnt) == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _ZP_RC_OP_INIT_CNT((_z_inner_rc_t*)*cnt) + return _Z_RES_OK; +} + +int8_t _z_rc_increase_strong(void* cnt) { + _z_inner_rc_t* c = (_z_inner_rc_t*)cnt; + if (_ZP_RC_OP_INCR_AND_CMP_WEAK(c, _Z_RC_MAX_COUNT)) { + _Z_ERROR("Rc weak count overflow"); + return _Z_ERR_OVERFLOW; + } + _ZP_RC_OP_INCR_STRONG_CNT(c); + return _Z_RES_OK; +} + +int8_t _z_rc_increase_weak(void* cnt) { + _z_inner_rc_t* c = (_z_inner_rc_t*)cnt; + if (_ZP_RC_OP_INCR_AND_CMP_WEAK(c, _Z_RC_MAX_COUNT)) { + _Z_ERROR("Rc weak count overflow"); + return _Z_ERR_OVERFLOW; + } + return _Z_RES_OK; +} + +_Bool _z_rc_decrease_strong(void** cnt) { + _z_inner_rc_t* c = (_z_inner_rc_t*)*cnt; + if (_ZP_RC_OP_DECR_AND_CMP_STRONG(c, 1)) { + return _z_rc_decrease_weak(cnt); + } + return _z_rc_decrease_weak(cnt); +} + +_Bool _z_rc_decrease_weak(void** cnt) { + _z_inner_rc_t* c = (_z_inner_rc_t*)*cnt; + if (_ZP_RC_OP_DECR_AND_CMP_WEAK(c, 1)) { + return false; + } + _ZP_RC_OP_SYNC + z_free(*cnt); + *cnt = NULL; + return true; +} + +_ZP_RC_OP_UPGRADE_CAS_LOOP + +int8_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; } diff --git a/src/collections/ring.c b/src/collections/ring.c new file mode 100644 index 000000000..66adb6c89 --- /dev/null +++ b/src/collections/ring.c @@ -0,0 +1,115 @@ +// +// 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/collections/ring.h" + +#include +#include +#include + +/*-------- ring --------*/ +int8_t _z_ring_init(_z_ring_t *r, size_t capacity) { + // We need one more element to differentiate wether the ring is empty or full + capacity++; + + memset(r, 0, sizeof(_z_ring_t)); + if (capacity != (size_t)0) { + r->_val = (void **)z_malloc(sizeof(void *) * capacity); + } + if (r->_val != NULL) { + memset(r->_val, 0, capacity); + r->_capacity = capacity; + } + return 0; +} + +_z_ring_t _z_ring_make(size_t capacity) { + _z_ring_t v; + _z_ring_init(&v, capacity); + return v; +} + +size_t _z_ring_capacity(const _z_ring_t *r) { return r->_capacity - (size_t)1; } + +size_t _z_ring_len(const _z_ring_t *r) { + if (r->_w_idx >= r->_r_idx) { + return r->_w_idx - r->_r_idx; + } else { + return r->_w_idx + (r->_capacity - r->_r_idx); + } +} + +bool _z_ring_is_empty(const _z_ring_t *r) { return r->_w_idx == r->_r_idx; } + +bool _z_ring_is_full(const _z_ring_t *r) { return _z_ring_len(r) == _z_ring_capacity(r); } + +void *_z_ring_push(_z_ring_t *r, void *e) { + void *ret = e; + if (!_z_ring_is_full(r)) { + r->_val[r->_w_idx] = e; + r->_w_idx = (r->_w_idx + (size_t)1) % r->_capacity; + ret = NULL; + } + return ret; +} + +void *_z_ring_push_force(_z_ring_t *r, void *e) { + void *ret = _z_ring_push(r, e); + if (ret != NULL) { + ret = _z_ring_pull(r); + _z_ring_push(r, e); + } + return ret; +} + +void _z_ring_push_force_drop(_z_ring_t *r, void *e, z_element_free_f free_f) { + void *ret = _z_ring_push_force(r, e); + if (ret != NULL) { + free_f(&ret); + } +} + +void *_z_ring_pull(_z_ring_t *r) { + void *ret = NULL; + if (!_z_ring_is_empty(r)) { + ret = r->_val[r->_r_idx]; + r->_val[r->_r_idx] = NULL; + r->_r_idx = (r->_r_idx + (size_t)1) % r->_capacity; + } + return ret; +} + +void _z_ring_clear(_z_ring_t *r, z_element_free_f free_f) { + void *e = _z_ring_pull(r); + while (e != NULL) { + free_f(&e); + e = _z_ring_pull(r); + } + z_free(r->_val); + + r->_val = NULL; + r->_capacity = (size_t)0; + r->_len = (size_t)0; + r->_r_idx = (size_t)0; + r->_w_idx = (size_t)0; +} + +void _z_ring_free(_z_ring_t **r, z_element_free_f free_f) { + _z_ring_t *ptr = (_z_ring_t *)*r; + if (ptr != NULL) { + _z_ring_clear(ptr, free_f); + z_free(ptr); + *r = NULL; + } +} diff --git a/src/collections/ring_mt.c b/src/collections/ring_mt.c new file mode 100644 index 000000000..fdc9d7193 --- /dev/null +++ b/src/collections/ring_mt.c @@ -0,0 +1,143 @@ +// +// Copyright (c) 2024 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/collections/ring_mt.h" + +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/utils/logging.h" + +/*-------- Ring Buffer Multithreaded --------*/ +int8_t _z_ring_mt_init(_z_ring_mt_t *ring, size_t capacity) { + _Z_RETURN_IF_ERR(_z_ring_init(&ring->_ring, capacity)) + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_init(&ring->_mutex)) + _Z_RETURN_IF_ERR(_z_condvar_init(&ring->_cv_not_empty)) +#endif + ring->is_closed = false; + return _Z_RES_OK; +} + +_z_ring_mt_t *_z_ring_mt_new(size_t capacity) { + _z_ring_mt_t *ring = (_z_ring_mt_t *)z_malloc(sizeof(_z_ring_mt_t)); + if (ring == NULL) { + _Z_ERROR("z_malloc failed"); + return NULL; + } + + int8_t ret = _z_ring_mt_init(ring, capacity); + if (ret != _Z_RES_OK) { + _Z_ERROR("_z_ring_mt_init failed: %i", ret); + return NULL; + } + + return ring; +} + +void _z_ring_mt_clear(_z_ring_mt_t *ring, z_element_free_f free_f) { +#if Z_FEATURE_MULTI_THREAD == 1 + _z_mutex_drop(&ring->_mutex); + _z_condvar_drop(&ring->_cv_not_empty); +#endif + + _z_ring_clear(&ring->_ring, free_f); +} + +void _z_ring_mt_free(_z_ring_mt_t *ring, z_element_free_f free_f) { + _z_ring_mt_clear(ring, free_f); + + z_free(ring); +} + +int8_t _z_ring_mt_push(const void *elem, void *context, z_element_free_f element_free) { + if (elem == NULL || context == NULL) { + return _Z_ERR_GENERIC; + } + + _z_ring_mt_t *r = (_z_ring_mt_t *)context; + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_lock(&r->_mutex)) +#endif + + _z_ring_push_force_drop(&r->_ring, (void *)elem, element_free); + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_condvar_signal(&r->_cv_not_empty)) + _Z_RETURN_IF_ERR(_z_mutex_unlock(&r->_mutex)) +#endif + return _Z_RES_OK; +} + +int8_t _z_ring_mt_close(_z_ring_mt_t *ring) { +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_lock(&ring->_mutex)) + ring->is_closed = true; + _Z_RETURN_IF_ERR(_z_condvar_signal_all(&ring->_cv_not_empty)) + _Z_RETURN_IF_ERR(_z_mutex_unlock(&ring->_mutex)) +#else + ring->is_closed = true; +#endif + return _Z_RES_OK; +} + +int8_t _z_ring_mt_pull(void *dst, void *context, z_element_move_f element_move) { + _z_ring_mt_t *r = (_z_ring_mt_t *)context; + +#if Z_FEATURE_MULTI_THREAD == 1 + void *src = NULL; + _Z_RETURN_IF_ERR(_z_mutex_lock(&r->_mutex)) + while (src == NULL) { + src = _z_ring_pull(&r->_ring); + if (src == NULL) { + if (r->is_closed) break; + _Z_RETURN_IF_ERR(_z_condvar_wait(&r->_cv_not_empty, &r->_mutex)) + } + } + _Z_RETURN_IF_ERR(_z_mutex_unlock(&r->_mutex)) + if (r->is_closed && src == NULL) return _Z_RES_CHANNEL_CLOSED; + element_move(dst, src); +#else // Z_FEATURE_MULTI_THREAD == 1 + void *src = _z_ring_pull(&r->_ring); + if (src != NULL) { + element_move(dst, src); + } +#endif // Z_FEATURE_MULTI_THREAD == 1 + + return _Z_RES_OK; +} + +int8_t _z_ring_mt_try_pull(void *dst, void *context, z_element_move_f element_move) { + _z_ring_mt_t *r = (_z_ring_mt_t *)context; + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_lock(&r->_mutex)) +#endif + + void *src = _z_ring_pull(&r->_ring); + +#if Z_FEATURE_MULTI_THREAD == 1 + _Z_RETURN_IF_ERR(_z_mutex_unlock(&r->_mutex)) +#endif + + if (src != NULL) { + element_move(dst, src); + } else if (r->is_closed) { + return _Z_RES_CHANNEL_CLOSED; + } else { + return _Z_RES_CHANNEL_NODATA; + } + return _Z_RES_OK; +} diff --git a/src/collections/slice.c b/src/collections/slice.c new file mode 100644 index 000000000..730ce618c --- /dev/null +++ b/src/collections/slice.c @@ -0,0 +1,168 @@ +// +// 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/collections/slice.h" + +#include +#include +#include + +#include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/endianness.h" +#include "zenoh-pico/utils/pointers.h" +#include "zenoh-pico/utils/result.h" + +void _z_default_deleter(void *data, void *context) { + _ZP_UNUSED(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) { + if (!_z_delete_context_is_null(c)) { + c->deleter(data, c->context); + } +} + +/*-------- Slice --------*/ +_z_slice_t _z_slice_empty(void) { + return (_z_slice_t){.start = NULL, .len = 0, ._delete_context = _z_delete_context_null()}; +} + +int8_t _z_slice_init(_z_slice_t *bs, size_t capacity) { + int8_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->len = 0; + bs->_delete_context = _z_delete_context_null(); + } + + if (bs->len != capacity) { + ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + + return ret; +} + +_z_slice_t _z_slice_make(size_t capacity) { + _z_slice_t bs; + (void)_z_slice_init(&bs, capacity); + return bs; +} + +_z_slice_t _z_slice_from_buf_custom_deleter(const uint8_t *p, size_t len, _z_delete_context_t dc) { + _z_slice_t bs; + bs.start = p; + bs.len = len; + bs._delete_context = dc; + 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()); +} + +_z_slice_t _z_slice_copy_from_buf(const uint8_t *p, size_t len) { + _z_slice_t bs = _z_slice_alias_buf(p, 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); + } + _z_slice_reset(bs); +} + +void _z_slice_free(_z_slice_t **bs) { + _z_slice_t *ptr = *bs; + + if (ptr != NULL) { + _z_slice_clear(ptr); + + z_free(ptr); + *bs = NULL; + } +} + +int8_t _z_slice_copy(_z_slice_t *dst, const _z_slice_t *src) { + // Make sure dst slice is not init beforehand, or suffer memory leak + int8_t ret = _z_slice_init(dst, src->len); + if (ret == _Z_RES_OK) { + (void)memcpy((uint8_t *)dst->start, src->start, src->len); + } + return ret; +} + +int8_t _z_slice_n_copy(_z_slice_t *dst, const _z_slice_t *src, size_t offset, size_t len) { + assert(offset + len <= src->len); + // Make sure dst slice is not init beforehand, or suffer memory leak + int8_t ret = _z_slice_init(dst, len); + if (ret == _Z_RES_OK) { + const uint8_t *start = _z_cptr_u8_offset(src->start, (ptrdiff_t)offset); + (void)memcpy((uint8_t *)dst->start, start, len); + } + return ret; +} + +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; + + _z_slice_reset(src); +} + +_z_slice_t _z_slice_duplicate(const _z_slice_t *src) { + _z_slice_t dst = _z_slice_empty(); + _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(); + return ret; +} +_Bool _z_slice_eq(const _z_slice_t *left, const _z_slice_t *right) { + return left->len == right->len && memcmp(left->start, right->start, left->len) == 0; +} + +_Bool _z_slice_is_alloced(const _z_slice_t *s) { return !_z_delete_context_is_null(&s->_delete_context); } diff --git a/src/collections/string.c b/src/collections/string.c index 51a19c38b..0e8129be4 100644 --- a/src/collections/string.c +++ b/src/collections/string.c @@ -17,46 +17,83 @@ #include #include +#include "zenoh-pico/utils/pointers.h" + /*-------- string --------*/ -_z_string_t _z_string_make(const char *value) { +_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.val = _z_str_clone(value); - s.len = strlen(value); + s._slice = _z_slice_copy_from_buf((uint8_t *)value, strlen(value)); return s; } -void _z_string_copy(_z_string_t *dst, const _z_string_t *src) { - if (src->val != NULL) { - dst->val = _z_str_clone(src->val); - } else { - dst->val = NULL; - } - dst->len = src->len; +_z_string_t _z_string_copy_from_substr(const char *value, size_t len) { + _z_string_t s; + s._slice = _z_slice_copy_from_buf((uint8_t *)value, len); + return s; } -void _z_string_move(_z_string_t *dst, _z_string_t *src) { - dst->val = src->val; - dst->len = src->len; +_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)); + return s; +} - src->val = NULL; - src->len = 0; +_z_string_t _z_string_alias_substr(const char *value, size_t len) { + _z_string_t s; + s._slice = _z_slice_alias_buf((const uint8_t *)(value), len); + return s; } -void _z_string_move_str(_z_string_t *dst, char *src) { - dst->val = src; - dst->len = strlen(src); +_z_string_t _z_string_from_str_custom_deleter(char *value, _z_delete_context_t c) { + _z_string_t s; + s._slice = _z_slice_from_buf_custom_deleter((const uint8_t *)(value), strlen(value), c); + return s; } -void _z_string_reset(_z_string_t *str) { - str->val = NULL; - str->len = 0; +_z_string_t *_z_string_copy_from_str_as_ptr(const char *value) { + _z_string_t *s = (_z_string_t *)z_malloc(sizeof(_z_string_t)); + *s = _z_string_copy_from_str(value); + if (_z_slice_is_empty(&s->_slice) && value != NULL) { + z_free(s); + return NULL; + } + return s; } -void _z_string_clear(_z_string_t *str) { - z_free(str->val); - _z_string_reset(str); +size_t _z_string_len(const _z_string_t *s) { return s->_slice.len; } + +int8_t _z_string_copy(_z_string_t *dst, const _z_string_t *src) { return _z_slice_copy(&dst->_slice, &src->_slice); } + +int8_t _z_string_copy_substring(_z_string_t *dst, const _z_string_t *src, size_t offset, size_t len) { + 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); } + +_z_string_t _z_string_steal(_z_string_t *str) { + _z_string_t ret; + ret._slice = _z_slice_steal(&str->_slice); + 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); } + +void _z_string_clear(_z_string_t *str) { _z_slice_clear(&str->_slice); } + void _z_string_free(_z_string_t **str) { _z_string_t *ptr = *str; if (ptr != NULL) { @@ -67,27 +104,75 @@ void _z_string_free(_z_string_t **str) { } } -_z_string_t _z_string_from_bytes(const _z_bytes_t *bs) { - _z_string_t s; - size_t len = bs->len * (size_t)2; - char *s_val = (char *)z_malloc((len + (size_t)1) * sizeof(char)); +_Bool _z_string_equals(const _z_string_t *left, const _z_string_t *right) { + if (_z_string_len(left) != _z_string_len(right)) { + return false; + } + return (strncmp(_z_string_data(left), _z_string_data(right), _z_string_len(left)) == 0); +} - if (s_val != NULL) { - const char c[] = "0123456789ABCDEF"; - 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) + (size_t)1] = c[bs->start[i] & (uint8_t)0x0F]; - } - s_val[len] = '\0'; - } else { - len = 0; +_z_string_t _z_string_convert_bytes(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)); + if (s_val == NULL) { + return s; } - s.val = s_val; - s.len = len; + const char c[] = "0123456789ABCDEF"; + 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._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(); + } return s; } +const char *_z_string_data(const _z_string_t *s) { return (const char *)s->_slice.start; } + +_Bool _z_string_is_empty(const _z_string_t *s) { return s->_slice.len <= 1; } + +const char *_z_string_rchr(_z_string_t *str, char filter) { + const char *curr_res = NULL; + const char *ret = NULL; + const char *curr_addr = _z_string_data(str); + size_t curr_len = _z_string_len(str); + do { + curr_res = (char *)memchr(curr_addr, (int)filter, curr_len); + if (curr_res != NULL) { + ret = curr_res; + curr_addr = curr_res + 1; + curr_len = _z_ptr_char_diff(curr_addr, _z_string_data(str)); + if (curr_len >= _z_string_len(str)) { + break; + } + curr_len = _z_string_len(str) - curr_len; + } + } while (curr_res != NULL); + return ret; +} + +char *_z_string_pbrk(_z_string_t *str, const char *filter) { + const char *data = _z_string_data(str); + for (size_t idx = 0; idx < _z_string_len(str); idx++) { + const char *curr_char = filter; + while (*curr_char != '\0') { + if (data[idx] == *curr_char) { + return (char *)&data[idx]; + } + curr_char++; + } + } + return NULL; +} /*-------- str --------*/ size_t _z_str_size(const char *src) { return strlen(src) + (size_t)1; } @@ -105,12 +190,12 @@ void _z_str_free(char **src) { void _z_str_copy(char *dst, const char *src) { size_t size = _z_str_size(src); - strncpy(dst, src, size); + strncpy(dst, src, size - 1); dst[size - 1] = '\0'; // No matter what, strings are always null-terminated upon copy } void _z_str_n_copy(char *dst, const char *src, size_t size) { - strncpy(dst, src, size); + strncpy(dst, src, size - 1); dst[size - 1] = '\0'; // No matter what, strings are always null-terminated upon copy } @@ -124,60 +209,13 @@ char *_z_str_clone(const char *src) { return dst; } -_Bool _z_str_eq(const char *left, const char *right) { return strcmp(left, right) == 0; } - -/*-------- str_array --------*/ -void _z_str_array_init(_z_str_array_t *sa, size_t len) { - char **val = (char **)&sa->val; - *val = (char *)z_malloc(len * sizeof(char *)); - if (*val != NULL) { - sa->len = len; - } -} - -_z_str_array_t _z_str_array_empty(void) { return (_z_str_array_t){.val = NULL, .len = 0}; } - -_z_str_array_t _z_str_array_make(size_t len) { - _z_str_array_t sa; - _z_str_array_init(&sa, len); - return sa; -} - -char **_z_str_array_get(const _z_str_array_t *sa, size_t pos) { return &sa->val[pos]; } - -size_t _z_str_array_len(const _z_str_array_t *sa) { return sa->len; } - -_Bool _z_str_array_is_empty(const _z_str_array_t *sa) { return sa->len == 0; } - -void _z_str_array_clear(_z_str_array_t *sa) { - for (size_t i = 0; i < sa->len; i++) { - z_free(sa->val[i]); - } - z_free(sa->val); -} - -void _z_str_array_free(_z_str_array_t **sa) { - _z_str_array_t *ptr = *sa; - if (ptr != NULL) { - _z_str_array_clear(ptr); - - z_free(ptr); - *sa = NULL; +char *_z_str_n_clone(const char *src, size_t len) { + char *dst = (char *)z_malloc(len + 1); + if (dst != NULL) { + _z_str_n_copy(dst, src, len + 1); } -} -void _z_str_array_copy(_z_str_array_t *dst, const _z_str_array_t *src) { - _z_str_array_init(dst, src->len); - for (size_t i = 0; i < src->len; i++) { - dst->val[i] = _z_str_clone(src->val[i]); - } - dst->len = src->len; + return dst; } -void _z_str_array_move(_z_str_array_t *dst, _z_str_array_t *src) { - dst->val = src->val; - dst->len = src->len; - - src->val = NULL; - src->len = 0; -} +_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 20afff6ca..e33034fd2 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -36,7 +36,7 @@ void _z_vec_copy(_z_vec_t *dst, const _z_vec_t *src, z_element_clone_f d_f) { dst->_val = (void **)z_malloc(sizeof(void *) * src->_capacity); if (dst->_val != NULL) { for (size_t i = 0; i < src->_len; i++) { - _z_vec_append(dst, d_f(src->_val[i])); + dst->_val[i] = d_f(src->_val[i]); } } } @@ -53,7 +53,10 @@ void _z_vec_clear(_z_vec_t *v, z_element_free_f free_f) { for (size_t i = 0; i < v->_len; i++) { free_f(&v->_val[i]); } + _z_vec_release(v); +} +void _z_vec_release(_z_vec_t *v) { z_free(v->_val); v->_val = NULL; @@ -124,3 +127,135 @@ void _z_vec_remove(_z_vec_t *v, size_t pos, z_element_free_f free_f) { v->_val[v->_len] = NULL; v->_len = v->_len - 1; } + +/*-------- svec --------*/ +_z_svec_t _z_svec_make(size_t capacity, size_t element_size) { + _z_svec_t v = {._capacity = 0, ._len = 0, ._val = NULL}; + if (capacity != 0) { + v._val = z_malloc(element_size * capacity); + } + if (v._val != NULL) { + v._capacity = capacity; + } + 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_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 { + 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; + } + } +} + +_Bool _z_svec_copy(_z_svec_t *dst, const _z_svec_t *src, z_element_copy_f copy, size_t element_size) { + 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); + } + return dst->_len == src->_len; +} + +void _z_svec_reset(_z_svec_t *v, z_element_clear_f clear, size_t element_size) { + if (clear != NULL) { + size_t offset = 0; + for (size_t i = 0; i < v->_len; i++) { + clear((uint8_t *)v->_val + offset); + offset += element_size; + } + } + v->_len = 0; +} + +void _z_svec_clear(_z_svec_t *v, z_element_clear_f clear_f, size_t element_size) { + _z_svec_reset(v, clear_f, element_size); + _z_svec_release(v); +} + +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) { + _z_svec_t *ptr = (_z_svec_t *)*v; + + if (ptr != NULL) { + _z_svec_clear(ptr, clear, element_size); + + z_free(ptr); + *v = NULL; + } +} + +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); + + // 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++; + } + return true; +} + +void *_z_svec_get(const _z_svec_t *v, size_t i, size_t element_size) { + assert(i < v->_len); + 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) { + 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--; +} diff --git a/src/deprecated/platform.c b/src/deprecated/platform.c deleted file mode 100644 index 252eb6d44..000000000 --- a/src/deprecated/platform.c +++ /dev/null @@ -1,63 +0,0 @@ -// -// Copyright (c) 2024 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/deprecated/platform.h" - -#include "zenoh-pico/system/platform-common.h" - -uint8_t zp_random_u8(void) { return z_random_u8(); }; -uint16_t zp_random_u16(void) { return z_random_u16(); }; -uint32_t zp_random_u32(void) { return z_random_u32(); }; -uint64_t zp_random_u64(void) { return z_random_u64(); }; -void zp_random_fill(void *buf, size_t len) { z_random_fill(buf, len); }; - -void *zp_malloc(size_t size) { return z_malloc(size); }; -void *zp_realloc(void *ptr, size_t size) { return z_realloc(ptr, size); }; -void zp_free(void *ptr) { z_free(ptr); }; - -#if Z_FEATURE_MULTI_THREAD == 1 - -int8_t zp_task_init(zp_task_t *task, zp_task_attr_t *attr, void *(*fun)(void *), void *arg) { - return z_task_init(task, attr, fun, arg); -}; -int8_t zp_task_join(zp_task_t *task) { return z_task_join(task); }; -void zp_task_free(zp_task_t **task) { z_task_free(task); }; - -int8_t zp_mutex_init(zp_mutex_t *m) { return z_mutex_init(m); }; -int8_t zp_mutex_free(zp_mutex_t *m) { return z_mutex_free(m); }; -int8_t zp_mutex_lock(zp_mutex_t *m) { return z_mutex_lock(m); }; -int8_t zp_mutex_trylock(zp_mutex_t *m) { return z_mutex_trylock(m); }; -int8_t zp_mutex_unlock(zp_mutex_t *m) { return z_mutex_unlock(m); }; - -int8_t zp_condvar_init(zp_condvar_t *cv) { return z_condvar_init(cv); }; -int8_t zp_condvar_free(zp_condvar_t *cv) { return z_condvar_free(cv); }; - -int8_t zp_condvar_signal(zp_condvar_t *cv) { return z_condvar_signal(cv); }; -int8_t zp_condvar_wait(zp_condvar_t *cv, zp_mutex_t *m) { return z_condvar_wait(cv, m); }; -#endif // Z_FEATURE_MULTI_THREAD == 1 - -int zp_sleep_us(size_t time) { return z_sleep_us(time); }; -int zp_sleep_ms(size_t time) { return z_sleep_ms(time); }; -int zp_sleep_s(size_t time) { return z_sleep_s(time); }; - -zp_clock_t zp_clock_now(void) { return z_clock_now(); }; -unsigned long zp_clock_elapsed_us(zp_clock_t *time) { return z_clock_elapsed_us(time); }; -unsigned long zp_clock_elapsed_ms(zp_clock_t *time) { return z_clock_elapsed_ms(time); }; -unsigned long zp_clock_elapsed_s(zp_clock_t *time) { return z_clock_elapsed_s(time); }; - -zp_time_t zp_time_now(void) { return z_time_now(); }; -const char *zp_time_now_as_str(char *const buf, unsigned long buflen) { return z_time_now_as_str(buf, buflen); }; -unsigned long zp_time_elapsed_us(zp_time_t *time) { return z_time_elapsed_us(time); }; -unsigned long zp_time_elapsed_ms(zp_time_t *time) { return z_time_elapsed_ms(time); }; -unsigned long zp_time_elapsed_s(zp_time_t *time) { return z_time_elapsed_s(time); }; diff --git a/src/link/config/ws.c b/src/link/config/ws.c index 14e4c113c..dd4378e6a 100644 --- a/src/link/config/ws.c +++ b/src/link/config/ws.c @@ -28,8 +28,7 @@ size_t _z_ws_config_strlen(const _z_str_intmap_t *s) { void _z_ws_config_onto_str(char *dst, size_t dst_len, const _z_str_intmap_t *s) { WS_CONFIG_MAPPING_BUILD - - return _z_str_intmap_onto_str(dst, dst_len, s, argc, args); + _z_str_intmap_onto_str(dst, dst_len, s, argc, args); } char *_z_ws_config_to_str(const _z_str_intmap_t *s) { diff --git a/src/link/endpoint.c b/src/link/endpoint.c index 035e646a6..400f2d1e6 100644 --- a/src/link/endpoint.c +++ b/src/link/endpoint.c @@ -19,6 +19,7 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/pointers.h" #if Z_FEATURE_LINK_TCP == 1 #include "zenoh-pico/link/config/tcp.h" @@ -39,14 +40,14 @@ /*------------------ Locator ------------------*/ void _z_locator_init(_z_locator_t *locator) { - locator->_protocol = NULL; - locator->_address = NULL; + locator->_protocol = _z_string_null(); + locator->_address = _z_string_null(); locator->_metadata = _z_str_intmap_make(); } void _z_locator_clear(_z_locator_t *lc) { - _z_str_free(&lc->_protocol); - _z_str_free(&lc->_address); + _z_string_clear(&lc->_protocol); + _z_string_clear(&lc->_address); _z_str_intmap_clear(&lc->_metadata); } @@ -61,20 +62,21 @@ void _z_locator_free(_z_locator_t **lc) { } } -void _z_locator_copy(_z_locator_t *dst, const _z_locator_t *src) { - dst->_protocol = _z_str_clone(src->_protocol); - dst->_address = _z_str_clone(src->_address); +int8_t _z_locator_copy(_z_locator_t *dst, const _z_locator_t *src) { + _Z_RETURN_IF_ERR(_z_string_copy(&dst->_protocol, &src->_protocol)); + _Z_RETURN_IF_ERR(_z_string_copy(&dst->_address, &src->_address)); // @TODO: implement copy for metadata dst->_metadata = _z_str_intmap_make(); + return _Z_RES_OK; } _Bool _z_locator_eq(const _z_locator_t *left, const _z_locator_t *right) { _Bool res = false; - res = _z_str_eq(left->_protocol, right->_protocol); + res = _z_string_equals(&left->_protocol, &right->_protocol); if (res == true) { - res = _z_str_eq(left->_address, right->_address); + res = _z_string_equals(&left->_address, &right->_address); // if (res == true) { // // @TODO: implement eq for metadata // } @@ -83,71 +85,78 @@ _Bool _z_locator_eq(const _z_locator_t *left, const _z_locator_t *right) { return res; } -char *_z_locator_protocol_from_str(const char *str) { - char *ret = NULL; - - if (str != NULL) { - const char *p_start = &str[0]; - const char *p_end = strchr(p_start, LOCATOR_PROTOCOL_SEPARATOR); - if ((p_end != NULL) && (p_start != p_end)) { - size_t p_len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; - ret = (char *)z_malloc(p_len); - if (ret != NULL) { - _z_str_n_copy(ret, p_start, p_len); - } - } - } +static int8_t _z_locator_protocol_from_string(_z_string_t *protocol, _z_string_t *str) { + *protocol = _z_string_null(); - return ret; + const char *p_start = _z_string_data(str); + const char *p_end = (char *)memchr(p_start, (int)LOCATOR_PROTOCOL_SEPARATOR, _z_string_len(str)); + if ((p_end == NULL) || (p_start == p_end)) { + return _Z_ERR_CONFIG_LOCATOR_INVALID; + } + size_t p_len = _z_ptr_char_diff(p_end, p_start); + return _z_string_copy_substring(protocol, str, 0, p_len); } -char *_z_locator_address_from_str(const char *str) { - char *ret = NULL; - - const char *p_start = strchr(str, LOCATOR_PROTOCOL_SEPARATOR); - if (p_start != NULL) { - p_start = _z_cptr_char_offset(p_start, 1); // Skip protocol separator character +static int8_t _z_locator_address_from_string(_z_string_t *address, _z_string_t *str) { + *address = _z_string_null(); - const char *p_end = strchr(p_start, LOCATOR_METADATA_SEPARATOR); - if (p_end == NULL) { // There is no metadata separator, then look for config separator - p_end = strchr(p_start, ENDPOINT_CONFIG_SEPARATOR); - } - if (p_end == NULL) { // There is no config separator, then address goes to the end of string - p_end = &str[strlen(str)]; - } - - if (p_start != p_end) { - size_t a_len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; - ret = (char *)z_malloc(a_len); - if (ret != NULL) { - _z_str_n_copy(ret, p_start, a_len); - } - } + // Find protocol separator + const char *p_start = (char *)memchr(_z_string_data(str), (int)LOCATOR_PROTOCOL_SEPARATOR, _z_string_len(str)); + if (p_start == NULL) { + return _Z_ERR_CONFIG_LOCATOR_INVALID; } - - return ret; + // Skip protocol separator + p_start = _z_cptr_char_offset(p_start, 1); + size_t start_offset = _z_ptr_char_diff(p_start, _z_string_data(str)); + if (start_offset >= _z_string_len(str)) { + return _Z_ERR_CONFIG_LOCATOR_INVALID; + } + // Find metadata separator + size_t curr_len = _z_string_len(str) - start_offset; + const char *p_end = (char *)memchr(p_start, (int)LOCATOR_METADATA_SEPARATOR, curr_len); + // There is no metadata separator, then look for config separator + if (p_end == NULL) { + p_end = memchr(p_start, (int)ENDPOINT_CONFIG_SEPARATOR, curr_len); + } + // There is no config separator, then address goes to the end of string + if (p_end == NULL) { + p_end = _z_cptr_char_offset(_z_string_data(str), (ptrdiff_t)_z_string_len(str)); + } + if (p_start >= p_end) { + return _Z_ERR_CONFIG_LOCATOR_INVALID; + } + // Copy data + size_t addr_len = _z_ptr_char_diff(p_end, p_start); + return _z_string_copy_substring(address, str, start_offset, addr_len); } -int8_t _z_locator_metadata_from_str(_z_str_intmap_t *strint, const char *str) { - int8_t ret = _Z_RES_OK; +int8_t _z_locator_metadata_from_string(_z_str_intmap_t *strint, _z_string_t *str) { *strint = _z_str_intmap_make(); - const char *p_start = strchr(str, LOCATOR_METADATA_SEPARATOR); - if (p_start != NULL) { - p_start = _z_cptr_char_offset(p_start, 1); - - const char *p_end = strchr(str, ENDPOINT_CONFIG_SEPARATOR); - if (p_end == NULL) { - p_end = &str[strlen(str)]; - } + // Find metadata separator + const char *p_start = (char *)memchr(_z_string_data(str), LOCATOR_METADATA_SEPARATOR, _z_string_len(str)); + if (p_start == NULL) { + return _Z_RES_OK; + } + p_start = _z_cptr_char_offset(p_start, 1); + size_t start_offset = _z_ptr_char_diff(p_start, _z_string_data(str)); + if (start_offset > _z_string_len(str)) { + return _Z_ERR_CONFIG_LOCATOR_INVALID; + } + if (start_offset == _z_string_len(str)) { + return _Z_RES_OK; + } - if (p_start != p_end) { - size_t p_len = _z_ptr_char_diff(p_end, p_start); - ret = _z_str_intmap_from_strn(strint, p_start, 0, NULL, p_len); - } + const char *p_end = (char *)memchr(_z_string_data(str), ENDPOINT_CONFIG_SEPARATOR, _z_string_len(str)); + if (p_end == NULL) { + p_end = _z_cptr_char_offset(_z_string_data(str), (ptrdiff_t)_z_string_len(str) + 1); } - return ret; + if (p_start != p_end) { + size_t p_len = _z_ptr_char_diff(p_end, p_start); + return _z_str_intmap_from_strn(strint, p_start, 0, NULL, p_len); + } + return _Z_RES_OK; } size_t _z_locator_metadata_strlen(const _z_str_intmap_t *s) { @@ -160,25 +169,17 @@ void _z_locator_metadata_onto_str(char *dst, size_t dst_len, const _z_str_intmap _z_str_intmap_onto_str(dst, dst_len, s, 0, NULL); } -int8_t _z_locator_from_str(_z_locator_t *lc, const char *str) { - int8_t ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - - // Parse protocol - lc->_protocol = _z_locator_protocol_from_str(str); - if (lc->_protocol != NULL) { - // Parse address - lc->_address = _z_locator_address_from_str(str); - if (lc->_address != NULL) { - // Parse metadata - ret = _z_locator_metadata_from_str(&lc->_metadata, str); - } +int8_t _z_locator_from_string(_z_locator_t *lc, _z_string_t *str) { + if (str == NULL || !_z_string_check(str)) { + return _Z_ERR_CONFIG_LOCATOR_INVALID; } - - if (ret != _Z_RES_OK) { - _z_locator_clear(lc); - } - - return ret; + // Parse protocol + _Z_RETURN_IF_ERR(_z_locator_protocol_from_string(&lc->_protocol, str)); + // Parse address + _Z_CLEAN_RETURN_IF_ERR(_z_locator_address_from_string(&lc->_address, str), _z_locator_clear(lc)); + // Parse metadata + _Z_CLEAN_RETURN_IF_ERR(_z_locator_metadata_from_string(&lc->_metadata, str), _z_locator_clear(lc)); + return _Z_RES_OK; } size_t _z_locator_strlen(const _z_locator_t *l) { @@ -186,9 +187,7 @@ size_t _z_locator_strlen(const _z_locator_t *l) { if (l != NULL) { // Calculate the string length to allocate - ret = ret + strlen(l->_protocol); // Locator protocol - ret = ret + (size_t)1; // Locator protocol separator - ret = ret + strlen(l->_address); // Locator address + ret = _z_string_len(&l->_protocol) + _z_string_len(&l->_address) + 1; // @TODO: define protocol-level metadata size_t md_len = _z_locator_metadata_strlen(&l->_metadata); @@ -207,60 +206,59 @@ size_t _z_locator_strlen(const _z_locator_t *l) { * dst: Pointer to the destination string. It MUST be already allocated with enough space to store the locator in * its string format. loc: :c:type:`_z_locator_t` to be converted into its string format. */ -void __z_locator_onto_str(char *dst, size_t dst_len, const _z_locator_t *loc) { - size_t len = dst_len; +static void __z_locator_onto_string(_z_string_t *dst, const _z_locator_t *loc) { + char *curr_dst = (char *)_z_string_data(dst); const char psep = LOCATOR_PROTOCOL_SEPARATOR; const char msep = LOCATOR_METADATA_SEPARATOR; - dst[0] = '\0'; - len = len - (size_t)1; + size_t prot_len = _z_string_len(&loc->_protocol); + size_t addr_len = _z_string_len(&loc->_address); - if (len > (size_t)0) { - (void)strncat(dst, loc->_protocol, dst_len); // Locator protocol - len = len - strlen(loc->_protocol); + if ((prot_len + addr_len + 1) > _z_string_len(dst)) { + _Z_ERROR("Buffer too small to write locator"); + return; } - - if (len > (size_t)0) { - (void)strncat(dst, &psep, 1); // Locator protocol separator - len = len - (size_t)1; - } - - if (len > (size_t)0) { - (void)strncat(dst, loc->_address, len); // Locator address - len = len - strlen(loc->_address); - } - + // Locator protocol + memcpy(curr_dst, _z_string_data(&loc->_protocol), prot_len); + curr_dst = _z_ptr_char_offset(curr_dst, (ptrdiff_t)prot_len); + // Locator protocol separator + memcpy(curr_dst, &psep, 1); + curr_dst = _z_ptr_char_offset(curr_dst, 1); + // Locator address + memcpy(curr_dst, _z_string_data(&loc->_address), addr_len); + curr_dst = _z_ptr_char_offset(curr_dst, (ptrdiff_t)addr_len); // @TODO: define protocol-level metadata size_t md_len = _z_locator_metadata_strlen(&loc->_metadata); if (md_len > (size_t)0) { - if (len > (size_t)0) { - (void)strncat(dst, &msep, 1); // Locator metadata separator - len = len - (size_t)1; - } - - if (len > (size_t)0) { - _z_locator_metadata_onto_str(&dst[strlen(dst)], len, &loc->_metadata); - len = len - md_len; + size_t curr_len = _z_string_len(dst) - _z_ptr_char_diff(curr_dst, _z_string_data(dst)); + if (curr_len == 0) { + _Z_ERROR("Buffer too small to write metadata"); + return; } + // Locator metadata separator + memcpy(curr_dst, &msep, 1); + curr_dst = _z_ptr_char_offset(curr_dst, 1); + // Locator metadata + _z_locator_metadata_onto_str(curr_dst, curr_len, &loc->_metadata); } } /** - * Converts a :c:type:`_z_locator_t` into its string format. + * Converts a :c:type:`_z_locator_t` into its _z_string format. * * Parameters: - * loc: :c:type:`_z_locator_t` to be converted into its string format. + * loc: :c:type:`_z_locator_t` to be converted into its _z_string format. * * Returns: - * The pointer to the stringified :c:type:`_z_locator_t`. + * The z_stringified :c:type:`_z_locator_t`. */ -char *_z_locator_to_str(const _z_locator_t *l) { - size_t len = _z_locator_strlen(l) + (size_t)1; - char *dst = (char *)z_malloc(len); - if (dst != NULL) { - __z_locator_onto_str(dst, len, l); +_z_string_t _z_locator_to_string(const _z_locator_t *loc) { + _z_string_t s = _z_string_preallocate(_z_locator_strlen(loc)); + if (!_z_string_check(&s)) { + return s; } - return dst; + __z_locator_onto_string(&s, loc); + return s; } /*------------------ Endpoint ------------------*/ @@ -286,168 +284,169 @@ void _z_endpoint_free(_z_endpoint_t **ep) { } } -int8_t _z_endpoint_config_from_str(_z_str_intmap_t *strint, const char *str, const char *proto) { - int8_t ret = _Z_RES_OK; - - char *p_start = strchr(str, ENDPOINT_CONFIG_SEPARATOR); +int8_t _z_endpoint_config_from_string(_z_str_intmap_t *strint, _z_string_t *str, _z_string_t *proto) { + char *p_start = (char *)memchr(_z_string_data(str), ENDPOINT_CONFIG_SEPARATOR, _z_string_len(str)); if (p_start != NULL) { p_start = _z_ptr_char_offset(p_start, 1); // Call the right configuration parser depending on the protocol + _z_string_t cmp_str = _z_string_null(); #if Z_FEATURE_LINK_TCP == 1 - if (_z_str_eq(proto, TCP_SCHEMA) == true) { - ret = _z_tcp_config_from_str(strint, p_start); - } else + cmp_str = _z_string_alias_str(TCP_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_tcp_config_from_str(strint, p_start); + } #endif #if Z_FEATURE_LINK_UDP_UNICAST == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 - if (_z_str_eq(proto, UDP_SCHEMA) == true) { - ret = _z_udp_config_from_str(strint, p_start); - } else + cmp_str = _z_string_alias_str(UDP_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_udp_config_from_str(strint, p_start); + } #endif #if Z_FEATURE_LINK_BLUETOOTH == 1 - if (_z_str_eq(proto, BT_SCHEMA) == true) { - ret = _z_bt_config_from_str(strint, p_start); - } else + cmp_str = _z_string_alias_str(BT_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_bt_config_from_str(strint, p_start); + } #endif #if Z_FEATURE_LINK_SERIAL == 1 - if (_z_str_eq(proto, SERIAL_SCHEMA) == true) { - ret = _z_serial_config_from_str(strint, p_start); - } else + cmp_str = _z_string_alias_str(SERIAL_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_serial_config_from_str(strint, p_start); + } #endif #if Z_FEATURE_LINK_WS == 1 - if (_z_str_eq(proto, WS_SCHEMA) == true) { - ret = _z_ws_config_from_str(strint, p_start); - } else + cmp_str = _z_string_alias_str(WS_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_ws_config_from_str(strint, p_start); + } #endif - if (_z_str_eq(proto, RAWETH_SCHEMA) == true) { - _z_raweth_config_from_str(strint, p_start); - } else { - ret = _Z_ERR_CONFIG_LOCATOR_SCHEMA_UNKNOWN; + cmp_str = _z_string_alias_str(RAWETH_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_raweth_config_from_str(strint, p_start); } } - - return ret; + return _Z_RES_OK; } -size_t _z_endpoint_config_strlen(const _z_str_intmap_t *s, const char *proto) { - size_t len = 0; - +size_t _z_endpoint_config_strlen(const _z_str_intmap_t *s, _z_string_t *proto) { // Call the right configuration parser depending on the protocol + _z_string_t cmp_str = _z_string_null(); #if Z_FEATURE_LINK_TCP == 1 - if (_z_str_eq(proto, TCP_SCHEMA) == true) { - len = _z_tcp_config_strlen(s); - } else + cmp_str = _z_string_alias_str(TCP_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_tcp_config_strlen(s); + } #endif #if Z_FEATURE_LINK_UDP_UNICAST == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 - if (_z_str_eq(proto, UDP_SCHEMA) == true) { - len = _z_udp_config_strlen(s); - } else + cmp_str = _z_string_alias_str(UDP_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_udp_config_strlen(s); + } #endif #if Z_FEATURE_LINK_BLUETOOTH == 1 - if (_z_str_eq(proto, BT_SCHEMA) == true) { - len = _z_bt_config_strlen(s); - } else + cmp_str = _z_string_alias_str(BT_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_bt_config_strlen(s); + } #endif #if Z_FEATURE_LINK_SERIAL == 1 - if (_z_str_eq(proto, SERIAL_SCHEMA) == true) { - len = _z_serial_config_strlen(s); - } else + cmp_str = _z_string_alias_str(SERIAL_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_serial_config_strlen(s); + } #endif #if Z_FEATURE_LINK_WS == 1 - if (_z_str_eq(proto, WS_SCHEMA) == true) { - len = _z_ws_config_strlen(s); - } else + cmp_str = _z_string_alias_str(WS_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_ws_config_strlen(s); + } #endif - if (_z_str_eq(proto, RAWETH_SCHEMA) == true) { - len = _z_raweth_config_strlen(s); + cmp_str = _z_string_alias_str(RAWETH_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_raweth_config_strlen(s); } - return len; + return 0; } -char *_z_endpoint_config_to_str(const _z_str_intmap_t *s, const char *proto) { - char *res = NULL; - +char *_z_endpoint_config_to_string(const _z_str_intmap_t *s, const _z_string_t *proto) { // Call the right configuration parser depending on the protocol + _z_string_t cmp_str = _z_string_null(); + #if Z_FEATURE_LINK_TCP == 1 - if (_z_str_eq(proto, TCP_SCHEMA) == true) { - res = _z_tcp_config_to_str(s); - } else + cmp_str = _z_string_alias_str(TCP_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_tcp_config_to_str(s); + } #endif #if Z_FEATURE_LINK_UDP_UNICAST == 1 || Z_FEATURE_LINK_UDP_MULTICAST == 1 - if (_z_str_eq(proto, UDP_SCHEMA) == true) { - res = _z_udp_config_to_str(s); - } else + cmp_str = _z_string_alias_str(UDP_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_udp_config_to_str(s); + } #endif #if Z_FEATURE_LINK_BLUETOOTH == 1 - if (_z_str_eq(proto, BT_SCHEMA) == true) { - res = _z_bt_config_to_str(s); - } else + cmp_str = _z_string_alias_str(BT_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_bt_config_to_str(s); + } #endif #if Z_FEATURE_LINK_SERIAL == 1 - if (_z_str_eq(proto, SERIAL_SCHEMA) == true) { - res = _z_serial_config_to_str(s); - } else + cmp_str = _z_string_alias_str(SERIAL_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_serial_config_to_str(s); + } #endif #if Z_FEATURE_LINK_WS == 1 - if (_z_str_eq(proto, WS_SCHEMA) == true) { - res = _z_ws_config_to_str(s); - } else + cmp_str = _z_string_alias_str(WS_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_ws_config_to_str(s); + } #endif - if (_z_str_eq(proto, RAWETH_SCHEMA) == true) { - _z_raweth_config_to_str(s); + cmp_str = _z_string_alias_str(RAWETH_SCHEMA); + if (_z_string_equals(proto, &cmp_str)) { + return _z_raweth_config_to_str(s); } - return res; + return NULL; } -int8_t _z_endpoint_from_str(_z_endpoint_t *ep, const char *str) { - int8_t ret = _Z_RES_OK; +int8_t _z_endpoint_from_string(_z_endpoint_t *ep, _z_string_t *str) { _z_endpoint_init(ep); + _Z_CLEAN_RETURN_IF_ERR(_z_locator_from_string(&ep->_locator, str), _z_endpoint_clear(ep)); + _Z_CLEAN_RETURN_IF_ERR(_z_endpoint_config_from_string(&ep->_config, str, &ep->_locator._protocol), + _z_endpoint_clear(ep)); + return _Z_RES_OK; +} - ret = _z_locator_from_str(&ep->_locator, str); - if (ret == _Z_RES_OK) { - ret = _z_endpoint_config_from_str(&ep->_config, str, ep->_locator._protocol); +_z_string_t _z_endpoint_to_string(const _z_endpoint_t *endpoint) { + _z_string_t ret = _z_string_null(); + // Retrieve locator + _z_string_t locator = _z_locator_to_string(&endpoint->_locator); + if (!_z_string_check(&locator)) { + return _z_string_null(); } - - if (ret != _Z_RES_OK) { - _z_endpoint_clear(ep); + size_t curr_len = _z_string_len(&locator); + // Retrieve config + char *config = _z_endpoint_config_to_string(&endpoint->_config, &endpoint->_locator._protocol); + size_t config_len = 0; + if (config != NULL) { + config_len = strlen(config); + curr_len += config_len; } - - return ret; -} - -char *_z_endpoint_to_str(const _z_endpoint_t *endpoint) { - char *ret = NULL; - - char *locator = _z_locator_to_str(&endpoint->_locator); - if (locator != NULL) { - size_t len = 1; // Start with space for the null-terminator - len = len + strlen(locator); - - char *config = _z_endpoint_config_to_str(&endpoint->_config, endpoint->_locator._protocol); - if (config != NULL) { - len = len + (size_t)1; // Config separator - len = len + strlen(config); // Config content - } - - // Reconstruct the endpoint as a string - ret = (char *)z_malloc(len); - if (ret != NULL) { - ret[0] = '\0'; - len = len - (size_t)1; - - if (len > (size_t)0) { - (void)strncat(ret, locator, len); - len = len - strlen(locator); - } - - if (config != NULL) { - if (len > (size_t)0) { - (void)strncat(ret, config, len); - len = len - strlen(config); - } - } - } + // Reconstruct the endpoint as a string + ret = _z_string_preallocate(curr_len); + if (!_z_string_check(&ret)) { + return ret; } - + // Copy locator + char *curr_dst = (char *)_z_string_data(&ret); + memcpy(curr_dst, _z_string_data(&locator), _z_string_len(&locator)); + curr_dst = _z_ptr_char_offset(curr_dst, (ptrdiff_t)_z_string_len(&locator)); + // Copy config + if (config != NULL) { + memcpy(curr_dst, config, config_len); + } + // Clean up + _z_string_clear(&locator); return ret; } diff --git a/src/link/link.c b/src/link/link.c index 91d484594..e7a20fba0 100644 --- a/src/link/link.c +++ b/src/link/link.c @@ -21,11 +21,11 @@ #include "zenoh-pico/link/manager.h" #include "zenoh-pico/utils/logging.h" -int8_t _z_open_link(_z_link_t *zl, const char *locator) { +int8_t _z_open_link(_z_link_t *zl, _z_string_t *locator) { int8_t ret = _Z_RES_OK; _z_endpoint_t ep; - ret = _z_endpoint_from_str(&ep, locator); + 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 @@ -74,11 +74,11 @@ int8_t _z_open_link(_z_link_t *zl, const char *locator) { return ret; } -int8_t _z_listen_link(_z_link_t *zl, const char *locator) { +int8_t _z_listen_link(_z_link_t *zl, _z_string_t *locator) { int8_t ret = _Z_RES_OK; _z_endpoint_t ep; - ret = _z_endpoint_from_str(&ep, locator); + 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 @@ -135,7 +135,7 @@ void _z_link_free(_z_link_t **l) { } } -size_t _z_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z_bytes_t *addr) { +size_t _z_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z_slice_t *addr) { size_t rb = link->_read_f(link, _z_zbuf_get_wptr(zbf), _z_zbuf_space_left(zbf), addr); if (rb != SIZE_MAX) { _z_zbuf_set_wpos(zbf, _z_zbuf_get_wpos(zbf) + rb); @@ -143,7 +143,7 @@ size_t _z_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z_bytes_t *addr return rb; } -size_t _z_link_recv_exact_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, size_t len, _z_bytes_t *addr) { +size_t _z_link_recv_exact_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, size_t len, _z_slice_t *addr) { size_t rb = link->_read_exact_f(link, _z_zbuf_get_wptr(zbf), len, addr); if (rb != SIZE_MAX) { _z_zbuf_set_wpos(zbf, _z_zbuf_get_wpos(zbf) + rb); @@ -165,7 +165,7 @@ int8_t _z_link_send_wbuf(const _z_link_t *link, const _z_wbuf_t *wbf) { break; } for (size_t i = 0; (i < _z_wbuf_len_iosli(wbf)) && (ret == _Z_RES_OK); i++) { - _z_bytes_t bs = _z_iosli_to_bytes(_z_wbuf_get_iosli(wbf, i)); + _z_slice_t bs = _z_iosli_to_bytes(_z_wbuf_get_iosli(wbf, i)); size_t n = bs.len; do { size_t wb = link->_write_f(link, bs.start, n); diff --git a/src/link/multicast/bt.c b/src/link/multicast/bt.c index 9c54b966c..8f6285eef 100644 --- a/src/link/multicast/bt.c +++ b/src/link/multicast/bt.c @@ -14,6 +14,7 @@ #include "zenoh-pico/link/config/bt.h" #include +#include #include #include "zenoh-pico/config.h" @@ -27,12 +28,13 @@ int8_t _z_endpoint_bt_valid(_z_endpoint_t *ep) { int8_t ret = _Z_RES_OK; - if (_z_str_eq(ep->_locator._protocol, BT_SCHEMA) != true) { + _z_string_t bt_str = _z_string_alias_str(BT_SCHEMA); + if (!_z_string_equals(&ep->_locator._protocol, &bt_str)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } if (ret == _Z_RES_OK) { - if (strlen(ep->_locator._address) == (size_t)0) { + if (_z_string_len(&ep->_locator._address) == (size_t)0) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } } @@ -40,6 +42,15 @@ int8_t _z_endpoint_bt_valid(_z_endpoint_t *ep) { return ret; } +static char *__z_convert_address_bt(_z_string_t *address) { + char *ret = NULL; + ret = (char *)z_malloc(_z_string_len(address) + 1); + if (ret != NULL) { + _z_str_n_copy(ret, _z_string_data(address), _z_string_len(address) + 1); + } + return ret; +} + int8_t _z_f_link_open_bt(_z_link_t *self) { int8_t ret = _Z_RES_OK; @@ -50,11 +61,11 @@ int8_t _z_f_link_open_bt(_z_link_t *self) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&self->_endpoint._config, BT_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } - self->_socket._bt._gname = self->_endpoint._locator._address; - ret = _z_open_bt(&self->_socket._bt._sock, self->_endpoint._locator._address, mode, profile, tout); + self->_socket._bt._gname = __z_convert_address_bt(&self->_endpoint._locator._address); + ret = _z_open_bt(&self->_socket._bt._sock, self->_socket._bt._gname, mode, profile, tout); return ret; } @@ -69,18 +80,18 @@ int8_t _z_f_link_listen_bt(_z_link_t *self) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&self->_endpoint._config, BT_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } - self->_socket._bt._gname = self->_endpoint._locator._address; - ret = _z_listen_bt(&self->_socket._bt._sock, self->_endpoint._locator._address, mode, profile, tout); + self->_socket._bt._gname = __z_convert_address_bt(&self->_endpoint._locator._address); + ret = _z_listen_bt(&self->_socket._bt._sock, self->_socket._bt._gname, mode, profile, tout); return ret; } void _z_f_link_close_bt(_z_link_t *self) { _z_close_bt(&self->_socket._bt._sock); } -void _z_f_link_free_bt(_z_link_t *self) {} +void _z_f_link_free_bt(_z_link_t *self) { _ZP_UNUSED(self); } size_t _z_f_link_write_bt(const _z_link_t *self, const uint8_t *ptr, size_t len) { return _z_send_bt(self->_socket._bt._sock, ptr, len); @@ -90,20 +101,20 @@ size_t _z_f_link_write_all_bt(const _z_link_t *self, const uint8_t *ptr, size_t return _z_send_bt(self->_socket._bt._sock, ptr, len); } -size_t _z_f_link_read_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +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_bytes_make(strlen(self->_socket._bt._gname)); + *addr = _z_slice_make(strlen(self->_socket._bt._gname)); (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, addr->len); } return rb; } -size_t _z_f_link_read_exact_bt(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +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_bytes_make(strlen(self->_socket._bt._gname)); + *addr = _z_slice_make(strlen(self->_socket._bt._gname)); (void)memcpy((uint8_t *)addr->start, self->_socket._bt._gname, addr->len); } diff --git a/src/link/multicast/udp.c b/src/link/multicast/udp.c index 69d359ba1..7169d0ac3 100644 --- a/src/link/multicast/udp.c +++ b/src/link/multicast/udp.c @@ -15,6 +15,7 @@ #include "zenoh-pico/link/config/udp.h" #include +#include #include #include @@ -25,30 +26,37 @@ #if Z_FEATURE_LINK_UDP_MULTICAST == 1 -char *__z_parse_port_segment_udp_multicast(const char *address) { +static char *__z_parse_port_segment_udp_multicast(_z_string_t *address) { char *ret = NULL; - const char *p_start = strrchr(address, ':'); - if (p_start != NULL) { - p_start = _z_cptr_char_offset(p_start, 1); - - const char *p_end = &address[strlen(address)]; + const char *p_start = _z_string_rchr(address, ':'); + if (p_start == NULL) { + return ret; + } + p_start = _z_cptr_char_offset(p_start, 1); + const char *p_end = _z_cptr_char_offset(_z_string_data(address), (ptrdiff_t)_z_string_len(address)); - size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; - ret = (char *)z_malloc(len); - if (ret != NULL) { - _z_str_n_copy(ret, p_start, len); - } + if (p_start >= p_end) { + return ret; + } + size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; + ret = (char *)z_malloc(len); + if (ret != NULL) { + _z_str_n_copy(ret, p_start, len); } return ret; } -char *__z_parse_address_segment_udp_multicast(const char *address) { +static char *__z_parse_address_segment_udp_multicast(_z_string_t *address) { char *ret = NULL; - const char *p_start = &address[0]; - const char *p_end = strrchr(address, ':'); + const char *p_start = _z_string_data(address); + const char *p_end = _z_string_rchr(address, ':'); + + if ((p_start == NULL) || (p_end == NULL)) { + return ret; + } // IPv6 if ((p_start[0] == '[') && (p_end[-1] == ']')) { @@ -63,7 +71,7 @@ char *__z_parse_address_segment_udp_multicast(const char *address) { // IPv4 else { size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; - ret = (char *)z_malloc(len); + ret = (char *)z_malloc(len + 1); if (ret != NULL) { _z_str_n_copy(ret, p_start, len); } @@ -75,12 +83,13 @@ char *__z_parse_address_segment_udp_multicast(const char *address) { int8_t _z_endpoint_udp_multicast_valid(_z_endpoint_t *endpoint) { int8_t ret = _Z_RES_OK; - if (_z_str_eq(endpoint->_locator._protocol, UDP_SCHEMA) != true) { + _z_string_t udp_str = _z_string_alias_str(UDP_SCHEMA); + if (!_z_string_equals(&endpoint->_locator._protocol, &udp_str)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } if (ret == _Z_RES_OK) { - char *s_address = __z_parse_address_segment_udp_multicast(endpoint->_locator._address); + char *s_address = __z_parse_address_segment_udp_multicast(&endpoint->_locator._address); if (s_address == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { @@ -89,11 +98,11 @@ int8_t _z_endpoint_udp_multicast_valid(_z_endpoint_t *endpoint) { } if (ret == _Z_RES_OK) { - char *s_port = __z_parse_port_segment_udp_multicast(endpoint->_locator._address); + char *s_port = __z_parse_port_segment_udp_multicast(&endpoint->_locator._address); if (s_port == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { - uint32_t port = strtoul(s_port, NULL, 10); + uint32_t port = (uint32_t)strtoul(s_port, NULL, 10); if ((port < (uint32_t)1) || (port > (uint32_t)65355)) { // Port numbers should range from 1 to 65355 ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } @@ -115,7 +124,7 @@ int8_t _z_f_link_open_udp_multicast(_z_link_t *self) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&self->_endpoint._config, UDP_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } const char *iface = _z_str_intmap_get(&self->_endpoint._config, UDP_CONFIG_IFACE_KEY); @@ -156,11 +165,11 @@ size_t _z_f_link_write_all_udp_multicast(const _z_link_t *self, const uint8_t *p return _z_send_udp_multicast(self->_socket._udp._msock, ptr, len, self->_socket._udp._rep); } -size_t _z_f_link_read_udp_multicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_udp_multicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { return _z_read_udp_multicast(self->_socket._udp._sock, ptr, len, self->_socket._udp._lep, addr); } -size_t _z_f_link_read_exact_udp_multicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_exact_udp_multicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { return _z_read_exact_udp_multicast(self->_socket._udp._sock, ptr, len, self->_socket._udp._lep, addr); } @@ -179,8 +188,8 @@ int8_t _z_new_link_udp_multicast(_z_link_t *zl, _z_endpoint_t endpoint) { zl->_mtu = _z_get_link_mtu_udp_multicast(); zl->_endpoint = endpoint; - char *s_address = __z_parse_address_segment_udp_multicast(endpoint._locator._address); - char *s_port = __z_parse_port_segment_udp_multicast(endpoint._locator._address); + char *s_address = __z_parse_address_segment_udp_multicast(&endpoint._locator._address); + char *s_port = __z_parse_port_segment_udp_multicast(&endpoint._locator._address); ret = _z_create_endpoint_udp(&zl->_socket._udp._rep, s_address, s_port); memset(&zl->_socket._udp._lep, 0, sizeof(zl->_socket._udp._lep)); z_free(s_address); diff --git a/src/link/unicast/serial.c b/src/link/unicast/serial.c index db034f07c..9f8f1d741 100644 --- a/src/link/unicast/serial.c +++ b/src/link/unicast/serial.c @@ -30,24 +30,36 @@ int8_t _z_endpoint_serial_valid(_z_endpoint_t *endpoint) { int8_t ret = _Z_RES_OK; - if (_z_str_eq(endpoint->_locator._protocol, SERIAL_SCHEMA) != true) { + _z_string_t ser_str = _z_string_alias_str(SERIAL_SCHEMA); + if (!_z_string_equals(&endpoint->_locator._protocol, &ser_str)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } if (ret == _Z_RES_OK) { - char *p_dot = strchr(endpoint->_locator._address, '.'); + size_t addr_len = _z_string_len(&endpoint->_locator._address); + const char *p_start = _z_string_data(&endpoint->_locator._address); + const char *p_dot = (char *)memchr(p_start, (int)'.', addr_len); if (p_dot != NULL) { - if ((endpoint->_locator._address == p_dot) || - (strlen(p_dot) == (size_t)1)) { // If dot is the first or last character + size_t dot_loc = _z_ptr_char_diff(p_dot, p_start); + // Check if dot is first or last character + if ((dot_loc == 0) || (dot_loc == addr_len)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } } else { - if (strlen(endpoint->_locator._address) == (size_t)0) { + if (_z_string_len(&endpoint->_locator._address) == (size_t)0) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } } } + return ret; +} +static char *__z_convert_address_serial(_z_string_t *address) { + char *ret = NULL; + ret = (char *)z_malloc(_z_string_len(address) + 1); + if (ret != NULL) { + _z_str_n_copy(ret, _z_string_data(address), _z_string_len(address) + 1); + } return ret; } @@ -55,16 +67,17 @@ int8_t _z_f_link_open_serial(_z_link_t *self) { int8_t ret = _Z_RES_OK; const char *baudrate_str = _z_str_intmap_get(&self->_endpoint._config, SERIAL_CONFIG_BAUDRATE_KEY); - uint32_t baudrate = strtoul(baudrate_str, NULL, 10); + uint32_t baudrate = (uint32_t)strtoul(baudrate_str, NULL, 10); + char *address = __z_convert_address_serial(&self->_endpoint._locator._address); + char *p_dot = strchr(address, '.'); - char *p_dot = strchr(self->_endpoint._locator._address, '.'); if (p_dot != NULL) { - uint32_t txpin = strtoul(self->_endpoint._locator._address, &p_dot, 10); + uint32_t txpin = (uint32_t)strtoul(address, &p_dot, 10); p_dot = _z_ptr_char_offset(p_dot, 1); - uint32_t rxpin = strtoul(p_dot, NULL, 10); + uint32_t rxpin = (uint32_t)strtoul(p_dot, NULL, 10); ret = _z_open_serial_from_pins(&self->_socket._serial._sock, txpin, rxpin, baudrate); } else { - ret = _z_open_serial_from_dev(&self->_socket._serial._sock, self->_endpoint._locator._address, baudrate); + ret = _z_open_serial_from_dev(&self->_socket._serial._sock, address, baudrate); } return ret; @@ -74,16 +87,17 @@ int8_t _z_f_link_listen_serial(_z_link_t *self) { int8_t ret = _Z_RES_OK; const char *baudrate_str = _z_str_intmap_get(&self->_endpoint._config, SERIAL_CONFIG_BAUDRATE_KEY); - uint32_t baudrate = strtoul(baudrate_str, NULL, 10); + uint32_t baudrate = (uint32_t)strtoul(baudrate_str, NULL, 10); + char *address = __z_convert_address_serial(&self->_endpoint._locator._address); + char *p_dot = strchr(address, '.'); - char *p_dot = strchr(self->_endpoint._locator._address, '.'); if (p_dot != NULL) { - uint32_t txpin = strtoul(self->_endpoint._locator._address, &p_dot, 10); + uint32_t txpin = (uint32_t)strtoul(address, &p_dot, 10); p_dot = _z_ptr_char_offset(p_dot, 1); - uint32_t rxpin = strtoul(p_dot, NULL, 10); + uint32_t rxpin = (uint32_t)strtoul(p_dot, NULL, 10); ret = _z_listen_serial_from_pins(&self->_socket._serial._sock, txpin, rxpin, baudrate); } else { - ret = _z_listen_serial_from_dev(&self->_socket._serial._sock, self->_endpoint._locator._address, baudrate); + ret = _z_listen_serial_from_dev(&self->_socket._serial._sock, address, baudrate); } return ret; @@ -101,12 +115,12 @@ size_t _z_f_link_write_all_serial(const _z_link_t *self, const uint8_t *ptr, siz return _z_send_serial(self->_socket._serial._sock, ptr, len); } -size_t _z_f_link_read_serial(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_serial(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_serial(self->_socket._serial._sock, ptr, len); } -size_t _z_f_link_read_exact_serial(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_exact_serial(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_exact_serial(self->_socket._serial._sock, ptr, len); } diff --git a/src/link/unicast/tcp.c b/src/link/unicast/tcp.c index a6cf3de7a..1d1038711 100644 --- a/src/link/unicast/tcp.c +++ b/src/link/unicast/tcp.c @@ -25,31 +25,37 @@ #if Z_FEATURE_LINK_TCP == 1 -char *__z_parse_port_segment_tcp(char *address) { +static char *__z_parse_port_segment_tcp(_z_string_t *address) { char *ret = NULL; - const char *p_start = strrchr(address, ':'); - if (p_start != NULL) { - p_start = _z_cptr_char_offset(p_start, 1); - - const char *p_end = &address[strlen(address)]; + const char *p_start = _z_string_rchr(address, ':'); + if (p_start == NULL) { + return ret; + } + p_start = _z_cptr_char_offset(p_start, 1); + const char *p_end = _z_cptr_char_offset(_z_string_data(address), (ptrdiff_t)_z_string_len(address)); - size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; - ret = (char *)z_malloc(len); - if (ret != NULL) { - _z_str_n_copy(ret, p_start, len); - } + if (p_start >= p_end) { + return ret; + } + size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; + ret = (char *)z_malloc(len); + if (ret != NULL) { + _z_str_n_copy(ret, p_start, len); } return ret; } -char *__z_parse_address_segment_tcp(char *address) { +static char *__z_parse_address_segment_tcp(_z_string_t *address) { char *ret = NULL; - const char *p_start = &address[0]; - const char *p_end = strrchr(address, ':'); + const char *p_start = _z_string_data(address); + const char *p_end = _z_string_rchr(address, ':'); + if ((p_start == NULL) || (p_end == NULL)) { + return ret; + } // IPv6 if ((p_start[0] == '[') && (p_end[-1] == ']')) { p_start = _z_cptr_char_offset(p_start, 1); @@ -75,12 +81,13 @@ char *__z_parse_address_segment_tcp(char *address) { int8_t _z_endpoint_tcp_valid(_z_endpoint_t *endpoint) { int8_t ret = _Z_RES_OK; - if (_z_str_eq(endpoint->_locator._protocol, TCP_SCHEMA) != true) { + _z_string_t tcp_str = _z_string_alias_str(TCP_SCHEMA); + if (!_z_string_equals(&endpoint->_locator._protocol, &tcp_str)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } if (ret == _Z_RES_OK) { - char *s_address = __z_parse_address_segment_tcp(endpoint->_locator._address); + char *s_address = __z_parse_address_segment_tcp(&endpoint->_locator._address); if (s_address == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { @@ -89,11 +96,11 @@ int8_t _z_endpoint_tcp_valid(_z_endpoint_t *endpoint) { } if (ret == _Z_RES_OK) { - char *s_port = __z_parse_port_segment_tcp(endpoint->_locator._address); + char *s_port = __z_parse_port_segment_tcp(&endpoint->_locator._address); if (s_port == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { - uint32_t port = strtoul(s_port, NULL, 10); + uint32_t port = (uint32_t)strtoul(s_port, NULL, 10); if ((port < (uint32_t)1) || (port > (uint32_t)65355)) { // Port numbers should range from 1 to 65355 ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } @@ -110,7 +117,7 @@ int8_t _z_f_link_open_tcp(_z_link_t *zl) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&zl->_endpoint._config, TCP_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } ret = _z_open_tcp(&zl->_socket._tcp._sock, zl->_socket._tcp._rep, tout); @@ -138,12 +145,12 @@ size_t _z_f_link_write_all_tcp(const _z_link_t *zl, const uint8_t *ptr, size_t l return _z_send_tcp(zl->_socket._tcp._sock, ptr, len); } -size_t _z_f_link_read_tcp(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_tcp(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_tcp(zl->_socket._tcp._sock, ptr, len); } -size_t _z_f_link_read_exact_tcp(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_exact_tcp(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_exact_tcp(zl->_socket._tcp._sock, ptr, len); } @@ -163,8 +170,8 @@ int8_t _z_new_link_tcp(_z_link_t *zl, _z_endpoint_t *endpoint) { zl->_mtu = _z_get_link_mtu_tcp(); zl->_endpoint = *endpoint; - char *s_address = __z_parse_address_segment_tcp(endpoint->_locator._address); - char *s_port = __z_parse_port_segment_tcp(endpoint->_locator._address); + char *s_address = __z_parse_address_segment_tcp(&endpoint->_locator._address); + char *s_port = __z_parse_port_segment_tcp(&endpoint->_locator._address); ret = _z_create_endpoint_tcp(&zl->_socket._tcp._rep, s_address, s_port); z_free(s_address); z_free(s_port); diff --git a/src/link/unicast/udp.c b/src/link/unicast/udp.c index cd93cdff7..8f38830bd 100644 --- a/src/link/unicast/udp.c +++ b/src/link/unicast/udp.c @@ -15,6 +15,7 @@ #include "zenoh-pico/link/config/udp.h" #include +#include #include #include @@ -25,31 +26,37 @@ #if Z_FEATURE_LINK_UDP_UNICAST == 1 -char *__z_parse_port_segment_udp_unicast(char *address) { +static char *__z_parse_port_segment_udp_unicast(_z_string_t *address) { char *ret = NULL; - const char *p_start = strrchr(address, ':'); - if (p_start != NULL) { - p_start = _z_cptr_char_offset(p_start, 1); - - const char *p_end = &address[strlen(address)]; + const char *p_start = _z_string_rchr(address, ':'); + if (p_start == NULL) { + return ret; + } + p_start = _z_cptr_char_offset(p_start, 1); + const char *p_end = _z_cptr_char_offset(_z_string_data(address), (ptrdiff_t)_z_string_len(address)); - size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; - ret = (char *)z_malloc(len); - if (ret != NULL) { - _z_str_n_copy(ret, p_start, len); - } + if (p_start >= p_end) { + return ret; + } + size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; + ret = (char *)z_malloc(len); + if (ret != NULL) { + _z_str_n_copy(ret, p_start, len); } return ret; } -char *__z_parse_address_segment_udp_unicast(char *address) { +static char *__z_parse_address_segment_udp_unicast(_z_string_t *address) { char *ret = NULL; - const char *p_start = &address[0]; - const char *p_end = strrchr(address, ':'); + const char *p_start = _z_string_data(address); + const char *p_end = _z_string_rchr(address, ':'); + if ((p_start == NULL) || (p_end == NULL)) { + return ret; + } // IPv6 if ((p_start[0] == '[') && (p_end[-1] == ']')) { p_start = _z_cptr_char_offset(p_start, 1); @@ -75,12 +82,13 @@ char *__z_parse_address_segment_udp_unicast(char *address) { int8_t _z_endpoint_udp_unicast_valid(_z_endpoint_t *endpoint) { int8_t ret = _Z_RES_OK; - if (_z_str_eq(endpoint->_locator._protocol, UDP_SCHEMA) != true) { + _z_string_t udp_str = _z_string_alias_str(UDP_SCHEMA); + if (!_z_string_equals(&endpoint->_locator._protocol, &udp_str)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } if (ret == _Z_RES_OK) { - char *s_address = __z_parse_address_segment_udp_unicast(endpoint->_locator._address); + char *s_address = __z_parse_address_segment_udp_unicast(&endpoint->_locator._address); if (s_address == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { @@ -89,11 +97,11 @@ int8_t _z_endpoint_udp_unicast_valid(_z_endpoint_t *endpoint) { } if (ret == _Z_RES_OK) { - char *s_port = __z_parse_port_segment_udp_unicast(endpoint->_locator._address); + char *s_port = __z_parse_port_segment_udp_unicast(&endpoint->_locator._address); if (s_port == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { - uint32_t port = strtoul(s_port, NULL, 10); + uint32_t port = (uint32_t)strtoul(s_port, NULL, 10); if ((port < (uint32_t)1) || (port > (uint32_t)65355)) { // Port numbers should range from 1 to 65355 ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } @@ -110,7 +118,7 @@ int8_t _z_f_link_open_udp_unicast(_z_link_t *self) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&self->_endpoint._config, UDP_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } ret = _z_open_udp_unicast(&self->_socket._udp._sock, self->_socket._udp._rep, tout); @@ -124,7 +132,7 @@ int8_t _z_f_link_listen_udp_unicast(_z_link_t *self) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&self->_endpoint._config, UDP_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } ret = _z_listen_udp_unicast(&self->_socket._udp._sock, self->_socket._udp._rep, tout); @@ -144,12 +152,12 @@ size_t _z_f_link_write_all_udp_unicast(const _z_link_t *self, const uint8_t *ptr return _z_send_udp_unicast(self->_socket._udp._sock, ptr, len, self->_socket._udp._rep); } -size_t _z_f_link_read_udp_unicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_udp_unicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_udp_unicast(self->_socket._udp._sock, ptr, len); } -size_t _z_f_link_read_exact_udp_unicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_exact_udp_unicast(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_exact_udp_unicast(self->_socket._udp._sock, ptr, len); } @@ -169,8 +177,8 @@ int8_t _z_new_link_udp_unicast(_z_link_t *zl, _z_endpoint_t endpoint) { zl->_mtu = _z_get_link_mtu_udp_unicast(); zl->_endpoint = endpoint; - char *s_address = __z_parse_address_segment_udp_unicast(endpoint._locator._address); - char *s_port = __z_parse_port_segment_udp_unicast(endpoint._locator._address); + char *s_address = __z_parse_address_segment_udp_unicast(&endpoint._locator._address); + char *s_port = __z_parse_port_segment_udp_unicast(&endpoint._locator._address); ret = _z_create_endpoint_udp(&zl->_socket._udp._rep, s_address, s_port); z_free(s_address); z_free(s_port); diff --git a/src/link/unicast/ws.c b/src/link/unicast/ws.c index f59fde872..970744051 100644 --- a/src/link/unicast/ws.c +++ b/src/link/unicast/ws.c @@ -26,14 +26,14 @@ #if Z_FEATURE_LINK_WS == 1 -char *__z_parse_port_segment_ws(char *address) { +char *__z_parse_port_segment_ws(_z_string_t *address) { char *ret = NULL; - const char *p_start = strrchr(address, ':'); + const char *p_start = _z_string_rchr(address, ':'); if (p_start != NULL) { p_start = _z_cptr_char_offset(p_start, 1); - const char *p_end = &address[strlen(address)]; + const char *p_end = _z_cptr_char_offset(_z_string_data(address), (ptrdiff_t)_z_string_len(address)); size_t len = _z_ptr_char_diff(p_end, p_start) + (size_t)1; ret = (char *)z_malloc(len); @@ -45,11 +45,11 @@ char *__z_parse_port_segment_ws(char *address) { return ret; } -char *__z_parse_address_segment_ws(char *address) { +char *__z_parse_address_segment_ws(_z_string_t *address) { char *ret = NULL; - const char *p_start = &address[0]; - const char *p_end = strrchr(address, ':'); + const char *p_start = _z_string_data(address); + const char *p_end = _z_string_rchr(address, ':'); // IPv6 if ((p_start[0] == '[') && (p_end[-1] == ']')) { @@ -76,12 +76,13 @@ char *__z_parse_address_segment_ws(char *address) { int8_t _z_endpoint_ws_valid(_z_endpoint_t *endpoint) { int8_t ret = _Z_RES_OK; - if (_z_str_eq(endpoint->_locator._protocol, WS_SCHEMA) != true) { + _z_string_t str = _z_string_alias_str(WS_SCHEMA); + if (_z_string_equals(&endpoint->_locator._protocol, &str)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } if (ret == _Z_RES_OK) { - char *s_addr = __z_parse_address_segment_ws(endpoint->_locator._address); + char *s_addr = __z_parse_address_segment_ws(&endpoint->_locator._address); if (s_addr == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { @@ -90,11 +91,11 @@ int8_t _z_endpoint_ws_valid(_z_endpoint_t *endpoint) { } if (ret == _Z_RES_OK) { - char *s_port = __z_parse_port_segment_ws(endpoint->_locator._address); + char *s_port = __z_parse_port_segment_ws(&endpoint->_locator._address); if (s_port == NULL) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } else { - uint32_t port = strtoul(s_port, NULL, 10); + uint32_t port = (uint32_t)strtoul(s_port, NULL, 10); if ((port < (uint32_t)1) || (port > (uint32_t)65355)) { // Port numbers should range from 1 to 65355 ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } @@ -111,7 +112,7 @@ int8_t _z_f_link_open_ws(_z_link_t *zl) { uint32_t tout = Z_CONFIG_SOCKET_TIMEOUT; char *tout_as_str = _z_str_intmap_get(&zl->_endpoint._config, WS_CONFIG_TOUT_KEY); if (tout_as_str != NULL) { - tout = strtoul(tout_as_str, NULL, 10); + tout = (uint32_t)strtoul(tout_as_str, NULL, 10); } ret = _z_open_ws(&zl->_socket._ws._sock, zl->_socket._ws._rep, tout); @@ -139,12 +140,12 @@ size_t _z_f_link_write_all_ws(const _z_link_t *zl, const uint8_t *ptr, size_t le return _z_send_ws(zl->_socket._ws._sock, ptr, len); } -size_t _z_f_link_read_ws(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_ws(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_ws(zl->_socket._ws._sock, ptr, len); } -size_t _z_f_link_read_exact_ws(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +size_t _z_f_link_read_exact_ws(const _z_link_t *zl, uint8_t *ptr, size_t len, _z_slice_t *addr) { (void)(addr); return _z_read_exact_ws(zl->_socket._ws._sock, ptr, len); } @@ -164,8 +165,8 @@ int8_t _z_new_link_ws(_z_link_t *zl, _z_endpoint_t *endpoint) { zl->_mtu = _z_get_link_mtu_ws(); zl->_endpoint = *endpoint; - char *s_addr = __z_parse_address_segment_ws(endpoint->_locator._address); - char *s_port = __z_parse_port_segment_ws(endpoint->_locator._address); + char *s_addr = __z_parse_address_segment_ws(&endpoint->_locator._address); + char *s_port = __z_parse_port_segment_ws(&endpoint->_locator._address); ret = _z_create_endpoint_ws(&zl->_socket._ws._rep, s_addr, s_port); z_free(s_addr); z_free(s_port); diff --git a/src/net/config.c b/src/net/config.c index 7b0457836..def05b16e 100644 --- a/src/net/config.c +++ b/src/net/config.c @@ -17,29 +17,30 @@ #include "zenoh-pico/net/config.h" -_z_config_t *_z_config_empty(void) { - _z_config_t *config = (_z_config_t *)z_malloc(sizeof(_z_config_t)); - if (config != NULL) { - _z_config_init(config); - } +_z_config_t _z_config_empty(void) { + _z_config_t config; + _z_config_init(&config); return config; } -_z_config_t *_z_config_default(void) { return _z_config_client(NULL); } +int8_t _z_config_default(_z_config_t *config) { return _z_config_client(config, NULL); } -_z_config_t *_z_config_client(const char *locator) { - _z_config_t *ps = _z_config_empty(); - if (ps != NULL) { - _zp_config_insert(ps, Z_CONFIG_MODE_KEY, _z_string_make(Z_CONFIG_MODE_CLIENT)); - if (locator != NULL) { - // Connect only to the provided locator - _zp_config_insert(ps, Z_CONFIG_CONNECT_KEY, _z_string_make(locator)); - } else { - // The locator is not provided, we should perform scouting - _zp_config_insert(ps, Z_CONFIG_MULTICAST_SCOUTING_KEY, _z_string_make(Z_CONFIG_MULTICAST_SCOUTING_DEFAULT)); - _zp_config_insert(ps, Z_CONFIG_MULTICAST_LOCATOR_KEY, _z_string_make(Z_CONFIG_MULTICAST_LOCATOR_DEFAULT)); - _zp_config_insert(ps, Z_CONFIG_SCOUTING_TIMEOUT_KEY, _z_string_make(Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT)); - } +int8_t _z_config_client(_z_config_t *ps, const char *locator) { + *ps = _z_config_empty(); + _Z_RETURN_IF_ERR(_zp_config_insert(ps, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_CLIENT)); + if (locator != NULL) { + // Connect only to the provided locator + _Z_CLEAN_RETURN_IF_ERR(_zp_config_insert(ps, Z_CONFIG_CONNECT_KEY, locator), _z_config_clear(ps)); + } else { + // The locator is not provided, we should perform scouting + _Z_CLEAN_RETURN_IF_ERR( + _zp_config_insert(ps, Z_CONFIG_MULTICAST_SCOUTING_KEY, Z_CONFIG_MULTICAST_SCOUTING_DEFAULT), + _z_config_clear(ps)); + _Z_CLEAN_RETURN_IF_ERR( + _zp_config_insert(ps, Z_CONFIG_MULTICAST_LOCATOR_KEY, Z_CONFIG_MULTICAST_LOCATOR_DEFAULT), + _z_config_clear(ps)); + _Z_CLEAN_RETURN_IF_ERR(_zp_config_insert(ps, Z_CONFIG_SCOUTING_TIMEOUT_KEY, Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT), + _z_config_clear(ps)); } - return ps; + return _Z_RES_OK; } diff --git a/src/net/encoding.c b/src/net/encoding.c new file mode 100644 index 000000000..2b2a48b6d --- /dev/null +++ b/src/net/encoding.c @@ -0,0 +1,69 @@ +// +// Copyright (c) 2024 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/net/encoding.h" + +#include + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" + +int8_t _z_encoding_make(_z_encoding_t *encoding, uint16_t id, const char *schema, size_t len) { + encoding->id = id; + // Clone schema + if (schema != NULL) { + encoding->schema = _z_string_copy_from_substr(schema, len); + if (_z_string_len(&encoding->schema) != len) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + } else { + encoding->schema = _z_string_null(); + } + 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)); +} + +int8_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; + 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); +} + +_z_encoding_t _z_encoding_steal(_z_encoding_t *val) { + _z_encoding_t ret = { + .id = val->id, + .schema = _z_string_steal(&val->schema), + }; + val->id = _Z_ENCODING_ID_DEFAULT; + return ret; +} diff --git a/src/net/filtering.c b/src/net/filtering.c new file mode 100644 index 000000000..0787c462b --- /dev/null +++ b/src/net/filtering.c @@ -0,0 +1,121 @@ +// +// 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/net/filtering.h" + +#include +#include +#include + +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/config.h" +#include "zenoh-pico/net/primitives.h" +#include "zenoh-pico/net/query.h" +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/network.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/queryable.h" +#include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/utils.h" +#include "zenoh-pico/utils/logging.h" + +#if Z_FEATURE_INTEREST == 1 +static void _z_write_filter_callback(const _z_interest_msg_t *msg, void *arg) { + _z_writer_filter_ctx_t *ctx = (_z_writer_filter_ctx_t *)arg; + + switch (ctx->state) { + // Update init state + case WRITE_FILTER_INIT: + switch (msg->type) { + case _Z_INTEREST_MSG_TYPE_FINAL: + ctx->state = WRITE_FILTER_ACTIVE; // No subscribers + break; + + case _Z_INTEREST_MSG_TYPE_DECL_SUBSCRIBER: + ctx->state = WRITE_FILTER_OFF; + ctx->decl_id = msg->id; + break; + + default: // Nothing to do + break; + } + break; + // Remove filter if we receive a subscribe + case WRITE_FILTER_ACTIVE: + if (msg->type == _Z_INTEREST_MSG_TYPE_DECL_SUBSCRIBER) { + ctx->state = WRITE_FILTER_OFF; + ctx->decl_id = msg->id; + } + break; + // Activate filter if subscribe is removed + case WRITE_FILTER_OFF: + if ((msg->type == _Z_INTEREST_MSG_TYPE_UNDECL_SUBSCRIBER) && (ctx->decl_id == msg->id)) { + ctx->state = WRITE_FILTER_ACTIVE; + ctx->decl_id = 0; + } + break; + // Nothing to do + default: + break; + } +} + +int8_t _z_write_filter_create(_z_publisher_t *pub) { + uint8_t flags = _Z_INTEREST_FLAG_KEYEXPRS | _Z_INTEREST_FLAG_SUBSCRIBERS | _Z_INTEREST_FLAG_RESTRICTED | + _Z_INTEREST_FLAG_CURRENT | _Z_INTEREST_FLAG_FUTURE | _Z_INTEREST_FLAG_AGGREGATE; + _z_writer_filter_ctx_t *ctx = (_z_writer_filter_ctx_t *)z_malloc(sizeof(_z_writer_filter_ctx_t)); + + if (ctx == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + ctx->state = WRITE_FILTER_INIT; + ctx->decl_id = 0; + + pub->_filter.ctx = ctx; + pub->_filter._interest_id = + _z_add_interest(_Z_RC_IN_VAL(&pub->_zn), _z_keyexpr_alias_from_user_defined(pub->_key, true), + _z_write_filter_callback, flags, (void *)ctx); + if (pub->_filter._interest_id == 0) { + z_free(ctx); + return _Z_ERR_GENERIC; + } + return _Z_RES_OK; +} + +int8_t _z_write_filter_destroy(const _z_publisher_t *pub) { + _Z_RETURN_IF_ERR(_z_remove_interest(_Z_RC_IN_VAL(&pub->_zn), pub->_filter._interest_id)); + z_free(pub->_filter.ctx); + return _Z_RES_OK; +} + +_Bool _z_write_filter_active(const _z_publisher_t *pub) { return (pub->_filter.ctx->state == WRITE_FILTER_ACTIVE); } + +#else +int8_t _z_write_filter_create(_z_publisher_t *pub) { + _ZP_UNUSED(pub); + return _Z_RES_OK; +} + +int8_t _z_write_filter_destroy(const _z_publisher_t *pub) { + _ZP_UNUSED(pub); + return _Z_RES_OK; +} + +_Bool _z_write_filter_active(const _z_publisher_t *pub) { + _ZP_UNUSED(pub); + return false; +} + +#endif diff --git a/src/net/memory.c b/src/net/memory.c index 33f7582ec..3152a85c0 100644 --- a/src/net/memory.c +++ b/src/net/memory.c @@ -11,49 +11,12 @@ // Contributors: // ZettaScale Zenoh Team, -#include "zenoh-pico/net/memory.h" - #include +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/protocol/core.h" -void _z_sample_move(_z_sample_t *dst, _z_sample_t *src) { - dst->keyexpr._id = src->keyexpr._id; // FIXME: call the z_keyexpr_move - dst->keyexpr._suffix = src->keyexpr._suffix; // FIXME: call the z_keyexpr_move - src->keyexpr._suffix = NULL; // FIXME: call the z_keyexpr_move - - _z_bytes_move(&dst->payload, &src->payload); - - dst->encoding.prefix = src->encoding.prefix; // FIXME: call the z_encoding_move - _z_bytes_move(&dst->encoding.suffix, &src->encoding.suffix); // FIXME: call the z_encoding_move - - 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_clear(&sample->payload); - _z_bytes_clear(&sample->encoding.suffix); // FIXME: call the z_encoding_clear - _z_timestamp_clear(&sample->timestamp); -} - -void _z_sample_free(_z_sample_t **sample) { - _z_sample_t *ptr = *sample; - - if (ptr != NULL) { - _z_sample_clear(ptr); - - z_free(ptr); - *sample = NULL; - } -} - -void _z_hello_clear(_z_hello_t *hello) { - if (hello->locators.len > 0) { - _z_str_array_clear(&hello->locators); - } -} +void _z_hello_clear(_z_hello_t *hello) { _z_string_svec_clear(&hello->_locators); } void _z_hello_free(_z_hello_t **hello) { _z_hello_t *ptr = *hello; @@ -66,25 +29,9 @@ void _z_hello_free(_z_hello_t **hello) { } } -void _z_reply_data_clear(_z_reply_data_t *reply_data) { - _z_sample_clear(&reply_data->sample); - reply_data->replier_id = _z_id_empty(); -} - -void _z_reply_data_free(_z_reply_data_t **reply_data) { - _z_reply_data_t *ptr = *reply_data; - - if (ptr != NULL) { - _z_reply_data_clear(ptr); - - z_free(ptr); - *reply_data = NULL; - } -} - void _z_value_clear(_z_value_t *value) { - _z_bytes_clear(&value->encoding.suffix); - _z_bytes_clear(&value->payload); + _z_encoding_clear(&value->encoding); + _z_bytes_drop(&value->payload); } void _z_value_free(_z_value_t **value) { @@ -97,3 +44,5 @@ void _z_value_free(_z_value_t **value) { *value = NULL; } } + +_Bool _z_hello_check(const _z_hello_t *hello) { return _z_id_check(hello->_zid); } diff --git a/src/net/primitives.c b/src/net/primitives.c index 0a31e89bd..70e4ab6e7 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -18,14 +18,16 @@ #include #include "zenoh-pico/api/constants.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/net/filtering.h" #include "zenoh-pico/net/logger.h" -#include "zenoh-pico/net/memory.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/declarations.h" #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/interest.h" #include "zenoh-pico/session/query.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" @@ -35,33 +37,35 @@ #include "zenoh-pico/utils/result.h" /*------------------ Scouting ------------------*/ -void _z_scout(const z_what_t what, const _z_id_t zid, const char *locator, const uint32_t timeout, +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_hello_list_t *hellos = _z_scout_inner(what, zid, locator, timeout, false); while (hellos != NULL) { _z_hello_t *hello = NULL; hellos = _z_hello_list_pop(hellos, &hello); - (*callback)(hello, arg_call); // callback takes ownership of hello + (*callback)(hello, arg_call); + _z_hello_free(&hello); } if (dropper != NULL) { (*dropper)(arg_drop); } + _z_hello_list_free(&hellos); } /*------------------ Resource Declaration ------------------*/ uint16_t _z_declare_resource(_z_session_t *zn, _z_keyexpr_t keyexpr) { uint16_t ret = Z_RESOURCE_ID_NONE; - if (zn->_tp._type == - _Z_TRANSPORT_UNICAST_TYPE) { // FIXME: remove when resource declaration is implemented for multicast transport + // FIXME: remove this check when resource declaration is implemented for multicast transport + if (zn->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { uint16_t id = _z_register_resource(zn, keyexpr, 0, _Z_KEYEXPR_MAPPING_LOCAL); if (id != 0) { // Build the declare message to send on the wire _z_keyexpr_t alias = _z_keyexpr_alias(keyexpr); _z_declaration_t declaration = _z_make_decl_keyexpr(id, &alias); - _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { ret = id; } else { @@ -81,7 +85,7 @@ int8_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid) { if (r != NULL) { // Build the declare message to send on the wire _z_declaration_t declaration = _z_make_undecl_keyexpr(rid); - _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { _z_unregister_resource(zn, rid, _Z_KEYEXPR_MAPPING_LOCAL); // Only if message is send, local resource is removed @@ -98,41 +102,37 @@ int8_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid) { #if Z_FEATURE_PUBLICATION == 1 /*------------------ Publisher Declaration ------------------*/ -_z_publisher_t *_z_declare_publisher(_z_session_rc_t *zn, _z_keyexpr_t keyexpr, - z_congestion_control_t congestion_control, z_priority_t priority) { +_z_publisher_t _z_declare_publisher(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_encoding_t *encoding, + z_congestion_control_t congestion_control, z_priority_t priority, + _Bool is_express) { // Allocate publisher - _z_publisher_t *ret = (_z_publisher_t *)z_malloc(sizeof(_z_publisher_t)); - if (ret == NULL) { - return NULL; - } + _z_publisher_t ret; // Fill publisher - ret->_key = _z_keyexpr_duplicate(keyexpr); - ret->_id = _z_get_entity_id(&zn->in->val); - ret->_congestion_control = congestion_control; - ret->_priority = priority; - ret->_zn = _z_session_rc_clone(zn); + 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; + ret._is_express = is_express; + ret._zn = _z_session_rc_clone(zn); + ret._encoding = encoding == NULL ? _z_encoding_null() : _z_encoding_steal(encoding); return ret; } int8_t _z_undeclare_publisher(_z_publisher_t *pub) { - if (pub == NULL) { + if (pub == NULL || _Z_RC_IS_NULL(&pub->_zn)) { return _Z_ERR_ENTITY_UNKNOWN; } // Clear publisher - _z_undeclare_resource(&pub->_zn.in->val, pub->_key._id); + _z_write_filter_destroy(pub); + _z_undeclare_resource(_Z_RC_IN_VAL(&pub->_zn), pub->_key._id); _z_session_rc_drop(&pub->_zn); return _Z_RES_OK; } /*------------------ Write ------------------*/ -int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, const size_t len, - const _z_encoding_t encoding, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, - z_priority_t priority -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t attachment -#endif -) { +int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, const _z_encoding_t *encoding, + const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, z_priority_t priority, + _Bool is_express, const _z_timestamp_t *timestamp, const _z_bytes_t attachment) { int8_t ret = _Z_RES_OK; _z_network_message_t msg; switch (kind) { @@ -142,17 +142,16 @@ int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *pay ._body._push = { ._key = keyexpr, - ._qos = _z_n_qos_make(0, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), + ._qos = _z_n_qos_make(is_express, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), ._timestamp = _z_timestamp_null(), ._body._is_put = true, ._body._body._put = { - ._commons = {._timestamp = _z_timestamp_null(), ._source_info = _z_source_info_null()}, - ._payload = _z_bytes_wrap(payload, len), - ._encoding = encoding, -#if Z_FEATURE_ATTACHMENT == 1 - ._attachment = {.is_encoded = false, .body.decoded = attachment}, -#endif + ._commons = {._timestamp = ((timestamp != NULL) ? *timestamp : _z_timestamp_null()), + ._source_info = _z_source_info_null()}, + ._payload = payload, + ._encoding = encoding == NULL ? _z_encoding_null() : *encoding, + ._attachment = attachment, }, }, }; @@ -163,14 +162,17 @@ int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *pay ._body._push = { ._key = keyexpr, - ._qos = _z_n_qos_make(0, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), + ._qos = _z_n_qos_make(is_express, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), ._timestamp = _z_timestamp_null(), ._body._is_put = false, - ._body._body._del = {._commons = {._timestamp = _z_timestamp_null(), + ._body._body._del = {._commons = {._timestamp = + ((timestamp != NULL) ? *timestamp : _z_timestamp_null()), ._source_info = _z_source_info_null()}}, }, }; break; + default: + return _Z_ERR_GENERIC; } if (_z_send_n_msg(zn, &msg, Z_RELIABILITY_RELIABLE, cong_ctrl) != _Z_RES_OK) { @@ -185,157 +187,144 @@ int8_t _z_write(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *pay #if Z_FEATURE_SUBSCRIPTION == 1 /*------------------ Subscriber Declaration ------------------*/ -_z_subscriber_t *_z_declare_subscriber(_z_session_rc_t *zn, _z_keyexpr_t keyexpr, _z_subinfo_t sub_info, - _z_data_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_subinfo_t sub_info, + _z_data_handler_t callback, _z_drop_handler_t dropper, void *arg) { _z_subscription_t s; - s._id = _z_get_entity_id(&zn->in->val); + s._id = _z_get_entity_id(_Z_RC_IN_VAL(zn)); s._key_id = keyexpr._id; - s._key = _z_get_expanded_key_from_key(&zn->in->val, &keyexpr); + s._key = _z_get_expanded_key_from_key(_Z_RC_IN_VAL(zn), &keyexpr); s._info = sub_info; s._callback = callback; s._dropper = dropper; s._arg = arg; - // Allocate subscriber - _z_subscriber_t *ret = (_z_subscriber_t *)z_malloc(sizeof(_z_subscriber_t)); - if (ret == NULL) { - _z_subscription_clear(&s); - return NULL; - } + _z_subscriber_t ret = _z_subscriber_null(); // Register subscription, stored at session-level, do not drop it by the end of this function. - _z_subscription_rc_t *sp_s = _z_register_subscription(&zn->in->val, _Z_RESOURCE_IS_LOCAL, &s); + _z_subscription_rc_t *sp_s = _z_register_subscription(_Z_RC_IN_VAL(zn), _Z_RESOURCE_IS_LOCAL, &s); if (sp_s == NULL) { - _z_subscriber_free(&ret); - return NULL; + _z_subscriber_clear(&ret); + return ret; } // Build the declare message to send on the wire - _z_declaration_t declaration = _z_make_decl_subscriber( - &keyexpr, s._id, sub_info.reliability == Z_RELIABILITY_RELIABLE, sub_info.mode == Z_SUBMODE_PULL); - _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); - if (_z_send_n_msg(&zn->in->val, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - _z_unregister_subscription(&zn->in->val, _Z_RESOURCE_IS_LOCAL, sp_s); - _z_subscriber_free(&ret); - return NULL; + _z_declaration_t declaration = + _z_make_decl_subscriber(&keyexpr, s._id, sub_info.reliability == Z_RELIABILITY_RELIABLE); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); + if (_z_send_n_msg(_Z_RC_IN_VAL(zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_unregister_subscription(_Z_RC_IN_VAL(zn), _Z_RESOURCE_IS_LOCAL, sp_s); + _z_subscriber_clear(&ret); + return ret; } _z_n_msg_clear(&n_msg); // Fill subscriber - ret->_entity_id = s._id; - ret->_zn = _z_session_rc_clone(zn); + ret._entity_id = s._id; + ret._zn = _z_session_rc_clone(zn); return ret; } int8_t _z_undeclare_subscriber(_z_subscriber_t *sub) { - if (sub == NULL) { + if (sub == NULL || _Z_RC_IS_NULL(&sub->_zn)) { return _Z_ERR_ENTITY_UNKNOWN; } // Find subscription entry - _z_subscription_rc_t *s = _z_get_subscription_by_id(&sub->_zn.in->val, _Z_RESOURCE_IS_LOCAL, sub->_entity_id); + _z_subscription_rc_t *s = _z_get_subscription_by_id(_Z_RC_IN_VAL(&sub->_zn), _Z_RESOURCE_IS_LOCAL, sub->_entity_id); if (s == NULL) { return _Z_ERR_ENTITY_UNKNOWN; } // Build the declare message to send on the wire - _z_declaration_t declaration = _z_make_undecl_subscriber(sub->_entity_id, &s->in->val._key); - _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); - if (_z_send_n_msg(&sub->_zn.in->val, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_declaration_t declaration; + if (_Z_RC_IN_VAL(&sub->_zn)->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + declaration = _z_make_undecl_subscriber(sub->_entity_id, NULL); + } else { + declaration = _z_make_undecl_subscriber(sub->_entity_id, &_Z_RC_IN_VAL(s)->_key); + } + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); + if (_z_send_n_msg(_Z_RC_IN_VAL(&sub->_zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != + _Z_RES_OK) { return _Z_ERR_TRANSPORT_TX_FAILED; } _z_n_msg_clear(&n_msg); // Only if message is successfully send, local subscription state can be removed - _z_undeclare_resource(&sub->_zn.in->val, s->in->val._key_id); - _z_unregister_subscription(&sub->_zn.in->val, _Z_RESOURCE_IS_LOCAL, s); + _z_undeclare_resource(_Z_RC_IN_VAL(&sub->_zn), _Z_RC_IN_VAL(s)->_key_id); + _z_unregister_subscription(_Z_RC_IN_VAL(&sub->_zn), _Z_RESOURCE_IS_LOCAL, s); _z_session_rc_drop(&sub->_zn); return _Z_RES_OK; } - -/*------------------ Pull ------------------*/ -int8_t _z_subscriber_pull(const _z_subscriber_t *sub) { - int8_t ret = _Z_RES_OK; - - _z_subscription_rc_t *s = _z_get_subscription_by_id(&sub->_zn.in->val, _Z_RESOURCE_IS_LOCAL, sub->_entity_id); - if (s != NULL) { - _z_zint_t pull_id = _z_get_pull_id(&sub->_zn.in->val); - _z_zenoh_message_t z_msg = _z_msg_make_pull(_z_keyexpr_alias(s->in->val._key), pull_id); - if (_z_send_n_msg(&sub->_zn.in->val, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - ret = _Z_ERR_TRANSPORT_TX_FAILED; - } - } else { - ret = _Z_ERR_ENTITY_UNKNOWN; - } - - return ret; -} #endif #if Z_FEATURE_QUERYABLE == 1 /*------------------ Queryable Declaration ------------------*/ -_z_queryable_t *_z_declare_queryable(_z_session_rc_t *zn, _z_keyexpr_t keyexpr, _Bool complete, - _z_queryable_handler_t callback, _z_drop_handler_t dropper, void *arg) { +_z_queryable_t _z_declare_queryable(const _z_session_rc_t *zn, _z_keyexpr_t keyexpr, _Bool complete, + _z_queryable_handler_t callback, _z_drop_handler_t dropper, void *arg) { _z_session_queryable_t q; - q._id = _z_get_entity_id(&zn->in->val); - q._key = _z_get_expanded_key_from_key(&zn->in->val, &keyexpr); + 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); q._complete = complete; q._callback = callback; q._dropper = dropper; q._arg = arg; - // Allocate queryable - _z_queryable_t *ret = (_z_queryable_t *)z_malloc(sizeof(_z_queryable_t)); - if (ret == NULL) { - _z_session_queryable_clear(&q); - return NULL; - } + _z_queryable_t ret; // Create session_queryable entry, stored at session-level, do not drop it by the end of this function. - _z_session_queryable_rc_t *sp_q = _z_register_session_queryable(&zn->in->val, &q); + _z_session_queryable_rc_t *sp_q = _z_register_session_queryable(_Z_RC_IN_VAL(zn), &q); if (sp_q == NULL) { - _z_queryable_free(&ret); - return NULL; + _z_queryable_clear(&ret); + return ret; } // Build the declare message to send on the wire _z_declaration_t declaration = _z_make_decl_queryable(&keyexpr, q._id, q._complete, _Z_QUERYABLE_DISTANCE_DEFAULT); - _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); - if (_z_send_n_msg(&zn->in->val, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - _z_unregister_session_queryable(&zn->in->val, sp_q); - _z_queryable_free(&ret); - return NULL; + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); + if (_z_send_n_msg(_Z_RC_IN_VAL(zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_unregister_session_queryable(_Z_RC_IN_VAL(zn), sp_q); + _z_queryable_clear(&ret); + return ret; } _z_n_msg_clear(&n_msg); // Fill queryable - ret->_entity_id = q._id; - ret->_zn = _z_session_rc_clone(zn); + ret._entity_id = q._id; + ret._zn = _z_session_rc_clone(zn); return ret; } int8_t _z_undeclare_queryable(_z_queryable_t *qle) { - if (qle == NULL) { + if (qle == NULL || _Z_RC_IS_NULL(&qle->_zn)) { return _Z_ERR_ENTITY_UNKNOWN; } // Find session_queryable entry - _z_session_queryable_rc_t *q = _z_get_session_queryable_by_id(&qle->_zn.in->val, qle->_entity_id); + _z_session_queryable_rc_t *q = _z_get_session_queryable_by_id(_Z_RC_IN_VAL(&qle->_zn), qle->_entity_id); if (q == NULL) { return _Z_ERR_ENTITY_UNKNOWN; } // Build the declare message to send on the wire - _z_declaration_t declaration = _z_make_undecl_queryable(qle->_entity_id, &q->in->val._key); - _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); - if (_z_send_n_msg(&qle->_zn.in->val, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_declaration_t declaration; + if (_Z_RC_IN_VAL(&qle->_zn)->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + declaration = _z_make_undecl_queryable(qle->_entity_id, NULL); + } else { + declaration = _z_make_undecl_queryable(qle->_entity_id, &_Z_RC_IN_VAL(q)->_key); + } + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, false, 0); + if (_z_send_n_msg(_Z_RC_IN_VAL(&qle->_zn), &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != + _Z_RES_OK) { return _Z_ERR_TRANSPORT_TX_FAILED; } _z_n_msg_clear(&n_msg); // Only if message is successfully send, local queryable state can be removed - _z_unregister_session_queryable(&qle->_zn.in->val, q); + _z_unregister_session_queryable(_Z_RC_IN_VAL(&qle->_zn), q); _z_session_rc_drop(&qle->_zn); return _Z_RES_OK; } -int8_t _z_send_reply(const _z_query_t *query, _z_keyexpr_t keyexpr, const _z_value_t payload) { +int8_t _z_send_reply(const _z_query_t *query, const _z_session_rc_t *zsrc, _z_keyexpr_t keyexpr, + const _z_value_t payload, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, + z_priority_t priority, _Bool is_express, const _z_timestamp_t *timestamp, const _z_bytes_t att) { int8_t ret = _Z_RES_OK; + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); _z_keyexpr_t q_ke; _z_keyexpr_t r_ke; if (query->_anyke == false) { - q_ke = _z_get_expanded_key_from_key(query->_zn, &query->_key); - r_ke = _z_get_expanded_key_from_key(query->_zn, &keyexpr); - if (_z_keyexpr_intersects(q_ke._suffix, strlen(q_ke._suffix), r_ke._suffix, strlen(r_ke._suffix)) == false) { + q_ke = _z_get_expanded_key_from_key(zn, &query->_key); + r_ke = _z_get_expanded_key_from_key(zn, &keyexpr); + if (_z_keyexpr_suffix_intersects(&q_ke, &r_ke) == false) { ret = _Z_ERR_KEYEXPR_NOT_MATCH; } _z_keyexpr_clear(&q_ke); @@ -344,26 +333,74 @@ int8_t _z_send_reply(const _z_query_t *query, _z_keyexpr_t keyexpr, const _z_val if (ret == _Z_RES_OK) { // Build the reply context decorator. This is NOT the final reply. - _z_id_t zid = ((_z_session_t *)query->_zn)->_local_zid; + _z_id_t zid = zn->_local_zid; _z_keyexpr_t ke = _z_keyexpr_alias(keyexpr); - _z_zenoh_message_t z_msg = { - ._tag = _Z_N_RESPONSE, - ._body._response = - { - ._request_id = query->_request_id, - ._key = ke, - ._ext_responder = {._zid = zid, ._eid = 0}, - ._ext_qos = _Z_N_QOS_DEFAULT, - ._ext_timestamp = _z_timestamp_null(), - ._tag = _Z_RESPONSE_BODY_REPLY, - ._body._reply = {._value = payload, - ._timestamp = _z_timestamp_null(), - ._ext_consolidation = Z_CONSOLIDATION_MODE_AUTO, - ._ext_source_info = _z_source_info_null()}, - }, - }; - - if (_z_send_n_msg(query->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_zenoh_message_t z_msg; + switch (kind) { + case Z_SAMPLE_KIND_PUT: + z_msg = (_z_zenoh_message_t){ + ._tag = _Z_N_RESPONSE, + ._body._response = + { + ._request_id = query->_request_id, + ._key = ke, + ._ext_responder = {._zid = zid, ._eid = 0}, + ._ext_qos = _z_n_qos_make(is_express, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), + ._ext_timestamp = _z_timestamp_null(), + ._tag = _Z_RESPONSE_BODY_REPLY, + ._body._reply = + { + ._consolidation = Z_CONSOLIDATION_MODE_DEFAULT, + ._body._is_put = true, + ._body._body._put = + { + ._payload = payload.payload, + ._encoding = payload.encoding, + ._commons = + { + ._timestamp = + (timestamp != NULL) ? *timestamp : _z_timestamp_null(), + ._source_info = _z_source_info_null(), + }, + ._attachment = att, + }, + }, + }, + }; + break; + case Z_SAMPLE_KIND_DELETE: + z_msg = (_z_zenoh_message_t){ + ._tag = _Z_N_RESPONSE, + ._body._response = + { + ._request_id = query->_request_id, + ._key = ke, + ._ext_responder = {._zid = zid, ._eid = 0}, + ._ext_qos = _z_n_qos_make(is_express, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), + ._ext_timestamp = _z_timestamp_null(), + ._tag = _Z_RESPONSE_BODY_REPLY, + ._body._reply = + { + ._consolidation = Z_CONSOLIDATION_MODE_DEFAULT, + ._body._is_put = false, + ._body._body._del = + { + ._commons = + { + ._timestamp = + (timestamp != NULL) ? *timestamp : _z_timestamp_null(), + ._source_info = _z_source_info_null(), + }, + ._attachment = att, + }, + }, + }, + }; + break; + default: + return _Z_ERR_GENERIC; + } + if (_z_send_n_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { ret = _Z_ERR_TRANSPORT_TX_FAILED; } @@ -372,18 +409,44 @@ int8_t _z_send_reply(const _z_query_t *query, _z_keyexpr_t keyexpr, const _z_val return ret; } + +int8_t _z_send_reply_err(const _z_query_t *query, const _z_session_rc_t *zsrc, const _z_value_t payload) { + int8_t ret = _Z_RES_OK; + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); + + // Build the reply context decorator. This is NOT the final reply. + _z_id_t zid = zn->_local_zid; + _z_zenoh_message_t msg = { + ._tag = _Z_N_RESPONSE, + ._body._response = + { + ._request_id = query->_request_id, + ._ext_responder = {._zid = zid, ._eid = 0}, + ._ext_qos = _z_n_qos_make(false, true, Z_PRIORITY_DEFAULT), + ._ext_timestamp = _z_timestamp_null(), + ._tag = _Z_RESPONSE_BODY_ERR, + ._body._err = + { + ._payload = payload.payload, + ._encoding = payload.encoding, + ._ext_source_info = _z_source_info_null(), + }, + }, + }; + if (_z_send_n_msg(zn, &msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + ret = _Z_ERR_TRANSPORT_TX_FAILED; + } + + return ret; +} #endif #if Z_FEATURE_QUERY == 1 /*------------------ Query ------------------*/ int8_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, - void *arg_call, _z_drop_handler_t dropper, void *arg_drop, uint32_t timeout_ms -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t attachment -#endif -) { + _z_drop_handler_t dropper, void *arg, uint32_t timeout_ms, const _z_bytes_t attachment, + z_congestion_control_t cong_ctrl, z_priority_t priority, _Bool is_express) { int8_t ret = _Z_RES_OK; // Create the pending query object @@ -391,28 +454,21 @@ int8_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, if (pq != NULL) { pq->_id = _z_get_query_id(zn); pq->_key = _z_get_expanded_key_from_key(zn, &keyexpr); - pq->_parameters = _z_str_clone(parameters); pq->_target = target; pq->_consolidation = consolidation; - pq->_anykey = (strstr(pq->_parameters, Z_SELECTOR_QUERY_MATCH) == NULL) ? false : true; + pq->_anykey = (strstr(parameters, Z_SELECTOR_QUERY_MATCH) == NULL) ? false : true; pq->_callback = callback; pq->_dropper = dropper; pq->_pending_replies = NULL; - pq->_call_arg = arg_call; - pq->_drop_arg = arg_drop; + pq->_arg = arg; ret = _z_register_pending_query(zn, pq); // Add the pending query to the current session if (ret == _Z_RES_OK) { - _z_bytes_t params = _z_bytes_wrap((uint8_t *)pq->_parameters, strlen(pq->_parameters)); - _z_zenoh_message_t z_msg = - _z_msg_make_query(&keyexpr, ¶ms, pq->_id, pq->_consolidation, &value, timeout_ms -#if Z_FEATURE_ATTACHMENT == 1 - , - attachment -#endif - ); + _z_slice_t params = _z_slice_alias_buf((uint8_t *)parameters, strlen(parameters)); + _z_zenoh_message_t z_msg = _z_msg_make_query(&keyexpr, ¶ms, pq->_id, pq->_consolidation, &value, + timeout_ms, attachment, cong_ctrl, priority, is_express); - if (_z_send_n_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + if (_z_send_n_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, cong_ctrl) != _Z_RES_OK) { _z_unregister_pending_query(zn, pq); ret = _Z_ERR_TRANSPORT_TX_FAILED; } @@ -424,3 +480,49 @@ int8_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, return ret; } #endif + +#if Z_FEATURE_INTEREST == 1 +/*------------------ Interest Declaration ------------------*/ +uint32_t _z_add_interest(_z_session_t *zn, _z_keyexpr_t keyexpr, _z_interest_handler_t callback, uint8_t flags, + void *arg) { + _z_session_interest_t intr; + intr._id = _z_get_entity_id(zn); + intr._key = _z_get_expanded_key_from_key(zn, &keyexpr); + intr._flags = flags; + intr._callback = callback; + intr._arg = arg; + + // Create interest entry, stored at session-level, do not drop it by the end of this function. + _z_session_interest_rc_t *sintr = _z_register_interest(zn, &intr); + if (sintr == NULL) { + return 0; + } + // Build the interest message to send on the wire + _z_interest_t interest = _z_make_interest(&keyexpr, intr._id, intr._flags); + _z_network_message_t n_msg = _z_n_msg_make_interest(interest); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_unregister_interest(zn, sintr); + return 0; + } + _z_n_msg_clear(&n_msg); + return intr._id; +} + +int8_t _z_remove_interest(_z_session_t *zn, uint32_t interest_id) { + // Find interest entry + _z_session_interest_rc_t *sintr = _z_get_interest_by_id(zn, interest_id); + if (sintr == NULL) { + return _Z_ERR_ENTITY_UNKNOWN; + } + // Build the declare message to send on the wire + _z_interest_t interest = _z_make_interest_final(_Z_RC_IN_VAL(sintr)->_id); + _z_network_message_t n_msg = _z_n_msg_make_interest(interest); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + // Only if message is successfully send, session interest can be removed + _z_unregister_interest(zn, sintr); + return _Z_RES_OK; +} +#endif diff --git a/src/net/publish.c b/src/net/publish.c index 7b2d1bffc..bde9b7298 100644 --- a/src/net/publish.c +++ b/src/net/publish.c @@ -17,7 +17,10 @@ #include #if Z_FEATURE_PUBLICATION == 1 -void _z_publisher_clear(_z_publisher_t *pub) { _z_keyexpr_clear(&pub->_key); } +void _z_publisher_clear(_z_publisher_t *pub) { + _z_keyexpr_clear(&pub->_key); + *pub = _z_publisher_null(); +} void _z_publisher_free(_z_publisher_t **pub) { _z_publisher_t *ptr = *pub; @@ -29,4 +32,17 @@ void _z_publisher_free(_z_publisher_t **pub) { *pub = NULL; } } + +_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_rc_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 74b1ad88c..d26d24265 100644 --- a/src/net/query.c +++ b/src/net/query.c @@ -16,38 +16,96 @@ #include "zenoh-pico/session/utils.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); +} + void _z_query_clear(_z_query_t *q) { - // Send REPLY_FINAL message - _z_zenoh_message_t z_msg = _z_n_msg_make_response_final(q->_request_id); - if (_z_send_n_msg(q->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - _Z_ERROR("Query send REPLY_FINAL transport failure !"); + // Try to upgrade session weak to rc + _z_session_rc_t sess_rc = _z_session_weak_upgrade(&q->_zn); + if (!_Z_RC_IS_NULL(&sess_rc)) { + // 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) != + _Z_RES_OK) { + _Z_ERROR("Query send REPLY_FINAL transport failure !"); + } + _z_msg_clear(&z_msg); + _z_session_rc_drop(&sess_rc); } // Clean up memory - _z_msg_clear(&z_msg); - z_free(q->_parameters); - _z_keyexpr_clear(&q->_key); - _z_value_clear(&q->_value); - // Ideally free session rc if you have one + _z_query_clear_inner(q); +} + +int8_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); + if (_Z_RC_IS_NULL(&dst->_zn)) { + _z_query_clear_inner(dst); + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + dst->_anyke = src->_anyke; + dst->_request_id = src->_request_id; + dst->_zn = src->_zn; + return _Z_RES_OK; +} + +void _z_query_free(_z_query_t **query) { + _z_query_t *ptr = *query; + if (ptr != NULL) { + _z_query_clear(ptr); + z_free(ptr); + *query = NULL; + } } #if Z_FEATURE_QUERYABLE == 1 -_z_query_t _z_query_create(const _z_value_t *value, const _z_keyexpr_t *key, const _z_bytes_t *parameters, - _z_session_t *zn, uint32_t request_id) { - _z_query_t q; +_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 = zn; // Ideally would have been an rc + 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; - _z_keyexpr_copy(&q._key, key); - _z_value_copy(&q._value, value); + 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_rc_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) { // Nothing to clear - (void)(qbl); + *qbl = _z_queryable_null(); } void _z_queryable_free(_z_queryable_t **qbl) { diff --git a/src/net/reply.c b/src/net/reply.c new file mode 100644 index 000000000..e28c63215 --- /dev/null +++ b/src/net/reply.c @@ -0,0 +1,141 @@ +// +// 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/net/reply.h" + +#include "zenoh-pico/net/sample.h" +#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) { + _z_sample_clear(&reply_data->_result.sample); + } else if (reply_data->_tag == _Z_REPLY_TAG_ERROR) { + _z_value_clear(&reply_data->_result.error); + } + reply_data->_tag = _Z_REPLY_TAG_NONE; + reply_data->replier_id = _z_id_empty(); +} + +void _z_reply_data_free(_z_reply_data_t **reply_data) { + _z_reply_data_t *ptr = *reply_data; + + if (ptr != NULL) { + _z_reply_data_clear(ptr); + z_free(ptr); + *reply_data = NULL; + } +} + +int8_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; + return _Z_RES_OK; +} + +_z_reply_t _z_reply_move(_z_reply_t *src_reply) { + _z_reply_t reply = *src_reply; + *src_reply = _z_reply_null(); + return reply; +} + +void _z_reply_clear(_z_reply_t *reply) { _z_reply_data_clear(&reply->data); } + +void _z_reply_free(_z_reply_t **reply) { + _z_reply_t *ptr = *reply; + + if (*reply != NULL) { + _z_reply_clear(ptr); + + z_free(ptr); + *reply = NULL; + } +} + +int8_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; +} + +_Bool _z_pending_reply_eq(const _z_pending_reply_t *one, const _z_pending_reply_t *two) { + return one->_tstamp.time == two->_tstamp.time; +} + +void _z_pending_reply_clear(_z_pending_reply_t *pr) { + // Free reply + _z_reply_clear(&pr->_reply); + + // Free the timestamp + _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 diff --git a/src/net/sample.c b/src/net/sample.c new file mode 100644 index 000000000..fc1444241 --- /dev/null +++ b/src/net/sample.c @@ -0,0 +1,112 @@ +// +// 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/net/sample.h" + +#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_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->attachment); +} + +void _z_sample_free(_z_sample_t **sample) { + _z_sample_t *ptr = *sample; + if (ptr != NULL) { + _z_sample_clear(ptr); + z_free(ptr); + *sample = NULL; + } +} + +int8_t _z_sample_copy(_z_sample_t *dst, const _z_sample_t *src) { + *dst = _z_sample_null(); + _Z_RETURN_IF_ERR(_z_keyexpr_copy(&dst->keyexpr, &src->keyexpr)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->payload, &src->payload), _z_sample_clear(dst)); + _Z_CLEAN_RETURN_IF_ERR(_z_encoding_copy(&dst->encoding, &src->encoding), _z_sample_clear(dst)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->attachment, &src->attachment), _z_sample_clear(dst)); + dst->kind = src->kind; + dst->timestamp = _z_timestamp_duplicate(&src->timestamp); + return _Z_RES_OK; +} + +_z_sample_t _z_sample_duplicate(const _z_sample_t *src) { + _z_sample_t dst; + _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_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; + _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) { + _ZP_UNUSED(key); + _ZP_UNUSED(payload); + _ZP_UNUSED(timestamp); + _ZP_UNUSED(encoding); + _ZP_UNUSED(kind); + _ZP_UNUSED(qos); + _ZP_UNUSED(attachment); + return _z_sample_null(); +} +#endif diff --git a/src/net/session.c b/src/net/session.c index fd3d5997d..f2d675720 100644 --- a/src/net/session.c +++ b/src/net/session.c @@ -18,10 +18,10 @@ #include #include "zenoh-pico/api/primitives.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" -#include "zenoh-pico/net/memory.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/common/lease.h" @@ -37,7 +37,7 @@ #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/uuid.h" -int8_t __z_open_inner(_z_session_t *zn, char *locator, z_whatami_t mode) { +int8_t __z_open_inner(_z_session_rc_t *zn, _z_string_t *locator, z_whatami_t mode) { int8_t ret = _Z_RES_OK; _z_id_t local_zid = _z_id_empty(); @@ -46,7 +46,7 @@ int8_t __z_open_inner(_z_session_t *zn, char *locator, z_whatami_t mode) { local_zid = _z_id_empty(); return ret; } - ret = _z_new_transport(&zn->_tp, &local_zid, locator, mode); + ret = _z_new_transport(&_Z_RC_IN_VAL(zn)->_tp, &local_zid, locator, mode); if (ret != _Z_RES_OK) { local_zid = _z_id_empty(); return ret; @@ -55,7 +55,7 @@ int8_t __z_open_inner(_z_session_t *zn, char *locator, z_whatami_t mode) { return ret; } -int8_t _z_open(_z_session_t *zn, _z_config_t *config) { +int8_t _z_open(_z_session_rc_t *zn, _z_config_t *config) { int8_t ret = _Z_RES_OK; _z_id_t zid = _z_id_empty(); @@ -65,7 +65,7 @@ int8_t _z_open(_z_session_t *zn, _z_config_t *config) { } if (config != NULL) { - _z_str_array_t locators = _z_str_array_empty(); + _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 @@ -79,40 +79,42 @@ int8_t _z_open(_z_session_t *zn, _z_config_t *config) { if (opt_as_str == NULL) { opt_as_str = (char *)Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; } - char *mcast_locator = opt_as_str; + _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 = strtoul(opt_as_str, NULL, 10); + 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); + _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_str_array_copy(&locators, &hello->locators); + _z_string_svec_copy(&locators, &hello->_locators); } _z_hello_list_free(&hellos); } else { - int key = Z_CONFIG_CONNECT_KEY; + 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_string_make(Z_CONFIG_MODE_PEER)); + _zp_config_insert(config, Z_CONFIG_MODE_KEY, Z_CONFIG_MODE_PEER); } else { return _Z_ERR_GENERIC; } } - locators = _z_str_array_make(1); - locators.val[0] = _z_str_clone(_z_config_get(config, key)); + 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); } ret = _Z_ERR_SCOUT_NO_RESULTS; - for (size_t i = 0; i < locators.len; i++) { + size_t len = _z_string_svec_len(&locators); + for (size_t i = 0; i < len; i++) { ret = _Z_RES_OK; - char *locator = locators.val[i]; + _z_string_t *locator = _z_string_svec_get(&locators, i); // @TODO: check invalid configurations // For example, client mode in multicast links @@ -138,7 +140,7 @@ int8_t _z_open(_z_session_t *zn, _z_config_t *config) { _Z_ERROR("Trying to configure an invalid mode."); } } - _z_str_array_clear(&locators); + _z_string_svec_clear(&locators); } else { _Z_ERROR("A valid config is missing."); ret = _Z_ERR_GENERIC; @@ -153,8 +155,12 @@ _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_bytes_t local_zid = _z_bytes_wrap(zn->_local_zid.id, _z_id_len(zn->_local_zid)); - _zp_config_insert(ps, Z_INFO_PID_KEY, _z_string_from_bytes(&local_zid)); + _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_clear(&s); switch (zn->_tp._type) { case _Z_TRANSPORT_UNICAST_TYPE: @@ -182,7 +188,7 @@ int8_t _zp_send_join(_z_session_t *zn) { return _z_send_join(&zn->_tp); } int8_t _zp_start_read_task(_z_session_t *zn, z_task_attr_t *attr) { int8_t ret = _Z_RES_OK; // Allocate task - z_task_t *task = (z_task_t *)z_malloc(sizeof(z_task_t)); + _z_task_t *task = (_z_task_t *)z_malloc(sizeof(_z_task_t)); if (task == NULL) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -211,7 +217,7 @@ int8_t _zp_start_read_task(_z_session_t *zn, z_task_attr_t *attr) { int8_t _zp_start_lease_task(_z_session_t *zn, z_task_attr_t *attr) { int8_t ret = _Z_RES_OK; // Allocate task - z_task_t *task = (z_task_t *)z_malloc(sizeof(z_task_t)); + _z_task_t *task = (_z_task_t *)z_malloc(sizeof(_z_task_t)); if (task == NULL) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; } diff --git a/src/net/subscribe.c b/src/net/subscribe.c index 44eb83770..6774f5daa 100644 --- a/src/net/subscribe.c +++ b/src/net/subscribe.c @@ -14,25 +14,16 @@ #include "zenoh-pico/net/subscribe.h" #if Z_FEATURE_SUBSCRIPTION == 1 -_z_subinfo_t _z_subinfo_push_default(void) { +_z_subinfo_t _z_subinfo_default(void) { _z_subinfo_t si; - si.reliability = Z_RELIABILITY_RELIABLE; - si.mode = Z_SUBMODE_PUSH; - si.period = (_z_period_t){.origin = 0, .period = 0, .duration = 0}; - return si; -} - -_z_subinfo_t _z_subinfo_pull_default(void) { - _z_subinfo_t si; - si.reliability = Z_RELIABILITY_RELIABLE; - si.mode = Z_SUBMODE_PULL; - si.period = (_z_period_t){.origin = 0, .period = 0, .duration = 0}; + si.reliability = Z_RELIABILITY_BEST_EFFORT; return si; } void _z_subscriber_clear(_z_subscriber_t *sub) { // Nothing to clear (void)(sub); + *sub = _z_subscriber_null(); } void _z_subscriber_free(_z_subscriber_t **sub) { @@ -45,4 +36,8 @@ void _z_subscriber_free(_z_subscriber_t **sub) { *sub = NULL; } } + +_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_rc_null()}; } + #endif diff --git a/src/protocol/codec.c b/src/protocol/codec.c index 65e13ec07..006490ae5 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -17,117 +17,43 @@ #include #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" -/*------------------ period ------------------*/ -int8_t _z_period_encode(_z_wbuf_t *buf, const _z_period_t *tp) { - _Z_RETURN_IF_ERR(_z_uint_encode(buf, tp->origin)) - _Z_RETURN_IF_ERR(_z_uint_encode(buf, tp->period)) - return _z_uint_encode(buf, tp->duration); -} - -int8_t _z_period_decode_na(_z_period_t *p, _z_zbuf_t *buf) { - int8_t ret = _Z_RES_OK; - - ret |= _z_uint_decode(&p->origin, buf); - if (ret == _Z_RES_OK) { - ret |= _z_uint_decode(&p->period, buf); - } else { - p->origin = 0; - } - - if (ret == _Z_RES_OK) { - ret |= _z_uint_decode(&p->duration, buf); - } else { - p->period = 0; - } - - if (ret != _Z_RES_OK) { - p->duration = 0; - } - - return ret; -} - -int8_t _z_period_decode(_z_period_t *p, _z_zbuf_t *buf) { return _z_period_decode_na(p, buf); } - /*------------------ uint8 -------------------*/ -int8_t _z_encoding_prefix_encode(_z_wbuf_t *wbf, z_encoding_prefix_t en) { return _z_zint_encode(wbf, en); } - -int8_t _z_encoding_prefix_decode(z_encoding_prefix_t *en, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - - _z_zint_t tmp; - ret |= _z_zint_decode(&tmp, zbf); - *en = tmp; - - return ret; -} - -int8_t _z_consolidation_mode_encode(_z_wbuf_t *wbf, z_consolidation_mode_t en) { return _z_zint_encode(wbf, en); } +int8_t _z_consolidation_mode_encode(_z_wbuf_t *wbf, z_consolidation_mode_t en) { return _z_zsize_encode(wbf, en); } int8_t _z_consolidation_mode_decode(z_consolidation_mode_t *en, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; _z_zint_t tmp; - ret |= _z_zint_decode(&tmp, zbf); + ret |= _z_zsize_decode(&tmp, zbf); *en = tmp; return ret; } -int8_t _z_query_target_encode(_z_wbuf_t *wbf, z_query_target_t en) { return _z_zint_encode(wbf, en); } +int8_t _z_query_target_encode(_z_wbuf_t *wbf, z_query_target_t en) { return _z_zsize_encode(wbf, en); } int8_t _z_query_target_decode(z_query_target_t *en, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; _z_zint_t tmp; - ret |= _z_zint_decode(&tmp, zbf); + ret |= _z_zsize_decode(&tmp, zbf); *en = tmp; return ret; } -int8_t _z_whatami_encode(_z_wbuf_t *wbf, z_whatami_t en) { return _z_zint_encode(wbf, en); } +int8_t _z_whatami_encode(_z_wbuf_t *wbf, z_whatami_t en) { return _z_zsize_encode(wbf, _z_whatami_to_uint8(en)); } int8_t _z_whatami_decode(z_whatami_t *en, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; _z_zint_t tmp; - ret |= _z_zint_decode(&tmp, zbf); - *en = tmp; - - return ret; -} - -int8_t _z_uint_encode(_z_wbuf_t *wbf, unsigned int uint) { - unsigned int lv = uint; - - while (lv > (unsigned int)0x7f) { - uint8_t c = (uint8_t)(lv & (unsigned int)0x7f) | (uint8_t)0x80; - _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) - lv = lv >> (unsigned int)7; - } - - uint8_t c = (uint8_t)(lv & (unsigned int)0xff); - return _z_wbuf_write(wbf, c); -} - -int8_t _z_uint_decode(unsigned int *uint, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - *uint = 0; - - uint8_t i = 0; - uint8_t u8 = 0; - do { - if (_z_uint8_decode(&u8, zbf) == _Z_RES_OK) { - *uint = *uint | (((unsigned int)u8 & (unsigned int)0x7f) << (unsigned int)i); - i = i + (uint8_t)7; - } else { - ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } - } while (u8 > (uint8_t)0x7f); + ret |= _z_zsize_decode(&tmp, zbf); + *en = _z_whatami_from_uint8((uint8_t)tmp); return ret; } @@ -151,93 +77,128 @@ int8_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *zbf) { int8_t _z_uint16_encode(_z_wbuf_t *wbf, uint16_t u16) { int8_t ret = _Z_RES_OK; - ret |= _z_wbuf_write(wbf, (u16 & 0xFF)); - ret |= _z_wbuf_write(wbf, ((u16 >> 8) & 0xFF)); + ret |= _z_wbuf_write(wbf, _z_get_u16_lsb(u16)); + ret |= _z_wbuf_write(wbf, _z_get_u16_msb(u16)); return ret; } int8_t _z_uint16_decode(uint16_t *u16, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; - *u16 = 0; + uint8_t enc_u16[2]; - uint8_t u8; - ret |= _z_uint8_decode(&u8, zbf); - *u16 |= u8; - ret |= _z_uint8_decode(&u8, zbf); - *u16 |= u8 << 8; + ret |= _z_uint8_decode(&enc_u16[0], zbf); + ret |= _z_uint8_decode(&enc_u16[1], zbf); + *u16 = _z_host_le_load16(enc_u16); return ret; } -int8_t _z_uint64_encode(_z_wbuf_t *wbf, uint64_t u64) { - uint64_t lv = u64; - - while (lv > (uint64_t)0x7f) { - uint8_t c = (uint8_t)(lv & (uint64_t)0x7f) | (uint8_t)0x80; - _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) - lv = lv >> (_z_zint_t)7; +/*------------------ z_zint ------------------*/ +// Zint is a variable int composed of up to 9 bytes. +// The msb of the 8 first bytes has meaning: (1: the zint continue, 0: end of the zint) +#define VLE_LEN 9 +#define VLE_LEN1_MASK (UINT64_MAX << (7 * 1)) +#define VLE_LEN2_MASK (UINT64_MAX << (7 * 2)) +#define VLE_LEN3_MASK (UINT64_MAX << (7 * 3)) +#define VLE_LEN4_MASK (UINT64_MAX << (7 * 4)) +#define VLE_LEN5_MASK (UINT64_MAX << (7 * 5)) +#define VLE_LEN6_MASK (UINT64_MAX << (7 * 6)) +#define VLE_LEN7_MASK (UINT64_MAX << (7 * 7)) +#define VLE_LEN8_MASK (UINT64_MAX << (7 * 8)) + +uint8_t _z_zint_len(uint64_t v) { + if ((v & VLE_LEN1_MASK) == 0) { + return 1; + } else if ((v & VLE_LEN2_MASK) == 0) { + return 2; + } else if ((v & VLE_LEN3_MASK) == 0) { + return 3; + } else if ((v & VLE_LEN4_MASK) == 0) { + return 4; + } else if ((v & VLE_LEN5_MASK) == 0) { + return 5; + } else if ((v & VLE_LEN6_MASK) == 0) { + return 6; + } else if ((v & VLE_LEN7_MASK) == 0) { + return 7; + } else if ((v & VLE_LEN8_MASK) == 0) { + return 8; + } else { + return 9; } - - uint8_t c = lv & (uint64_t)0xff; - return _z_wbuf_write(wbf, c); } -int8_t _z_uint64_decode(uint64_t *u64, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - *u64 = 0; - - uint8_t i = 0; - uint8_t u8 = 0; - do { - if (_z_uint8_decode(&u8, zbf) == _Z_RES_OK) { - *u64 = *u64 | (((_z_zint_t)u8 & 0x7f) << i); - i = i + (uint8_t)7; - } else { - ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } - } while (u8 > (uint8_t)0x7f); +uint8_t _z_zint64_encode_buf(uint8_t *buf, uint64_t v) { + uint64_t lv = v; + uint8_t len = 0; + size_t start = 0; + while ((lv & VLE_LEN1_MASK) != 0) { + uint8_t c = (lv & 0x7f) | 0x80; + buf[start++] = c; + len++; + lv = lv >> (uint64_t)7; + } + if (len != VLE_LEN) { + uint8_t c = (lv & 0xff); + buf[start++] = c; + } - return ret; + return (uint8_t)start; } -/*------------------ z_zint ------------------*/ -uint8_t _z_zint_len(_z_zint_t v) { - uint8_t len = 1; - while (v > 0x7f) { - v >>= 7; - len++; +int8_t _z_zint64_encode(_z_wbuf_t *wbf, uint64_t v) { + uint8_t buf[VLE_LEN]; + size_t len = _z_zint64_encode_buf(buf, v); + + for (size_t i = 0; i < len; i++) { + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, buf[i])); } - return len; + return _Z_RES_OK; } -int8_t _z_zint_encode(_z_wbuf_t *wbf, _z_zint_t v) { - _z_zint_t lv = v; - while (lv > 0x7f) { - uint8_t c = (lv & 0x7f) | 0x80; - _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) - lv = lv >> (_z_zint_t)7; +int8_t _z_zint16_encode(_z_wbuf_t *wbf, uint16_t v) { return _z_zint64_encode(wbf, (uint64_t)v); } +int8_t _z_zint32_encode(_z_wbuf_t *wbf, uint32_t v) { return _z_zint64_encode(wbf, (uint64_t)v); } +int8_t _z_zsize_encode(_z_wbuf_t *wbf, _z_zint_t v) { return _z_zint64_encode(wbf, (uint64_t)v); } + +int8_t _z_zint64_decode_with_reader(uint64_t *zint, __z_single_byte_reader_t reader, void *context) { + *zint = 0; + + uint8_t b = 0; + _Z_RETURN_IF_ERR(reader(&b, context)); + + uint8_t i = 0; + while (((b & 0x80) != 0) && (i != 7 * (VLE_LEN - 1))) { + *zint = *zint | ((uint64_t)(b & 0x7f)) << i; + _Z_RETURN_IF_ERR(reader(&b, context)); + i = i + (uint8_t)7; } + *zint = *zint | ((uint64_t)b << i); - uint8_t c = lv & 0xff; - return _z_wbuf_write(wbf, c); + return _Z_RES_OK; } -int8_t _z_zint64_encode(_z_wbuf_t *wbf, uint64_t v) { - uint64_t lv = v; - while (lv > 0x7f) { - uint8_t c = (lv & 0x7f) | 0x80; - _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) - lv = lv >> (uint64_t)7; +int8_t _z_zsize_decode_with_reader(_z_zint_t *zint, __z_single_byte_reader_t reader, void *context) { + uint64_t i = 0; + int8_t res = _z_zint64_decode_with_reader(&i, reader, context); + if (res != _Z_RES_OK || i > SIZE_MAX) { + res = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } else { + *zint = (_z_zint_t)i; } + return res; +} + +int8_t _z_uint8_decode_reader(uint8_t *zint, void *context) { return _z_uint8_decode(zint, (_z_zbuf_t *)context); } - uint8_t c = lv & 0xff; - return _z_wbuf_write(wbf, c); +int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { + return _z_zint64_decode_with_reader(zint, _z_uint8_decode_reader, (void *)zbf); } + int8_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; - _z_zint_t buf; - _Z_RETURN_IF_ERR(_z_zint_decode(&buf, zbf)); + uint64_t buf; + _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); if (buf <= UINT16_MAX) { *zint = (uint16_t)buf; } else { @@ -245,10 +206,11 @@ int8_t _z_zint16_decode(uint16_t *zint, _z_zbuf_t *zbf) { } return ret; } + int8_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; - _z_zint_t buf; - _Z_RETURN_IF_ERR(_z_zint_decode(&buf, zbf)); + uint64_t buf; + _Z_RETURN_IF_ERR(_z_zint64_decode(&buf, zbf)); if (buf <= UINT32_MAX) { *zint = (uint32_t)buf; } else { @@ -256,71 +218,42 @@ int8_t _z_zint32_decode(uint32_t *zint, _z_zbuf_t *zbf) { } return ret; } -int8_t _z_zint_decode(_z_zint_t *zint, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - *zint = 0; - uint8_t i = 0; - uint8_t u8 = 0; - do { - if (_z_uint8_decode(&u8, zbf) == _Z_RES_OK) { - *zint = *zint | (((_z_zint_t)u8 & 0x7f) << i); - i = i + (uint8_t)7; - } else { - ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } - } while (u8 > (uint8_t)0x7f); - - return ret; -} -int8_t _z_zint64_decode(uint64_t *zint, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - *zint = 0; - - uint8_t i = 0; - uint8_t u8 = 0; - do { - if (_z_uint8_decode(&u8, zbf) == _Z_RES_OK) { - *zint = *zint | (((uint64_t)u8 & 0x7f) << i); - i = i + (uint8_t)7; - } else { - ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } - } while (u8 > (uint8_t)0x7f); - - return ret; +int8_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); } /*------------------ uint8_array ------------------*/ -int8_t _z_bytes_val_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { +int8_t _z_buf_encode(_z_wbuf_t *wbf, const uint8_t *buf, size_t len) { int8_t ret = _Z_RES_OK; - if ((wbf->_expansion_step != 0) && (bs->len > Z_TSID_LENGTH)) { - ret |= _z_wbuf_wrap_bytes(wbf, bs->start, 0, bs->len); + if ((wbf->_expansion_step != 0) && (len > Z_TSID_LENGTH)) { + ret |= _z_wbuf_wrap_bytes(wbf, buf, 0, len); } else { - ret |= _z_wbuf_write_bytes(wbf, bs->start, 0, bs->len); + ret |= _z_wbuf_write_bytes(wbf, buf, 0, len); } return ret; } -int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { +int8_t _z_slice_val_encode(_z_wbuf_t *wbf, const _z_slice_t *bs) { return _z_buf_encode(wbf, bs->start, bs->len); } + +int8_t _z_slice_encode(_z_wbuf_t *wbf, const _z_slice_t *bs) { int8_t ret = _Z_RES_OK; - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, bs->len)) - _Z_RETURN_IF_ERR(_z_bytes_val_encode(wbf, bs)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, bs->len)) + _Z_RETURN_IF_ERR(_z_slice_val_encode(wbf, bs)) return ret; } -size_t _z_bytes_encode_len(const _z_bytes_t *bs) { return _z_zint_len(bs->len) + bs->len; } -int8_t _z_bytes_val_decode_na(_z_bytes_t *bs, _z_zbuf_t *zbf) { +int8_t _z_slice_val_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; if (ret == _Z_RES_OK) { - if (_z_zbuf_len(zbf) >= bs->len) { // Check if we have enough bytes to read - *bs = _z_bytes_wrap(_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 + if (_z_zbuf_len(zbf) >= bs->len) { // Check if we have enough bytes to read + *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"); bs->len = 0; @@ -335,23 +268,44 @@ int8_t _z_bytes_val_decode_na(_z_bytes_t *bs, _z_zbuf_t *zbf) { return ret; } -int8_t _z_bytes_decode_na(_z_bytes_t *bs, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; +int8_t _z_slice_decode_na(_z_slice_t *bs, _z_zbuf_t *zbf) { + _Z_RETURN_IF_ERR(_z_zsize_decode(&bs->len, zbf)); + return _z_slice_val_decode_na(bs, zbf); +} - ret |= _z_zint_decode(&bs->len, zbf); - ret |= _z_bytes_val_decode_na(bs, zbf); +int8_t _z_slice_val_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_val_decode_na(bs, zbf); } - return ret; +int8_t _z_slice_decode(_z_slice_t *bs, _z_zbuf_t *zbf) { return _z_slice_decode_na(bs, zbf); } + +int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { + _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); + } } -int8_t _z_bytes_val_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { return _z_bytes_val_decode_na(bs, zbf); } +int8_t _z_bytes_encode_val(_z_wbuf_t *wbf, const _z_bytes_t *bs) { + int8_t ret = _Z_RES_OK; + for (size_t i = 0; i < _z_bytes_num_slices(bs); ++i) { + const _z_arc_slice_t *arc_s = _z_bytes_get_slice(bs, i); + _Z_RETURN_IF_ERR(_z_buf_encode(wbf, _z_arc_slice_data(arc_s), _z_arc_slice_len(arc_s))) + } -int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { return _z_bytes_decode_na(bs, zbf); } + return ret; +} + +int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, _z_bytes_len(bs))) + return _z_bytes_encode_val(wbf, bs); +} /*------------------ string with null terminator ------------------*/ int8_t _z_str_encode(_z_wbuf_t *wbf, const char *s) { size_t len = strlen(s); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, len)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, len)) // Note that this does not put the string terminator on the wire. return _z_wbuf_write_bytes(wbf, (const uint8_t *)s, 0, len); } @@ -360,7 +314,7 @@ int8_t _z_str_decode(char **str, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; _z_zint_t len = 0; - ret |= _z_zint_decode(&len, zbf); + ret |= _z_zsize_decode(&len, zbf); if (ret == _Z_RES_OK) { if (_z_zbuf_len(zbf) >= len) { // Check if we have enough bytes to read char *tmp = (char *)z_malloc(len + (size_t)1); // Allocate space for the string terminator @@ -380,6 +334,82 @@ int8_t _z_str_decode(char **str, _z_zbuf_t *zbf) { *str = NULL; ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - return ret; } + +int8_t _z_string_encode(_z_wbuf_t *wbf, const _z_string_t *s) { + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, _z_string_len(s))) + // Note that this does not put the string terminator on the wire. + return _z_wbuf_write_bytes(wbf, (const uint8_t *)_z_string_data(s), 0, _z_string_len(s)); +} + +int8_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"); + 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); + return _Z_RES_OK; +} + +/*------------------ encoding ------------------*/ +#define _Z_ENCODING_FLAG_S 0x01 + +size_t _z_encoding_len(const _z_encoding_t *en) { + size_t en_len = _z_zint_len((uint32_t)(en->id) << 1); + if (_z_string_check(&en->schema)) { + en_len += _z_zint_len(_z_string_len(&en->schema)) + _z_string_len(&en->schema); + } + return en_len; +} + +int8_t _z_encoding_encode(_z_wbuf_t *wbf, const _z_encoding_t *en) { + _Bool has_schema = _z_string_check(&en->schema); + uint32_t id = (uint32_t)(en->id) << 1; + if (has_schema) { + id |= _Z_ENCODING_FLAG_S; + } + _Z_RETURN_IF_ERR(_z_zint32_encode(wbf, id)); + if (has_schema) { + _Z_RETURN_IF_ERR(_z_string_encode(wbf, &en->schema)); + } + return _Z_RES_OK; +} + +int8_t _z_encoding_decode(_z_encoding_t *en, _z_zbuf_t *zbf) { + uint32_t id = 0; + _Bool has_schema = false; + _Z_RETURN_IF_ERR(_z_zint32_decode(&id, zbf)); + if ((id & _Z_ENCODING_FLAG_S) != 0) { + has_schema = true; + } + en->id = (uint16_t)(id >> 1); + if (has_schema) { + _Z_RETURN_IF_ERR(_z_string_decode(&en->schema, zbf)); + } + return _Z_RES_OK; +} + +int8_t _z_value_encode(_z_wbuf_t *wbf, const _z_value_t *value) { + size_t total_len = _z_encoding_len(&value->encoding) + _z_bytes_len(&value->payload); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, total_len)); + _Z_RETURN_IF_ERR(_z_encoding_encode(wbf, &value->encoding)); + return _z_bytes_encode_val(wbf, &value->payload); +} + +int8_t _z_value_decode(_z_value_t *value, _z_zbuf_t *zbf) { + _Z_RETURN_IF_ERR(_z_encoding_decode(&value->encoding, zbf)); + _Z_RETURN_IF_ERR(_z_bytes_from_buf(&value->payload, (uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf))); + return _Z_RES_OK; +} diff --git a/src/protocol/codec/declarations.c b/src/protocol/codec/declarations.c index f139fbc3a..451a1d05c 100644 --- a/src/protocol/codec/declarations.c +++ b/src/protocol/codec/declarations.c @@ -36,32 +36,32 @@ int8_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); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - uint32_t kelen = (uint32_t)(_z_keyexpr_has_suffix(ke) ? strlen(ke._suffix) : 0); + uint32_t kelen = (uint32_t)(_z_keyexpr_has_suffix(&ke) ? _z_string_len(&ke._suffix) : 0); header = (_z_keyexpr_is_local(&ke) ? 2 : 0) | (kelen != 0 ? 1 : 0); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, 1 + kelen + _z_zint_len(ke._id))); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, 1 + kelen + _z_zint_len(ke._id))); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, ke._id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, ke._id)); if (kelen) { - _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, (const uint8_t *)ke._suffix, 0, kelen)) + _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, (const uint8_t *)_z_string_data(&ke._suffix), 0, kelen)) } return _Z_RES_OK; } int8_t _z_decl_kexpr_encode(_z_wbuf_t *wbf, const _z_decl_kexpr_t *decl) { uint8_t header = _Z_DECL_KEXPR_MID; - int has_kesuffix = _z_keyexpr_has_suffix(decl->_keyexpr); + int has_kesuffix = _z_keyexpr_has_suffix(&decl->_keyexpr); if (has_kesuffix) { header |= _Z_DECL_KEXPR_FLAG_N; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, decl->_id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, decl->_id)); _Z_RETURN_IF_ERR(_z_keyexpr_encode(wbf, has_kesuffix, &decl->_keyexpr)) return _Z_RES_OK; } int8_t _z_decl_commons_encode(_z_wbuf_t *wbf, uint8_t header, _Bool has_extensions, uint32_t id, _z_keyexpr_t keyexpr) { - _Bool has_kesuffix = _z_keyexpr_has_suffix(keyexpr); + _Bool has_kesuffix = _z_keyexpr_has_suffix(&keyexpr); if (has_extensions) { header |= _Z_FLAG_Z_Z; } @@ -72,32 +72,31 @@ int8_t _z_decl_commons_encode(_z_wbuf_t *wbf, uint8_t header, _Bool has_extensio header |= _Z_DECL_SUBSCRIBER_FLAG_M; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, id)); return _z_keyexpr_encode(wbf, has_kesuffix, &keyexpr); } int8_t _z_decl_subscriber_encode(_z_wbuf_t *wbf, const _z_decl_subscriber_t *decl) { uint8_t header = _Z_DECL_SUBSCRIBER_MID; - _Bool has_submode_ext = decl->_ext_subinfo._pull_mode || decl->_ext_subinfo._reliable; + _Bool has_submode_ext = decl->_ext_subinfo._reliable; _Z_RETURN_IF_ERR(_z_decl_commons_encode(wbf, header, has_submode_ext, decl->_id, decl->_keyexpr)); if (has_submode_ext) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZINT | 0x01)); - _Z_RETURN_IF_ERR( - _z_uint8_encode(wbf, (decl->_ext_subinfo._pull_mode ? 2 : 0) | (decl->_ext_subinfo._reliable ? 1 : 0))); + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, (decl->_ext_subinfo._reliable ? 1 : 0))); } return _Z_RES_OK; } int8_t _z_undecl_kexpr_encode(_z_wbuf_t *wbf, const _z_undecl_kexpr_t *decl) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_UNDECL_KEXPR)); - return _z_zint_encode(wbf, decl->_id); + return _z_zsize_encode(wbf, decl->_id); } int8_t _z_undecl_encode(_z_wbuf_t *wbf, uint8_t header, _z_zint_t decl_id, _z_keyexpr_t ke) { - _Bool has_keyexpr_ext = _z_keyexpr_check(ke); + _Bool has_keyexpr_ext = _z_keyexpr_check(&ke); if (has_keyexpr_ext) { header |= _Z_FLAG_Z_Z; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, decl_id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, decl_id)); if (has_keyexpr_ext) { _Z_RETURN_IF_ERR(_z_decl_ext_keyexpr_encode(wbf, ke, false)); } @@ -108,12 +107,16 @@ int8_t _z_undecl_subscriber_encode(_z_wbuf_t *wbf, const _z_undecl_subscriber_t } int8_t _z_decl_queryable_encode(_z_wbuf_t *wbf, const _z_decl_queryable_t *decl) { uint8_t header = _Z_DECL_QUERYABLE_MID; - _Bool has_info_ext = (decl->_ext_queryable_info._complete != 0) || (decl->_ext_queryable_info._distance != 0); + _Bool has_info_ext = decl->_ext_queryable_info._complete || (decl->_ext_queryable_info._distance != 0); _Z_RETURN_IF_ERR(_z_decl_commons_encode(wbf, header, has_info_ext, decl->_id, decl->_keyexpr)); if (has_info_ext) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZINT | 0x01)); - _Z_RETURN_IF_ERR(_z_zint64_encode( - wbf, ((uint64_t)decl->_ext_queryable_info._distance << 8) | decl->_ext_queryable_info._complete)); + uint8_t flags = 0; + if (decl->_ext_queryable_info._complete) { + flags |= 0x01; + } + uint64_t value = (uint64_t)flags | (uint64_t)decl->_ext_queryable_info._distance << 8; + _Z_RETURN_IF_ERR(_z_zint64_encode(wbf, value)); } return _Z_RES_OK; } @@ -128,24 +131,12 @@ int8_t _z_decl_token_encode(_z_wbuf_t *wbf, const _z_decl_token_t *decl) { int8_t _z_undecl_token_encode(_z_wbuf_t *wbf, const _z_undecl_token_t *decl) { return _z_undecl_encode(wbf, _Z_UNDECL_TOKEN_MID, decl->_id, decl->_ext_keyexpr); } - -int8_t _z_decl_interest_encode(_z_wbuf_t *wbf, const _z_decl_interest_t *decl) { - uint8_t header = _Z_DECL_INTEREST_MID; - _Z_RETURN_IF_ERR(_z_decl_commons_encode(wbf, header, false, decl->_id, decl->_keyexpr)); - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, decl->interest_flags)); - return _Z_RES_OK; -} - -int8_t _z_final_interest_encode(_z_wbuf_t *wbf, const _z_final_interest_t *decl) { - uint8_t header = _Z_FINAL_INTEREST_MID; +int8_t _z_decl_final_encode(_z_wbuf_t *wbf) { + uint8_t header = _Z_DECL_FINAL_MID; _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, decl->_id)); return _Z_RES_OK; } -int8_t _z_undecl_interest_encode(_z_wbuf_t *wbf, const _z_undecl_interest_t *decl) { - return _z_undecl_encode(wbf, _Z_UNDECL_INTEREST_MID, decl->_id, decl->_ext_keyexpr); -} int8_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl) { int8_t ret = _Z_RES_OK; switch (decl->_tag) { @@ -173,15 +164,10 @@ int8_t _z_declaration_encode(_z_wbuf_t *wbf, const _z_declaration_t *decl) { case _Z_UNDECL_TOKEN: { ret = _z_undecl_token_encode(wbf, &decl->_body._undecl_token); } break; - case _Z_DECL_INTEREST: { - ret = _z_decl_interest_encode(wbf, &decl->_body._decl_interest); - } break; - case _Z_FINAL_INTEREST: { - ret = _z_final_interest_encode(wbf, &decl->_body._final_interest); - } break; - case _Z_UNDECL_INTEREST: { - ret = _z_undecl_interest_encode(wbf, &decl->_body._undecl_interest); + case _Z_DECL_FINAL: { + ret = _z_decl_final_encode(wbf); } break; + ; } return ret; } @@ -210,7 +196,7 @@ int8_t _z_undecl_decode_extensions(_z_msg_ext_t *extension, void *ctx) { _z_keyexpr_t *ke = (_z_keyexpr_t *)ctx; switch (extension->_header) { case _Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 0x0f: { - _z_zbuf_t _zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t _zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); _z_zbuf_t *zbf = &_zbf; uint8_t header; _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); @@ -218,15 +204,14 @@ int8_t _z_undecl_decode_extensions(_z_msg_ext_t *extension, void *ctx) { _Z_RETURN_IF_ERR(_z_zint16_decode(&ke->_id, zbf)); if (_Z_HAS_FLAG(header, 1)) { size_t len = _z_zbuf_len(zbf); - ke->_suffix = z_malloc(len + 1); - if (!ke->_suffix) { + ke->_suffix = _z_string_preallocate(len); + if (!_z_keyexpr_has_suffix(ke)) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - ke->_mapping = _z_keyexpr_mapping(mapping, true); - _z_zbuf_read_bytes(zbf, (uint8_t *)ke->_suffix, 0, len); - ke->_suffix[len] = 0; + ke->_mapping = _z_keyexpr_mapping(mapping); + _z_zbuf_read_bytes(zbf, (uint8_t *)_z_string_data(&ke->_suffix), 0, len); } else { - ke->_mapping = _z_keyexpr_mapping(mapping, false); + ke->_mapping = _z_keyexpr_mapping(mapping); } } break; default: @@ -251,20 +236,19 @@ int8_t _z_decl_commons_decode(_z_zbuf_t *zbf, uint8_t header, _Bool *has_extensi _Z_RETURN_IF_ERR(_z_zint16_decode(&ke->_id, zbf)); if (_Z_HAS_FLAG(header, _Z_DECL_SUBSCRIBER_FLAG_N)) { _z_zint_t len; - _Z_RETURN_IF_ERR(_z_zint_decode(&len, zbf)); + _Z_RETURN_IF_ERR(_z_zsize_decode(&len, zbf)); if (_z_zbuf_len(zbf) < len) { return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - ke->_suffix = z_malloc(len + 1); - if (ke->_suffix == NULL) { + ke->_suffix = _z_string_preallocate(len); + if (!_z_keyexpr_has_suffix(ke)) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - ke->_mapping = _z_keyexpr_mapping(mapping, true); - _z_zbuf_read_bytes(zbf, (uint8_t *)ke->_suffix, 0, len); - ke->_suffix[len] = 0; + ke->_mapping = _z_keyexpr_mapping(mapping); + _z_zbuf_read_bytes(zbf, (uint8_t *)_z_string_data(&ke->_suffix), 0, len); } else { - ke->_suffix = NULL; - ke->_mapping = _z_keyexpr_mapping(mapping, false); + ke->_suffix = _z_string_null(); + ke->_mapping = _z_keyexpr_mapping(mapping); } return _Z_RES_OK; } @@ -272,7 +256,6 @@ int8_t _z_decl_subscriber_decode_extensions(_z_msg_ext_t *extension, void *ctx) _z_decl_subscriber_t *decl = (_z_decl_subscriber_t *)ctx; switch (extension->_header) { case _Z_MSG_EXT_ENC_ZINT | 0x01: { - decl->_ext_subinfo._pull_mode = _Z_HAS_FLAG(extension->_body._zint._val, 2); decl->_ext_subinfo._reliable = _Z_HAS_FLAG(extension->_body._zint._val, 1); } break; default: @@ -301,8 +284,8 @@ int8_t _z_decl_queryable_decode_extensions(_z_msg_ext_t *extension, void *ctx) { switch (extension->_header) { case _Z_MSG_EXT_ENC_ZINT | 0x01: { uint64_t val = extension->_body._zint._val; - decl->_ext_queryable_info._complete = val & 0xff; - decl->_ext_queryable_info._distance = (uint32_t)(val >> 8); + decl->_ext_queryable_info._complete = _Z_HAS_FLAG(val, 0x01); + decl->_ext_queryable_info._distance = (uint16_t)(val >> 8); } break; default: if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { @@ -336,32 +319,20 @@ int8_t _z_decl_token_decode(_z_decl_token_t *decl, _z_zbuf_t *zbf, uint8_t heade int8_t _z_undecl_token_decode(_z_undecl_token_t *decl, _z_zbuf_t *zbf, uint8_t header) { return _z_undecl_trivial_decode(zbf, &decl->_ext_keyexpr, &decl->_id, header); } -int8_t _z_decl_interest_decode(_z_decl_interest_t *decl, _z_zbuf_t *zbf, uint8_t header) { - _Bool has_ext; - *decl = _z_decl_interest_null(); - _Z_RETURN_IF_ERR(_z_decl_commons_decode(zbf, header, &has_ext, &decl->_id, &decl->_keyexpr)); - _Z_RETURN_IF_ERR(_z_uint8_decode(&decl->interest_flags, zbf)); - if (has_ext) { - _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x13)); - } - return _Z_RES_OK; -} -int8_t _z_final_interest_decode(_z_final_interest_t *decl, _z_zbuf_t *zbf, uint8_t header) { - *decl = _z_final_interest_null(); - _Z_RETURN_IF_ERR(_z_zint32_decode(&decl->_id, zbf)); + +int8_t _z_decl_final_decode(_z_decl_final_t *decl, _z_zbuf_t *zbf, uint8_t header) { + // Nothing to do + _ZP_UNUSED(decl); if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { - _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x10)); + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x13)); } return _Z_RES_OK; } -int8_t _z_undecl_interest_decode(_z_undecl_interest_t *decl, _z_zbuf_t *zbf, uint8_t header) { - *decl = _z_undecl_interest_null(); - return _z_undecl_trivial_decode(zbf, &decl->_ext_keyexpr, &decl->_id, header); -} + int8_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf) { - int8_t ret; uint8_t header; _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); + int8_t ret; switch (_Z_MID(header)) { case _Z_DECL_KEXPR_MID: { decl->_tag = _Z_DECL_KEXPR; @@ -395,17 +366,9 @@ int8_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf) { decl->_tag = _Z_UNDECL_TOKEN; ret = _z_undecl_token_decode(&decl->_body._undecl_token, zbf, header); } break; - case _Z_DECL_INTEREST_MID: { - decl->_tag = _Z_DECL_INTEREST; - ret = _z_decl_interest_decode(&decl->_body._decl_interest, zbf, header); - } break; - case _Z_FINAL_INTEREST_MID: { - decl->_tag = _Z_FINAL_INTEREST; - ret = _z_final_interest_decode(&decl->_body._final_interest, zbf, header); - } break; - case _Z_UNDECL_INTEREST_MID: { - decl->_tag = _Z_UNDECL_INTEREST; - ret = _z_undecl_interest_decode(&decl->_body._undecl_interest, zbf, header); + case _Z_DECL_FINAL_MID: { + decl->_tag = _Z_DECL_FINAL; + ret = _z_decl_final_decode(&decl->_body._decl_final, zbf, header); } break; default: { ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; diff --git a/src/protocol/codec/ext.c b/src/protocol/codec/ext.c index 6ca7ecaee..c1188431e 100644 --- a/src/protocol/codec/ext.c +++ b/src/protocol/codec/ext.c @@ -18,7 +18,7 @@ #include #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/codec.h" #include "zenoh-pico/protocol/codec/ext.h" #include "zenoh-pico/system/platform.h" @@ -57,13 +57,13 @@ int8_t _z_msg_ext_decode_zint_na(_z_msg_ext_zint_t *ext, _z_zbuf_t *zbf) { retur int8_t _z_msg_ext_encode_zbuf(_z_wbuf_t *wbf, const _z_msg_ext_zbuf_t *ext) { int8_t ret = _Z_RES_OK; - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &ext->_val)) + _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &ext->_val)) return ret; } int8_t _z_msg_ext_decode_zbuf(_z_msg_ext_zbuf_t *ext, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; - ret |= _z_bytes_decode(&ext->_val, zbf); + ret |= _z_slice_decode(&ext->_val, zbf); return ret; } @@ -180,7 +180,7 @@ int8_t _z_msg_ext_unknown_error(_z_msg_ext_t *extension, uint8_t trace_id) { break; } case _Z_MSG_EXT_ENC_ZBUF: { - _z_bytes_t buf = extension->_body._zbuf._val; + _z_slice_t buf = extension->_body._zbuf._val; char *hex = z_malloc(buf.len * 2 + 1); for (size_t i = 0; i < buf.len; ++i) { snprintf(hex + 2 * i, 3, "%02x", buf.start[i]); diff --git a/src/protocol/codec/interest.c b/src/protocol/codec/interest.c new file mode 100644 index 000000000..5ead72645 --- /dev/null +++ b/src/protocol/codec/interest.c @@ -0,0 +1,95 @@ +// +// Copyright (c) 2024 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/protocol/codec/interest.h" + +#include +#include +#include +#include +#include + +#include "zenoh-pico/protocol/codec.h" +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/codec/ext.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/core.h" +#include "zenoh-pico/protocol/definitions/interest.h" +#include "zenoh-pico/protocol/definitions/message.h" +#include "zenoh-pico/protocol/ext.h" +#include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/session.h" +#include "zenoh-pico/system/platform.h" + +#define _Z_INTEREST_CODEC_FLAG_N 0x20 +#define _Z_INTEREST_CODEC_FLAG_M 0x40 +#define _Z_INTEREST_FLAG_COPY_MASK 0x9f // N & M flags occupy the place of C & F + +#define _Z_INTEREST_TRACE_ID 0x13 + +int8_t _z_interest_encode(_z_wbuf_t *wbf, const _z_interest_t *interest, _Bool is_final) { + // Set id + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, interest->_id)); + if (is_final) { + return _Z_RES_OK; + } + // Copy flags but clear current and future that are already processed. + uint8_t flags = interest->flags; + _Z_CLEAR_FLAG(flags, _Z_INTEREST_FLAG_CURRENT); + _Z_CLEAR_FLAG(flags, _Z_INTEREST_FLAG_FUTURE); + // Process restricted flag + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_RESTRICTED)) { + // Set Named & Mapping flags + _Bool has_kesuffix = _z_keyexpr_has_suffix(&interest->_keyexpr); + if (has_kesuffix) { + _Z_SET_FLAG(flags, _Z_INTEREST_CODEC_FLAG_N); + } + if (_z_keyexpr_is_local(&interest->_keyexpr)) { + _Z_SET_FLAG(flags, _Z_INTEREST_CODEC_FLAG_M); + } + // Set decl flags & keyexpr + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, flags)); + _Z_RETURN_IF_ERR(_z_keyexpr_encode(wbf, has_kesuffix, &interest->_keyexpr)); + } else { + // Set decl flags + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, flags)); + } + return _Z_RES_OK; +} + +int8_t _z_interest_decode(_z_interest_t *interest, _z_zbuf_t *zbf, _Bool is_final, _Bool has_ext) { + // Decode id + _Z_RETURN_IF_ERR(_z_zint32_decode(&interest->_id, zbf)); + if (!is_final) { + uint8_t flags = 0; + // Decode interest flags + _Z_RETURN_IF_ERR(_z_uint8_decode(&flags, zbf)); + // Process restricted flag + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_RESTRICTED)) { + // Decode ke + _Z_RETURN_IF_ERR(_z_keyexpr_decode(&interest->_keyexpr, zbf, _Z_HAS_FLAG(flags, _Z_INTEREST_CODEC_FLAG_N))); + // Set mapping + if (_Z_HAS_FLAG(flags, _Z_INTEREST_CODEC_FLAG_M)) { + _z_keyexpr_set_mapping(&interest->_keyexpr, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + } + } + // Store interest flags (current and future already processed) + interest->flags |= (flags & _Z_INTEREST_FLAG_COPY_MASK); + } + if (has_ext) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, _Z_INTEREST_TRACE_ID)); + } + return _Z_RES_OK; +} diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c index a182326be..960f54498 100644 --- a/src/protocol/codec/message.c +++ b/src/protocol/codec/message.c @@ -22,7 +22,7 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/types.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/link/endpoint.h" #include "zenoh-pico/protocol/codec.h" #include "zenoh-pico/protocol/codec/core.h" @@ -40,29 +40,28 @@ /* Fields */ /*=============================*/ /*------------------ Payload field ------------------*/ -int8_t _z_payload_encode(_z_wbuf_t *wbf, const _z_bytes_t *pld) { +int8_t _z_payload_encode(_z_wbuf_t *wbf, const _z_slice_t *pld) { int8_t ret = _Z_RES_OK; _Z_DEBUG("Encoding _PAYLOAD"); - ret |= _z_bytes_encode(wbf, pld); + ret |= _z_slice_encode(wbf, pld); return ret; } -int8_t _z_payload_decode_na(_z_bytes_t *pld, _z_zbuf_t *zbf) { +int8_t _z_payload_decode_na(_z_slice_t *pld, _z_zbuf_t *zbf) { _Z_DEBUG("Decoding _PAYLOAD"); - return _z_bytes_decode(pld, zbf); + return _z_slice_decode(pld, zbf); } -int8_t _z_payload_decode(_z_bytes_t *pld, _z_zbuf_t *zbf) { return _z_payload_decode_na(pld, zbf); } +int8_t _z_payload_decode(_z_slice_t *pld, _z_zbuf_t *zbf) { return _z_payload_decode_na(pld, zbf); } -int8_t _z_id_encode_as_zbytes(_z_wbuf_t *wbf, const _z_id_t *id) { +int8_t _z_id_encode_as_slice(_z_wbuf_t *wbf, const _z_id_t *id) { int8_t ret = _Z_RES_OK; uint8_t len = _z_id_len(*id); if (len != 0) { - printf("ZIDLEN: %d\n", len); - _z_bytes_t buf = _z_bytes_wrap(id->id, len); - ret = _z_bytes_encode(wbf, &buf); + _z_slice_t buf = _z_slice_alias_buf(id->id, len); + ret = _z_slice_encode(wbf, &buf); } else { _Z_DEBUG("Attempted to encode invalid ID 0"); ret = _Z_ERR_MESSAGE_ZENOH_UNKNOWN; @@ -74,7 +73,7 @@ int8_t _z_id_encode_as_zbytes(_z_wbuf_t *wbf, const _z_id_t *id) { /// /// Note that while `_z_id_t` has an error state (full 0s), this function doesn't /// guarantee that this state will be set in case of errors. -int8_t _z_id_decode_as_zbytes(_z_id_t *id, _z_zbuf_t *zbf) { +int8_t _z_id_decode_as_slice(_z_id_t *id, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; uint8_t len = _z_zbuf_read(zbf); _z_zbuf_read_bytes(zbf, id->id, 0, len); @@ -87,13 +86,15 @@ int8_t _z_timestamp_encode(_z_wbuf_t *wbf, const _z_timestamp_t *ts) { int8_t ret = _Z_RES_OK; _Z_DEBUG("Encoding _TIMESTAMP"); - _Z_RETURN_IF_ERR(_z_uint64_encode(wbf, ts->time)) - ret |= _z_id_encode_as_zbytes(wbf, &ts->id); + _Z_RETURN_IF_ERR(_z_zint64_encode(wbf, ts->time)) + ret |= _z_id_encode_as_slice(wbf, &ts->id); return ret; } int8_t _z_timestamp_encode_ext(_z_wbuf_t *wbf, const _z_timestamp_t *ts) { - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, _z_zint_len(ts->time) + 1 + _z_id_len(ts->id))); + // Encode extension size then timestamp + size_t ext_size = (size_t)(_z_zint_len(ts->time) + 1 + _z_id_len(ts->id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, ext_size)); return _z_timestamp_encode(wbf, ts); } @@ -101,8 +102,8 @@ int8_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *zbf) { _Z_DEBUG("Decoding _TIMESTAMP"); int8_t ret = _Z_RES_OK; - ret |= _z_uint64_decode(&ts->time, zbf); - ret |= _z_id_decode_as_zbytes(&ts->id, zbf); + ret |= _z_zint64_decode(&ts->time, zbf); + ret |= _z_id_decode_as_slice(&ts->id, zbf); return ret; } @@ -112,9 +113,9 @@ int8_t _z_keyexpr_encode(_z_wbuf_t *wbf, _Bool has_suffix, const _z_keyexpr_t *f int8_t ret = _Z_RES_OK; _Z_DEBUG("Encoding _RESKEY"); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, fld->_id)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, fld->_id)) if (has_suffix == true) { - _Z_RETURN_IF_ERR(_z_str_encode(wbf, fld->_suffix)) + _Z_RETURN_IF_ERR(_z_string_encode(wbf, &fld->_suffix)) } return ret; @@ -126,17 +127,17 @@ int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *zbf, _Bool has_suffix) { ret |= _z_zint16_decode(&ke->_id, zbf); if (has_suffix == true) { - char *str = NULL; - ret |= _z_str_decode(&str, zbf); + _z_string_t str = _z_string_null(); + ret |= _z_string_decode(&str, zbf); if (ret == _Z_RES_OK) { ke->_suffix = str; - ke->_mapping = _z_keyexpr_mapping(0, true); + ke->_mapping = _z_keyexpr_mapping(0); } else { - ke->_suffix = NULL; - ke->_mapping = _z_keyexpr_mapping(0, false); + ke->_suffix = _z_string_null(); + ke->_mapping = _z_keyexpr_mapping(0); } } else { - ke->_suffix = NULL; + ke->_suffix = _z_string_null(); } return ret; @@ -146,11 +147,11 @@ int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *zbf, _Bool has_suffix) { int8_t _z_locators_encode(_z_wbuf_t *wbf, const _z_locator_array_t *la) { int8_t ret = _Z_RES_OK; _Z_DEBUG("Encoding _LOCATORS"); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, la->_len)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, la->_len)) for (size_t i = 0; i < la->_len; i++) { - char *s = _z_locator_to_str(&la->_val[i]); - _Z_RETURN_IF_ERR(_z_str_encode(wbf, s)) - z_free(s); + _z_string_t s = _z_locator_to_string(&la->_val[i]); + _Z_RETURN_IF_ERR(_z_string_encode(wbf, &s)) + _z_string_clear(&s); } return ret; @@ -161,18 +162,18 @@ int8_t _z_locators_decode_na(_z_locator_array_t *a_loc, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; _z_zint_t len = 0; // Number of elements in the array - ret |= _z_zint_decode(&len, zbf); + ret |= _z_zsize_decode(&len, zbf); if (ret == _Z_RES_OK) { *a_loc = _z_locator_array_make(len); // Decode the elements for (size_t i = 0; i < len; i++) { - char *str = NULL; - ret |= _z_str_decode(&str, zbf); + _z_string_t str = _z_string_null(); + ret |= _z_string_decode(&str, zbf); if (ret == _Z_RES_OK) { _z_locator_init(&a_loc->_val[i]); - ret |= _z_locator_from_str(&a_loc->_val[i], str); - z_free(str); + ret |= _z_locator_from_string(&a_loc->_val[i], &str); + _z_string_clear(&str); } else { a_loc->_len = i; } @@ -203,7 +204,7 @@ int8_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { } } if (ret == _Z_RES_OK) { - ret = _z_zint_decode(&intbuf, zbf); + ret = _z_zsize_decode(&intbuf, zbf); if (intbuf <= UINT32_MAX) { info->_entity_id = (uint32_t)intbuf; } else { @@ -211,7 +212,7 @@ int8_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { } } if (ret == _Z_RES_OK) { - ret = _z_zint_decode(&intbuf, zbf); + ret = _z_zsize_decode(&intbuf, zbf); if (intbuf <= UINT32_MAX) { info->_source_sn = (uint32_t)intbuf; } else { @@ -224,38 +225,25 @@ int8_t _z_source_info_encode(_z_wbuf_t *wbf, const _z_source_info_t *info) { int8_t ret = 0; uint8_t zidlen = _z_id_len(info->_id); ret |= _z_uint8_encode(wbf, zidlen << 4); - _z_bytes_t zid = _z_bytes_wrap(info->_id.id, zidlen); - ret |= _z_bytes_val_encode(wbf, &zid); - ret |= _z_zint_encode(wbf, info->_entity_id); - ret |= _z_zint_encode(wbf, info->_source_sn); + _z_slice_t zid = _z_slice_alias_buf(info->_id.id, zidlen); + ret |= _z_slice_val_encode(wbf, &zid); + ret |= _z_zsize_encode(wbf, info->_entity_id); + ret |= _z_zsize_encode(wbf, info->_source_sn); return ret; } int8_t _z_source_info_encode_ext(_z_wbuf_t *wbf, const _z_source_info_t *info) { int8_t ret = 0; uint8_t zidlen = _z_id_len(info->_id); - uint16_t len = 1 + zidlen + _z_zint_len(info->_entity_id) + _z_zint_len(info->_source_sn); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, len)); + size_t ext_size = 1u + zidlen + _z_zint_len(info->_entity_id) + _z_zint_len(info->_source_sn); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, ext_size)); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, zidlen << 4)); - _z_bytes_t zid = _z_bytes_wrap(info->_id.id, zidlen); - _Z_RETURN_IF_ERR(_z_bytes_val_encode(wbf, &zid)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, info->_entity_id)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, info->_source_sn)); + _z_slice_t zid = _z_slice_alias_buf(info->_id.id, zidlen); + _Z_RETURN_IF_ERR(_z_slice_val_encode(wbf, &zid)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, info->_entity_id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, info->_source_sn)); return ret; } -#if Z_FEATURE_ATTACHMENT == 1 -int8_t _z_attachment_encode_ext_kv(_z_bytes_t key, _z_bytes_t value, void *ctx) { - _z_wbuf_t *wbf = (_z_wbuf_t *)ctx; - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &key)); - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &value)); - return 0; -} -int8_t _z_attachment_encode_ext(_z_wbuf_t *wbf, z_attachment_t att) { - size_t len = _z_attachment_estimate_length(att); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, len)); - _Z_RETURN_IF_ERR(z_attachment_iterate(att, _z_attachment_encode_ext_kv, wbf)); - return 0; -} -#endif + /*------------------ Push Body Field ------------------*/ int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { (void)(wbf); @@ -264,12 +252,8 @@ int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { _Bool has_source_info = _z_id_check(pshb->_body._put._commons._source_info._id) || pshb->_body._put._commons._source_info._source_sn != 0 || pshb->_body._put._commons._source_info._entity_id != 0; -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t att = _z_encoded_as_attachment(&pshb->_body._put._attachment); - _Bool has_attachment = pshb->_is_put && z_attachment_check(&att); -#else - _Bool has_attachment = false; -#endif + + _Bool has_attachment = pshb->_is_put && _z_bytes_check(&pshb->_body._put._attachment); _Bool has_timestamp = _z_timestamp_check(&pshb->_body._put._commons._timestamp); _Bool has_encoding = false; if (has_source_info || has_attachment) { @@ -279,8 +263,7 @@ int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { if (has_timestamp) { header |= _Z_FLAG_Z_P_T; } - has_encoding = pshb->_body._put._encoding.prefix != Z_ENCODING_PREFIX_EMPTY || - !_z_bytes_is_empty(&pshb->_body._put._encoding.suffix); + has_encoding = _z_encoding_check(&pshb->_body._put._encoding); if (has_encoding) { header |= _Z_FLAG_Z_P_E; } @@ -295,20 +278,17 @@ int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { } if (has_encoding) { - _Z_RETURN_IF_ERR(_z_encoding_prefix_encode(wbf, pshb->_body._put._encoding.prefix)); - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &pshb->_body._put._encoding.suffix)); + _Z_RETURN_IF_ERR(_z_encoding_encode(wbf, &pshb->_body._put._encoding)); } if (has_source_info) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x01 | (has_attachment ? _Z_FLAG_Z_Z : 0))); _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &pshb->_body._put._commons._source_info)); } -#if Z_FEATURE_ATTACHMENT == 1 if (has_attachment) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x03)); - _Z_RETURN_IF_ERR(_z_attachment_encode_ext(wbf, att)); + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &pshb->_body._put._attachment)); } -#endif if (pshb->_is_put) { _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &pshb->_body._put._payload)); } @@ -320,19 +300,20 @@ int8_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { int8_t ret = _Z_RES_OK; switch (_Z_EXT_FULL_ID(extension->_header)) { case _Z_MSG_EXT_ENC_ZBUF | 0x01: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); ret = _z_source_info_decode(&pshb->_body._put._commons._source_info, &zbf); break; } -#if Z_FEATURE_ATTACHMENT == 1 - case _Z_MSG_EXT_ENC_ZBUF | 0x03: { - pshb->_body._put._attachment.is_encoded = true; - pshb->_body._put._attachment.body.encoded = extension->_body._zbuf._val._is_alloc - ? _z_bytes_steal(&extension->_body._zbuf._val) - : _z_bytes_duplicate(&extension->_body._zbuf._val); + case _Z_MSG_EXT_ENC_ZBUF | 0x03: { // Attachment + _z_slice_t s; + if (_z_slice_is_alloced(&extension->_body._zbuf._val)) { + s = _z_slice_steal(&extension->_body._zbuf._val); + } else { + _Z_RETURN_IF_ERR(_z_slice_copy(&s, &extension->_body._zbuf._val)); + } + ret = _z_bytes_from_slice(&pshb->_body._put._attachment, s); break; } -#endif default: if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { ret = _z_msg_ext_unknown_error(extension, 0x08); @@ -343,43 +324,39 @@ int8_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { int8_t _z_push_body_decode(_z_push_body_t *pshb, _z_zbuf_t *zbf, uint8_t header) { int8_t ret = _Z_RES_OK; - if (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)); - } - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_P_E)) { - _Z_RETURN_IF_ERR(_z_encoding_prefix_decode(&pshb->_body._put._encoding.prefix, zbf)); - _Z_RETURN_IF_ERR(_z_bytes_decode(&pshb->_body._put._encoding.suffix, zbf)); - } - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { - _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)); - } - break; + 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)); } - 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)); - } - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { - _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_push_body_decode_extensions, pshb)); - } - break; + if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_P_E)) { + _Z_RETURN_IF_ERR(_z_encoding_decode(&pshb->_body._put._encoding, zbf)); } - default: { - ret = _Z_ERR_MESSAGE_ZENOH_UNKNOWN; + if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _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)); + } + 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)); + } + if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_push_body_decode_extensions, pshb)); + } + break; + } + default: { + ret = _Z_ERR_MESSAGE_ZENOH_UNKNOWN; } } - return ret; } @@ -412,40 +389,32 @@ int8_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *msg) { int8_t ret = _Z_RES_OK; uint8_t header = _Z_MID_Z_QUERY; - _Bool has_params = z_bytes_check(&msg->_parameters); + _Bool has_params = _z_slice_check(&msg->_parameters); if (has_params) { - header |= _Z_FLAG_Z_P; + _Z_SET_FLAG(header, _Z_FLAG_Z_Q_P); + } + _Bool has_consolidation = (msg->_consolidation != Z_CONSOLIDATION_MODE_DEFAULT); + if (has_consolidation) { + _Z_SET_FLAG(header, _Z_FLAG_Z_Q_C); } _z_msg_query_reqexts_t required_exts = _z_msg_query_required_extensions(msg); - if (required_exts.body || required_exts.consolidation || required_exts.info || required_exts.attachment) { + if (required_exts.body || required_exts.info || required_exts.attachment) { header |= _Z_FLAG_Z_Z; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - + if (has_consolidation) { + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, msg->_consolidation)); + } if (has_params) { - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_parameters)); + _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &msg->_parameters)); } - if (required_exts.body) { uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x03; - if (required_exts.consolidation || required_exts.info || required_exts.attachment) { - extheader |= _Z_FLAG_Z_Z; - } - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, _z_zint_len(msg->_ext_value.encoding.prefix) + - _z_bytes_encode_len(&msg->_ext_value.encoding.suffix) + - msg->_ext_value.payload.len)); - _Z_RETURN_IF_ERR(_z_encoding_prefix_encode(wbf, msg->_ext_value.encoding.prefix)); - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_ext_value.encoding.suffix)); - _Z_RETURN_IF_ERR(_z_bytes_val_encode(wbf, &msg->_ext_value.payload)); - } - if (required_exts.consolidation) { - uint8_t extheader = _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M | 0x02; if (required_exts.info || required_exts.attachment) { extheader |= _Z_FLAG_Z_Z; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_consolidation)); + _Z_RETURN_IF_ERR(_z_value_encode(wbf, &msg->_ext_value)); } if (required_exts.info) { uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x01; @@ -455,14 +424,10 @@ int8_t _z_query_encode(_z_wbuf_t *wbf, const _z_msg_query_t *msg) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &msg->_ext_info)); } -#if Z_FEATURE_ATTACHMENT == 1 if (required_exts.attachment) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x05)); - z_attachment_t att = _z_encoded_as_attachment(&msg->_ext_attachment); - _Z_RETURN_IF_ERR(_z_attachment_encode_ext(wbf, att)); + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_ext_attachment)); } -#endif - return ret; } @@ -471,31 +436,25 @@ int8_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { int8_t ret = _Z_RES_OK; switch (_Z_EXT_FULL_ID(extension->_header)) { case _Z_MSG_EXT_ENC_ZBUF | 0x01: { // Source Info - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); ret = _z_source_info_decode(&msg->_ext_info, &zbf); break; } - case _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M | 0x02: { // Consolidation - msg->_ext_consolidation = extension->_body._zint._val; - break; - } case _Z_MSG_EXT_ENC_ZBUF | 0x03: { // Payload - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); - ret = _z_encoding_prefix_decode(&msg->_ext_value.encoding.prefix, &zbf); - ret |= _z_bytes_decode(&msg->_ext_value.encoding.suffix, &zbf); - _z_bytes_t bytes = _z_bytes_wrap((uint8_t *)_z_zbuf_start(&zbf), _z_zbuf_len(&zbf)); - _z_bytes_copy(&msg->_ext_value.payload, &bytes); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); + ret = _z_value_decode(&msg->_ext_value, &zbf); break; } -#if Z_FEATURE_ATTACHMENT == 1 - case _Z_MSG_EXT_ENC_ZBUF | 0x05: { - msg->_ext_attachment.is_encoded = true; - msg->_ext_attachment.body.encoded = extension->_body._zbuf._val._is_alloc - ? _z_bytes_steal(&extension->_body._zbuf._val) - : _z_bytes_duplicate(&extension->_body._zbuf._val); + case _Z_MSG_EXT_ENC_ZBUF | 0x05: { // Attachment + _z_slice_t s; + if (_z_slice_is_alloced(&extension->_body._zbuf._val)) { + s = _z_slice_steal(&extension->_body._zbuf._val); + } else { + _Z_RETURN_IF_ERR(_z_slice_copy(&s, &extension->_body._zbuf._val)); + } + ret = _z_bytes_from_slice(&msg->_ext_attachment, s); break; } -#endif default: if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { ret = _z_msg_ext_unknown_error(extension, 0x09); @@ -507,165 +466,90 @@ int8_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { int8_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}; - msg->_ext_consolidation = Z_CONSOLIDATION_MODE_AUTO; int8_t ret = _Z_RES_OK; - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_P)) { - _Z_RETURN_IF_ERR(_z_bytes_decode(&msg->_parameters, zbf)); + + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Q_C)) { + _Z_RETURN_IF_ERR(_z_uint8_decode((uint8_t *)&msg->_consolidation, zbf)); } else { - _z_bytes_clear(&msg->_parameters); + msg->_consolidation = Z_CONSOLIDATION_MODE_DEFAULT; + } + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Q_P)) { + _Z_RETURN_IF_ERR(_z_slice_decode(&msg->_parameters, zbf)); + } else { + _z_slice_clear(&msg->_parameters); } - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_query_decode_extensions, msg)); } - return ret; } int8_t _z_reply_encode(_z_wbuf_t *wbf, const _z_msg_reply_t *reply) { uint8_t header = _Z_MID_Z_REPLY; - if (_z_timestamp_check(&reply->_timestamp)) { - header |= _Z_FLAG_Z_R_T; - } - if (reply->_value.encoding.prefix != Z_ENCODING_PREFIX_EMPTY || - !_z_bytes_is_empty(&reply->_value.encoding.suffix)) { - header |= _Z_FLAG_Z_R_E; - } -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t att = _z_encoded_as_attachment(&reply->_ext_attachment); - _Bool has_attachment = z_attachment_check(&att); -#else - _Bool has_attachment = false; -#endif - _Bool has_sourceinfo = _z_id_check(reply->_ext_source_info._id) || reply->_ext_source_info._source_sn != 0 || - reply->_ext_source_info._entity_id != 0; - _Bool has_consolidation_ext = reply->_ext_consolidation != Z_CONSOLIDATION_MODE_AUTO; - if (has_consolidation_ext || has_sourceinfo || has_attachment) { - header |= _Z_FLAG_Z_Z; + _Bool has_consolidation = reply->_consolidation != Z_CONSOLIDATION_MODE_DEFAULT; + if (has_consolidation) { + _Z_SET_FLAG(header, _Z_FLAG_Z_R_C); } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - int8_t ret = _Z_RES_OK; - if (_z_timestamp_check(&reply->_timestamp)) { - assert(_Z_HAS_FLAG(header, _Z_FLAG_Z_R_T)); - _Z_RETURN_IF_ERR(_z_timestamp_encode(wbf, &reply->_timestamp)); - } - if (((reply->_value.encoding.prefix != 0) || !_z_bytes_is_empty(&reply->_value.encoding.suffix))) { - assert(_Z_HAS_FLAG(header, _Z_FLAG_Z_R_E)); - _Z_RETURN_IF_ERR(_z_encoding_prefix_encode(wbf, reply->_value.encoding.prefix)); - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &reply->_value.encoding.suffix)); - } - if (has_sourceinfo) { - uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x01; - if (has_consolidation_ext || has_attachment) { - extheader |= _Z_MSG_EXT_FLAG_Z; - } - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &reply->_ext_source_info)); + if (has_consolidation) { + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, reply->_consolidation)); } - if (has_consolidation_ext) { - uint8_t extheader = _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M | 0x02; - if (has_attachment) { - extheader |= _Z_MSG_EXT_FLAG_Z; - } - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, reply->_ext_consolidation)); - } -#if Z_FEATURE_ATTACHMENT == 1 - if (has_attachment) { - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x04)); - _Z_RETURN_IF_ERR(_z_attachment_encode_ext(wbf, att)); - } -#endif - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &reply->_value.payload)); - return ret; + _Z_RETURN_IF_ERR(_z_push_body_encode(wbf, &reply->_body)); + return _Z_RES_OK; } int8_t _z_reply_decode_extension(_z_msg_ext_t *extension, void *ctx) { + _ZP_UNUSED(ctx); int8_t ret = _Z_RES_OK; - _z_msg_reply_t *reply = (_z_msg_reply_t *)ctx; switch (_Z_EXT_FULL_ID(extension->_header)) { - case _Z_MSG_EXT_ENC_ZBUF | 0x01: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); - ret = _z_source_info_decode(&reply->_ext_source_info, &zbf); - break; - } - case _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M | 0x02: { - reply->_ext_consolidation = extension->_body._zint._val; - break; - } -#if Z_FEATURE_ATTACHMENT == 1 - case _Z_MSG_EXT_ENC_ZBUF | 0x04: { - reply->_ext_attachment.is_encoded = true; - reply->_ext_attachment.body.encoded = extension->_body._zbuf._val._is_alloc - ? _z_bytes_steal(&extension->_body._zbuf._val) - : _z_bytes_duplicate(&extension->_body._zbuf._val); - break; - } -#endif default: - if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { - ret = _z_msg_ext_unknown_error(extension, 0x0a); - } + ret = _z_msg_ext_unknown_error(extension, 0x0a); + break; } return ret; } int8_t _z_reply_decode(_z_msg_reply_t *reply, _z_zbuf_t *zbf, uint8_t header) { - int8_t ret = _Z_RES_OK; *reply = (_z_msg_reply_t){0}; - reply->_ext_consolidation = Z_CONSOLIDATION_MODE_AUTO; - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R_T)) { - _Z_RETURN_IF_ERR(_z_timestamp_decode(&reply->_timestamp, zbf)); - } - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R_E)) { - _Z_RETURN_IF_ERR(_z_encoding_prefix_decode(&reply->_value.encoding.prefix, zbf)); - _Z_RETURN_IF_ERR(_z_bytes_decode(&reply->_value.encoding.suffix, zbf)); + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R_C)) { + _Z_RETURN_IF_ERR(_z_uint8_decode((uint8_t *)&reply->_consolidation, zbf)); + } else { + reply->_consolidation = Z_CONSOLIDATION_MODE_DEFAULT; } if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_reply_decode_extension, reply)); } - _Z_RETURN_IF_ERR(_z_bytes_decode(&reply->_value.payload, zbf)); - - return ret; + 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)); + return _Z_RES_OK; } int8_t _z_err_encode(_z_wbuf_t *wbf, const _z_msg_err_t *err) { int8_t ret = _Z_RES_OK; uint8_t header = _Z_MID_Z_ERR; - _Bool has_timestamp = _z_timestamp_check(&err->_timestamp); - if (has_timestamp) { - header |= _Z_FLAG_Z_E_T; - } - if (err->_is_infrastructure) { - header |= _Z_FLAG_Z_E_I; + + // Encode header + _Bool has_encoding = _z_encoding_check(&err->_encoding); + if (has_encoding) { + _Z_SET_FLAG(header, _Z_FLAG_Z_E_E); } - _Bool has_payload_ext = err->_ext_value.payload.start != NULL || err->_ext_value.encoding.prefix != 0 || - !_z_bytes_is_empty(&err->_ext_value.encoding.suffix); _Bool has_sinfo_ext = _z_id_check(err->_ext_source_info._id) || err->_ext_source_info._entity_id != 0 || err->_ext_source_info._source_sn != 0; - if (has_sinfo_ext || has_payload_ext) { - header |= _Z_FLAG_Z_Z; + if (has_sinfo_ext) { + _Z_SET_FLAG(header, _Z_FLAG_Z_Z); } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, err->_code)); - if (has_timestamp) { - _Z_RETURN_IF_ERR(_z_timestamp_encode(wbf, &err->_timestamp)); + // Encode encoding + if (has_encoding) { + _Z_RETURN_IF_ERR(_z_encoding_encode(wbf, &err->_encoding)); } + // Encode extensions if (has_sinfo_ext) { uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x01; - if (has_payload_ext) { - extheader |= _Z_MSG_EXT_FLAG_Z; - } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &err->_ext_source_info)); } - if (has_payload_ext) { - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x02)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, _z_zint_len(err->_ext_value.encoding.prefix) + - _z_bytes_encode_len(&err->_ext_value.encoding.suffix) + - _z_bytes_encode_len(&err->_ext_value.payload))); - _Z_RETURN_IF_ERR(_z_encoding_prefix_encode(wbf, err->_ext_value.encoding.prefix)); - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &err->_ext_value.encoding.suffix)); - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &err->_ext_value.payload)); - } + // Encode payload + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &err->_payload)); return ret; } int8_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { @@ -673,17 +557,10 @@ int8_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { _z_msg_err_t *reply = (_z_msg_err_t *)ctx; switch (_Z_EXT_FULL_ID(extension->_header)) { case _Z_MSG_EXT_ENC_ZBUF | 0x01: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); ret = _z_source_info_decode(&reply->_ext_source_info, &zbf); break; } - case _Z_MSG_EXT_ENC_ZBUF | 0x02: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); - ret = _z_encoding_prefix_decode(&reply->_ext_value.encoding.prefix, &zbf); - ret |= _z_bytes_decode(&reply->_ext_value.encoding.suffix, &zbf); - ret |= _z_bytes_decode(&reply->_ext_value.payload, &zbf); - break; - } default: if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { ret = _z_msg_ext_unknown_error(extension, 0x0a); @@ -693,113 +570,15 @@ int8_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { } int8_t _z_err_decode(_z_msg_err_t *err, _z_zbuf_t *zbf, uint8_t header) { *err = (_z_msg_err_t){0}; - int8_t ret = _Z_RES_OK; - _z_zint_t code; - ret = _z_zint_decode(&code, zbf); - if (code <= UINT16_MAX) { - err->_code = (uint16_t)code; - } else { - ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } - err->_is_infrastructure = _Z_HAS_FLAG(header, _Z_FLAG_Z_E_I); - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_E_T)) { - ret = _z_timestamp_decode(&err->_timestamp, zbf); - } - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { - ret = _z_msg_ext_decode_iter(zbf, _z_err_decode_extension, err); - } - return ret; -} - -int8_t _z_ack_encode(_z_wbuf_t *wbf, const _z_msg_ack_t *ack) { - int8_t ret = _Z_RES_OK; - uint8_t header = _Z_MID_Z_ACK; - _Bool has_ts = _z_timestamp_check(&ack->_timestamp); - _Bool has_sinfo_ext = _z_id_check(ack->_ext_source_info._id) || ack->_ext_source_info._source_sn != 0 || - ack->_ext_source_info._entity_id != 0; - if (has_ts) { - header |= _Z_FLAG_Z_A_T; - } - if (has_sinfo_ext) { - header |= _Z_FLAG_Z_Z; - } - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - if (has_ts) { - _Z_RETURN_IF_ERR(_z_timestamp_encode(wbf, &ack->_timestamp)); - } - if (has_sinfo_ext) { - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x01)); - _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &ack->_ext_source_info)); - } - return ret; -} -int8_t _z_ack_decode_extension(_z_msg_ext_t *extension, void *ctx) { - int8_t ret = _Z_RES_OK; - _z_msg_ack_t *ack = (_z_msg_ack_t *)ctx; - switch (_Z_EXT_FULL_ID(extension->_header)) { - case _Z_MSG_EXT_ENC_ZBUF | 0x01: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); - ret = _z_source_info_decode(&ack->_ext_source_info, &zbf); - break; - } - default: - if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { - ret = _z_msg_ext_unknown_error(extension, 0x0b); - } - } - return ret; -} -int8_t _z_ack_decode(_z_msg_ack_t *ack, _z_zbuf_t *zbf, uint8_t header) { - int8_t ret = _Z_RES_OK; - *ack = (_z_msg_ack_t){0}; - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_A_T)) { - _Z_RETURN_IF_ERR(_z_timestamp_decode(&ack->_timestamp, zbf)); + 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)) { - ret = _z_msg_ext_decode_iter(zbf, _z_ack_decode_extension, ack); - } - return ret; -} - -int8_t _z_pull_encode(_z_wbuf_t *wbf, const _z_msg_pull_t *pull) { - int8_t ret = _Z_RES_OK; - uint8_t header = _Z_MID_Z_PULL; - _Bool has_info_ext = _z_id_check(pull->_ext_source_info._id) || pull->_ext_source_info._source_sn != 0 || - pull->_ext_source_info._entity_id != 0; - if (has_info_ext) { - header |= _Z_FLAG_Z_Z; - } - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - if (has_info_ext) { - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x01)); - _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &pull->_ext_source_info)); + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_err_decode_extension, err)); } - return ret; -} -int8_t _z_pull_decode_extension(_z_msg_ext_t *extension, void *ctx) { - int8_t ret = _Z_RES_OK; - _z_msg_pull_t *pull = (_z_msg_pull_t *)ctx; - switch (_Z_EXT_FULL_ID(extension->_header)) { - case _Z_MSG_EXT_ENC_ZBUF | 0x01: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); - ret = _z_source_info_decode(&pull->_ext_source_info, &zbf); - break; - } - default: - if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { - ret = _z_msg_ext_unknown_error(extension, 0x0c); - } - } - return ret; -} -int8_t _z_pull_decode(_z_msg_pull_t *pull, _z_zbuf_t *zbf, uint8_t header) { - *pull = (_z_msg_pull_t){0}; - int8_t ret = _Z_RES_OK; - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { - ret = _z_msg_ext_decode_iter(zbf, _z_pull_decode_extension, pull); - } - return ret; + _Z_RETURN_IF_ERR(_z_bytes_decode(&err->_payload, zbf)); + return _Z_RES_OK; } /*=============================*/ @@ -818,7 +597,7 @@ int8_t _z_scout_encode(_z_wbuf_t *wbf, uint8_t header, const _z_s_msg_scout_t *m uint8_t zid_len = _z_id_len(msg->_zid); if (zid_len > 0) { _Z_SET_FLAG(cbyte, _Z_FLAG_T_SCOUT_I); - cbyte |= ((zid_len - 1) & 0x0F) << 4; + cbyte |= (uint8_t)(((zid_len - 1) & 0x0F) << 4); } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)) @@ -840,7 +619,7 @@ int8_t _z_scout_decode(_z_s_msg_scout_t *msg, _z_zbuf_t *zbf, uint8_t header) { msg->_what = cbyte & 0x07; msg->_zid = _z_id_empty(); if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(cbyte, _Z_FLAG_T_SCOUT_I) == true)) { - uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + (uint8_t)1; _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); } @@ -855,10 +634,11 @@ int8_t _z_hello_encode(_z_wbuf_t *wbf, uint8_t header, const _z_s_msg_hello_t *m _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, msg->_version)) uint8_t zidlen = _z_id_len(msg->_zid); uint8_t cbyte = 0; - cbyte |= (msg->_whatami & 0x03); - cbyte |= ((zidlen - 1) & 0x0F) << 4; + cbyte |= _z_whatami_to_uint8(msg->_whatami); + cbyte |= (uint8_t)(((zidlen - 1) & 0x0F) << 4); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)) - _Z_RETURN_IF_ERR(_z_bytes_val_encode(wbf, &(_z_bytes_t){.start = msg->_zid.id, .len = zidlen, ._is_alloc = false})); + _z_slice_t s = _z_slice_alias_buf(msg->_zid.id, zidlen); + _Z_RETURN_IF_ERR(_z_slice_val_encode(wbf, &s)); if (_Z_HAS_FLAG(header, _Z_FLAG_T_HELLO_L) == true) { _Z_RETURN_IF_ERR(_z_locators_encode(wbf, &msg->_locators)) @@ -876,8 +656,8 @@ int8_t _z_hello_decode_na(_z_s_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header) uint8_t cbyte = 0; ret |= _z_uint8_decode(&cbyte, zbf); - msg->_whatami = cbyte & 0x03; - uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + msg->_whatami = _z_whatami_from_uint8(cbyte); + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + (uint8_t)1; if (ret == _Z_RES_OK) { msg->_zid = _z_id_empty(); diff --git a/src/protocol/codec/network.c b/src/protocol/codec/network.c index 22615cc09..e4bcf977c 100644 --- a/src/protocol/codec/network.c +++ b/src/protocol/codec/network.c @@ -20,14 +20,16 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/types.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/codec.h" #include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/protocol/codec/declarations.h" #include "zenoh-pico/protocol/codec/ext.h" +#include "zenoh-pico/protocol/codec/interest.h" #include "zenoh-pico/protocol/codec/network.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/core.h" +#include "zenoh-pico/protocol/definitions/interest.h" #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/iobuf.h" @@ -38,7 +40,7 @@ int8_t _z_push_encode(_z_wbuf_t *wbf, const _z_n_msg_push_t *msg) { uint8_t header = _Z_MID_N_PUSH | (_z_keyexpr_is_local(&msg->_key) ? _Z_FLAG_N_REQUEST_M : 0); - _Bool has_suffix = _z_keyexpr_has_suffix(msg->_key); + _Bool has_suffix = _z_keyexpr_has_suffix(&msg->_key); _Bool has_qos_ext = msg->_qos._val != _Z_N_QOS_DEFAULT._val; _Bool has_timestamp_ext = _z_timestamp_check(&msg->_timestamp); if (has_suffix) { @@ -73,11 +75,11 @@ int8_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { if (extension->_body._zint._val > UINT32_MAX) { return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } - msg->_qos = (_z_n_qos_t){._val = (uint32_t)extension->_body._zint._val}; + msg->_qos = (_z_n_qos_t){._val = (uint8_t)extension->_body._zint._val}; break; } case _Z_MSG_EXT_ENC_ZBUF | 0x02: { // Timestamp ext - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); ret = _z_timestamp_decode(&msg->_timestamp, &zbf); break; } @@ -112,20 +114,20 @@ int8_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) { int8_t _z_request_encode(_z_wbuf_t *wbf, const _z_n_msg_request_t *msg) { int8_t ret = _Z_RES_OK; uint8_t header = _Z_MID_N_REQUEST | (_z_keyexpr_is_local(&msg->_key) ? _Z_FLAG_N_REQUEST_M : 0); - _Bool has_suffix = _z_keyexpr_has_suffix(msg->_key); + _Bool has_suffix = _z_keyexpr_has_suffix(&msg->_key); if (has_suffix) { header |= _Z_FLAG_N_REQUEST_N; } _z_n_msg_request_exts_t exts = _z_n_msg_request_needed_exts(msg); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header | (exts.n != 0 ? _Z_FLAG_Z_Z : 0))); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_rid)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_rid)); _Z_RETURN_IF_ERR(_z_keyexpr_encode(wbf, has_suffix, &msg->_key)); if (exts.ext_qos) { exts.n -= 1; uint8_t extheader = 0x01 | _Z_MSG_EXT_ENC_ZINT | (exts.n ? _Z_FLAG_Z_Z : 0); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_qos._val)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_ext_qos._val)); } if (exts.ext_tstamp) { exts.n -= 1; @@ -137,19 +139,19 @@ int8_t _z_request_encode(_z_wbuf_t *wbf, const _z_n_msg_request_t *msg) { exts.n -= 1; uint8_t extheader = 0x04 | _Z_MSG_EXT_ENC_ZINT | (exts.n ? _Z_FLAG_Z_Z : 0) | _Z_MSG_EXT_FLAG_M; _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_target)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_ext_target)); } if (exts.ext_budget) { exts.n -= 1; uint8_t extheader = 0x05 | _Z_MSG_EXT_ENC_ZINT | (exts.n ? _Z_FLAG_Z_Z : 0); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_budget)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_ext_budget)); } if (exts.ext_timeout_ms) { exts.n -= 1; uint8_t extheader = 0x06 | _Z_MSG_EXT_ENC_ZINT | (exts.n ? _Z_FLAG_Z_Z : 0); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_timeout_ms)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_ext_timeout_ms)); } switch (msg->_tag) { @@ -162,9 +164,6 @@ int8_t _z_request_encode(_z_wbuf_t *wbf, const _z_n_msg_request_t *msg) { case _Z_REQUEST_DEL: { _Z_RETURN_IF_ERR(_z_del_encode(wbf, &msg->_body._del)); } break; - case _Z_REQUEST_PULL: { - _Z_RETURN_IF_ERR(_z_pull_encode(wbf, &msg->_body._pull)); - } break; } return ret; } @@ -179,7 +178,7 @@ int8_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { break; } case 0x02 | _Z_MSG_EXT_ENC_ZBUF: { // Timestamp ext - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); _Z_RETURN_IF_ERR(_z_timestamp_decode(&msg->_ext_timestamp, &zbf)); break; } @@ -211,7 +210,7 @@ int8_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { int8_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}; msg->_ext_qos = _Z_N_QOS_DEFAULT; - _Z_RETURN_IF_ERR(_z_zint_decode(&msg->_rid, zbf)); + _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))); _z_keyexpr_set_mapping(&msg->_key, _Z_HAS_FLAG(header, _Z_FLAG_N_REQUEST_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE : _Z_KEYEXPR_MAPPING_LOCAL); @@ -233,10 +232,6 @@ int8_t _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, const uint8_t msg->_tag = _Z_REQUEST_DEL; _Z_RETURN_IF_ERR(_z_del_decode(&msg->_body._del, zbf, zheader)); } break; - case _Z_MID_Z_PULL: { - msg->_tag = _Z_REQUEST_PULL; - _Z_RETURN_IF_ERR(_z_pull_decode(&msg->_body._pull, zbf, zheader)); - } break; default: return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } @@ -251,8 +246,8 @@ int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg) { _Bool has_qos_ext = msg->_ext_qos._val != _Z_N_QOS_DEFAULT._val; _Bool has_ts_ext = _z_timestamp_check(&msg->_ext_timestamp); _Bool has_responder_ext = _z_id_check(msg->_ext_responder._zid) || msg->_ext_responder._eid != 0; - uint8_t n_ext = (has_qos_ext ? 1 : 0) + (has_ts_ext ? 1 : 0) + (has_responder_ext ? 1 : 0); - _Bool has_suffix = _z_keyexpr_has_suffix(msg->_key); + int n_ext = (has_qos_ext ? 1 : 0) + (has_ts_ext ? 1 : 0) + (has_responder_ext ? 1 : 0); + _Bool has_suffix = _z_keyexpr_has_suffix(&msg->_key); if (_z_keyexpr_is_local(&msg->_key)) { _Z_SET_FLAG(header, _Z_FLAG_N_RESPONSE_M); } @@ -264,10 +259,10 @@ int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg) { } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_request_id)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_key._id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_request_id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_key._id)); if (has_suffix) { - _Z_RETURN_IF_ERR(_z_str_encode(wbf, msg->_key._suffix)) + _Z_RETURN_IF_ERR(_z_string_encode(wbf, &msg->_key._suffix)) } if (has_qos_ext) { n_ext -= 1; @@ -276,7 +271,7 @@ int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg) { extheader |= _Z_FLAG_Z_Z; } _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_qos._val)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_ext_qos._val)); } if (has_ts_ext) { n_ext -= 1; @@ -289,13 +284,13 @@ int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg) { uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x03 | (n_ext != 0 ? _Z_FLAG_Z_Z : 0); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); uint8_t zidlen = _z_id_len(msg->_ext_responder._zid); - extheader = (zidlen - 1) << 4; - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, zidlen + 1 + _z_zint_len(msg->_ext_responder._eid))); + extheader = (uint8_t)((zidlen - 1) << 4); + size_t ext_size = (size_t)(zidlen + 1 + _z_zint_len(msg->_ext_responder._eid)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, ext_size)); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, msg->_ext_responder._zid.id, 0, zidlen)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_ext_responder._eid)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_ext_responder._eid)); } - switch (msg->_tag) { case _Z_RESPONSE_BODY_REPLY: { _Z_RETURN_IF_ERR(_z_reply_encode(wbf, &msg->_body._reply)); @@ -305,22 +300,10 @@ int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg) { _Z_RETURN_IF_ERR(_z_err_encode(wbf, &msg->_body._err)); break; } - case _Z_RESPONSE_BODY_ACK: { - _Z_RETURN_IF_ERR(_z_ack_encode(wbf, &msg->_body._ack)); - break; - } - case _Z_RESPONSE_BODY_PUT: { - _Z_RETURN_IF_ERR(_z_put_encode(wbf, &msg->_body._put)); - break; - } - case _Z_RESPONSE_BODY_DEL: { - _Z_RETURN_IF_ERR(_z_del_encode(wbf, &msg->_body._del)); - break; - } } - return ret; } + int8_t _z_response_decode_extension(_z_msg_ext_t *extension, void *ctx) { int8_t ret = _Z_RES_OK; _z_n_msg_response_t *msg = (_z_n_msg_response_t *)ctx; @@ -330,16 +313,16 @@ int8_t _z_response_decode_extension(_z_msg_ext_t *extension, void *ctx) { break; } case _Z_MSG_EXT_ENC_ZBUF | 0x02: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); ret = _z_timestamp_decode(&msg->_ext_timestamp, &zbf); break; } case _Z_MSG_EXT_ENC_ZBUF | 0x03: { - _z_zbuf_t _zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t _zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); _z_zbuf_t *zbf = &_zbf; uint8_t header; _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); - uint8_t zidlen = (header >> 4) + 1; + uint8_t zidlen = (header >> 4) + (uint8_t)1; _Z_RETURN_IF_ERR(_z_zbuf_read_exact(zbf, msg->_ext_responder._zid.id, zidlen)); _Z_RETURN_IF_ERR(_z_zint32_decode(&msg->_ext_responder._eid, zbf)); break; @@ -359,7 +342,7 @@ int8_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t head int8_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 : _Z_KEYEXPR_MAPPING_LOCAL); - _Z_RETURN_IF_ERR(_z_zint_decode(&msg->_request_id, zbf)); + _Z_RETURN_IF_ERR(_z_zsize_decode(&msg->_request_id, zbf)); _Z_RETURN_IF_ERR(_z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_RESPONSE_N))); if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_response_decode_extension, msg)); @@ -379,21 +362,6 @@ int8_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t head ret = _z_err_decode(&msg->_body._err, zbf, inner_header); break; } - case _Z_MID_Z_ACK: { - msg->_tag = _Z_RESPONSE_BODY_ACK; - ret = _z_ack_decode(&msg->_body._ack, zbf, inner_header); - break; - } - case _Z_MID_Z_PUT: { - msg->_tag = _Z_RESPONSE_BODY_PUT; - ret = _z_put_decode(&msg->_body._put, zbf, inner_header); - break; - } - case _Z_MID_Z_DEL: { - msg->_tag = _Z_RESPONSE_BODY_DEL; - ret = _z_del_decode(&msg->_body._del, zbf, inner_header); - break; - } default: { _Z_ERROR("Unknown N_MID: %d", _Z_MID(inner_header)); ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; @@ -405,10 +373,10 @@ int8_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t head /*------------------ Response Final Message ------------------*/ int8_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_final_t *msg) { int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_N_RESPONSE"); + _Z_DEBUG("Encoding _Z_MID_N_RESPONSE_FINAL"); uint8_t header = _Z_MID_N_RESPONSE_FINAL; _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_request_id)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_request_id)); return ret; } @@ -418,7 +386,7 @@ int8_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, *msg = (_z_n_msg_response_final_t){0}; int8_t ret = _Z_RES_OK; - ret |= _z_zint_decode(&msg->_request_id, zbf); + ret |= _z_zsize_decode(&msg->_request_id, zbf); if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x1a)); } @@ -429,21 +397,31 @@ int8_t _z_declare_encode(_z_wbuf_t *wbf, const _z_n_msg_declare_t *decl) { uint8_t header = _Z_MID_N_DECLARE; _Bool has_qos_ext = decl->_ext_qos._val != _Z_N_QOS_DEFAULT._val; _Bool has_timestamp_ext = _z_timestamp_check(&decl->_ext_timestamp); - uint8_t n = (has_qos_ext ? 1 : 0) + (has_timestamp_ext ? 1 : 0); - if (n != 0) { + int n_ext = (has_qos_ext ? 1 : 0) + (has_timestamp_ext ? 1 : 0); + if (n_ext != 0) { header |= _Z_FLAG_N_Z; } + if (decl->has_interest_id) { + header |= _Z_FLAG_N_DECLARE_I; + } + // Encode header _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); + // Encode interest id + if (decl->has_interest_id) { + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, decl->_interest_id)); + } + // Encode extensions if (has_qos_ext) { - n -= 1; - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, 0x01 | _Z_MSG_EXT_ENC_ZINT | (n != 0 ? _Z_FLAG_Z_Z : 0))); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, decl->_ext_qos._val)); + n_ext -= 1; + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, 0x01 | _Z_MSG_EXT_ENC_ZINT | (n_ext != 0 ? _Z_FLAG_Z_Z : 0))); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, decl->_ext_qos._val)); } if (has_timestamp_ext) { - n -= 1; - _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, 0x02 | _Z_MSG_EXT_ENC_ZBUF | (n != 0 ? _Z_FLAG_Z_Z : 0))); + n_ext -= 1; + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, 0x02 | _Z_MSG_EXT_ENC_ZBUF | (n_ext != 0 ? _Z_FLAG_Z_Z : 0))); _Z_RETURN_IF_ERR(_z_timestamp_encode_ext(wbf, &decl->_ext_timestamp)); } + // Encode declaration return _z_declaration_encode(wbf, &decl->_decl); } int8_t _z_declare_decode_extensions(_z_msg_ext_t *extension, void *ctx) { @@ -454,7 +432,7 @@ int8_t _z_declare_decode_extensions(_z_msg_ext_t *extension, void *ctx) { break; } case _Z_MSG_EXT_ENC_ZBUF | 0x02: { - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); return _z_timestamp_decode(&decl->_ext_timestamp, &zbf); } default: @@ -467,12 +445,55 @@ int8_t _z_declare_decode_extensions(_z_msg_ext_t *extension, void *ctx) { int8_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)) { + _Z_RETURN_IF_ERR(_z_zint32_decode(&decl->_interest_id, zbf)); + decl->has_interest_id = true; + } + // Decode extensions if (_Z_HAS_FLAG(header, _Z_FLAG_N_Z)) { _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_declare_decode_extensions, decl)) } + // Decode declaration return _z_declaration_decode(&decl->_decl, zbf); } +int8_t _z_n_interest_encode(_z_wbuf_t *wbf, const _z_n_msg_interest_t *interest) { + // Set header + uint8_t header = _Z_MID_N_INTEREST; + _Bool is_final = true; + if (_Z_HAS_FLAG(interest->_interest.flags, _Z_INTEREST_FLAG_CURRENT)) { + is_final = false; + _Z_SET_FLAG(header, _Z_FLAG_N_INTEREST_CURRENT); + } + if (_Z_HAS_FLAG(interest->_interest.flags, _Z_INTEREST_FLAG_FUTURE)) { + is_final = false; + _Z_SET_FLAG(header, _Z_FLAG_N_INTEREST_FUTURE); + } + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); + return _z_interest_encode(wbf, &interest->_interest, is_final); +} + +int8_t _z_n_interest_decode(_z_n_msg_interest_t *interest, _z_zbuf_t *zbf, uint8_t header) { + interest->_interest = _z_interest_null(); + _Bool is_final = true; + _Bool has_ext = false; + + if (_Z_HAS_FLAG(header, _Z_FLAG_N_INTEREST_CURRENT)) { + _Z_SET_FLAG(interest->_interest.flags, _Z_INTEREST_FLAG_CURRENT); + is_final = false; + } + if (_Z_HAS_FLAG(header, _Z_FLAG_N_INTEREST_FUTURE)) { + _Z_SET_FLAG(interest->_interest.flags, _Z_INTEREST_FLAG_FUTURE); + is_final = false; + } + // Decode extention + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + has_ext = true; + } + return _z_interest_decode(&interest->_interest, zbf, is_final, has_ext); +} + int8_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg) { switch (msg->_tag) { case _Z_N_DECLARE: { @@ -490,8 +511,12 @@ int8_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg case _Z_N_RESPONSE_FINAL: { return _z_response_final_encode(wbf, &msg->_body._response_final); } break; + case _Z_N_INTEREST: { + return _z_n_interest_encode(wbf, &msg->_body._interest); + } break; + default: + return _Z_ERR_GENERIC; } - return _Z_ERR_GENERIC; } int8_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) { uint8_t header; @@ -517,6 +542,10 @@ int8_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) { msg->_tag = _Z_N_RESPONSE_FINAL; return _z_response_final_decode(&msg->_body._response_final, zbf, header); } break; + case _Z_MID_N_INTEREST: { + msg->_tag = _Z_N_INTEREST; + return _z_n_interest_decode(&msg->_body._interest, zbf, header); + } break; default: return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; } diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c index 66b0a1142..90b8efbba 100644 --- a/src/protocol/codec/transport.c +++ b/src/protocol/codec/transport.c @@ -17,7 +17,7 @@ #include #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/protocol/codec/ext.h" #include "zenoh-pico/protocol/codec/network.h" @@ -27,6 +27,15 @@ #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/utils/logging.h" #include "zenoh-pico/utils/result.h" + +uint8_t _z_whatami_to_uint8(z_whatami_t whatami) { + return (whatami >> 1) & 0x03; // get set bit index; only first 3 bits can be set +} + +z_whatami_t _z_whatami_from_uint8(uint8_t b) { + return 1 << (b & 0x03); // convert set bit idx into bitmask +} + /*------------------ Join Message ------------------*/ int8_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg) { int8_t ret = _Z_RES_OK; @@ -35,26 +44,26 @@ int8_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, msg->_version)); uint8_t cbyte = 0; - cbyte |= (msg->_whatami & 0x03); + cbyte |= _z_whatami_to_uint8(msg->_whatami); uint8_t zidlen = _z_id_len(msg->_zid); - cbyte |= ((zidlen - 1) & 0x0F) << 4; + cbyte |= (uint8_t)(((zidlen - 1) & 0x0F) << 4); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)); _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, msg->_zid.id, 0, zidlen)); if (_Z_HAS_FLAG(header, _Z_FLAG_T_JOIN_S)) { - uint8_t cbyte = 0; + cbyte = 0; cbyte |= (msg->_seq_num_res & 0x03); cbyte |= ((msg->_req_id_res & 0x03) << 2); _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)); _Z_RETURN_IF_ERR(_z_uint16_encode(wbf, msg->_batch_size)); } if (_Z_HAS_FLAG(header, _Z_FLAG_T_JOIN_T) == true) { - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_lease / 1000)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_lease / 1000)); } else { - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_lease)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_lease)); } - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_next_sn._val._plain._reliable)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_next_sn._val._plain._best_effort)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_next_sn._val._plain._reliable)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_next_sn._val._plain._best_effort)); if (msg->_next_sn._is_qos) { if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 1)); @@ -63,10 +72,10 @@ int8_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg len += _z_zint_len(msg->_next_sn._val._qos[i]._reliable) + _z_zint_len(msg->_next_sn._val._qos[i]._best_effort); } - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, len)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, len)); for (uint8_t i = 0; (i < Z_PRIORITIES_NUM) && (ret == _Z_RES_OK); i++) { - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_next_sn._val._qos[i]._reliable)); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_next_sn._val._qos[i]._best_effort)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_next_sn._val._qos[i]._reliable)); + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_next_sn._val._qos[i]._best_effort)); } } else { _Z_DEBUG("Attempted to serialize QoS-SN extension, but the header extension flag was unset"); @@ -83,10 +92,10 @@ int8_t _z_join_decode_ext(_z_msg_ext_t *extension, void *ctx) { if (_Z_EXT_FULL_ID(extension->_header) == (_Z_MSG_EXT_ENC_ZBUF | _Z_MSG_EXT_FLAG_M | 1)) { // QOS: (enc=zbuf)(mandatory=true)(id=1) msg->_next_sn._is_qos = true; - _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _z_zbuf_t zbf = _z_slice_as_zbuf(extension->_body._zbuf._val); for (int i = 0; (ret == _Z_RES_OK) && (i < Z_PRIORITIES_NUM); ++i) { - ret |= _z_zint_decode(&msg->_next_sn._val._qos[i]._reliable, &zbf); - ret |= _z_zint_decode(&msg->_next_sn._val._qos[i]._best_effort, &zbf); + ret |= _z_zsize_decode(&msg->_next_sn._val._qos[i]._reliable, &zbf); + ret |= _z_zsize_decode(&msg->_next_sn._val._qos[i]._best_effort, &zbf); } } else if (_Z_MSG_EXT_IS_MANDATORY(extension->_header)) { ret = _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN; @@ -103,9 +112,9 @@ int8_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) { uint8_t cbyte = 0; ret |= _z_uint8_decode(&cbyte, zbf); - msg->_whatami = cbyte & 0x03; + msg->_whatami = _z_whatami_from_uint8(cbyte); - uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + (uint8_t)1; msg->_zid = _z_id_empty(); if (ret == _Z_RES_OK) { if (_z_zbuf_len(zbf) >= zidlen) { @@ -128,15 +137,15 @@ int8_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) { } } if (ret == _Z_RES_OK) { - ret |= _z_zint_decode(&msg->_lease, zbf); + ret |= _z_zsize_decode(&msg->_lease, zbf); if (_Z_HAS_FLAG(header, _Z_FLAG_T_JOIN_T) == true) { msg->_lease = msg->_lease * 1000; } } if (ret == _Z_RES_OK) { msg->_next_sn._is_qos = false; - ret |= _z_zint_decode(&msg->_next_sn._val._plain._reliable, zbf); - ret |= _z_zint_decode(&msg->_next_sn._val._plain._best_effort, zbf); + ret |= _z_zsize_decode(&msg->_next_sn._val._plain._reliable, zbf); + ret |= _z_zsize_decode(&msg->_next_sn._val._plain._best_effort, zbf); } if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { ret |= _z_msg_ext_decode_iter(zbf, _z_join_decode_ext, msg); @@ -153,9 +162,9 @@ int8_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t *msg _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, msg->_version)) uint8_t cbyte = 0; - cbyte |= (msg->_whatami & 0x03); + cbyte |= _z_whatami_to_uint8(msg->_whatami); uint8_t zidlen = _z_id_len(msg->_zid); - cbyte |= ((zidlen - 1) & 0x0F) << 4; // TODO[protocol]: check if ZID > 0 && <= 16 + cbyte |= (uint8_t)(((zidlen - 1) & 0x0F) << 4); // TODO[protocol]: check if ZID > 0 && <= 16 _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)) _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, msg->_zid.id, 0, zidlen)) @@ -168,7 +177,7 @@ int8_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t *msg } if (_Z_HAS_FLAG(header, _Z_FLAG_T_INIT_A) == true) { - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_cookie)) + _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &msg->_cookie)) } return ret; @@ -186,8 +195,8 @@ int8_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) { msg->_zid = _z_id_empty(); if (ret == _Z_RES_OK) { - msg->_whatami = cbyte & 0x03; - uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + msg->_whatami = _z_whatami_from_uint8(cbyte); + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + (uint8_t)1; if (_z_zbuf_len(zbf) >= zidlen) { _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); } else { @@ -208,9 +217,9 @@ int8_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_bytes_decode(&msg->_cookie, zbf); + ret |= _z_slice_decode(&msg->_cookie, zbf); } else { - msg->_cookie = _z_bytes_empty(); + msg->_cookie = _z_slice_empty(); } if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { @@ -226,15 +235,15 @@ int8_t _z_open_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_open_t *msg _Z_DEBUG("Encoding _Z_MID_T_OPEN"); if (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_T) == true) { - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_lease / 1000)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_lease / 1000)) } else { - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_lease)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_lease)) } - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_initial_sn)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_initial_sn)) if (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_A) == false) { - _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_cookie)) + _Z_RETURN_IF_ERR(_z_slice_encode(wbf, &msg->_cookie)) } return ret; @@ -245,20 +254,20 @@ int8_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header) { int8_t ret = _Z_RES_OK; *msg = (_z_t_msg_open_t){0}; - ret |= _z_zint_decode(&msg->_lease, zbf); + ret |= _z_zsize_decode(&msg->_lease, zbf); if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_T) == true)) { msg->_lease = msg->_lease * 1000; } - ret |= _z_zint_decode(&msg->_initial_sn, zbf); + ret |= _z_zsize_decode(&msg->_initial_sn, zbf); if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_A) == false)) { - ret |= _z_bytes_decode(&msg->_cookie, zbf); + ret |= _z_slice_decode(&msg->_cookie, zbf); if (ret != _Z_RES_OK) { - msg->_cookie = _z_bytes_empty(); + msg->_cookie = _z_slice_empty(); } } else { - msg->_cookie = _z_bytes_empty(); + msg->_cookie = _z_slice_empty(); } if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x02); @@ -322,7 +331,7 @@ int8_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t int8_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_t *msg) { int8_t ret = _Z_RES_OK; - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_sn)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_sn)) if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { ret = _Z_ERR_MESSAGE_SERIALIZATION_FAILED; @@ -341,7 +350,7 @@ int8_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header) { int8_t ret = _Z_RES_OK; *msg = (_z_t_msg_frame_t){0}; - ret |= _z_zint_decode(&msg->_sn, zbf); + 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); } @@ -378,11 +387,11 @@ int8_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header) { int8_t _z_fragment_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_fragment_t *msg) { int8_t ret = _Z_RES_OK; _Z_DEBUG("Encoding _Z_TRANSPORT_FRAGMENT"); - _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_sn)) + _Z_RETURN_IF_ERR(_z_zsize_encode(wbf, msg->_sn)) if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { ret = _Z_ERR_MESSAGE_SERIALIZATION_FAILED; } - if (ret == _Z_RES_OK && _z_bytes_check(msg->_payload)) { + if (ret == _Z_RES_OK && _z_slice_check(&msg->_payload)) { _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, msg->_payload.start, 0, msg->_payload.len)); } @@ -394,14 +403,14 @@ int8_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t head *msg = (_z_t_msg_fragment_t){0}; _Z_DEBUG("Decoding _Z_TRANSPORT_FRAGMENT"); - ret |= _z_zint_decode(&msg->_sn, zbf); + 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, 0x05); } - _z_bytes_t bytes = _z_bytes_wrap((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf)); - _z_bytes_copy(&msg->_payload, &bytes); + _z_slice_t slice = _z_slice_alias_buf((uint8_t *)_z_zbuf_start(zbf), _z_zbuf_len(zbf)); + _z_slice_copy(&msg->_payload, &slice); zbf->_ios._r_pos = zbf->_ios._w_pos; return ret; diff --git a/src/protocol/config.c b/src/protocol/config.c index 3c70a27e6..ad4440fc2 100644 --- a/src/protocol/config.c +++ b/src/protocol/config.c @@ -25,11 +25,11 @@ int8_t _z_config_init(_z_config_t *ps) { return 0; } -int8_t _zp_config_insert(_z_config_t *ps, uint8_t key, _z_string_t value) { +int8_t _zp_config_insert(_z_config_t *ps, uint8_t key, const char *value) { int8_t ret = _Z_RES_OK; - char *res = _z_str_intmap_insert(ps, key, value.val); - if (res != value.val) { + char *res = _z_str_intmap_insert(ps, key, _z_str_clone(value)); + if (strcmp(res, value) != 0) { ret = _Z_ERR_CONFIG_FAILED_INSERT; } diff --git a/src/protocol/core.c b/src/protocol/core.c index 2e4619443..8228bc2a3 100644 --- a/src/protocol/core.c +++ b/src/protocol/core.c @@ -19,13 +19,16 @@ #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" +#define _Z_ID_LEN (16) + uint8_t _z_id_len(_z_id_t id) { - uint8_t len = 16; + uint8_t len = _Z_ID_LEN; while (len > 0) { --len; if (id.id[len] != 0) { @@ -37,12 +40,12 @@ uint8_t _z_id_len(_z_id_t id) { } _Bool _z_id_check(_z_id_t id) { _Bool ret = false; - for (int i = 0; !ret && i < 16; i++) { + for (int i = 0; !ret && i < _Z_ID_LEN; i++) { ret |= id.id[i] != 0; } return ret; } -_z_id_t _z_id_empty() { +_z_id_t _z_id_empty(void) { return (_z_id_t){.id = { 0, 0, @@ -62,82 +65,47 @@ _z_id_t _z_id_empty() { 0, }}; } -_z_source_info_t _z_source_info_null() { + +_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() { return (_z_timestamp_t){.id = _z_id_empty(), .time = 0}; } -_z_value_t _z_value_null(void) { return (_z_value_t){.payload = _z_bytes_empty(), .encoding = z_encoding_default()}; } +_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; + const uint64_t NANOS_PER_SEC = 1000000000; + + uint32_t fractions = (uint32_t)((uint64_t)nanos * FRAC_PER_SEC / NANOS_PER_SEC + 1); + 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(); return ret; } -void _z_value_copy(_z_value_t *dst, const _z_value_t *src) { - dst->encoding.prefix = src->encoding.prefix; - _z_bytes_copy(&dst->encoding.suffix, &src->encoding.suffix); - _z_bytes_copy(&dst->payload, &src->payload); +int8_t _z_value_copy(_z_value_t *dst, const _z_value_t *src) { + *dst = _z_value_null(); + _Z_RETURN_IF_ERR(_z_encoding_copy(&dst->encoding, &src->encoding)); + _Z_CLEAN_RETURN_IF_ERR(_z_bytes_copy(&dst->payload, &src->payload), _z_encoding_clear(&dst->encoding)); + return _Z_RES_OK; } -#if Z_FEATURE_ATTACHMENT == 1 -struct _z_seeker_t { - _z_bytes_t key; - _z_bytes_t value; -}; -int8_t _z_attachment_get_seeker(_z_bytes_t key, _z_bytes_t value, void *ctx) { - struct _z_seeker_t *seeker = (struct _z_seeker_t *)ctx; - _z_bytes_t seeked = seeker->key; - if (key.len == seeked.len && memcmp(key.start, seeked.start, seeked.len)) { - seeker->value = (_z_bytes_t){.start = value.start, .len = value.len, ._is_alloc = false}; - return 1; - } - return 0; -} -_z_bytes_t z_attachment_get(z_attachment_t this_, _z_bytes_t key) { - struct _z_seeker_t seeker = {.value = {0}, .key = key}; - z_attachment_iterate(this_, _z_attachment_get_seeker, (void *)&seeker); - return seeker.value; -} -int8_t _z_attachment_estimate_length_body(_z_bytes_t key, _z_bytes_t value, void *ctx) { - size_t *len = (size_t *)ctx; - *len += _z_zint_len(key.len) + key.len + _z_zint_len(value.len) + value.len; - return 0; -} -size_t _z_attachment_estimate_length(z_attachment_t att) { - size_t len = 0; - z_attachment_iterate(att, _z_attachment_estimate_length_body, &len); - return len; +int8_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); + dst->_version = src->_version; + dst->_whatami = src->_whatami; + memcpy(&dst->_zid.id, &src->_zid.id, _Z_ID_LEN); + return _Z_RES_OK; } -int8_t _z_encoded_attachment_iteration_driver(const void *this_, z_attachment_iter_body_t body, void *ctx) { - _z_zbuf_t data = _z_zbytes_as_zbuf(*(_z_bytes_t *)this_); - while (_z_zbuf_can_read(&data)) { - _z_bytes_t key = _z_bytes_empty(); - _z_bytes_t value = _z_bytes_empty(); - _z_bytes_decode(&key, &data); - _z_bytes_decode(&value, &data); - int8_t ret = body(key, value, ctx); - if (ret != 0) { - return ret; - } - } - return 0; +_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)}; } -z_attachment_t _z_encoded_as_attachment(const _z_owned_encoded_attachment_t *att) { - if (att->is_encoded) { - return (z_attachment_t){.data = &att->body.encoded, .iteration_driver = _z_encoded_attachment_iteration_driver}; - } else { - return att->body.decoded; - } -} -void _z_encoded_attachment_drop(_z_owned_encoded_attachment_t *att) { - if (att->is_encoded) { - _z_bytes_clear(&att->body.encoded); - } -} -_Bool z_attachment_check(const z_attachment_t *attachment) { return attachment->iteration_driver != NULL; } -int8_t z_attachment_iterate(z_attachment_t this_, z_attachment_iter_body_t body, void *ctx) { - return this_.iteration_driver(this_.data, body, ctx); +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); } -z_attachment_t z_attachment_null(void) { return (z_attachment_t){.data = NULL, .iteration_driver = NULL}; } -#endif \ No newline at end of file diff --git a/src/protocol/definitions/declarations.c b/src/protocol/definitions/declarations.c index 712eff09b..cd903aa03 100644 --- a/src/protocol/definitions/declarations.c +++ b/src/protocol/definitions/declarations.c @@ -49,15 +49,8 @@ void _z_declaration_clear(_z_declaration_t *decl) { _z_keyexpr_clear(&decl->_body._undecl_token._ext_keyexpr); break; } - case _Z_DECL_INTEREST: { - _z_keyexpr_clear(&decl->_body._decl_interest._keyexpr); - break; - } - case _Z_FINAL_INTEREST: { - break; - } - case _Z_UNDECL_INTEREST: { - _z_keyexpr_clear(&decl->_body._undecl_interest._ext_keyexpr); + default: + case _Z_DECL_FINAL: { break; } } @@ -69,18 +62,21 @@ _z_declaration_t _z_make_decl_keyexpr(uint16_t id, _Z_MOVE(_z_keyexpr_t) key) { _z_declaration_t _z_make_undecl_keyexpr(uint16_t id) { return (_z_declaration_t){._tag = _Z_UNDECL_KEXPR, ._body = {._undecl_kexpr = {._id = id}}}; } -_z_declaration_t _z_make_decl_subscriber(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, _Bool reliable, _Bool pull_mode) { +_z_declaration_t _z_make_decl_subscriber(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, _Bool reliable) { return (_z_declaration_t){ ._tag = _Z_DECL_SUBSCRIBER, - ._body = {._decl_subscriber = {._id = id, - ._keyexpr = _z_keyexpr_steal(key), - ._ext_subinfo = {._pull_mode = pull_mode, ._reliable = reliable}}}}; + ._body = {._decl_subscriber = { + ._id = id, ._keyexpr = _z_keyexpr_steal(key), ._ext_subinfo = {._reliable = reliable}}}}; } + _z_declaration_t _z_make_undecl_subscriber(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t *key) { - return (_z_declaration_t){._tag = _Z_UNDECL_SUBSCRIBER, - ._body = {._undecl_subscriber = {._id = id, ._ext_keyexpr = _z_keyexpr_duplicate(*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)}}}; } -_z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint32_t distance, uint8_t complete) { + +_z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint16_t distance, _Bool complete) { return (_z_declaration_t){ ._tag = _Z_DECL_QUERYABLE, ._body = {._decl_queryable = {._id = id, @@ -88,8 +84,10 @@ _z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, ._ext_queryable_info = {._complete = complete, ._distance = distance}}}}; } _z_declaration_t _z_make_undecl_queryable(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t *key) { - return (_z_declaration_t){._tag = _Z_UNDECL_QUERYABLE, - ._body = {._undecl_queryable = {._id = id, ._ext_keyexpr = _z_keyexpr_duplicate(*key)}}}; + return (_z_declaration_t){ + ._tag = _Z_UNDECL_QUERYABLE, + ._body = {._undecl_queryable = { + ._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, @@ -99,34 +97,25 @@ _z_declaration_t _z_make_decl_token(_Z_MOVE(_z_keyexpr_t) key, uint32_t id) { }}}; } _z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t *key) { - return (_z_declaration_t){._tag = _Z_UNDECL_TOKEN, - ._body = {._undecl_token = {._id = id, ._ext_keyexpr = _z_keyexpr_duplicate(*key)}}}; -} -_z_declaration_t _z_make_undecl_interest(uint32_t id, _Z_OPTIONAL const _z_keyexpr_t *key) { - return (_z_declaration_t){._tag = _Z_UNDECL_TOKEN, - ._body = {._undecl_token = {._id = id, ._ext_keyexpr = _z_keyexpr_duplicate(*key)}}}; -} -_z_declaration_t _z_make_decl_interest(_Z_MOVE(_z_keyexpr_t) key, uint32_t id) { - return (_z_declaration_t){._tag = _Z_DECL_TOKEN, - ._body = {._decl_token = { - ._id = id, - ._keyexpr = _z_keyexpr_steal(key), - }}}; + return (_z_declaration_t){ + ._tag = _Z_UNDECL_TOKEN, + ._body = {._undecl_token = {._id = id, + ._ext_keyexpr = (key == NULL) ? _z_keyexpr_null() : _z_keyexpr_duplicate(*key)}}}; } -_z_declaration_t _z_make_final_decl(uint32_t id) { - return (_z_declaration_t){._tag = _Z_FINAL_INTEREST, ._body = {._final_interest = {._id = id}}}; +_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_decl_interest_t _z_decl_interest_null(void) { return (_z_decl_interest_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_undecl_interest_t _z_undecl_interest_null(void) { return (_z_undecl_interest_t){0}; } -_z_final_interest_t _z_final_interest_null(void) { return (_z_final_interest_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: { @@ -150,12 +139,6 @@ void _z_decl_fix_mapping(_z_declaration_t *msg, uint16_t mapping) { case _Z_UNDECL_TOKEN: { _z_keyexpr_fix_mapping(&msg->_body._undecl_token._ext_keyexpr, mapping); } break; - case _Z_DECL_INTEREST: { - _z_keyexpr_fix_mapping(&msg->_body._decl_interest._keyexpr, mapping); - } break; - case _Z_UNDECL_INTEREST: { - _z_keyexpr_fix_mapping(&msg->_body._undecl_interest._ext_keyexpr, mapping); - } break; default: break; } diff --git a/src/protocol/definitions/interest.c b/src/protocol/definitions/interest.c new file mode 100644 index 000000000..7c0254ee7 --- /dev/null +++ b/src/protocol/definitions/interest.c @@ -0,0 +1,37 @@ +// +// Copyright (c) 2024 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/protocol/definitions/interest.h" + +#include "zenoh-pico/protocol/keyexpr.h" + +void _z_interest_clear(_z_interest_t *interest) { _z_keyexpr_clear(&interest->_keyexpr); } + +_z_interest_t _z_make_interest(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint8_t flags) { + return (_z_interest_t){ + ._id = id, + ._keyexpr = _z_keyexpr_steal(key), + .flags = flags, + }; +} + +_z_interest_t _z_make_interest_final(uint32_t id) { + return (_z_interest_t){ + ._id = id, + ._keyexpr = _z_keyexpr_null(), + .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 0fc391f62..3001b3372 100644 --- a/src/protocol/definitions/message.c +++ b/src/protocol/definitions/message.c @@ -16,39 +16,33 @@ #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/network.h" -void _z_msg_reply_clear(_z_msg_reply_t *msg) { _z_value_clear(&msg->_value); } +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_clear(&msg->_encoding.suffix); - _z_bytes_clear(&msg->_payload); + _z_bytes_drop(&msg->_payload); + _z_bytes_drop(&msg->_attachment); + _z_encoding_clear(&msg->_encoding); _z_timestamp_clear(&msg->_commons._timestamp); } _z_msg_query_reqexts_t _z_msg_query_required_extensions(const _z_msg_query_t *msg) { -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t att = _z_encoded_as_attachment(&msg->_ext_attachment); -#endif - return (_z_msg_query_reqexts_t) { - .body = msg->_ext_value.payload.start != NULL || msg->_ext_value.encoding.prefix != 0 || - !_z_bytes_is_empty(&msg->_ext_value.encoding.suffix), + return (_z_msg_query_reqexts_t){ + .body = _z_bytes_check(&msg->_ext_value.payload) || _z_encoding_check(&msg->_ext_value.encoding), .info = _z_id_check(msg->_ext_info._id) || msg->_ext_info._entity_id != 0 || msg->_ext_info._source_sn != 0, - .consolidation = msg->_ext_consolidation != Z_CONSOLIDATION_MODE_AUTO, -#if Z_FEATURE_ATTACHMENT == 1 - .attachment = z_attachment_check(&att) -#else - .attachment = false -#endif + .attachment = _z_bytes_check(&msg->_ext_attachment), }; } void _z_msg_query_clear(_z_msg_query_t *msg) { - _z_bytes_clear(&msg->_parameters); + _z_slice_clear(&msg->_parameters); + _z_bytes_drop(&msg->_ext_attachment); _z_value_clear(&msg->_ext_value); } void _z_msg_err_clear(_z_msg_err_t *err) { - _z_timestamp_clear(&err->_timestamp); - _z_value_clear(&err->_ext_value); + _z_encoding_clear(&err->_encoding); + _z_bytes_drop(&err->_payload); } diff --git a/src/protocol/definitions/network.c b/src/protocol/definitions/network.c index a496a1a8b..f0f73917d 100644 --- a/src/protocol/definitions/network.c +++ b/src/protocol/definitions/network.c @@ -56,9 +56,6 @@ void _z_n_msg_request_clear(_z_n_msg_request_t *msg) { case _Z_REQUEST_DEL: { _z_msg_del_clear(&msg->_body._del); } break; - case _Z_REQUEST_PULL: { - _z_msg_pull_clear(&msg->_body._pull); - } break; } } @@ -75,7 +72,7 @@ _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() { +_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()}}; @@ -100,16 +97,6 @@ void _z_n_msg_response_clear(_z_n_msg_response_t *msg) { _z_msg_err_clear(&msg->_body._err); break; } - case _Z_RESPONSE_BODY_ACK: { - break; - } - case _Z_RESPONSE_BODY_PUT: { - _z_msg_put_clear(&msg->_body._put); - break; - } - case _Z_RESPONSE_BODY_DEL: { - break; - } } } @@ -130,6 +117,11 @@ void _z_n_msg_clear(_z_network_message_t *msg) { case _Z_N_DECLARE: _z_n_msg_declare_clear(&msg->_body._declare); break; + case _Z_N_INTEREST: + _z_n_msg_interest_clear(&msg->_body._interest); + break; + default: + break; } } @@ -143,38 +135,11 @@ void _z_n_msg_free(_z_network_message_t **msg) { *msg = NULL; } } -_z_network_message_t _z_msg_make_pull(_z_keyexpr_t key, _z_zint_t pull_id) { - _z_network_message_t ret = { - ._tag = _Z_N_REQUEST, - ._body = - { - ._request = - { - ._rid = pull_id, - ._key = key, - ._tag = _Z_REQUEST_PULL, - ._body = - { - ._pull = {._ext_source_info = _z_source_info_null()}, - }, - ._ext_budget = 0, - ._ext_qos = _Z_N_QOS_DEFAULT, - ._ext_target = Z_QUERY_TARGET_BEST_MATCHING, - ._ext_timestamp = _z_timestamp_null(), - ._ext_timeout_ms = 0, - }, - }, - }; - return ret; -} -_z_zenoh_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_bytes_t) parameters, _z_zint_t qid, + +_z_zenoh_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_slice_t) parameters, _z_zint_t qid, z_consolidation_mode_t consolidation, _Z_MOVE(_z_value_t) value, - uint32_t timeout_ms -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t attachment -#endif -) { + uint32_t timeout_ms, _z_bytes_t attachment, z_congestion_control_t cong_ctrl, + z_priority_t priority, _Bool is_express) { return (_z_zenoh_message_t){ ._tag = _Z_N_REQUEST, ._body._request = @@ -182,16 +147,16 @@ _z_zenoh_message_t _z_msg_make_query(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_bytes ._rid = qid, ._key = _z_keyexpr_steal(key), ._tag = _Z_REQUEST_QUERY, - ._body._query = {._parameters = _z_bytes_steal(parameters), - ._ext_consolidation = consolidation, - ._ext_value = _z_value_steal(value), - ._ext_info = _z_source_info_null(), -#if Z_FEATURE_ATTACHMENT == 1 - ._ext_attachment = {.body.decoded = attachment, .is_encoded = false} -#endif - }, + ._body._query = + { + ._parameters = _z_slice_steal(parameters), + ._consolidation = consolidation, + ._ext_value = _z_value_steal(value), + ._ext_info = _z_source_info_null(), + ._ext_attachment = attachment, + }, ._ext_budget = 0, - ._ext_qos = _Z_N_QOS_DEFAULT, + ._ext_qos = _z_n_qos_make(is_express, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), ._ext_target = Z_QUERY_TARGET_BEST_MATCHING, ._ext_timeout_ms = timeout_ms, ._ext_timestamp = _z_timestamp_null(), @@ -204,11 +169,13 @@ _z_network_message_t _z_n_msg_make_response_final(_z_zint_t rid) { ._body = {._response_final = {._request_id = rid}}, }; } -_z_network_message_t _z_n_msg_make_declare(_z_declaration_t declaration) { +_z_network_message_t _z_n_msg_make_declare(_z_declaration_t declaration, _Bool has_interest_id, uint32_t interest_id) { return (_z_network_message_t){ ._tag = _Z_N_DECLARE, ._body._declare = { + .has_interest_id = has_interest_id, + ._interest_id = interest_id, ._decl = declaration, ._ext_qos = _Z_N_QOS_DEFAULT, ._ext_timestamp = _z_timestamp_null(), @@ -221,7 +188,7 @@ _z_network_message_t _z_n_msg_make_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_pu ._body._push = {._key = _z_keyexpr_steal(key), ._body = _z_push_body_steal(body)}, }; } -_z_network_message_t _z_n_msg_make_reply(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_value_t) value) { +_z_network_message_t _z_n_msg_make_reply(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_push_body_t) body) { return (_z_network_message_t){ ._tag = _Z_N_RESPONSE, ._body._response = @@ -231,10 +198,8 @@ _z_network_message_t _z_n_msg_make_reply(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) ke ._request_id = rid, ._body._reply = { - ._timestamp = _z_timestamp_null(), - ._value = _z_value_steal(value), - ._ext_source_info = _z_source_info_null(), - ._ext_consolidation = Z_CONSOLIDATION_MODE_AUTO, + ._consolidation = Z_CONSOLIDATION_MODE_AUTO, + ._body = _z_push_body_steal(body), }, ._ext_qos = _Z_N_QOS_DEFAULT, ._ext_timestamp = _z_timestamp_null(), @@ -247,18 +212,17 @@ _z_network_message_t _z_n_msg_make_reply(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) ke }; } -_z_network_message_t _z_n_msg_make_ack(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key) { + +_z_network_message_t _z_n_msg_make_interest(_z_interest_t interest) { return (_z_network_message_t){ - ._tag = _Z_N_RESPONSE, - ._body._response = + ._tag = _Z_N_INTEREST, + ._body._interest = { - ._tag = _Z_RESPONSE_BODY_ACK, - ._request_id = rid, - ._key = _z_keyexpr_steal(key), - ._body._ack = {._timestamp = _z_timestamp_null(), ._ext_source_info = _z_source_info_null()}, + ._interest = interest, }, }; } + void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping) { switch (msg->_tag) { case _Z_N_DECLARE: { @@ -273,6 +237,9 @@ void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping) { case _Z_N_RESPONSE: { _z_keyexpr_fix_mapping(&msg->_body._response._key, mapping); } break; + case _Z_N_INTEREST: { + _z_keyexpr_fix_mapping(&msg->_body._interest._interest._keyexpr, mapping); + } break; default: break; } diff --git a/src/protocol/definitions/transport.c b/src/protocol/definitions/transport.c index fdf4c6265..28b670f5d 100644 --- a/src/protocol/definitions/transport.c +++ b/src/protocol/definitions/transport.c @@ -14,21 +14,27 @@ #include "zenoh-pico/protocol/definitions/transport.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/utils/logging.h" -void _z_s_msg_scout_clear(_z_s_msg_scout_t *msg) {} +void _z_s_msg_scout_clear(_z_s_msg_scout_t *msg) { + // Nothing to do + _ZP_UNUSED(msg); +} /*------------------ Locators Field ------------------*/ void _z_locators_clear(_z_locator_array_t *ls) { _z_locator_array_clear(ls); } void _z_s_msg_hello_clear(_z_s_msg_hello_t *msg) { _z_locators_clear(&msg->_locators); } -void _z_t_msg_join_clear(_z_t_msg_join_t *msg) {} +void _z_t_msg_join_clear(_z_t_msg_join_t *msg) { + // Nothing to do + _ZP_UNUSED(msg); +} -void _z_t_msg_init_clear(_z_t_msg_init_t *msg) { _z_bytes_clear(&msg->_cookie); } +void _z_t_msg_init_clear(_z_t_msg_init_t *msg) { _z_slice_clear(&msg->_cookie); } -void _z_t_msg_open_clear(_z_t_msg_open_t *msg) { _z_bytes_clear(&msg->_cookie); } +void _z_t_msg_open_clear(_z_t_msg_open_t *msg) { _z_slice_clear(&msg->_cookie); } void _z_t_msg_close_clear(_z_t_msg_close_t *msg) { (void)(msg); } @@ -36,7 +42,7 @@ 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_fragment_clear(_z_t_msg_fragment_t *msg) { _z_bytes_clear(&msg->_payload); } +void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg) { _z_slice_clear(&msg->_payload); } void _z_t_msg_clear(_z_transport_message_t *msg) { uint8_t mid = _Z_MID(msg->_header); @@ -117,7 +123,7 @@ _z_transport_message_t _z_t_msg_make_init_syn(z_whatami_t whatami, _z_id_t zid) msg._body._init._seq_num_res = Z_SN_RESOLUTION; msg._body._init._req_id_res = Z_REQ_RESOLUTION; msg._body._init._batch_size = Z_BATCH_UNICAST_SIZE; - _z_bytes_reset(&msg._body._init._cookie); + _z_slice_reset(&msg._body._init._cookie); if ((msg._body._init._batch_size != _Z_DEFAULT_UNICAST_BATCH_SIZE) || (msg._body._init._seq_num_res != _Z_DEFAULT_RESOLUTION_SIZE) || @@ -128,7 +134,7 @@ _z_transport_message_t _z_t_msg_make_init_syn(z_whatami_t whatami, _z_id_t zid) return msg; } -_z_transport_message_t _z_t_msg_make_init_ack(z_whatami_t whatami, _z_id_t zid, _z_bytes_t cookie) { +_z_transport_message_t _z_t_msg_make_init_ack(z_whatami_t whatami, _z_id_t zid, _z_slice_t cookie) { _z_transport_message_t msg; msg._header = _Z_MID_T_INIT; _Z_SET_FLAG(msg._header, _Z_FLAG_T_INIT_A); @@ -151,7 +157,7 @@ _z_transport_message_t _z_t_msg_make_init_ack(z_whatami_t whatami, _z_id_t zid, } /*------------------ Open Message ------------------*/ -_z_transport_message_t _z_t_msg_make_open_syn(_z_zint_t lease, _z_zint_t initial_sn, _z_bytes_t cookie) { +_z_transport_message_t _z_t_msg_make_open_syn(_z_zint_t lease, _z_zint_t initial_sn, _z_slice_t cookie) { _z_transport_message_t msg; msg._header = _Z_MID_T_OPEN; @@ -173,7 +179,7 @@ _z_transport_message_t _z_t_msg_make_open_ack(_z_zint_t lease, _z_zint_t initial msg._body._open._lease = lease; msg._body._open._initial_sn = initial_sn; - _z_bytes_reset(&msg._body._open._cookie); + _z_slice_reset(&msg._body._open._cookie); if ((lease % 1000) == 0) { _Z_SET_FLAG(msg._header, _Z_FLAG_T_OPEN_T); @@ -235,9 +241,9 @@ _z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, z_reliability_t /*------------------ 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_bytes_empty(), reliability, is_last); + return _z_t_msg_make_fragment(sn, _z_slice_empty(), reliability, is_last); } -_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_bytes_t payload, z_reliability_t reliability, +_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_slice_t payload, z_reliability_t reliability, _Bool is_last) { _z_transport_message_t msg; msg._header = _Z_MID_T_FRAGMENT; @@ -255,7 +261,7 @@ _z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_bytes_t payload, } void _z_t_msg_copy_fragment(_z_t_msg_fragment_t *clone, _z_t_msg_fragment_t *msg) { - _z_bytes_copy(&clone->_payload, &msg->_payload); + _z_slice_copy(&clone->_payload, &msg->_payload); } void _z_t_msg_copy_join(_z_t_msg_join_t *clone, _z_t_msg_join_t *msg) { @@ -276,13 +282,13 @@ void _z_t_msg_copy_init(_z_t_msg_init_t *clone, _z_t_msg_init_t *msg) { clone->_req_id_res = msg->_req_id_res; clone->_batch_size = msg->_batch_size; memcpy(clone->_zid.id, msg->_zid.id, 16); - _z_bytes_copy(&clone->_cookie, &msg->_cookie); + _z_slice_copy(&clone->_cookie, &msg->_cookie); } void _z_t_msg_copy_open(_z_t_msg_open_t *clone, _z_t_msg_open_t *msg) { clone->_lease = msg->_lease; clone->_initial_sn = msg->_initial_sn; - _z_bytes_copy(&clone->_cookie, &msg->_cookie); + _z_slice_copy(&clone->_cookie, &msg->_cookie); } void _z_t_msg_copy_close(_z_t_msg_close_t *clone, _z_t_msg_close_t *msg) { clone->_reason = msg->_reason; } @@ -416,4 +422,4 @@ void _z_s_msg_copy(_z_scouting_message_t *clone, _z_scouting_message_t *msg) { _Z_DEBUG("WARNING: Trying to copy session message with unknown ID(%d)", mid); } break; } -} \ No newline at end of file +} diff --git a/src/protocol/ext.c b/src/protocol/ext.c index 0f3c3a56c..c40f2d75c 100644 --- a/src/protocol/ext.c +++ b/src/protocol/ext.c @@ -16,7 +16,7 @@ #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/utils/logging.h" _z_msg_ext_t _z_msg_ext_make_unit(uint8_t id) { @@ -52,22 +52,22 @@ void _z_msg_ext_clear_zint(_z_msg_ext_zint_t *ext) { (void)(ext); } void _z_msg_ext_copy_zint(_z_msg_ext_zint_t *clone, const _z_msg_ext_zint_t *ext) { clone->_val = ext->_val; } -_z_msg_ext_t _z_msg_ext_make_zbuf(uint8_t id, _z_bytes_t zbuf) { +_z_msg_ext_t _z_msg_ext_make_zbuf(uint8_t id, _z_slice_t zbuf) { _z_msg_ext_t ext; ext._header = 0; ext._header |= (id & _Z_EXT_ID_MASK); ext._header |= _Z_MSG_EXT_ENC_ZBUF; - _z_bytes_move(&ext._body._zbuf._val, &zbuf); + _z_slice_move(&ext._body._zbuf._val, &zbuf); return ext; } -void _z_msg_ext_clear_zbuf(_z_msg_ext_zbuf_t *ext) { _z_bytes_clear(&ext->_val); } +void _z_msg_ext_clear_zbuf(_z_msg_ext_zbuf_t *ext) { _z_slice_clear(&ext->_val); } void _z_msg_ext_copy_zbuf(_z_msg_ext_zbuf_t *clone, const _z_msg_ext_zbuf_t *ext) { - _z_bytes_copy(&clone->_val, &ext->_val); + _z_slice_copy(&clone->_val, &ext->_val); } void _z_msg_ext_copy(_z_msg_ext_t *clone, const _z_msg_ext_t *ext) { diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index c5700886f..aa1f0346f 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -70,7 +70,7 @@ uint8_t _z_iosli_read(_z_iosli_t *ios) { void _z_iosli_read_bytes(_z_iosli_t *ios, uint8_t *dst, size_t offset, size_t length) { assert(_z_iosli_readable(ios) >= length); - uint8_t *w_pos = _z_ptr_u8_offset(dst, offset); + uint8_t *w_pos = _z_ptr_u8_offset(dst, (ptrdiff_t)offset); (void)memcpy(w_pos, ios->_buf + ios->_r_pos, length); ios->_r_pos = ios->_r_pos + length; } @@ -90,8 +90,8 @@ void _z_iosli_write(_z_iosli_t *ios, uint8_t b) { void _z_iosli_write_bytes(_z_iosli_t *ios, const uint8_t *bs, size_t offset, size_t length) { assert(_z_iosli_writable(ios) >= length); - uint8_t *w_pos = _z_ptr_u8_offset(ios->_buf, ios->_w_pos); - (void)memcpy(w_pos, _z_cptr_u8_offset(bs, offset), length); + uint8_t *w_pos = _z_ptr_u8_offset(ios->_buf, (ptrdiff_t)ios->_w_pos); + (void)memcpy(w_pos, _z_cptr_u8_offset(bs, (ptrdiff_t)offset), length); ios->_w_pos += length; } @@ -100,10 +100,10 @@ void _z_iosli_put(_z_iosli_t *ios, uint8_t b, size_t pos) { ios->_buf[pos] = b; } -_z_bytes_t _z_iosli_to_bytes(const _z_iosli_t *ios) { - _z_bytes_t a; +_z_slice_t _z_iosli_to_bytes(const _z_iosli_t *ios) { + _z_slice_t a; a.len = _z_iosli_readable(ios); - a.start = _z_cptr_u8_offset(ios->_buf, ios->_r_pos); + a.start = _z_cptr_u8_offset(ios->_buf, (ptrdiff_t)ios->_r_pos); return a; } @@ -171,7 +171,7 @@ _z_zbuf_t _z_zbuf_view(_z_zbuf_t *zbf, size_t length) { v._ios = _z_iosli_wrap(_z_zbuf_get_rptr(zbf), length, 0, length); return v; } -_z_zbuf_t _z_zbytes_as_zbuf(_z_bytes_t slice) { +_z_zbuf_t _z_slice_as_zbuf(_z_slice_t slice) { return (_z_zbuf_t){._ios = {._buf = (uint8_t *)slice.start, // Safety: `_z_zbuf_t` is an immutable buffer ._is_alloc = false, ._capacity = slice.len, @@ -183,7 +183,9 @@ size_t _z_zbuf_capacity(const _z_zbuf_t *zbf) { return zbf->_ios._capacity; } size_t _z_zbuf_space_left(const _z_zbuf_t *zbf) { return _z_iosli_writable(&zbf->_ios); } -uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf) { return _z_ptr_u8_offset(zbf->_ios._buf, zbf->_ios._r_pos); } +uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf) { + return _z_ptr_u8_offset(zbf->_ios._buf, (ptrdiff_t)zbf->_ios._r_pos); +} size_t _z_zbuf_len(const _z_zbuf_t *zbf) { return _z_iosli_readable(&zbf->_ios); } _Bool _z_zbuf_can_read(const _z_zbuf_t *zbf) { return _z_zbuf_len(zbf) > (size_t)0; } diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index 49fefcbf7..6d87cbd73 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -27,16 +27,36 @@ _z_keyexpr_t _z_rname(const char *rname) { return _z_rid_with_suffix(0, rname); _z_keyexpr_t _z_rid_with_suffix(uint16_t rid, const char *suffix) { return (_z_keyexpr_t){ ._id = rid, - ._mapping = _z_keyexpr_mapping(_Z_KEYEXPR_MAPPING_LOCAL, false), - ._suffix = (char *)suffix, + ._mapping = _z_keyexpr_mapping(_Z_KEYEXPR_MAPPING_LOCAL), + ._suffix = (suffix == NULL) ? _z_string_null() : _z_string_alias_str(suffix), }; } -void _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { +_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(), + }; +} + +_z_keyexpr_t _z_keyexpr_from_substr(uint16_t rid, const char *str, size_t len) { + return (_z_keyexpr_t){ + ._id = rid, + ._mapping = _z_keyexpr_mapping(_Z_KEYEXPR_MAPPING_LOCAL), + ._suffix = (str != NULL) ? _z_string_alias_substr(str, len) : _z_string_null(), + }; +} + +int8_t _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { + *dst = _z_keyexpr_null(); dst->_id = src->_id; - dst->_suffix = src->_suffix ? _z_str_clone(src->_suffix) : NULL; dst->_mapping = src->_mapping; - _z_keyexpr_set_owns_suffix(dst, true); + + if (_z_keyexpr_has_suffix(src)) { + _Z_RETURN_IF_ERR(_z_string_copy(&dst->_suffix, &src->_suffix)); + } + return _Z_RES_OK; } _z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src) { @@ -45,22 +65,24 @@ _z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src) { return dst; } -_z_keyexpr_t _z_keyexpr_to_owned(_z_keyexpr_t src) { - return _z_keyexpr_owns_suffix(&src) ? src : _z_keyexpr_duplicate(src); -} - _z_keyexpr_t _z_keyexpr_steal(_Z_MOVE(_z_keyexpr_t) src) { _z_keyexpr_t stolen = *src; *src = _z_keyexpr_null(); return stolen; } +void _z_keyexpr_move(_z_keyexpr_t *dst, _z_keyexpr_t *src) { + dst->_id = src->_id; + dst->_mapping = src->_mapping; + _z_string_move(&dst->_suffix, &src->_suffix); +} + void _z_keyexpr_clear(_z_keyexpr_t *rk) { rk->_id = 0; - if (rk->_suffix != NULL && _z_keyexpr_owns_suffix(rk)) { - _z_str_clear((char *)rk->_suffix); - _z_keyexpr_set_owns_suffix(rk, false); + if (_z_keyexpr_has_suffix(rk)) { + _z_string_clear(&rk->_suffix); } + rk->_suffix = _z_string_null(); } void _z_keyexpr_free(_z_keyexpr_t **rk) { @@ -73,23 +95,45 @@ void _z_keyexpr_free(_z_keyexpr_t **rk) { *rk = NULL; } } + +_Bool _z_keyexpr_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { + if (left->_id != right->_id) { + return false; + } + 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 = src._suffix, + ._suffix = _z_string_alias(&src._suffix), }; - _z_keyexpr_set_owns_suffix(&alias, false); return alias; } +_z_keyexpr_t _z_keyexpr_alias_from_user_defined(_z_keyexpr_t src, _Bool try_declared) { + if ((try_declared && src._id != Z_RESOURCE_ID_NONE) || !_z_keyexpr_has_suffix(&src)) { + return (_z_keyexpr_t){ + ._id = src._id, + ._mapping = src._mapping, + ._suffix = _z_string_null(), + }; + } else { + return _z_keyexpr_from_string(0, &src._suffix); + } +} + /*------------------ Canonize helpers ------------------*/ zp_keyexpr_canon_status_t __zp_canon_prefix(const char *start, size_t *len) { zp_keyexpr_canon_status_t ret = Z_KEYEXPR_CANON_SUCCESS; _Bool in_big_wild = false; char const *chunk_start = start; - const char *end = _z_cptr_char_offset(start, *len); + const char *end = _z_cptr_char_offset(start, (ptrdiff_t)(*len)); char const *next_slash; do { @@ -192,7 +236,7 @@ zp_keyexpr_canon_status_t __zp_canon_prefix(const char *start, size_t *len) { } void __zp_singleify(char *start, size_t *len, const char *needle) { - const char *end = _z_cptr_char_offset(start, *len); + const char *end = _z_cptr_char_offset(start, (ptrdiff_t)(*len)); _Bool right_after_needle = false; char *reader = start; @@ -203,7 +247,7 @@ void __zp_singleify(char *start, size_t *len, const char *needle) { break; } right_after_needle = true; - reader = _z_ptr_char_offset(reader, pos); + reader = _z_ptr_char_offset(reader, (ptrdiff_t)pos); } else { right_after_needle = false; reader = _z_ptr_char_offset(reader, 1); @@ -218,10 +262,10 @@ void __zp_singleify(char *start, size_t *len, const char *needle) { for (size_t i = 0; i < pos; i++) { writer[i] = reader[i]; } - writer = _z_ptr_char_offset(writer, pos); + writer = _z_ptr_char_offset(writer, (ptrdiff_t)pos); } right_after_needle = true; - reader = _z_ptr_char_offset(reader, pos); + reader = _z_ptr_char_offset(reader, (ptrdiff_t)pos); } else { right_after_needle = false; *writer = *reader; @@ -239,7 +283,7 @@ void __zp_ke_write_chunk(char **writer, const char *chunk, size_t len, const cha } (void)memcpy(writer[0], chunk, len); - writer[0] = _z_ptr_char_offset(writer[0], len); + writer[0] = _z_ptr_char_offset(writer[0], (ptrdiff_t)len); } /*------------------ Common helpers ------------------*/ @@ -291,7 +335,7 @@ _Bool _z_ke_isdoublestar(_z_str_se_t s) { /*------------------ Inclusion helpers ------------------*/ _Bool _z_ke_chunk_includes_nodsl(_z_str_se_t l, _z_str_se_t r) { - size_t llen = l.end - l.start; + size_t llen = (size_t)(l.end - l.start); _Bool result = !(r.start[0] == _Z_VERBATIM) && ((llen == (size_t)1) && (l.start[0] == '*') && (((_z_ptr_char_diff(r.end, r.start) == 2) && (r.start[0] == '*')) == false)); @@ -360,14 +404,14 @@ _Bool _z_keyexpr_has_verbatim(_z_str_se_t s) { return false; } -_Bool _z_keyexpr_includes_superwild(_z_str_se_t left, _z_str_se_t right, _z_ke_chunk_matcher chunk_includer) { +_Bool _z_keyexpr_suffix_includes_superwild(_z_str_se_t left, _z_str_se_t right, _z_ke_chunk_matcher chunk_includer) { for (;;) { _z_str_se_t lchunk = {0}; _z_str_se_t lrest = _z_splitstr_split_once((_z_splitstr_t){.s = left, .delimiter = _Z_DELIMITER}, &lchunk); _Bool lempty = lrest.start == NULL; if (_z_keyexpr_is_superwild_chunk(lchunk)) { if (lempty ? !_z_keyexpr_has_verbatim(right) - : _z_keyexpr_includes_superwild(lrest, right, chunk_includer)) { + : _z_keyexpr_suffix_includes_superwild(lrest, right, chunk_includer)) { return true; } if (right.start[0] == _Z_VERBATIM) { @@ -393,11 +437,16 @@ _Bool _z_keyexpr_includes_superwild(_z_str_se_t left, _z_str_se_t right, _z_ke_c } /*------------------ Zenoh-Core helpers ------------------*/ -_Bool _z_keyexpr_includes(const char *lstart, const size_t llen, const char *rstart, const size_t rlen) { +_Bool _z_keyexpr_suffix_includes(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { + size_t llen = _z_string_len(&left->_suffix); + size_t rlen = _z_string_len(&right->_suffix); + const char *lstart = _z_string_data(&left->_suffix); + const char *rstart = _z_string_data(&right->_suffix); _Bool result = ((llen == rlen) && (strncmp(lstart, rstart, llen) == 0)); + if (result == false) { - _z_str_se_t l = {.start = lstart, .end = _z_cptr_char_offset(lstart, llen)}; - _z_str_se_t r = {.start = rstart, .end = _z_cptr_char_offset(rstart, rlen)}; + _z_str_se_t l = {.start = lstart, .end = _z_cptr_char_offset(lstart, (ptrdiff_t)llen)}; + _z_str_se_t r = {.start = rstart, .end = _z_cptr_char_offset(rstart, (ptrdiff_t)rlen)}; size_t ln_chunks = 0, ln_verbatim = 0; size_t rn_chunks = 0, rn_verbatim = 0; int8_t lwildness = _zp_ke_wildness(l, &ln_chunks, &ln_verbatim); @@ -408,7 +457,7 @@ _Bool _z_keyexpr_includes(const char *lstart, const size_t llen, const char *rst ? _z_ke_chunk_includes_stardsl : _z_ke_chunk_includes_nodsl; if ((lwildness & (int8_t)_ZP_WILDNESS_SUPERCHUNKS) == (int8_t)_ZP_WILDNESS_SUPERCHUNKS) { - return _z_keyexpr_includes_superwild(l, r, chunk_includer); + return _z_keyexpr_suffix_includes_superwild(l, r, chunk_includer); } else if (((rwildness & (int8_t)_ZP_WILDNESS_SUPERCHUNKS) == 0) && (ln_chunks == rn_chunks)) { _z_splitstr_t lchunks = {.s = l, .delimiter = _Z_DELIMITER}; _z_splitstr_t rchunks = {.s = r, .delimiter = _Z_DELIMITER}; @@ -627,11 +676,16 @@ _Bool _z_keyexpr_intersect_bothsuper(_z_str_se_t l, _z_str_se_t r, _z_ke_chunk_m (_z_splitstr_is_empty(&it2) || _z_keyexpr_is_superwild_chunk(it2.s)); } -_Bool _z_keyexpr_intersects(const char *lstart, const size_t llen, const char *rstart, const size_t rlen) { +_Bool _z_keyexpr_suffix_intersects(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { + size_t llen = _z_string_len(&left->_suffix); + size_t rlen = _z_string_len(&right->_suffix); + const char *lstart = _z_string_data(&left->_suffix); + const char *rstart = _z_string_data(&right->_suffix); _Bool result = ((llen == rlen) && (strncmp(lstart, rstart, llen) == 0)); + if (result == false) { - _z_str_se_t l = {.start = lstart, .end = _z_cptr_char_offset(lstart, llen)}; - _z_str_se_t r = {.start = rstart, .end = _z_cptr_char_offset(rstart, rlen)}; + _z_str_se_t l = {.start = lstart, .end = _z_cptr_char_offset(lstart, (ptrdiff_t)llen)}; + _z_str_se_t r = {.start = rstart, .end = _z_cptr_char_offset(rstart, (ptrdiff_t)rlen)}; size_t ln_chunks = 0, ln_verbatim = 0; size_t rn_chunks = 0, rn_verbatim = 0; int8_t lwildness = _zp_ke_wildness(l, &ln_chunks, &ln_verbatim); @@ -685,8 +739,8 @@ zp_keyexpr_canon_status_t _z_keyexpr_canonize(char *start, size_t *len) { (ret == Z_KEYEXPR_CANON_DOUBLE_STAR_AFTER_DOUBLE_STAR)) { ret = Z_KEYEXPR_CANON_SUCCESS; - const char *end = _z_cptr_char_offset(start, *len); - char *reader = _z_ptr_char_offset(start, canon_len); + const char *end = _z_cptr_char_offset(start, (ptrdiff_t)(*len)); + char *reader = _z_ptr_char_offset(start, (ptrdiff_t)canon_len); const char *write_start = reader; char *writer = reader; char *next_slash = strchr(reader, '/'); @@ -799,4 +853,20 @@ zp_keyexpr_canon_status_t _z_keyexpr_canonize(char *start, size_t *len) { return ret; } -zp_keyexpr_canon_status_t _z_keyexpr_is_canon(const char *start, size_t len) { return __zp_canon_prefix(start, &len); } \ No newline at end of file +zp_keyexpr_canon_status_t _z_keyexpr_is_canon(const char *start, size_t len) { return __zp_canon_prefix(start, &len); } + +_Bool _z_keyexpr_suffix_equals(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { + size_t llen = _z_string_len(&left->_suffix); + size_t rlen = _z_string_len(&right->_suffix); + const char *lstart = _z_string_data(&left->_suffix); + const char *rstart = _z_string_data(&right->_suffix); + + if (lstart != NULL && rstart != NULL) { + if (llen == rlen) { + if (strncmp(lstart, rstart, llen) == 0) { + return true; + } + } + } + return false; +} diff --git a/src/session/interest.c b/src/session/interest.c new file mode 100644 index 000000000..ef11c7d1f --- /dev/null +++ b/src/session/interest.c @@ -0,0 +1,448 @@ +// +// 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 +#include +#include + +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/config.h" +#include "zenoh-pico/net/query.h" +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/network.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/queryable.h" +#include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/utils.h" +#include "zenoh-pico/utils/logging.h" + +#if Z_FEATURE_INTEREST == 1 +void _z_declare_data_clear(_z_declare_data_t *data) { _z_keyexpr_clear(&data->_key); } + +_Bool _z_declare_data_eq(const _z_declare_data_t *left, const _z_declare_data_t *right) { + return ((left->_id == right->_id) && (left->_type == right->_type)); +} + +_Bool _z_session_interest_eq(const _z_session_interest_t *one, const _z_session_interest_t *two) { + return one->_id == two->_id; +} + +void _z_session_interest_clear(_z_session_interest_t *intr) { _z_keyexpr_clear(&intr->_key); } + +/*------------------ interest ------------------*/ +static _z_session_interest_rc_t *__z_get_interest_by_id(_z_session_interest_rc_list_t *intrs, const _z_zint_t id) { + _z_session_interest_rc_t *ret = NULL; + _z_session_interest_rc_list_t *xs = intrs; + while (xs != NULL) { + _z_session_interest_rc_t *intr = _z_session_interest_rc_list_head(xs); + if (id == _Z_RC_IN_VAL(intr)->_id) { + ret = intr; + break; + } + xs = _z_session_interest_rc_list_tail(xs); + } + return ret; +} + +static _z_session_interest_rc_list_t *__z_get_interest_by_key_and_flags(_z_session_interest_rc_list_t *intrs, + uint8_t flags, const _z_keyexpr_t *key) { + _z_session_interest_rc_list_t *ret = NULL; + _z_session_interest_rc_list_t *xs = intrs; + while (xs != NULL) { + _z_session_interest_rc_t *intr = _z_session_interest_rc_list_head(xs); + if ((_Z_RC_IN_VAL(intr)->_flags & flags) != 0) { + if (_z_keyexpr_suffix_intersects(&_Z_RC_IN_VAL(intr)->_key, key)) { + ret = _z_session_interest_rc_list_push(ret, _z_session_interest_rc_clone_as_ptr(intr)); + } + } + xs = _z_session_interest_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 + */ +static _z_session_interest_rc_t *__unsafe_z_get_interest_by_id(_z_session_t *zn, const _z_zint_t id) { + _z_session_interest_rc_list_t *intrs = zn->_local_interests; + return __z_get_interest_by_id(intrs, id); +} + +/** + * 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 + */ +static _z_session_interest_rc_list_t *__unsafe_z_get_interest_by_key_and_flags(_z_session_t *zn, uint8_t flags, + const _z_keyexpr_t *key) { + _z_session_interest_rc_list_t *intrs = zn->_local_interests; + return __z_get_interest_by_key_and_flags(intrs, flags, key); +} + +static int8_t _z_interest_send_decl_resource(_z_session_t *zn, uint32_t interest_id) { + _zp_session_lock_mutex(zn); + _z_resource_list_t *res_list = _z_resource_list_clone(zn->_local_resources); + _zp_session_unlock_mutex(zn); + _z_resource_list_t *xs = res_list; + while (xs != NULL) { + _z_resource_t *res = _z_resource_list_head(xs); + // Build the declare message to send on the wire + _z_keyexpr_t key = _z_keyexpr_alias(res->_key); + _z_declaration_t declaration = _z_make_decl_keyexpr(res->_id, &key); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, true, interest_id); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + xs = _z_resource_list_tail(xs); + } + _z_resource_list_free(&res_list); + return _Z_RES_OK; +} + +#if Z_FEATURE_SUBSCRIPTION == 1 +static int8_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t interest_id) { + _zp_session_lock_mutex(zn); + _z_subscription_rc_list_t *sub_list = _z_subscription_rc_list_clone(zn->_local_subscriptions); + _zp_session_unlock_mutex(zn); + _z_subscription_rc_list_t *xs = sub_list; + while (xs != NULL) { + _z_subscription_rc_t *sub = _z_subscription_rc_list_head(xs); + // Build the declare message to send on the wire + _z_keyexpr_t key = _z_keyexpr_alias(_Z_RC_IN_VAL(sub)->_key); + _z_declaration_t declaration = _z_make_decl_subscriber( + &key, _Z_RC_IN_VAL(sub)->_id, _Z_RC_IN_VAL(sub)->_info.reliability == Z_RELIABILITY_RELIABLE); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, true, interest_id); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + xs = _z_subscription_rc_list_tail(xs); + } + _z_subscription_rc_list_free(&sub_list); + return _Z_RES_OK; +} +#else +static int8_t _z_interest_send_decl_subscriber(_z_session_t *zn, uint32_t interest_id) { + _ZP_UNUSED(zn); + _ZP_UNUSED(interest_id); + return _Z_RES_OK; +} +#endif + +#if Z_FEATURE_QUERYABLE == 1 +static int8_t _z_interest_send_decl_queryable(_z_session_t *zn, uint32_t interest_id) { + _zp_session_lock_mutex(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_queryable_rc_list_t *xs = qle_list; + while (xs != NULL) { + _z_session_queryable_rc_t *qle = _z_session_queryable_rc_list_head(xs); + // Build the declare message to send on the wire + _z_keyexpr_t key = _z_keyexpr_alias(_Z_RC_IN_VAL(qle)->_key); + _z_declaration_t declaration = _z_make_decl_queryable( + &key, _Z_RC_IN_VAL(qle)->_id, _Z_RC_IN_VAL(qle)->_complete, _Z_QUERYABLE_DISTANCE_DEFAULT); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration, true, interest_id); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + xs = _z_subscription_rc_list_tail(xs); + } + _z_session_queryable_rc_list_free(&qle_list); + return _Z_RES_OK; +} +#else +static int8_t _z_interest_send_decl_queryable(_z_session_t *zn, uint32_t interest_id) { + _ZP_UNUSED(zn); + _ZP_UNUSED(interest_id); + return _Z_RES_OK; +} +#endif + +static int8_t _z_interest_send_declare_final(_z_session_t *zn, uint32_t interest_id) { + _z_declaration_t decl = _z_make_decl_final(); + _z_network_message_t n_msg = _z_n_msg_make_declare(decl, true, interest_id); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + return _Z_ERR_TRANSPORT_TX_FAILED; + } + _z_n_msg_clear(&n_msg); + return _Z_RES_OK; +} + +_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_interest_rc_t *intr = __unsafe_z_get_interest_by_id(zn, id); + _zp_session_unlock_mutex(zn); + return intr; +} + +_z_session_interest_rc_t *_z_register_interest(_z_session_t *zn, _z_session_interest_t *intr) { + _Z_DEBUG(">>> Allocating interest for (%ju:%.*s)", (uintmax_t)intr->_key._id, + (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); + 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); + return ret; +} + +static int8_t _unsafe_z_register_declare(_z_session_t *zn, const _z_keyexpr_t *key, uint32_t id, uint8_t type) { + _z_declare_data_t *decl = NULL; + decl = (_z_declare_data_t *)z_malloc(sizeof(_z_declare_data_t)); + if (decl == NULL) { + return _Z_ERR_SYSTEM_OUT_OF_MEMORY; + } + _z_keyexpr_copy(&decl->_key, key); + decl->_id = id; + decl->_type = type; + zn->_remote_declares = _z_declare_data_list_push(zn->_remote_declares, decl); + return _Z_RES_OK; +} + +static _z_keyexpr_t _unsafe_z_get_key_from_declare(_z_session_t *zn, uint32_t id, uint8_t type) { + _z_declare_data_list_t *xs = zn->_remote_declares; + _z_declare_data_t comp = { + ._key = _z_keyexpr_null(), + ._id = id, + ._type = type, + }; + 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); + } + xs = _z_declare_data_list_tail(xs); + } + return _z_keyexpr_null(); +} + +static int8_t _unsafe_z_unregister_declare(_z_session_t *zn, uint32_t id, uint8_t type) { + _z_declare_data_t decl = { + ._key = _z_keyexpr_null(), + ._id = id, + ._type = type, + }; + zn->_remote_declares = _z_declare_data_list_drop_filter(zn->_remote_declares, _z_declare_data_eq, &decl); + return _Z_RES_OK; +} + +int8_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t *decl) { + const _z_keyexpr_t *decl_key = NULL; + _z_interest_msg_t msg; + uint8_t flags = 0; + uint8_t decl_type = 0; + switch (decl->_tag) { + case _Z_DECL_SUBSCRIBER: + msg.type = _Z_INTEREST_MSG_TYPE_DECL_SUBSCRIBER; + msg.id = decl->_body._decl_subscriber._id; + decl_key = &decl->_body._decl_subscriber._keyexpr; + decl_type = _Z_DECLARE_TYPE_SUBSCRIBER; + flags = _Z_INTEREST_FLAG_SUBSCRIBERS; + break; + case _Z_DECL_QUERYABLE: + msg.type = _Z_INTEREST_MSG_TYPE_DECL_QUERYABLE; + msg.id = decl->_body._decl_queryable._id; + decl_key = &decl->_body._decl_queryable._keyexpr; + decl_type = _Z_DECLARE_TYPE_QUERYABLE; + flags = _Z_INTEREST_FLAG_QUERYABLES; + break; + default: + 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); + if (!_z_keyexpr_has_suffix(&key)) { + _zp_session_unlock_mutex(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); + // Parse session_interest list + _z_session_interest_rc_list_t *xs = intrs; + while (xs != NULL) { + _z_session_interest_rc_t *intr = _z_session_interest_rc_list_head(xs); + if (_Z_RC_IN_VAL(intr)->_callback != NULL) { + _Z_RC_IN_VAL(intr)->_callback(&msg, _Z_RC_IN_VAL(intr)->_arg); + } + xs = _z_session_interest_rc_list_tail(xs); + } + // Clean up + _z_keyexpr_clear(&key); + _z_session_interest_rc_list_free(&intrs); + return _Z_RES_OK; +} + +int8_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration_t *decl) { + _z_interest_msg_t msg; + uint8_t flags = 0; + uint8_t decl_type = 0; + switch (decl->_tag) { + case _Z_UNDECL_SUBSCRIBER: + msg.type = _Z_INTEREST_MSG_TYPE_UNDECL_SUBSCRIBER; + msg.id = decl->_body._undecl_subscriber._id; + decl_type = _Z_DECLARE_TYPE_SUBSCRIBER; + flags = _Z_INTEREST_FLAG_SUBSCRIBERS; + break; + case _Z_UNDECL_QUERYABLE: + msg.type = _Z_INTEREST_MSG_TYPE_UNDECL_QUERYABLE; + msg.id = decl->_body._undecl_queryable._id; + decl_type = _Z_DECLARE_TYPE_QUERYABLE; + flags = _Z_INTEREST_FLAG_QUERYABLES; + break; + default: + return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; + } + _zp_session_lock_mutex(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); + 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); + + // Parse session_interest list + _z_session_interest_rc_list_t *xs = intrs; + while (xs != NULL) { + _z_session_interest_rc_t *intr = _z_session_interest_rc_list_head(xs); + if (_Z_RC_IN_VAL(intr)->_callback != NULL) { + _Z_RC_IN_VAL(intr)->_callback(&msg, _Z_RC_IN_VAL(intr)->_arg); + } + xs = _z_session_interest_rc_list_tail(xs); + } + // Clean up + _z_keyexpr_clear(&key); + _z_session_interest_rc_list_free(&intrs); + return _Z_RES_OK; +} + +void _z_unregister_interest(_z_session_t *zn, _z_session_interest_rc_t *intr) { + _zp_session_lock_mutex(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); +} + +void _z_flush_interest(_z_session_t *zn) { + _zp_session_lock_mutex(zn); + _z_session_interest_rc_list_free(&zn->_local_interests); + _z_declare_data_list_free(&zn->_remote_declares); + _zp_session_unlock_mutex(zn); +} + +int8_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_interest_rc_t *intr = __unsafe_z_get_interest_by_id(zn, id); + _zp_session_unlock_mutex(zn); + if (intr == NULL) { + return _Z_RES_OK; + } + // Trigger callback + if (_Z_RC_IN_VAL(intr)->_callback != NULL) { + _Z_RC_IN_VAL(intr)->_callback(&msg, _Z_RC_IN_VAL(intr)->_arg); + } + return _Z_RES_OK; +} + +int8_t _z_interest_process_interest_final(_z_session_t *zn, uint32_t id) { + _ZP_UNUSED(zn); + _ZP_UNUSED(id); + // TODO: Update future masks + return _Z_RES_OK; +} + +int8_t _z_interest_process_interest(_z_session_t *zn, _z_keyexpr_t key, uint32_t id, uint8_t flags) { + // TODO: process restricted flag & associated key + _ZP_UNUSED(key); + // Check transport type + if (zn->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { + return _Z_RES_OK; // Nothing to do on unicast + } + // Current flags process + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_CURRENT)) { + // Send all declare + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_KEYEXPRS)) { + _Z_DEBUG("Sending declare resources"); + _Z_RETURN_IF_ERR(_z_interest_send_decl_resource(zn, id)); + } + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_SUBSCRIBERS)) { + _Z_DEBUG("Sending declare subscribers"); + _Z_RETURN_IF_ERR(_z_interest_send_decl_subscriber(zn, id)); + } + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_QUERYABLES)) { + _Z_DEBUG("Sending declare queryables"); + _Z_RETURN_IF_ERR(_z_interest_send_decl_queryable(zn, id)); + } + if (_Z_HAS_FLAG(flags, _Z_INTEREST_FLAG_TOKENS)) { + // Zenoh pico doesn't support liveliness token for now + } + // Send final declare + _Z_RETURN_IF_ERR(_z_interest_send_declare_final(zn, id)); + } + return _Z_RES_OK; +} + +#else +void _z_flush_interest(_z_session_t *zn) { _ZP_UNUSED(zn); } + +int8_t _z_interest_process_declares(_z_session_t *zn, const _z_declaration_t *decl) { + _ZP_UNUSED(zn); + _ZP_UNUSED(decl); + return _Z_RES_OK; +} + +int8_t _z_interest_process_undeclares(_z_session_t *zn, const _z_declaration_t *decl) { + _ZP_UNUSED(zn); + _ZP_UNUSED(decl); + return _Z_RES_OK; +} + +int8_t _z_interest_process_declare_final(_z_session_t *zn, uint32_t id) { + _ZP_UNUSED(zn); + _ZP_UNUSED(id); + return _Z_RES_OK; +} + +int8_t _z_interest_process_interest_final(_z_session_t *zn, uint32_t id) { + _ZP_UNUSED(zn); + _ZP_UNUSED(id); + return _Z_RES_OK; +} + +int8_t _z_interest_process_interest(_z_session_t *zn, _z_keyexpr_t key, uint32_t id, uint8_t flags) { + _ZP_UNUSED(zn); + _ZP_UNUSED(key); + _ZP_UNUSED(id); + _ZP_UNUSED(flags); + return _Z_RES_OK; +} +#endif diff --git a/src/session/push.c b/src/session/push.c index 0fa85cb4c..277f52f38 100644 --- a/src/session/push.c +++ b/src/session/push.c @@ -16,7 +16,7 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/primitives.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/config.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/utils/logging.h" @@ -25,19 +25,23 @@ int8_t _z_trigger_push(_z_session_t *zn, _z_n_msg_push_t *push) { int8_t ret = _Z_RES_OK; // TODO check body to know where to dispatch - _z_bytes_t payload = push->_body._is_put ? push->_body._body._put._payload : _z_bytes_empty(); - _z_encoding_t encoding = push->_body._is_put ? push->_body._body._put._encoding : z_encoding_default(); - int kind = push->_body._is_put ? Z_SAMPLE_KIND_PUT : Z_SAMPLE_KIND_DELETE; #if Z_FEATURE_SUBSCRIPTION == 1 -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t att = _z_encoded_as_attachment(&push->_body._body._put._attachment); -#endif - ret = _z_trigger_subscriptions(zn, push->_key, payload, encoding, kind, push->_timestamp, push->_qos -#if Z_FEATURE_ATTACHMENT == 1 - , - att -#endif - ); + + 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); + } 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); + } +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(push); #endif return ret; } diff --git a/src/session/query.c b/src/session/query.c index 83c474049..fef9dbaa0 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -17,56 +17,19 @@ #include #include "zenoh-pico/config.h" -#include "zenoh-pico/net/memory.h" +#include "zenoh-pico/net/reply.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_QUERY == 1 -_z_reply_t *_z_reply_alloc_and_move(_z_reply_t *_reply) { - _z_reply_t *reply = (_z_reply_t *)z_malloc(sizeof(_z_reply_t)); - if (reply != NULL) { - *reply = *_reply; - (void)memset(_reply, 0, sizeof(_z_reply_t)); - } - return reply; -} - -void _z_reply_clear(_z_reply_t *reply) { _z_reply_data_clear(&reply->data); } - -void _z_reply_free(_z_reply_t **reply) { - _z_reply_t *ptr = *reply; - - if (*reply != NULL) { - _z_reply_clear(ptr); - - z_free(ptr); - *reply = NULL; - } -} - -_Bool _z_pending_reply_eq(const _z_pending_reply_t *one, const _z_pending_reply_t *two) { - return one->_tstamp.time == two->_tstamp.time; -} - -void _z_pending_reply_clear(_z_pending_reply_t *pr) { - // Free reply - _z_reply_clear(&pr->_reply); - - // Free the timestamp - _z_timestamp_clear(&pr->_tstamp); -} - void _z_pending_query_clear(_z_pending_query_t *pen_qry) { if (pen_qry->_dropper != NULL) { - pen_qry->_dropper(pen_qry->_drop_arg); + pen_qry->_dropper(pen_qry->_arg); } - - z_free(pen_qry->_call_arg); - _z_keyexpr_clear(&pen_qry->_key); - _z_str_clear(pen_qry->_parameters); - _z_pending_reply_list_free(&pen_qry->_pending_replies); } @@ -103,27 +66,21 @@ _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) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_pending_query_t *pql = __unsafe__z_get_pending_query_by_id(zn, id); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return pql; } int8_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_qry) { int8_t ret = _Z_RES_OK; - _Z_DEBUG(">>> Allocating query for (%ju:%s,%s)", (uintmax_t)pen_qry->_key._id, pen_qry->_key._suffix, - pen_qry->_parameters); + _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)); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(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 @@ -132,21 +89,16 @@ int8_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_qry) ret = _Z_ERR_ENTITY_DECLARATION_FAILED; } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return ret; } int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, const _z_keyexpr_t keyexpr, - const _z_bytes_t payload, const _z_encoding_t encoding, const _z_zint_t kind, - const _z_timestamp_t timestamp) { + _z_msg_put_t *msg, z_sample_kind_t kind) { int8_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, id); if ((ret == _Z_RES_OK) && (pen_qry == NULL)) { @@ -155,34 +107,27 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, cons _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_intersects(pen_qry->_key._suffix, strlen(pen_qry->_key._suffix), - keyexpr._suffix, strlen(keyexpr._suffix)) == false))) { + ((pen_qry->_anykey == false) && (_z_keyexpr_suffix_intersects(&pen_qry->_key, &keyexpr) == false))) { ret = _Z_ERR_QUERY_NOT_MATCH; } // Build the reply - _z_reply_t reply; - reply._tag = Z_REPLY_TAG_DATA; - reply.data.replier_id = zn->_local_zid; - reply.data.sample.keyexpr = expanded_ke; - _z_bytes_copy(&reply.data.sample.payload, &payload); - reply.data.sample.encoding.prefix = encoding.prefix; - _z_bytes_copy(&reply.data.sample.encoding.suffix, &encoding.suffix); - reply.data.sample.kind = kind; - reply.data.sample.timestamp = _z_timestamp_duplicate(×tamp); + _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))) { - _Bool drop = false; _z_pending_reply_list_t *pen_rps = pen_qry->_pending_replies; _z_pending_reply_t *pen_rep = NULL; while (pen_rps != NULL) { pen_rep = _z_pending_reply_list_head(pen_rps); // Check if this is the same resource key - if (_z_str_eq(pen_rep->_reply.data.sample.keyexpr._suffix, reply.data.sample.keyexpr._suffix) == true) { - if (timestamp.time <= pen_rep->_tstamp.time) { + if (_z_string_equals(&pen_rep->_reply.data._result.sample.keyexpr._suffix, + &reply.data._result.sample.keyexpr._suffix) == true) { + if (msg->_commons._timestamp.time <= pen_rep->_tstamp.time) { drop = true; } else { pen_qry->_pending_replies = @@ -190,7 +135,6 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, cons } break; } - pen_rps = _z_pending_reply_list_tail(pen_rps); } @@ -203,12 +147,13 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, cons _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.sample.keyexpr = _z_keyexpr_duplicate(reply.data.sample.keyexpr); + 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(×tamp); + pen_rep->_tstamp = _z_timestamp_duplicate(&msg->_commons._timestamp); pen_qry->_pending_replies = _z_pending_reply_list_push(pen_qry->_pending_replies, pen_rep); } else { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; @@ -216,13 +161,45 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, cons } } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); // Trigger the user callback if ((ret == _Z_RES_OK) && (pen_qry->_consolidation != Z_CONSOLIDATION_MODE_LATEST)) { - pen_qry->_callback(_z_reply_alloc_and_move(&reply), pen_qry->_call_arg); + _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); + } + + return ret; +} + +int8_t _z_trigger_query_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *msg) { + int8_t ret = _Z_RES_OK; + + _zp_session_lock_mutex(zn); + + _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; + } + + // Build the reply + _z_reply_t reply = _z_reply_err_create(msg->_payload, &msg->_encoding); + + _zp_session_unlock_mutex(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) { @@ -235,24 +212,24 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_zint_t id, cons int8_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { int8_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); // Final reply received for unknown query id _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; } - // The reply is the final one, apply consolidation if needed if ((ret == _Z_RES_OK) && (pen_qry->_consolidation == Z_CONSOLIDATION_MODE_LATEST)) { while (pen_qry->_pending_replies != NULL) { _z_pending_reply_t *pen_rep = _z_pending_reply_list_head(pen_qry->_pending_replies); // Trigger the query handler - pen_qry->_callback(_z_reply_alloc_and_move(&pen_rep->_reply), pen_qry->_call_arg); + _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->_pending_replies = _z_pending_reply_list_pop(pen_qry->_pending_replies, NULL); + _z_reply_clear(&cb_reply); } } @@ -261,34 +238,24 @@ int8_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return ret; } void _z_unregister_pending_query(_z_session_t *zn, _z_pending_query_t *pen_qry) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); zn->_pending_queries = _z_pending_query_list_drop_filter(zn->_pending_queries, _z_pending_query_eq, pen_qry); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } void _z_flush_pending_queries(_z_session_t *zn) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_pending_query_list_free(&zn->_pending_queries); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } #endif diff --git a/src/session/queryable.c b/src/session/queryable.c index ce6044a54..1e14b69ca 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -45,7 +45,7 @@ _z_session_queryable_rc_t *__z_get_session_queryable_by_id(_z_session_queryable_ _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 (id == qle->in->val._id) { + if (id == _Z_RC_IN_VAL(qle)->_id) { ret = qle; break; } @@ -63,8 +63,7 @@ _z_session_queryable_rc_list_t *__z_get_session_queryable_by_key(_z_session_quer _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_intersects(qle->in->val._key._suffix, strlen(qle->in->val._key._suffix), key._suffix, - strlen(key._suffix)) == true) { + 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)); } @@ -95,89 +94,72 @@ _z_session_queryable_rc_list_t *__unsafe_z_get_session_queryable_by_key(_z_sessi } _z_session_queryable_rc_t *_z_get_session_queryable_by_id(_z_session_t *zn, const _z_zint_t id) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_session_queryable_rc_t *qle = __unsafe_z_get_session_queryable_by_id(zn, id); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return qle; } _z_session_queryable_rc_list_t *_z_get_session_queryable_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _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); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _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, q->_key._suffix); + _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; -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); ret = (_z_session_queryable_rc_t *)z_malloc(sizeof(_z_session_queryable_rc_t)); if (ret != NULL) { - *ret = _z_session_queryable_rc_new_from_val(*q); + *ret = _z_session_queryable_rc_new_from_val(q); zn->_local_queryable = _z_session_queryable_rc_list_push(zn->_local_queryable, ret); } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return ret; } -int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *msgq, const _z_keyexpr_t q_key, uint32_t qid) { +int8_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) { int8_t ret = _Z_RES_OK; + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key); - if (key._suffix != NULL) { + if (_z_keyexpr_has_suffix(&key)) { _z_session_queryable_rc_list_t *qles = __unsafe_z_get_session_queryable_by_key(zn, key); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); // Build the z_query - z_query_t query = {._val = {._rc = _z_query_rc_new()}}; - query._val._rc.in->val = _z_query_create(&msgq->_ext_value, &key, &msgq->_parameters, zn, qid); + _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); - qle->in->val._callback(&query, qle->in->val._arg); + _Z_RC_IN_VAL(qle)->_callback(&query, _Z_RC_IN_VAL(qle)->_arg); xs = _z_session_queryable_rc_list_tail(xs); } // Clean up - _z_query_rc_drop(&query._val._rc); - _z_keyexpr_clear(&key); + _z_query_rc_drop(&query); _z_session_queryable_rc_list_free(&qles); } else { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 - + _zp_session_unlock_mutex(zn); ret = _Z_ERR_KEYEXPR_UNKNOWN; } @@ -185,28 +167,20 @@ int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *msgq, const } void _z_unregister_session_queryable(_z_session_t *zn, _z_session_queryable_rc_t *qle) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); zn->_local_queryable = _z_session_queryable_rc_list_drop_filter(zn->_local_queryable, _z_session_queryable_rc_eq, qle); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } void _z_flush_session_queryable(_z_session_t *zn) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_session_queryable_rc_list_free(&zn->_local_queryable); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } #endif diff --git a/src/session/reply.c b/src/session/reply.c index 15cf19407..19835aa49 100644 --- a/src/session/reply.c +++ b/src/session/reply.c @@ -25,8 +25,28 @@ int8_t _z_trigger_reply_partial(_z_session_t *zn, _z_zint_t id, _z_keyexpr_t key // TODO check id to know where to dispatch #if Z_FEATURE_QUERY == 1 - ret = _z_trigger_query_reply_partial(zn, id, key, reply->_value.payload, reply->_value.encoding, Z_SAMPLE_KIND_PUT, - reply->_timestamp); + ret = _z_trigger_query_reply_partial(zn, id, key, &reply->_body._body._put, + (reply->_body._is_put ? Z_SAMPLE_KIND_PUT : Z_SAMPLE_KIND_DELETE)); +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(id); + _ZP_UNUSED(key); + _ZP_UNUSED(reply); +#endif + return ret; +} + +int8_t _z_trigger_reply_err(_z_session_t *zn, _z_zint_t id, _z_msg_err_t *error) { + int8_t ret = _Z_RES_OK; + + // TODO check id to know where to dispatch + +#if Z_FEATURE_QUERY == 1 + ret = _z_trigger_query_reply_err(zn, id, error); +#else + _ZP_UNUSED(zn); + _ZP_UNUSED(id); + _ZP_UNUSED(error); #endif return ret; } @@ -39,6 +59,7 @@ int8_t _z_trigger_reply_final(_z_session_t *zn, _z_n_msg_response_final_t *final _z_zint_t id = final->_request_id; _z_trigger_query_reply_final(zn, id); #else + _ZP_UNUSED(zn); _ZP_UNUSED(final); #endif return ret; diff --git a/src/session/resource.c b/src/session/resource.c index ca107f4e7..3c165266e 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -22,13 +22,21 @@ #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/session.h" +#include "zenoh-pico/session/utils.h" #include "zenoh-pico/system/platform.h" #include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/pointers.h" _Bool _z_resource_eq(const _z_resource_t *other, const _z_resource_t *this_) { return this_->_id == other->_id; } void _z_resource_clear(_z_resource_t *res) { _z_keyexpr_clear(&res->_key); } +void _z_resource_copy(_z_resource_t *dst, const _z_resource_t *src) { + _z_keyexpr_copy(&dst->_key, &src->_key); + dst->_id = src->_id; + dst->_refcount = src->_refcount; +} + void _z_resource_free(_z_resource_t **res) { _z_resource_t *ptr = *res; @@ -65,13 +73,10 @@ _z_resource_t *__z_get_resource_by_id(_z_resource_list_t *rl, uint16_t mapping, _z_resource_t *__z_get_resource_by_key(_z_resource_list_t *rl, const _z_keyexpr_t *keyexpr) { _z_resource_t *ret = NULL; - uint16_t mapping = _z_keyexpr_mapping_id(keyexpr); - _z_resource_list_t *xs = rl; while (xs != NULL) { _z_resource_t *r = _z_resource_list_head(xs); - if ((r->_key._id == keyexpr->_id) && _z_keyexpr_mapping_id(&r->_key) == mapping && - (_z_str_eq(r->_key._suffix, keyexpr->_suffix) == true)) { + if (_z_keyexpr_equals(&r->_key, keyexpr)) { ret = r; break; } @@ -83,19 +88,19 @@ _z_resource_t *__z_get_resource_by_key(_z_resource_list_t *rl, const _z_keyexpr_ } _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 = NULL, ._mapping = _z_keyexpr_mapping(0, true)}; + _z_keyexpr_t ret = {._id = Z_RESOURCE_ID_NONE, ._suffix = _z_string_null(), ._mapping = _z_keyexpr_mapping(0)}; // Need to build the complete resource name, by recursively look at RIDs // Resource names are looked up from right to left - _z_str_list_t *strs = NULL; - size_t len = 1; // Start with space for the null-terminator + _z_string_list_t *strs = NULL; + size_t len = 0; // Append suffix as the right-most segment - if (keyexpr->_suffix != NULL) { - len = len + strlen(keyexpr->_suffix); - strs = _z_str_list_push(strs, (char *)keyexpr->_suffix); // Warning: list must be release with - // _z_list_free(&strs, _z_noop_free); - // or will release the suffix as well + 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 } // Recursively go through all the RIDs @@ -107,39 +112,31 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye len = 0; break; } - - if (res->_key._suffix != NULL) { - len = len + strlen(res->_key._suffix); - strs = _z_str_list_push(strs, (char *)res->_key._suffix); // Warning: list must be release with - // _z_list_free(&strs, _z_noop_free); - // or will release the suffix as well + 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 } id = res->_key._id; } - + // Copy the data if (len != (size_t)0) { - char *rname = NULL; - rname = (char *)z_malloc(len); - if (rname != NULL) { - rname[0] = '\0'; // NULL terminator must be set (required to strcat) - len = len - (size_t)1; + ret._suffix = _z_string_preallocate(len); + if (_z_keyexpr_has_suffix(&ret)) { + char *curr_ptr = (char *)_z_string_data(&ret._suffix); // Concatenate all the partial resource names - _z_str_list_t *xstr = strs; + _z_string_list_t *xstr = strs; while (xstr != NULL) { - char *s = _z_str_list_head(xstr); - if (len > (size_t)0) { - (void)strncat(rname, s, len); - len = len - strlen(s); - } - xstr = _z_str_list_tail(xstr); + _z_string_t *s = _z_string_list_head(xstr); + memcpy(curr_ptr, _z_string_data(s), _z_string_len(s)); + curr_ptr = _z_ptr_char_offset(curr_ptr, (ptrdiff_t)_z_string_len(s)); + xstr = _z_string_list_tail(xstr); } - ret._suffix = rname; } } - _z_list_free(&strs, _z_noop_free); - return ret; } @@ -174,59 +171,45 @@ _z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_key } _z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t rid) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_resource_t *res = __unsafe_z_get_resource_by_id(zn, mapping, rid); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return res; } _z_resource_t *_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { - if (keyexpr->_suffix == NULL) { + if (!_z_keyexpr_has_suffix(keyexpr)) { return _z_get_resource_by_id(zn, _z_keyexpr_mapping_id(keyexpr), keyexpr->_id); } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_resource_t *res = __unsafe_z_get_resource_by_key(zn, keyexpr); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return res; } _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return res; } /// Returns the ID of the registered keyexpr. Returns 0 if registration failed. -int16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, uint16_t register_to_mapping) { - int16_t ret = Z_RESOURCE_ID_NONE; +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); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); if (key._id != Z_RESOURCE_ID_NONE) { if (parent_mapping == mapping) { @@ -237,13 +220,13 @@ int16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, ui } } ret = key._id; - if ((key._suffix != NULL)) { + if (_z_keyexpr_has_suffix(&key)) { _z_resource_t *res = z_malloc(sizeof(_z_resource_t)); if (res == NULL) { ret = Z_RESOURCE_ID_NONE; } else { res->_refcount = 1; - res->_key = _z_keyexpr_to_owned(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 @@ -255,9 +238,7 @@ int16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, ui } } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return ret; } @@ -265,9 +246,7 @@ int16_t _z_register_resource(_z_session_t *zn, _z_keyexpr_t key, uint16_t id, ui 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); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(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; @@ -289,9 +268,7 @@ void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping) { parent = *parent_mut; } } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } _Bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, const _z_resource_t *ctx) { @@ -299,27 +276,19 @@ _Bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, con return _z_keyexpr_mapping_id(&candidate->_key) == mapping; } void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(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); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } void _z_flush_resources(_z_session_t *zn) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_resource_list_free(&zn->_local_resources); _z_resource_list_free(&zn->_remote_resources); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } diff --git a/src/session/rx.c b/src/session/rx.c index 0428aef12..6109a5455 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -18,12 +18,13 @@ #include "zenoh-pico/api/constants.h" #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/declarations.h" #include "zenoh-pico/protocol/definitions/message.h" #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/interest.h" #include "zenoh-pico/session/push.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/reply.h" @@ -34,34 +35,35 @@ #include "zenoh-pico/utils/logging.h" /*------------------ Handle message ------------------*/ -int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint16_t local_peer_id) { +int8_t _z_handle_network_message(_z_session_rc_t *zsrc, _z_zenoh_message_t *msg, uint16_t local_peer_id) { int8_t ret = _Z_RES_OK; + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); switch (msg->_tag) { case _Z_N_DECLARE: { _Z_DEBUG("Handling _Z_N_DECLARE"); - _z_n_msg_declare_t decl = msg->_body._declare; - switch (decl._decl._tag) { + _z_n_msg_declare_t *decl = &msg->_body._declare; + switch (decl->_decl._tag) { case _Z_DECL_KEXPR: { - if (_z_register_resource(zn, decl._decl._body._decl_kexpr._keyexpr, - decl._decl._body._decl_kexpr._id, local_peer_id) == 0) { + if (_z_register_resource(zn, decl->_decl._body._decl_kexpr._keyexpr, + decl->_decl._body._decl_kexpr._id, local_peer_id) == 0) { ret = _Z_ERR_ENTITY_DECLARATION_FAILED; } } break; case _Z_UNDECL_KEXPR: { - _z_unregister_resource(zn, decl._decl._body._undecl_kexpr._id, local_peer_id); + _z_unregister_resource(zn, decl->_decl._body._undecl_kexpr._id, local_peer_id); } break; case _Z_DECL_SUBSCRIBER: { - // TODO: add support or explicitly discard - } break; - case _Z_UNDECL_SUBSCRIBER: { - // TODO: add support or explicitly discard + _z_interest_process_declares(zn, &decl->_decl); } break; case _Z_DECL_QUERYABLE: { - // TODO: add support or explicitly discard + _z_interest_process_declares(zn, &decl->_decl); + } break; + case _Z_UNDECL_SUBSCRIBER: { + _z_interest_process_undeclares(zn, &decl->_decl); } break; case _Z_UNDECL_QUERYABLE: { - // TODO: add support or explicitly discard + _z_interest_process_undeclares(zn, &decl->_decl); } break; case _Z_DECL_TOKEN: { // TODO: add support or explicitly discard @@ -69,14 +71,12 @@ int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint case _Z_UNDECL_TOKEN: { // TODO: add support or explicitly discard } break; - case _Z_DECL_INTEREST: { - // TODO: add support or explicitly discard - } break; - case _Z_FINAL_INTEREST: { - // TODO: add support or explicitly discard - } break; - case _Z_UNDECL_INTEREST: { - // TODO: add support or explicitly discard + case _Z_DECL_FINAL: { + // Check that interest id is valid + if (!decl->has_interest_id) { + return _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; + } + _z_interest_process_declare_final(zn, decl->_interest_id); } break; } } break; @@ -87,105 +87,53 @@ int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint } break; case _Z_N_REQUEST: { _Z_DEBUG("Handling _Z_N_REQUEST"); - _z_n_msg_request_t req = msg->_body._request; - switch (req._tag) { + _z_n_msg_request_t *req = &msg->_body._request; + switch (req->_tag) { case _Z_REQUEST_QUERY: { #if Z_FEATURE_QUERYABLE == 1 - _z_msg_query_t *query = &req._body._query; - ret = _z_trigger_queryables(zn, query, req._key, (uint32_t)req._rid); + _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); #else _Z_DEBUG("_Z_REQUEST_QUERY dropped, queryables not supported"); #endif } break; case _Z_REQUEST_PUT: { - _z_msg_put_t put = req._body._put; #if Z_FEATURE_SUBSCRIPTION == 1 -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t att = _z_encoded_as_attachment(&put._attachment); -#endif - ret = _z_trigger_subscriptions(zn, req._key, put._payload, put._encoding, Z_SAMPLE_KIND_PUT, - put._commons._timestamp, req._ext_qos -#if Z_FEATURE_ATTACHMENT == 1 - , - att -#endif - ); + _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); #endif if (ret == _Z_RES_OK) { - _z_network_message_t ack = _z_n_msg_make_ack(req._rid, &req._key); - ret = _z_send_n_msg(zn, &ack, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); - _z_network_message_t final = _z_n_msg_make_response_final(req._rid); + _z_network_message_t final = _z_n_msg_make_response_final(req->_rid); ret |= _z_send_n_msg(zn, &final, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); } } break; case _Z_REQUEST_DEL: { - _z_msg_del_t del = req._body._del; #if Z_FEATURE_SUBSCRIPTION == 1 - ret = _z_trigger_subscriptions(zn, req._key, _z_bytes_empty(), z_encoding_default(), - Z_SAMPLE_KIND_DELETE, del._commons._timestamp, req._ext_qos -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_null() -#endif - ); + _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); #endif if (ret == _Z_RES_OK) { - _z_network_message_t ack = _z_n_msg_make_ack(req._rid, &req._key); - ret = _z_send_n_msg(zn, &ack, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); - _z_network_message_t final = _z_n_msg_make_response_final(req._rid); + _z_network_message_t final = _z_n_msg_make_response_final(req->_rid); ret |= _z_send_n_msg(zn, &final, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK); } } break; - case _Z_REQUEST_PULL: { - // @TODO: define behaviour - } break; } } break; case _Z_N_RESPONSE: { _Z_DEBUG("Handling _Z_N_RESPONSE"); - _z_n_msg_response_t response = msg->_body._response; - switch (response._tag) { + _z_n_msg_response_t *response = &msg->_body._response; + 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); + _z_msg_reply_t *reply = &response->_body._reply; + ret = _z_trigger_reply_partial(zn, response->_request_id, response->_key, reply); } break; case _Z_RESPONSE_BODY_ERR: { - // @TODO: expose errors to the user - _z_msg_err_t error = response._body._err; - _z_bytes_t payload = error._ext_value.payload; - _ZP_UNUSED(payload); // Unused when logs are deactivated - _Z_ERROR("Received Err for query %zu: code=%d, message=%.*s", response._request_id, error._code, - (int)payload.len, payload.start); - } break; - case _Z_RESPONSE_BODY_ACK: { - // @TODO: implement ACKs for puts/dels - } break; - case _Z_RESPONSE_BODY_PUT: { - _z_msg_put_t put = response._body._put; -#if Z_FEATURE_SUBSCRIPTION == 1 -#if Z_FEATURE_ATTACHMENT == 1 - z_attachment_t att = _z_encoded_as_attachment(&put._attachment); -#endif - ret = _z_trigger_subscriptions(zn, response._key, put._payload, put._encoding, Z_SAMPLE_KIND_PUT, - put._commons._timestamp, response._ext_qos -#if Z_FEATURE_ATTACHMENT == 1 - , - att -#endif - ); -#endif - } break; - case _Z_RESPONSE_BODY_DEL: { - _z_msg_del_t del = response._body._del; -#if Z_FEATURE_SUBSCRIPTION == 1 - ret = _z_trigger_subscriptions(zn, response._key, _z_bytes_empty(), z_encoding_default(), - Z_SAMPLE_KIND_DELETE, del._commons._timestamp, response._ext_qos -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_null() -#endif - ); -#endif + _z_msg_err_t *error = &response->_body._err; + ret = _z_trigger_reply_err(zn, response->_request_id, error); } break; } } break; @@ -193,6 +141,19 @@ int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint _Z_DEBUG("Handling _Z_N_RESPONSE_FINAL"); ret = _z_trigger_reply_final(zn, &msg->_body._response_final); } break; + + case _Z_N_INTEREST: { + _Z_DEBUG("Handling _Z_N_INTEREST"); + _z_n_msg_interest_t *interest = &msg->_body._interest; + + _Bool not_final = ((interest->_interest.flags & _Z_INTEREST_NOT_FINAL_MASK) != 0); + if (not_final) { + _z_interest_process_interest(zn, interest->_interest._keyexpr, interest->_interest._id, + interest->_interest.flags); + } else { + _z_interest_process_interest_final(zn, interest->_interest._id); + } + } } _z_msg_clear(msg); return ret; diff --git a/src/session/scout.c b/src/session/scout.c index b3a8dffb8..7f11fb0de 100644 --- a/src/session/scout.c +++ b/src/session/scout.c @@ -25,16 +25,17 @@ #error "Scouting UDP requires UDP unicast links to be enabled (Z_FEATURE_LINK_UDP_UNICAST = 1 in config.h)" #endif -_z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, const char *locator, unsigned long period, _Bool exit_on_first) { +_z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, _z_string_t *locator, unsigned long period, _Bool exit_on_first) { // Define an empty array _z_hello_list_t *ret = NULL; int8_t err = _Z_RES_OK; _z_endpoint_t ep; - err = _z_endpoint_from_str(&ep, locator); + err = _z_endpoint_from_string(&ep, locator); #if Z_FEATURE_SCOUTING_UDP == 1 - if ((err == _Z_RES_OK) && (_z_str_eq(ep._locator._protocol, UDP_SCHEMA) == true)) { + _z_string_t cmp_str = _z_string_alias_str(UDP_SCHEMA); + if ((err == _Z_RES_OK) && _z_string_equals(&ep._locator._protocol, &cmp_str)) { _z_endpoint_clear(&ep); } else #endif @@ -78,21 +79,21 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, const char *locator, unsig _Z_INFO("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; - hello->whatami = s_msg._body._hello._whatami; - memcpy(hello->zid.id, s_msg._body._hello._zid.id, 16); + hello->_version = s_msg._body._hello._version; + hello->_whatami = s_msg._body._hello._whatami; + memcpy(hello->_zid.id, s_msg._body._hello._zid.id, 16); size_t n_loc = _z_locator_array_len(&s_msg._body._hello._locators); if (n_loc > 0) { - hello->locators = _z_str_array_make(n_loc); + hello->_locators = _z_string_svec_make(n_loc); + for (size_t i = 0; i < n_loc; i++) { - hello->locators.val[i] = - _z_locator_to_str(&s_msg._body._hello._locators._val[i]); + _z_string_t s = _z_locator_to_string(&s_msg._body._hello._locators._val[i]); + _z_string_svec_append(&hello->_locators, &s); } } else { // @TODO: construct the locator departing from the sock address - hello->locators.len = 0; - hello->locators.val = NULL; + _z_string_svec_clear(&hello->_locators); } ret = _z_hello_list_push(ret, hello); @@ -128,7 +129,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, const char *locator, unsig return ret; } -_z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t zid, const char *locator, const uint32_t timeout, +_z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t zid, _z_string_t *locator, const uint32_t timeout, const _Bool exit_on_first) { _z_hello_list_t *ret = NULL; diff --git a/src/session/subscription.c b/src/session/subscription.c index 280b5d1c9..90a681ff2 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -17,12 +17,15 @@ #include #include +#include "zenoh-pico/api/types.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/net/sample.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/session.h" +#include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_SUBSCRIPTION == 1 @@ -37,16 +40,13 @@ void _z_subscription_clear(_z_subscription_t *sub) { _z_keyexpr_clear(&sub->_key); } -/*------------------ Pull ------------------*/ -_z_zint_t _z_get_pull_id(_z_session_t *zn) { return zn->_pull_id++; } - _z_subscription_rc_t *__z_get_subscription_by_id(_z_subscription_rc_list_t *subs, const _z_zint_t id) { _z_subscription_rc_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 (id == sub->in->val._id) { + if (id == _Z_RC_IN_VAL(sub)->_id) { ret = sub; break; } @@ -57,14 +57,13 @@ _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 *__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_intersects(sub->in->val._key._suffix, strlen(sub->in->val._key._suffix), key._suffix, - strlen(key._suffix)) == true) { + 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)); } @@ -91,135 +90,93 @@ _z_subscription_rc_t *__unsafe_z_get_subscription_by_id(_z_session_t *zn, uint8_ * - 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) { + const _z_keyexpr_t *key) { _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); } _z_subscription_rc_t *_z_get_subscription_by_id(_z_session_t *zn, uint8_t is_local, const _z_zint_t id) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_subscription_rc_t *sub = __unsafe_z_get_subscription_by_id(zn, is_local, id); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(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) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, is_local, *key); + _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, is_local, key); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _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, s->_key._suffix); + _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; -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 - - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, is_local, s->_key); - if (subs == NULL) { // A subscription for this name does not yet exists - ret = (_z_subscription_rc_t *)z_malloc(sizeof(_z_subscription_rc_t)); - if (ret != NULL) { - *ret = _z_subscription_rc_new_from_val(*s); - if (is_local == _Z_RESOURCE_IS_LOCAL) { - zn->_local_subscriptions = _z_subscription_rc_list_push(zn->_local_subscriptions, ret); - } else { - zn->_remote_subscriptions = _z_subscription_rc_list_push(zn->_remote_subscriptions, ret); - } + _zp_session_lock_mutex(zn); + + ret = (_z_subscription_rc_t *)z_malloc(sizeof(_z_subscription_rc_t)); + if (ret != NULL) { + *ret = _z_subscription_rc_new_from_val(s); + if (is_local == _Z_RESOURCE_IS_LOCAL) { + zn->_local_subscriptions = _z_subscription_rc_list_push(zn->_local_subscriptions, ret); + } else { + zn->_remote_subscriptions = _z_subscription_rc_list_push(zn->_remote_subscriptions, ret); } } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); return ret; } -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, - _z_zint_t payload_len, _z_n_qos_t qos -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t att -#endif -) { - _z_encoding_t encoding = {.prefix = Z_ENCODING_PREFIX_DEFAULT, .suffix = _z_bytes_wrap(NULL, 0)}; - int8_t ret = _z_trigger_subscriptions(zn, keyexpr, _z_bytes_wrap(payload, payload_len), encoding, Z_SAMPLE_KIND_PUT, - _z_timestamp_null(), qos -#if Z_FEATURE_ATTACHMENT == 1 - , - att -#endif - ); +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, + _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, + const _z_bytes_t attachment) { + int8_t ret = + _z_trigger_subscriptions(zn, keyexpr, payload, encoding, Z_SAMPLE_KIND_PUT, timestamp, qos, attachment); (void)ret; } int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, - const _z_encoding_t encoding, const _z_zint_t kind, const _z_timestamp_t timestamp, - const _z_n_qos_t qos -#if Z_FEATURE_ATTACHMENT == 1 - , - z_attachment_t att -#endif -) { + _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) { int8_t ret = _Z_RES_OK; -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); - _Z_DEBUG("Resolving %d - %s on mapping 0x%x", keyexpr._id, keyexpr._suffix, _z_keyexpr_mapping_id(&keyexpr)); + _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, key._suffix); - if (key._suffix != NULL) { - _z_subscription_rc_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, key); + _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); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); // Build the sample - _z_sample_t s; - s.keyexpr = key; - s.payload = payload; - s.encoding = encoding; - s.kind = kind; - s.timestamp = timestamp; - s.qos = qos; -#if Z_FEATURE_ATTACHMENT == 1 - s.attachment = att; -#endif + _z_sample_t sample = _z_sample_create(&key, payload, timestamp, encoding, kind, qos, attachment); + // 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); - sub->in->val._callback(&s, sub->in->val._arg); + _Z_RC_IN_VAL(sub)->_callback(&sample, _Z_RC_IN_VAL(sub)->_arg); xs = _z_subscription_rc_list_tail(xs); } - - _z_keyexpr_clear(&key); + // Clean up + _z_sample_clear(&sample); _z_subscription_rc_list_free(&subs); } else { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); ret = _Z_ERR_KEYEXPR_UNKNOWN; } @@ -227,9 +184,7 @@ int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, co } void _z_unregister_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_rc_t *sub) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); if (is_local == _Z_RESOURCE_IS_LOCAL) { zn->_local_subscriptions = @@ -239,32 +194,29 @@ 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); } -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } void _z_flush_subscriptions(_z_session_t *zn) { -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_lock_mutex(zn); _z_subscription_rc_list_free(&zn->_local_subscriptions); _z_subscription_rc_list_free(&zn->_remote_subscriptions); -#if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&zn->_mutex_inner); -#endif // Z_FEATURE_MULTI_THREAD == 1 + _zp_session_unlock_mutex(zn); } #else // Z_FEATURE_SUBSCRIPTION == 0 -void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const uint8_t *payload, - _z_zint_t payload_len, _z_n_qos_t qos) { +void _z_trigger_local_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, const _z_bytes_t payload, + _z_encoding_t *encoding, const _z_n_qos_t qos, const _z_timestamp_t *timestamp, + const _z_bytes_t attachment) { _ZP_UNUSED(zn); _ZP_UNUSED(keyexpr); _ZP_UNUSED(payload); - _ZP_UNUSED(payload_len); + _ZP_UNUSED(encoding); _ZP_UNUSED(qos); + _ZP_UNUSED(timestamp); + _ZP_UNUSED(attachment); } #endif // Z_FEATURE_SUBSCRIPTION == 1 diff --git a/src/session/utils.c b/src/session/utils.c index a95643888..7479f82e4 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -18,10 +18,12 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/session/interest.h" #include "zenoh-pico/session/query.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/subscription.h" +#include "zenoh-pico/utils/logging.h" /*------------------ clone helpers ------------------*/ _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { @@ -36,11 +38,7 @@ void _z_timestamp_clear(_z_timestamp_t *tstamp) { tstamp->time = 0; } -_Bool _z_timestamp_check(const _z_timestamp_t *stamp) { - for (uint8_t i = 0; i < sizeof(_z_id_t); ++i) - if (stamp->id.id[i]) return true; - return false; -} +_Bool _z_timestamp_check(const _z_timestamp_t *stamp) { return _z_id_check(stamp->id); } int8_t _z_session_generate_zid(_z_id_t *bs, uint8_t size) { int8_t ret = _Z_RES_OK; @@ -49,14 +47,14 @@ int8_t _z_session_generate_zid(_z_id_t *bs, uint8_t size) { } /*------------------ Init/Free/Close session ------------------*/ -int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid) { +int8_t _z_session_init(_z_session_rc_t *zsrc, _z_id_t *zid) { int8_t ret = _Z_RES_OK; + _z_session_t *zn = _Z_RC_IN_VAL(zsrc); // Initialize the counters to 1 zn->_entity_id = 1; zn->_resource_id = 1; zn->_query_id = 1; - zn->_pull_id = 1; // Initialize the data structs zn->_local_resources = NULL; @@ -73,7 +71,7 @@ int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid) { #endif #if Z_FEATURE_MULTI_THREAD == 1 - ret = z_mutex_init(&zn->_mutex_inner); + ret = _z_mutex_init(&zn->_mutex_inner); if (ret != _Z_RES_OK) { _z_transport_clear(&zn->_tp); return ret; @@ -84,13 +82,13 @@ int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid) { // Note session in transport switch (zn->_tp._type) { case _Z_TRANSPORT_UNICAST_TYPE: - zn->_tp._transport._unicast._session = zn; + zn->_tp._transport._unicast._session = zsrc; break; case _Z_TRANSPORT_MULTICAST_TYPE: - zn->_tp._transport._multicast._session = zn; + zn->_tp._transport._multicast._session = zsrc; break; case _Z_TRANSPORT_RAWETH_TYPE: - zn->_tp._transport._raweth._session = zn; + zn->_tp._transport._raweth._session = zsrc; break; default: break; @@ -99,8 +97,12 @@ int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid) { } void _z_session_clear(_z_session_t *zn) { +#if Z_FEATURE_MULTI_THREAD == 1 + _zp_stop_read_task(zn); + _zp_stop_lease_task(zn); +#endif + _z_close(zn); // Clear Zenoh PID - // Clean up transports _z_transport_clear(&zn->_tp); @@ -115,9 +117,10 @@ void _z_session_clear(_z_session_t *zn) { #if Z_FEATURE_QUERY == 1 _z_flush_pending_queries(zn); #endif + _z_flush_interest(zn); #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_free(&zn->_mutex_inner); + _z_mutex_drop(&zn->_mutex_inner); #endif // Z_FEATURE_MULTI_THREAD == 1 } @@ -130,3 +133,11 @@ int8_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 ba4e65206..cbfe0360c 100644 --- a/src/system/arduino/esp32/network.cpp +++ b/src/system/arduino/esp32/network.cpp @@ -21,7 +21,7 @@ extern "C" { #include #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" #include "zenoh-pico/system/link/bt.h" @@ -475,7 +475,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { struct sockaddr_storage raddr; unsigned int raddrlen = sizeof(struct sockaddr_storage); @@ -493,7 +493,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_bytes_make(sizeof(in_addr_t) + sizeof(in_port_t)); + *addr = _z_slice_make(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)); } @@ -506,7 +506,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_bytes_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + *addr = _z_slice_make(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)); } @@ -521,7 +521,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; diff --git a/src/system/arduino/esp32/system.c b/src/system/arduino/esp32/system.c index 6c82757a5..3e3266c0a 100644 --- a/src/system/arduino/esp32/system.c +++ b/src/system/arduino/esp32/system.c @@ -60,7 +60,7 @@ void z_task_wrapper(z_task_arg *targ) { } /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { int ret = 0; z_task_arg *z_arg = (z_task_arg *)z_malloc(sizeof(z_task_arg)); @@ -77,41 +77,43 @@ int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), vo return ret; } -int8_t z_task_join(z_task_t *task) { +int8_t _z_task_join(_z_task_t *task) { // Note: task/thread join not supported on FreeRTOS API, so we force its deletion instead. - return zp_task_cancel(task); + return _z_task_cancel(task); } -int8_t zp_task_cancel(z_task_t *task) { +int8_t _z_task_cancel(_z_task_t *task) { vTaskDelete(*task); return 0; } -void z_task_free(z_task_t **task) { - z_task_t *ptr = *task; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { return pthread_mutex_init(m, NULL); } +int8_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, NULL)); } -int8_t z_mutex_free(z_mutex_t *m) { return pthread_mutex_destroy(m); } +int8_t _z_mutex_drop(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_destroy(m)); } -int8_t z_mutex_lock(z_mutex_t *m) { return pthread_mutex_lock(m); } +int8_t _z_mutex_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_lock(m)); } -int8_t z_mutex_trylock(z_mutex_t *m) { return pthread_mutex_trylock(m); } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_trylock(m)); } -int8_t z_mutex_unlock(z_mutex_t *m) { return pthread_mutex_unlock(m); } +int8_t _z_mutex_unlock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_unlock(m)); } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return pthread_cond_init(cv, NULL); } +int8_t _z_condvar_init(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_init(cv, NULL)); } -int8_t z_condvar_free(z_condvar_t *cv) { return pthread_cond_destroy(cv); } +int8_t _z_condvar_free(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_destroy(cv)); } -int8_t z_condvar_signal(z_condvar_t *cv) { return pthread_cond_signal(cv); } +int8_t _z_condvar_signal(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_signal(cv)); } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return pthread_cond_wait(cv, m); } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_broadcast(cv)); } + +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_cond_wait(cv, m)); } #endif // Z_FEATURE_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ @@ -201,3 +203,11 @@ unsigned long z_time_elapsed_s(z_time_t *time) { unsigned long elapsed = now.tv_sec - time->tv_sec; return elapsed; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + gettimeofday(&now, NULL); + t->secs = now.tv_sec; + t->nanos = now.tv_usec * 1000; + return 0; +} \ No newline at end of file diff --git a/src/system/arduino/opencr/network.cpp b/src/system/arduino/opencr/network.cpp index 247ba82f6..0d75a298d 100644 --- a/src/system/arduino/opencr/network.cpp +++ b/src/system/arduino/opencr/network.cpp @@ -281,7 +281,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { // Block until something to read // FIXME: provide some kind of timeout functionality ssize_t rb = 0; @@ -295,7 +295,7 @@ 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_bytes_make(strlen((const char *)&rip[0]) + strlen((const char *)&rip[1]) + + *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)); uint8_t offset = 0; for (uint8_t i = 0; i < (uint8_t)4; i++) { @@ -313,7 +313,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; diff --git a/src/system/arduino/opencr/system.c b/src/system/arduino/opencr/system.c index ed017d200..9fb1c93c3 100644 --- a/src/system/arduino/opencr/system.c +++ b/src/system/arduino/opencr/system.c @@ -63,37 +63,38 @@ void z_free(void *ptr) { #error "Multi-threading not supported yet on OpenCR port. Disable it by defining Z_FEATURE_MULTI_THREAD=0" /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { return -1; } +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { return -1; } -int8_t z_task_join(z_task_t *task) { return -1; } +int8_t _z_task_join(_z_task_t *task) { return -1; } -int8_t zp_task_cancel(z_task_t *task) { return -1; } +int8_t _z_task_cancel(_z_task_t *task) { return -1; } -void z_task_free(z_task_t **task) { - z_task_t *ptr = *task; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { return -1; } +int8_t _z_mutex_init(_z_mutex_t *m) { return -1; } -int8_t z_mutex_free(z_mutex_t *m) { return -1; } +int8_t _z_mutex_drop(_z_mutex_t *m) { return -1; } -int8_t z_mutex_lock(z_mutex_t *m) { return -1; } +int8_t _z_mutex_lock(_z_mutex_t *m) { return -1; } -int8_t z_mutex_trylock(z_mutex_t *m) { return -1; } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { return -1; } -int8_t z_mutex_unlock(z_mutex_t *m) { return -1; } +int8_t _z_mutex_unlock(_z_mutex_t *m) { return -1; } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return -1; } +int8_t _z_condvar_init(_z_condvar_t *cv) { return -1; } -int8_t z_condvar_free(z_condvar_t *cv) { return -1; } +int8_t _z_condvar_drop(_z_condvar_t *cv) { return -1; } -int8_t z_condvar_signal(z_condvar_t *cv) { return -1; } +int8_t _z_condvar_signal(_z_condvar_t *cv) { return -1; } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { return -1; } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return -1; } +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { return -1; } #endif // Z_FEATURE_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ @@ -195,3 +196,11 @@ unsigned long z_time_elapsed_s(z_time_t *time) { unsigned long elapsed = now.tv_sec - time->tv_sec; return elapsed; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + gettimeofday(&now, NULL); + t->secs = now.tv_sec; + t->nanos = now.tv_usec * 1000; + return 0; +} \ No newline at end of file diff --git a/src/system/emscripten/system.c b/src/system/emscripten/system.c index 121724269..e576fdb28 100644 --- a/src/system/emscripten/system.c +++ b/src/system/emscripten/system.c @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // -#include +#include #include #include #include @@ -44,39 +44,41 @@ void z_free(void *ptr) { free(ptr); } #if Z_FEATURE_MULTI_THREAD == 1 /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, pthread_attr_t *attr, void *(*fun)(void *), void *arg) { - return pthread_create(task, attr, fun, arg); +int8_t _z_task_init(_z_task_t *task, pthread_attr_t *attr, void *(*fun)(void *), void *arg) { + _Z_CHECK_SYS_ERR(pthread_create(task, attr, fun, arg)); } -int8_t z_task_join(z_task_t *task) { return pthread_join(*task, NULL); } +int8_t _z_task_join(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_join(*task, NULL)); } -int8_t zp_task_cancel(z_task_t *task) { return pthread_cancel(*task); } +int8_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; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { return pthread_mutex_init(m, 0); } +int8_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } -int8_t z_mutex_free(z_mutex_t *m) { return pthread_mutex_destroy(m); } +int8_t _z_mutex_drop(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_destroy(m)); } -int8_t z_mutex_lock(z_mutex_t *m) { return pthread_mutex_lock(m); } +int8_t _z_mutex_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_lock(m)); } -int8_t z_mutex_trylock(z_mutex_t *m) { return pthread_mutex_trylock(m); } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_trylock(m)); } -int8_t z_mutex_unlock(z_mutex_t *m) { return pthread_mutex_unlock(m); } +int8_t _z_mutex_unlock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_unlock(m)); } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return pthread_cond_init(cv, 0); } +int8_t _z_condvar_init(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_init(cv, 0)); } -int8_t z_condvar_free(z_condvar_t *cv) { return pthread_cond_destroy(cv); } +int8_t _z_condvar_drop(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_destroy(cv)); } -int8_t z_condvar_signal(z_condvar_t *cv) { return pthread_cond_signal(cv); } +int8_t _z_condvar_signal(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_signal(cv)); } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return pthread_cond_wait(cv, m); } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_broadcast(cv)); } + +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_cond_wait(cv, m)); } #endif // Z_FEATURE_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ @@ -130,3 +132,10 @@ unsigned long z_time_elapsed_ms(z_time_t *time) { } unsigned long z_time_elapsed_s(z_time_t *time) { return z_time_elapsed_ms(time) * 1000; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + double date = emscripten_date_now(); + t->secs = (uint32_t)(date / 1000); + t->nanos = (uint32_t)((date - t->secs * 1000) * 1000000); + return 0; +} diff --git a/src/system/espidf/network.c b/src/system/espidf/network.c index c051eb6f3..d60a9a4f4 100644 --- a/src/system/espidf/network.c +++ b/src/system/espidf/network.c @@ -17,7 +17,7 @@ #include #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" #include "zenoh-pico/system/link/bt.h" @@ -471,7 +471,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { struct sockaddr_storage raddr; socklen_t raddrlen = sizeof(struct sockaddr_storage); @@ -489,7 +489,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_bytes_make(sizeof(in_addr_t) + sizeof(in_port_t)); + *addr = _z_slice_make(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)); } @@ -502,7 +502,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_bytes_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + *addr = _z_slice_make(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)); } @@ -517,7 +517,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; @@ -594,8 +594,8 @@ int8_t _z_open_serial_from_dev(_z_sys_net_socket_t *sock, char *dev, uint32_t ba QueueHandle_t uart_queue; uart_driver_install(sock->_serial, uart_buffer_size, 0, 100, &uart_queue, 0); uart_flush_input(sock->_serial); - sock->after_cobs = (uint8_t *)zp_malloc(_Z_SERIAL_MFS_SIZE); - sock->before_cobs = (uint8_t *)zp_malloc(_Z_SERIAL_MAX_COBS_BUF_SIZE); + sock->after_cobs = (uint8_t *)z_malloc(_Z_SERIAL_MFS_SIZE); + sock->before_cobs = (uint8_t *)z_malloc(_Z_SERIAL_MAX_COBS_BUF_SIZE); return ret; } @@ -628,8 +628,8 @@ void _z_close_serial(_z_sys_net_socket_t *sock) { uart_wait_tx_done(sock->_serial, 1000); uart_flush(sock->_serial); uart_driver_delete(sock->_serial); - zp_free(sock->after_cobs); - zp_free(sock->before_cobs); + z_free(sock->after_cobs); + z_free(sock->before_cobs); } size_t _z_read_serial(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) { diff --git a/src/system/espidf/system.c b/src/system/espidf/system.c index e6d3d018f..351591891 100644 --- a/src/system/espidf/system.c +++ b/src/system/espidf/system.c @@ -74,7 +74,7 @@ static z_task_attr_t z_default_task_attr = { }; /*------------------ Thread ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *arg_attr, void *(*fun)(void *), void *arg) { +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *arg_attr, void *(*fun)(void *), void *arg) { z_task_attr_t *attr = arg_attr; z_task_arg *z_arg = (z_task_arg *)z_malloc(sizeof(z_task_arg)); if (z_arg == NULL) { @@ -110,40 +110,42 @@ int8_t z_task_init(z_task_t *task, z_task_attr_t *arg_attr, void *(*fun)(void *) return 0; } -int8_t z_task_join(z_task_t *task) { +int8_t _z_task_join(_z_task_t *task) { xEventGroupWaitBits(task->join_event, 1, pdFALSE, pdFALSE, portMAX_DELAY); return 0; } -int8_t z_task_cancel(z_task_t *task) { +int8_t z_task_cancel(_z_task_t *task) { vTaskDelete(task->handle); return 0; } -void z_task_free(z_task_t **task) { +void _z_task_free(_z_task_t **task) { z_free((*task)->join_event); z_free(*task); } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { return pthread_mutex_init(m, NULL); } +int8_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, NULL)); } -int8_t z_mutex_free(z_mutex_t *m) { return pthread_mutex_destroy(m); } +int8_t _z_mutex_drop(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_destroy(m)); } -int8_t z_mutex_lock(z_mutex_t *m) { return pthread_mutex_lock(m); } +int8_t _z_mutex_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_lock(m)); } -int8_t z_mutex_trylock(z_mutex_t *m) { return pthread_mutex_trylock(m); } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_trylock(m)); } -int8_t z_mutex_unlock(z_mutex_t *m) { return pthread_mutex_unlock(m); } +int8_t _z_mutex_unlock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_unlock(m)); } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return pthread_cond_init(cv, NULL); } +int8_t _z_condvar_init(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_init(cv, NULL)); } -int8_t z_condvar_free(z_condvar_t *cv) { return pthread_cond_destroy(cv); } +int8_t _z_condvar_drop(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_destroy(cv)); } -int8_t z_condvar_signal(z_condvar_t *cv) { return pthread_cond_signal(cv); } +int8_t _z_condvar_signal(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_signal(cv)); } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return pthread_cond_wait(cv, m); } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_broadcast(cv)); } + +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_cond_wait(cv, m)); } #endif // Z_FEATURE_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ @@ -233,3 +235,11 @@ unsigned long z_time_elapsed_s(z_time_t *time) { unsigned long elapsed = now.tv_sec - time->tv_sec; return elapsed; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + gettimeofday(&now, NULL); + t->secs = now.tv_sec; + t->nanos = now.tv_usec * 1000; + return 0; +} diff --git a/src/system/flipper/system.c b/src/system/flipper/system.c index e723f6aa5..ec264137d 100644 --- a/src/system/flipper/system.c +++ b/src/system/flipper/system.c @@ -62,7 +62,7 @@ void z_free(void* ptr) { return free(ptr); } /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t* task, z_task_attr_t* attr, void* (*fun)(void*), void* arg) { +int8_t _z_task_init(_z_task_t* task, z_task_attr_t* attr, void* (*fun)(void*), void* arg) { if (task == NULL) { return -1; } @@ -80,16 +80,16 @@ int8_t z_task_init(z_task_t* task, z_task_attr_t* attr, void* (*fun)(void*), voi return _Z_RES_OK; } -int8_t z_task_join(z_task_t* task) { +int8_t _z_task_join(_z_task_t* task) { if (task == NULL) { return -1; } return furi_thread_join(*task); } -int8_t zp_task_cancel(z_task_t* task) { return -1; } +int8_t _z_task_cancel(_z_task_t* task) { return -1; } -void z_task_free(z_task_t** task) { +void _z_task_free(_z_task_t** task) { if (task == NULL || *task == NULL) { return; } @@ -98,7 +98,7 @@ void z_task_free(z_task_t** task) { } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t* m) { +int8_t _z_mutex_init(_z_mutex_t* m) { if (m == NULL) { return -1; } @@ -106,7 +106,7 @@ int8_t z_mutex_init(z_mutex_t* m) { return (*m != 0) ? _Z_RES_OK : _Z_ERR_SYSTEM_TASK_FAILED; } -int8_t z_mutex_free(z_mutex_t* m) { +int8_t _z_mutex_drop(_z_mutex_t* m) { if (m == NULL) { return -1; } @@ -118,7 +118,7 @@ int8_t z_mutex_free(z_mutex_t* m) { return 0; } -int8_t z_mutex_lock(z_mutex_t* m) { +int8_t _z_mutex_lock(_z_mutex_t* m) { if (m == NULL) { return -1; } @@ -128,9 +128,9 @@ int8_t z_mutex_lock(z_mutex_t* m) { return furi_mutex_acquire(*m, FuriWaitForever); } -int8_t z_mutex_trylock(z_mutex_t* m) { return -1; } +int8_t _z_mutex_try_lock(_z_mutex_t* m) { return -1; } -int8_t z_mutex_unlock(z_mutex_t* m) { +int8_t _z_mutex_unlock(_z_mutex_t* m) { if (m == NULL) { return -1; } @@ -141,13 +141,15 @@ int8_t z_mutex_unlock(z_mutex_t* m) { } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t* cv) { return -1; } +int8_t _z_condvar_init(_z_condvar_t* cv) { return -1; } -int8_t z_condvar_free(z_condvar_t* cv) { return -1; } +int8_t _z_condvar_drop(_z_condvar_t* cv) { return -1; } -int8_t z_condvar_signal(z_condvar_t* cv) { return -1; } +int8_t _z_condvar_signal(_z_condvar_t* cv) { return -1; } -int8_t z_condvar_wait(z_condvar_t* cv, z_mutex_t* m) { return -1; } +int8_t _z_condvar_signal_all(_z_condvar_t* cv) { return -1; } + +int8_t _z_condvar_wait(_z_condvar_t* cv, _z_mutex_t* m) { return -1; } /*------------------ Sleep ------------------*/ int z_sleep_us(size_t time) { @@ -293,3 +295,5 @@ struct tm* localtime(const time_t* timep) { static struct tm t; return &t; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch* t) { return -1; } diff --git a/src/system/freertos_plus_tcp/system.c b/src/system/freertos_plus_tcp/system.c index 4c4d88b5a..54a9fbf24 100644 --- a/src/system/freertos_plus_tcp/system.c +++ b/src/system/freertos_plus_tcp/system.c @@ -85,7 +85,7 @@ static z_task_attr_t z_default_task_attr = { }; /*------------------ Thread ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { z_task_arg *z_arg = (z_task_arg *)z_malloc(sizeof(z_task_arg)); if (z_arg == NULL) { return -1; @@ -119,53 +119,45 @@ int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), vo return 0; } -int8_t z_task_join(z_task_t *task) { +int8_t _z_task_join(_z_task_t *task) { xEventGroupWaitBits(task->join_event, 1, pdFALSE, pdFALSE, portMAX_DELAY); return 0; } -int8_t zp_task_cancel(z_task_t *task) { +int8_t _z_task_cancel(_z_task_t *task) { vTaskDelete(task->handle); return 0; } -void z_task_free(z_task_t **task) { +void _z_task_free(_z_task_t **task) { z_free((*task)->join_event); z_free(*task); } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { - if (m == NULL) { - return -1; - } +int8_t _z_mutex_init(_z_mutex_t *m) { *m = xSemaphoreCreateRecursiveMutex(); return *m == NULL ? -1 : 0; } -int8_t z_mutex_free(z_mutex_t *m) { - if (m == NULL) { - return -1; - } - if (*m == NULL) { - return 0; - } +int8_t _z_mutex_drop(_z_mutex_t *m) { z_free(*m); return 0; } -int8_t z_mutex_lock(z_mutex_t *m) { return xSemaphoreTakeRecursive(*m, portMAX_DELAY) == pdTRUE ? 0 : -1; } +int8_t _z_mutex_lock(_z_mutex_t *m) { return xSemaphoreTakeRecursive(*m, portMAX_DELAY) == pdTRUE ? 0 : -1; } -int8_t z_mutex_trylock(z_mutex_t *m) { return xSemaphoreTakeRecursive(*m, 0) == pdTRUE ? 0 : -1; } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { return xSemaphoreTakeRecursive(*m, 0) == pdTRUE ? 0 : -1; } -int8_t z_mutex_unlock(z_mutex_t *m) { return xSemaphoreGiveRecursive(*m) == pdTRUE ? 0 : -1; } +int8_t _z_mutex_unlock(_z_mutex_t *m) { return xSemaphoreGiveRecursive(*m) == pdTRUE ? 0 : -1; } /*------------------ CondVar ------------------*/ // Condition variables not supported in FreeRTOS -int8_t z_condvar_init(z_condvar_t *cv) { return -1; } -int8_t z_condvar_free(z_condvar_t *cv) { return -1; } -int8_t z_condvar_signal(z_condvar_t *cv) { return -1; } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return -1; } +int8_t _z_condvar_init(_z_condvar_t *cv) { return -1; } +int8_t _z_condvar_drop(_z_condvar_t *cv) { return -1; } +int8_t _z_condvar_signal(_z_condvar_t *cv) { return -1; } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { return -1; } +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { return -1; } #endif // Z_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ @@ -211,3 +203,5 @@ unsigned long z_time_elapsed_ms(z_time_t *time) { } unsigned long z_time_elapsed_s(z_time_t *time) { return z_time_elapsed_ms(time) / 1000; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { return -1; } diff --git a/src/system/mbed/network.cpp b/src/system/mbed/network.cpp index 7ab41e452..8b96a86e9 100644 --- a/src/system/mbed/network.cpp +++ b/src/system/mbed/network.cpp @@ -262,7 +262,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { SocketAddress raddr; nsapi_size_or_error_t rb = 0; @@ -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_bytes_make(NSAPI_IPv4_BYTES + sizeof(uint16_t)); + *addr = _z_slice_make(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_bytes_make(NSAPI_IPv6_BYTES + sizeof(uint16_t)); + *addr = _z_slice_make(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)); @@ -294,7 +294,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; diff --git a/src/system/mbed/system.cpp b/src/system/mbed/system.cpp index 7b2ffc65f..036225e9b 100644 --- a/src/system/mbed/system.cpp +++ b/src/system/mbed/system.cpp @@ -41,67 +41,72 @@ void z_free(void *ptr) { free(ptr); } #if Z_FEATURE_MULTI_THREAD == 1 /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { *task = new Thread(); mbed::Callback c = mbed::Callback(fun, arg); return ((Thread *)*task)->start(c); } -int8_t z_task_join(z_task_t *task) { +int8_t _z_task_join(_z_task_t *task) { int res = ((Thread *)*task)->join(); delete ((Thread *)*task); return res; } -int8_t zp_task_cancel(z_task_t *task) { +int8_t _z_task_cancel(_z_task_t *task) { int res = ((Thread *)*task)->terminate(); delete ((Thread *)*task); return res; } -void z_task_free(z_task_t **task) { - z_task_t *ptr = *task; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { +int8_t _z_mutex_init(_z_mutex_t *m) { *m = new Mutex(); return 0; } -int8_t z_mutex_free(z_mutex_t *m) { +int8_t _z_mutex_drop(_z_mutex_t *m) { delete ((Mutex *)*m); return 0; } -int8_t z_mutex_lock(z_mutex_t *m) { +int8_t _z_mutex_lock(_z_mutex_t *m) { ((Mutex *)*m)->lock(); return 0; } -int8_t z_mutex_trylock(z_mutex_t *m) { return (((Mutex *)*m)->trylock() == true) ? 0 : -1; } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { return (((Mutex *)*m)->trylock() == true) ? 0 : -1; } -int8_t z_mutex_unlock(z_mutex_t *m) { +int8_t _z_mutex_unlock(_z_mutex_t *m) { ((Mutex *)*m)->unlock(); return 0; } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return 0; } +int8_t _z_condvar_init(_z_condvar_t *cv) { return 0; } -int8_t z_condvar_free(z_condvar_t *cv) { +int8_t _z_condvar_drop(_z_condvar_t *cv) { delete ((ConditionVariable *)*cv); return 0; } -int8_t z_condvar_signal(z_condvar_t *cv) { +int8_t _z_condvar_signal(_z_condvar_t *cv) { + ((ConditionVariable *)*cv)->notify_one(); + return 0; +} + +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { ((ConditionVariable *)*cv)->notify_all(); return 0; } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { *cv = new ConditionVariable(*((Mutex *)*m)); ((ConditionVariable *)*cv)->wait(); return 0; @@ -184,4 +189,12 @@ unsigned long z_time_elapsed_s(z_time_t *time) { return elapsed; } +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + gettimeofday(&now, NULL); + t->secs = now.tv_sec; + t->nanos = now.tv_usec * 1000; + return 0; +} + } // extern "C" diff --git a/src/system/platform-common.c b/src/system/platform-common.c new file mode 100644 index 000000000..ab1a9d2e4 --- /dev/null +++ b/src/system/platform-common.c @@ -0,0 +1,56 @@ +// +// Copyright (c) 2024 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/system/platform-common.h" + +#include "zenoh-pico/api/olv_macros.h" +#include "zenoh-pico/utils/logging.h" + +void _z_report_system_error(int errcode) { _Z_ERROR("System error: %i", errcode); } + +#if Z_FEATURE_MULTI_THREAD == 1 + +/*------------------ Thread ------------------*/ +_Z_OWNED_FUNCTIONS_SYSTEM_IMPL(_z_task_t, task) + +int8_t z_task_init(z_owned_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { + return _z_task_init(&task->_val, attr, fun, arg); +} + +int8_t z_task_join(z_owned_task_t *task) { + _z_task_t *ptr = &task->_val; + int8_t ret = _z_task_join(ptr); + _z_task_free(&ptr); + return ret; +} + +/*------------------ Mutex ------------------*/ +_Z_OWNED_FUNCTIONS_SYSTEM_IMPL(_z_mutex_t, mutex) + +int8_t z_mutex_init(z_owned_mutex_t *m) { return _z_mutex_init(&m->_val); } +int8_t z_mutex_drop(z_moved_mutex_t *m) { return _z_mutex_drop(&m->_this._val); } + +int8_t z_mutex_lock(z_loaned_mutex_t *m) { return _z_mutex_lock(m); } +int8_t z_mutex_try_lock(z_loaned_mutex_t *m) { return _z_mutex_try_lock(m); } +int8_t z_mutex_unlock(z_loaned_mutex_t *m) { return _z_mutex_unlock(m); } + +/*------------------ CondVar ------------------*/ +_Z_OWNED_FUNCTIONS_SYSTEM_IMPL(_z_condvar_t, condvar) + +int8_t z_condvar_init(z_owned_condvar_t *cv) { return _z_condvar_init(&cv->_val); } +int8_t z_condvar_drop(z_moved_condvar_t *cv) { return _z_condvar_drop(&cv->_this._val); } + +int8_t z_condvar_signal(z_loaned_condvar_t *cv) { return _z_condvar_signal(cv); } +int8_t z_condvar_wait(z_loaned_condvar_t *cv, z_loaned_mutex_t *m) { return _z_condvar_wait(cv, m); } + +#endif // Z_FEATURE_MULTI_THREAD == 1 diff --git a/src/system/unix/link/raweth.c b/src/system/unix/link/raweth.c index 10e35c565..9a97546f2 100644 --- a/src/system/unix/link/raweth.c +++ b/src/system/unix/link/raweth.c @@ -92,11 +92,11 @@ size_t _z_send_raweth(const _z_sys_net_socket_t *sock, const void *buff, size_t return (size_t)wb; } -size_t _z_receive_raweth(const _z_sys_net_socket_t *sock, void *buff, size_t buff_len, _z_bytes_t *addr, +size_t _z_receive_raweth(const _z_sys_net_socket_t *sock, void *buff, size_t buff_len, _z_slice_t *addr, const _zp_raweth_whitelist_array_t *whitelist) { // Read from socket ssize_t bytesRead = recvfrom(sock->_fd, buff, buff_len, 0, NULL, NULL); - if ((bytesRead < 0) || (bytesRead < sizeof(_zp_eth_header_t))) { + if ((bytesRead < 0) || (bytesRead < (ssize_t)sizeof(_zp_eth_header_t))) { return SIZE_MAX; } _Bool is_valid = true; @@ -118,15 +118,16 @@ 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) { - *addr = _z_bytes_make(sizeof(ETH_ALEN)); - (void)memcpy((uint8_t *)addr->start, (buff + ETH_ALEN), sizeof(ETH_ALEN)); + uint8_t *header_addr = (uint8_t *)buff; + *addr = _z_slice_make(sizeof(ETH_ALEN)); + (void)memcpy((uint8_t *)addr->start, (header_addr + ETH_ALEN), sizeof(ETH_ALEN)); } - return bytesRead; + return (size_t)bytesRead; } -size_t _z_raweth_ntohs(size_t val) { return ntohs(val); } +uint16_t _z_raweth_ntohs(uint16_t val) { return ntohs(val); } -size_t _z_raweth_htons(size_t val) { return htons(val); } +uint16_t _z_raweth_htons(uint16_t val) { return htons(val); } #endif // defined(__linux) #endif // Z_FEATURE_RAWETH_TRANSPORT == 1 diff --git a/src/system/unix/network.c b/src/system/unix/network.c index d5ec40393..95ae2ddf9 100644 --- a/src/system/unix/network.c +++ b/src/system/unix/network.c @@ -125,10 +125,10 @@ void _z_close_tcp(_z_sys_net_socket_t *sock) { size_t _z_read_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) { ssize_t rb = recv(sock._fd, ptr, len, 0); if (rb < (ssize_t)0) { - rb = SIZE_MAX; + return SIZE_MAX; } - return rb; + return (size_t)rb; } size_t _z_read_exact_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) { @@ -143,7 +143,7 @@ size_t _z_read_exact_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t le } n = n + rb; - pos = _z_ptr_u8_offset(pos, n); + pos = _z_ptr_u8_offset(pos, (ptrdiff_t)n); } while (n != len); return n; @@ -151,7 +151,7 @@ size_t _z_read_exact_tcp(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t le size_t _z_send_tcp(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len) { #if defined(ZENOH_LINUX) - return send(sock._fd, ptr, len, MSG_NOSIGNAL); + return (size_t)send(sock._fd, ptr, len, MSG_NOSIGNAL); #else return send(sock._fd, ptr, len, 0); #endif @@ -223,10 +223,9 @@ size_t _z_read_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t ssize_t rb = recvfrom(sock._fd, ptr, len, 0, (struct sockaddr *)&raddr, &addrlen); if (rb < (ssize_t)0) { - rb = SIZE_MAX; + return SIZE_MAX; } - - return rb; + return (size_t)rb; } size_t _z_read_exact_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len) { @@ -241,7 +240,7 @@ size_t _z_read_exact_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, s } n = n + rb; - pos = _z_ptr_u8_offset(pos, n); + pos = _z_ptr_u8_offset(pos, (ptrdiff_t)n); } while (n != len); return n; @@ -249,7 +248,7 @@ size_t _z_read_exact_udp_unicast(const _z_sys_net_socket_t sock, uint8_t *ptr, s size_t _z_send_udp_unicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t rep) { - return sendto(sock._fd, ptr, len, 0, rep._iptcp->ai_addr, rep._iptcp->ai_addrlen); + return (size_t)sendto(sock._fd, ptr, len, 0, rep._iptcp->ai_addr, rep._iptcp->ai_addrlen); } #endif @@ -324,7 +323,7 @@ int8_t _z_open_udp_multicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoin ret = _Z_ERR_GENERIC; } } else if (lsockaddr->sa_family == AF_INET6) { - int ifindex = if_nametoindex(iface); + int ifindex = (int)if_nametoindex(iface); if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &ifindex, sizeof(ifindex)) < 0)) { ret = _Z_ERR_GENERIC; @@ -389,14 +388,16 @@ int8_t _z_listen_udp_multicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpo if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value)) < 0)) { ret = _Z_ERR_GENERIC; } +#ifdef SO_REUSEPORT if ((ret == _Z_RES_OK) && (setsockopt(sock->_fd, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value)) < 0)) { ret = _Z_ERR_GENERIC; } +#endif if (rep._iptcp->ai_family == AF_INET) { struct sockaddr_in address; (void)memset(&address, 0, sizeof(address)); - address.sin_family = rep._iptcp->ai_family; + address.sin_family = (sa_family_t)rep._iptcp->ai_family; address.sin_port = ((struct sockaddr_in *)rep._iptcp->ai_addr)->sin_port; inet_pton(address.sin_family, "0.0.0.0", &address.sin_addr); if ((ret == _Z_RES_OK) && (bind(sock->_fd, (struct sockaddr *)&address, sizeof(address)) < 0)) { @@ -405,7 +406,7 @@ int8_t _z_listen_udp_multicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpo } else if (rep._iptcp->ai_family == AF_INET6) { struct sockaddr_in6 address; (void)memset(&address, 0, sizeof(address)); - address.sin6_family = rep._iptcp->ai_family; + address.sin6_family = (sa_family_t)rep._iptcp->ai_family; address.sin6_port = ((struct sockaddr_in6 *)rep._iptcp->ai_addr)->sin6_port; inet_pton(address.sin6_family, "::", &address.sin6_addr); if ((ret == _Z_RES_OK) && (bind(sock->_fd, (struct sockaddr *)&address, sizeof(address)) < 0)) { @@ -509,7 +510,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { struct sockaddr_storage raddr; unsigned int replen = sizeof(struct sockaddr_storage); @@ -517,8 +518,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ do { rb = recvfrom(sock._fd, ptr, len, 0, (struct sockaddr *)&raddr, &replen); if (rb < (ssize_t)0) { - rb = SIZE_MAX; - break; + return SIZE_MAX; } if (lep._iptcp->ai_family == AF_INET) { @@ -527,7 +527,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_bytes_make(sizeof(in_addr_t) + sizeof(in_port_t)); + *addr = _z_slice_make(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)); } @@ -540,7 +540,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_bytes_make(sizeof(struct in6_addr) + sizeof(in_port_t)); + *addr = _z_slice_make(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)); } @@ -551,11 +551,11 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } } while (1); - return rb; + return (size_t)rb; } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; @@ -567,7 +567,7 @@ size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, } n = n + rb; - pos = _z_ptr_u8_offset(pos, n); + pos = _z_ptr_u8_offset(pos, (ptrdiff_t)n); } while (n != len); return n; @@ -575,7 +575,7 @@ size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t _z_send_udp_multicast(const _z_sys_net_socket_t sock, const uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t rep) { - return sendto(sock._fd, ptr, len, 0, rep._iptcp->ai_addr, rep._iptcp->ai_addrlen); + return (size_t)sendto(sock._fd, ptr, len, 0, rep._iptcp->ai_addr, rep._iptcp->ai_addrlen); } #endif diff --git a/src/system/unix/system.c b/src/system/unix/system.c index 799b60519..e38233daa 100644 --- a/src/system/unix/system.c +++ b/src/system/unix/system.c @@ -101,43 +101,45 @@ void z_free(void *ptr) { free(ptr); } #if Z_FEATURE_MULTI_THREAD == 1 /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { - return pthread_create(task, attr, fun, arg); +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { + _Z_CHECK_SYS_ERR(pthread_create(task, attr, fun, arg)); } -int8_t z_task_join(z_task_t *task) { return pthread_join(*task, NULL); } +int8_t _z_task_join(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_join(*task, NULL)); } -int8_t zp_task_cancel(z_task_t *task) { return pthread_cancel(*task); } +int8_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; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { return pthread_mutex_init(m, 0); } +int8_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } -int8_t z_mutex_free(z_mutex_t *m) { return pthread_mutex_destroy(m); } +int8_t _z_mutex_drop(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_destroy(m)); } -int8_t z_mutex_lock(z_mutex_t *m) { return pthread_mutex_lock(m); } +int8_t _z_mutex_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_lock(m)); } -int8_t z_mutex_trylock(z_mutex_t *m) { return pthread_mutex_trylock(m); } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_trylock(m)); } -int8_t z_mutex_unlock(z_mutex_t *m) { return pthread_mutex_unlock(m); } +int8_t _z_mutex_unlock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_unlock(m)); } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return pthread_cond_init(cv, 0); } +int8_t _z_condvar_init(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_init(cv, 0)); } -int8_t z_condvar_free(z_condvar_t *cv) { return pthread_cond_destroy(cv); } +int8_t _z_condvar_drop(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_destroy(cv)); } -int8_t z_condvar_signal(z_condvar_t *cv) { return pthread_cond_signal(cv); } +int8_t _z_condvar_signal(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_signal(cv)); } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return pthread_cond_wait(cv, m); } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_broadcast(cv)); } + +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_cond_wait(cv, m)); } #endif // Z_FEATURE_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ -int z_sleep_us(size_t time) { return usleep(time); } +int z_sleep_us(size_t time) { return usleep((unsigned int)time); } int z_sleep_ms(size_t time) { z_time_t start = z_time_now(); @@ -152,7 +154,7 @@ int z_sleep_ms(size_t time) { return 0; } -int z_sleep_s(size_t time) { return sleep(time); } +int z_sleep_s(size_t time) { return (int)sleep((unsigned int)time); } /*------------------ Instant ------------------*/ z_clock_t z_clock_now(void) { @@ -165,7 +167,8 @@ unsigned long z_clock_elapsed_us(z_clock_t *instant) { z_clock_t now; clock_gettime(CLOCK_MONOTONIC, &now); - unsigned long elapsed = (1000000 * (now.tv_sec - instant->tv_sec) + (now.tv_nsec - instant->tv_nsec) / 1000); + unsigned long elapsed = + (unsigned long)(1000000 * (now.tv_sec - instant->tv_sec) + (now.tv_nsec - instant->tv_nsec) / 1000); return elapsed; } @@ -173,7 +176,8 @@ unsigned long z_clock_elapsed_ms(z_clock_t *instant) { z_clock_t now; clock_gettime(CLOCK_MONOTONIC, &now); - unsigned long elapsed = (1000 * (now.tv_sec - instant->tv_sec) + (now.tv_nsec - instant->tv_nsec) / 1000000); + unsigned long elapsed = + (unsigned long)(1000 * (now.tv_sec - instant->tv_sec) + (now.tv_nsec - instant->tv_nsec) / 1000000); return elapsed; } @@ -181,7 +185,7 @@ unsigned long z_clock_elapsed_s(z_clock_t *instant) { z_clock_t now; clock_gettime(CLOCK_MONOTONIC, &now); - unsigned long elapsed = now.tv_sec - instant->tv_sec; + unsigned long elapsed = (unsigned long)(now.tv_sec - instant->tv_sec); return elapsed; } @@ -204,7 +208,7 @@ unsigned long z_time_elapsed_us(z_time_t *time) { z_time_t now; gettimeofday(&now, NULL); - unsigned long elapsed = (1000000 * (now.tv_sec - time->tv_sec) + (now.tv_usec - time->tv_usec)); + unsigned long elapsed = (unsigned long)(1000000 * (now.tv_sec - time->tv_sec) + (now.tv_usec - time->tv_usec)); return elapsed; } @@ -212,7 +216,7 @@ unsigned long z_time_elapsed_ms(z_time_t *time) { z_time_t now; gettimeofday(&now, NULL); - unsigned long elapsed = (1000 * (now.tv_sec - time->tv_sec) + (now.tv_usec - time->tv_usec) / 1000); + unsigned long elapsed = (unsigned long)(1000 * (now.tv_sec - time->tv_sec) + (now.tv_usec - time->tv_usec) / 1000); return elapsed; } @@ -220,6 +224,14 @@ unsigned long z_time_elapsed_s(z_time_t *time) { z_time_t now; gettimeofday(&now, NULL); - unsigned long elapsed = now.tv_sec - time->tv_sec; + unsigned long elapsed = (unsigned long)(now.tv_sec - time->tv_sec); return elapsed; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + gettimeofday(&now, NULL); + t->secs = (uint32_t)now.tv_sec; + t->nanos = (uint32_t)now.tv_usec * 1000; + return 0; +} diff --git a/src/system/windows/network.c b/src/system/windows/network.c index 8cdecf657..4d00ebd2a 100644 --- a/src/system/windows/network.c +++ b/src/system/windows/network.c @@ -523,7 +523,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { SOCKADDR_STORAGE raddr; unsigned int replen = sizeof(SOCKADDR_STORAGE); @@ -541,7 +541,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_bytes_make(sizeof(IN_ADDR) + sizeof(USHORT)); + *addr = _z_slice_make(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)); } @@ -554,7 +554,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_bytes_make(sizeof(struct in6_addr) + sizeof(USHORT)); + *addr = _z_slice_make(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)); } @@ -569,7 +569,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; diff --git a/src/system/windows/system.c b/src/system/windows/system.c index 3997df9ab..6356fe077 100644 --- a/src/system/windows/system.c +++ b/src/system/windows/system.c @@ -60,7 +60,7 @@ void z_free(void *ptr) { free(ptr); } #if Z_FEATURE_MULTI_THREAD == 1 /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { (void)(attr); int8_t ret = _Z_RES_OK; *task = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fun, arg, 0, NULL); @@ -70,45 +70,45 @@ int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), vo return ret; } -int8_t z_task_join(z_task_t *task) { +int8_t _z_task_join(_z_task_t *task) { int8_t ret = _Z_RES_OK; WaitForSingleObject(*task, INFINITE); return ret; } -int8_t zp_task_cancel(z_task_t *task) { +int8_t _z_task_cancel(_z_task_t *task) { int8_t ret = _Z_RES_OK; TerminateThread(*task, 0); return ret; } -void z_task_free(z_task_t **task) { - z_task_t *ptr = *task; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; CloseHandle(*ptr); z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { +int8_t _z_mutex_init(_z_mutex_t *m) { int8_t ret = _Z_RES_OK; InitializeSRWLock(m); return ret; } -int8_t z_mutex_free(z_mutex_t *m) { +int8_t _z_mutex_drop(_z_mutex_t *m) { (void)(m); int8_t ret = _Z_RES_OK; return ret; } -int8_t z_mutex_lock(z_mutex_t *m) { +int8_t _z_mutex_lock(_z_mutex_t *m) { int8_t ret = _Z_RES_OK; AcquireSRWLockExclusive(m); return ret; } -int8_t z_mutex_trylock(z_mutex_t *m) { +int8_t _z_mutex_try_lock(_z_mutex_t *m) { int8_t ret = _Z_RES_OK; if (TryAcquireSRWLockExclusive(m) == 0) { ret = _Z_ERR_GENERIC; @@ -116,32 +116,38 @@ int8_t z_mutex_trylock(z_mutex_t *m) { return ret; } -int8_t z_mutex_unlock(z_mutex_t *m) { +int8_t _z_mutex_unlock(_z_mutex_t *m) { int8_t ret = _Z_RES_OK; ReleaseSRWLockExclusive(m); return ret; } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { +int8_t _z_condvar_init(_z_condvar_t *cv) { int8_t ret = _Z_RES_OK; InitializeConditionVariable(cv); return ret; } -int8_t z_condvar_free(z_condvar_t *cv) { +int8_t _z_condvar_drop(_z_condvar_t *cv) { (void)(cv); int8_t ret = _Z_RES_OK; return ret; } -int8_t z_condvar_signal(z_condvar_t *cv) { +int8_t _z_condvar_signal(_z_condvar_t *cv) { int8_t ret = _Z_RES_OK; WakeConditionVariable(cv); return ret; } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { + int8_t ret = _Z_RES_OK; + WakeAllConditionVariable(cv); + return ret; +} + +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { int8_t ret = _Z_RES_OK; SleepConditionVariableSRW(cv, m, INFINITE, 0); return ret; @@ -257,3 +263,11 @@ unsigned long z_time_elapsed_s(z_time_t *time) { unsigned long elapsed = (unsigned long)(now.time - time->time); return elapsed; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + ftime(&now); + t->secs = (uint32_t)now.time; + t->nanos = (uint32_t)(now.millitm * 1000000); + return 0; +} diff --git a/src/system/zephyr/network.c b/src/system/zephyr/network.c index 00d3ec1ce..c115d95fb 100644 --- a/src/system/zephyr/network.c +++ b/src/system/zephyr/network.c @@ -483,7 +483,7 @@ void _z_close_udp_multicast(_z_sys_net_socket_t *sockrecv, _z_sys_net_socket_t * } size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, const _z_sys_net_endpoint_t lep, - _z_bytes_t *addr) { + _z_slice_t *addr) { struct sockaddr_storage raddr; unsigned int raddrlen = sizeof(struct sockaddr_storage); @@ -501,7 +501,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_bytes_make(sizeof(uint32_t) + sizeof(uint16_t)); + *addr = _z_slice_make(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)); } @@ -514,7 +514,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_bytes_make((sizeof(uint32_t) * 4UL) + sizeof(uint16_t)); + *addr = _z_slice_make((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)); } @@ -529,7 +529,7 @@ size_t _z_read_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_ } size_t _z_read_exact_udp_multicast(const _z_sys_net_socket_t sock, uint8_t *ptr, size_t len, - const _z_sys_net_endpoint_t lep, _z_bytes_t *addr) { + const _z_sys_net_endpoint_t lep, _z_slice_t *addr) { size_t n = 0; uint8_t *pos = &ptr[0]; diff --git a/src/system/zephyr/system.c b/src/system/zephyr/system.c index 916800ef0..8cb8e89d1 100644 --- a/src/system/zephyr/system.c +++ b/src/system/zephyr/system.c @@ -71,7 +71,7 @@ K_THREAD_STACK_ARRAY_DEFINE(thread_stack_area, Z_THREADS_NUM, Z_PTHREAD_STACK_SI static int thread_index = 0; /*------------------ Task ------------------*/ -int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { +int8_t _z_task_init(_z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), void *arg) { z_task_attr_t *lattr = NULL; z_task_attr_t tmp; if (attr == NULL) { @@ -80,43 +80,45 @@ int8_t z_task_init(z_task_t *task, z_task_attr_t *attr, void *(*fun)(void *), vo lattr = &tmp; } - return pthread_create(task, lattr, fun, arg); + _Z_CHECK_SYS_ERR(pthread_create(task, lattr, fun, arg)); } -int8_t z_task_join(z_task_t *task) { return pthread_join(*task, NULL); } +int8_t _z_task_join(_z_task_t *task) { _Z_CHECK_SYS_ERR(pthread_join(*task, NULL)); } -int8_t zp_task_cancel(z_task_t *task) { return pthread_cancel(*task); } +int8_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; +void _z_task_free(_z_task_t **task) { + _z_task_t *ptr = *task; z_free(ptr); *task = NULL; } /*------------------ Mutex ------------------*/ -int8_t z_mutex_init(z_mutex_t *m) { return pthread_mutex_init(m, 0); } +int8_t _z_mutex_init(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_init(m, 0)); } -int8_t z_mutex_free(z_mutex_t *m) { - if (*m == NULL) { +int8_t _z_mutex_drop(_z_mutex_t *m) { + if (m == NULL) { return 0; } - return pthread_mutex_destroy(m); + _Z_CHECK_SYS_ERR(pthread_mutex_destroy(m)); } -int8_t z_mutex_lock(z_mutex_t *m) { return pthread_mutex_lock(m); } +int8_t _z_mutex_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_lock(m)); } -int8_t z_mutex_trylock(z_mutex_t *m) { return pthread_mutex_trylock(m); } +int8_t _z_mutex_try_lock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_trylock(m)); } -int8_t z_mutex_unlock(z_mutex_t *m) { return pthread_mutex_unlock(m); } +int8_t _z_mutex_unlock(_z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_mutex_unlock(m)); } /*------------------ Condvar ------------------*/ -int8_t z_condvar_init(z_condvar_t *cv) { return pthread_cond_init(cv, 0); } +int8_t _z_condvar_init(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_init(cv, 0)); } -int8_t z_condvar_free(z_condvar_t *cv) { return pthread_cond_destroy(cv); } +int8_t _z_condvar_drop(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_destroy(cv)); } -int8_t z_condvar_signal(z_condvar_t *cv) { return pthread_cond_signal(cv); } +int8_t _z_condvar_signal(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_signal(cv)); } -int8_t z_condvar_wait(z_condvar_t *cv, z_mutex_t *m) { return pthread_cond_wait(cv, m); } +int8_t _z_condvar_signal_all(_z_condvar_t *cv) { _Z_CHECK_SYS_ERR(pthread_cond_broadcast(cv)); } + +int8_t _z_condvar_wait(_z_condvar_t *cv, _z_mutex_t *m) { _Z_CHECK_SYS_ERR(pthread_cond_wait(cv, m)); } #endif // Z_FEATURE_MULTI_THREAD == 1 /*------------------ Sleep ------------------*/ @@ -221,3 +223,11 @@ unsigned long z_time_elapsed_s(z_time_t *time) { unsigned long elapsed = now.tv_sec - time->tv_sec; return elapsed; } + +int8_t zp_get_time_since_epoch(zp_time_since_epoch *t) { + z_time_t now; + gettimeofday(&now, NULL); + t->secs = now.tv_sec; + t->nanos = now.tv_usec * 1000; + return 0; +} diff --git a/src/transport/common/rx.c b/src/transport/common/rx.c index 8f25fff0f..fd8343f8b 100644 --- a/src/transport/common/rx.c +++ b/src/transport/common/rx.c @@ -12,15 +12,26 @@ // ZettaScale Zenoh Team, // -#include "zenoh-pico/transport/multicast/rx.h" +#include "zenoh-pico/transport/common/rx.h" #include #include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/transport/multicast/rx.h" #include "zenoh-pico/transport/unicast/rx.h" +#include "zenoh-pico/utils/endianness.h" #include "zenoh-pico/utils/logging.h" /*------------------ Reception helper ------------------*/ +size_t _z_read_stream_size(_z_zbuf_t *zbuf) { + uint8_t stream_size[_Z_MSG_LEN_ENC_SIZE]; + // Read the bytes from stream + for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { + stream_size[i] = _z_zbuf_read(zbuf); + } + return _z_host_le_load16(stream_size); +} + int8_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl) { int8_t ret = _Z_RES_OK; diff --git a/src/transport/common/tx.c b/src/transport/common/tx.c index 3508493f4..15020cbe3 100644 --- a/src/transport/common/tx.c +++ b/src/transport/common/tx.c @@ -21,6 +21,7 @@ #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/endianness.h" #include "zenoh-pico/utils/logging.h" /*------------------ Transmission helper ------------------*/ @@ -57,9 +58,9 @@ void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, uint8_t link_flow_capability) { // Stream capable links case Z_LINK_CAP_FLOW_STREAM: { size_t len = _z_wbuf_len(buf) - _Z_MSG_LEN_ENC_SIZE; - for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { - _z_wbuf_put(buf, (uint8_t)((len >> (uint8_t)8 * i) & (uint8_t)0xFF), i); - } + // Encode the u16 size as little endian + _z_wbuf_put(buf, _z_get_u16_lsb((uint_fast16_t)len), 0); + _z_wbuf_put(buf, _z_get_u16_msb((uint_fast16_t)len), 1); break; } // Datagram capable links diff --git a/src/transport/manager.c b/src/transport/manager.c index 3d430465f..5d9f1646c 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" -int8_t _z_new_transport_client(_z_transport_t *zt, char *locator, _z_id_t *local_zid) { +int8_t _z_new_transport_client(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { int8_t ret = _Z_RES_OK; // Init link _z_link_t zl; @@ -62,7 +62,7 @@ int8_t _z_new_transport_client(_z_transport_t *zt, char *locator, _z_id_t *local return ret; } -int8_t _z_new_transport_peer(_z_transport_t *zt, char *locator, _z_id_t *local_zid) { +int8_t _z_new_transport_peer(_z_transport_t *zt, _z_string_t *locator, _z_id_t *local_zid) { int8_t ret = _Z_RES_OK; // Init link _z_link_t zl; @@ -101,7 +101,7 @@ int8_t _z_new_transport_peer(_z_transport_t *zt, char *locator, _z_id_t *local_z return ret; } -int8_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, char *locator, z_whatami_t mode) { +int8_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, _z_string_t *locator, z_whatami_t mode) { int8_t ret; if (mode == Z_WHATAMI_CLIENT) { diff --git a/src/transport/multicast.c b/src/transport/multicast.c index d8613dc89..42059f6dc 100644 --- a/src/transport/multicast.c +++ b/src/transport/multicast.c @@ -30,7 +30,7 @@ #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_MULTICAST_TRANSPORT == 1 -void _zp_multicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *callback) { +void _zp_multicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { void *ctx = callback->context; _z_transport_peer_entry_list_t *l = zt->_transport._multicast._peers; for (; l != NULL; l = _z_transport_peer_entry_list_tail(l)) { @@ -45,15 +45,17 @@ 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_bytes_t remote_zid = _z_bytes_wrap(peer->_remote_zid.id, _z_id_len(peer->_remote_zid)); - _zp_config_insert(ps, Z_INFO_PEER_PID_KEY, _z_string_from_bytes(&remote_zid)); + _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_clear(&remote_zid_str); xs = _z_transport_peer_entry_list_tail(xs); } } #else -void _zp_multicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *callback) { +void _zp_multicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { _ZP_UNUSED(zt); _ZP_UNUSED(callback); } diff --git a/src/transport/multicast/lease.c b/src/transport/multicast/lease.c index 7db7a8bfa..f9b5e78f3 100644 --- a/src/transport/multicast/lease.c +++ b/src/transport/multicast/lease.c @@ -23,6 +23,37 @@ #if Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1 +int8_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; + + _z_id_t zid = _Z_RC_IN_VAL(ztm->_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); +} + +int8_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); +} + +#else +int8_t _zp_multicast_send_join(_z_transport_multicast_t *ztm) { + _ZP_UNUSED(ztm); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} + +int8_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm) { + _ZP_UNUSED(ztm); + return _Z_ERR_TRANSPORT_NOT_AVAILABLE; +} +#endif // Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1 + +#if Z_FEATURE_MULTI_THREAD == 1 && (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) + static _z_zint_t _z_get_minimum_lease(_z_transport_peer_entry_list_t *peers, _z_zint_t local_lease) { _z_zint_t ret = local_lease; @@ -57,49 +88,18 @@ static _z_zint_t _z_get_next_lease(_z_transport_peer_entry_list_t *peers) { return ret; } -int8_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; - - _z_id_t zid = ((_z_session_t *)ztm->_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); -} - -int8_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); -} - -#else -int8_t _zp_multicast_send_join(_z_transport_multicast_t *ztm) { - _ZP_UNUSED(ztm); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} - -int8_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm) { - _ZP_UNUSED(ztm); - return _Z_ERR_TRANSPORT_NOT_AVAILABLE; -} -#endif // Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1 - -#if Z_FEATURE_MULTI_THREAD == 1 && (Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1) - void *_zp_multicast_lease_task(void *ztm_arg) { _z_transport_multicast_t *ztm = (_z_transport_multicast_t *)ztm_arg; ztm->_transmitted = false; // From all peers, get the next lease time (minimum) - _z_zint_t next_lease = _z_get_minimum_lease(ztm->_peers, ztm->_lease); - _z_zint_t next_keep_alive = (_z_zint_t)(next_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); - _z_zint_t next_join = Z_JOIN_INTERVAL; + int next_lease = (int)_z_get_minimum_lease(ztm->_peers, ztm->_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) { - z_mutex_lock(&ztm->_mutex_peer); + _z_mutex_lock(&ztm->_mutex_peer); if (next_lease <= 0) { it = ztm->_peers; @@ -137,12 +137,11 @@ void *_zp_multicast_lease_task(void *ztm_arg) { // Reset the keep alive parameters ztm->_transmitted = false; - next_keep_alive = - (_z_zint_t)(_z_get_minimum_lease(ztm->_peers, ztm->_lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + next_keep_alive = (int)(_z_get_minimum_lease(ztm->_peers, ztm->_lease) / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } // Compute the target interval to sleep - _z_zint_t interval; + int interval; if (next_lease > 0) { interval = next_lease; if (next_keep_alive < interval) { @@ -158,35 +157,41 @@ void *_zp_multicast_lease_task(void *ztm_arg) { } } - z_mutex_unlock(&ztm->_mutex_peer); + _z_mutex_unlock(&ztm->_mutex_peer); // The keep alive and lease intervals are expressed in milliseconds - z_sleep_ms(interval); + z_sleep_ms((size_t)interval); // Decrement all intervals - z_mutex_lock(&ztm->_mutex_peer); + _z_mutex_lock(&ztm->_mutex_peer); it = ztm->_peers; while (it != NULL) { _z_transport_peer_entry_t *entry = _z_transport_peer_entry_list_head(it); - entry->_next_lease = entry->_next_lease - interval; + int entry_next_lease = (int)entry->_next_lease - interval; + if (entry_next_lease >= 0) { + entry->_next_lease = (size_t)entry_next_lease; + } else { + _Z_ERROR("Negative next lease value"); + entry->_next_lease = 0; + } it = _z_transport_peer_entry_list_tail(it); } - next_lease = _z_get_next_lease(ztm->_peers); + next_lease = (int)_z_get_next_lease(ztm->_peers); next_keep_alive = next_keep_alive - interval; next_join = next_join - interval; - z_mutex_unlock(&ztm->_mutex_peer); + _z_mutex_unlock(&ztm->_mutex_peer); } return 0; } -int8_t _zp_multicast_start_lease_task(_z_transport_multicast_t *ztm, z_task_attr_t *attr, z_task_t *task) { +int8_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)); + (void)memset(task, 0, sizeof(_z_task_t)); ztm->_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) { + if (_z_task_init(task, attr, _zp_multicast_lease_task, ztm) != _Z_RES_OK) { ztm->_lease_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } diff --git a/src/transport/multicast/read.c b/src/transport/multicast/read.c index 609e5d27c..5565dd005 100644 --- a/src/transport/multicast/read.c +++ b/src/transport/multicast/read.c @@ -19,6 +19,7 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/transport/common/rx.h" #include "zenoh-pico/transport/multicast/rx.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/utils/logging.h" @@ -28,7 +29,7 @@ int8_t _zp_multicast_read(_z_transport_multicast_t *ztm) { int8_t ret = _Z_RES_OK; - _z_bytes_t addr; + _z_slice_t addr; _z_transport_message_t t_msg; ret = _z_multicast_recv_t_msg(ztm, &t_msg, &addr); if (ret == _Z_RES_OK) { @@ -51,12 +52,12 @@ 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->_mutex_rx); // Prepare the buffer _z_zbuf_reset(&ztm->_zbuf); - _z_bytes_t addr = _z_bytes_wrap(NULL, 0); + _z_slice_t addr = _z_slice_alias_buf(NULL, 0); while (ztm->_read_task_running == true) { // Read bytes from socket to the main buffer size_t to_read = 0; @@ -66,16 +67,14 @@ void *_zp_multicast_read_task(void *ztm_arg) { 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_bytes_clear(&addr); + _z_slice_clear(&addr); _z_zbuf_compact(&ztm->_zbuf); continue; } } - - for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { - to_read |= _z_zbuf_read(&ztm->_zbuf) << (i * (uint8_t)8); - } - + // Get stream size + to_read = _z_read_stream_size(&ztm->_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) { @@ -109,7 +108,7 @@ void *_zp_multicast_read_task(void *ztm_arg) { if (ret == _Z_RES_OK) { _z_t_msg_clear(&t_msg); - _z_bytes_clear(&addr); + _z_slice_clear(&addr); } else { ztm->_read_task_running = false; continue; @@ -124,16 +123,16 @@ void *_zp_multicast_read_task(void *ztm_arg) { // Move the read position of the read buffer _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) + to_read); } - z_mutex_unlock(&ztm->_mutex_rx); + _z_mutex_unlock(&ztm->_mutex_rx); return NULL; } -int8_t _zp_multicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task) { +int8_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)); + (void)memset(task, 0, sizeof(_z_task_t)); zt->_transport._multicast._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) { + if (_z_task_init(task, attr, _zp_multicast_read_task, &zt->_transport._multicast) != _Z_RES_OK) { zt->_transport._multicast._read_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } diff --git a/src/transport/multicast/rx.c b/src/transport/multicast/rx.c index 048a6563f..badd82bc0 100644 --- a/src/transport/multicast/rx.c +++ b/src/transport/multicast/rx.c @@ -24,18 +24,19 @@ #include "zenoh-pico/protocol/definitions/transport.h" #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/transport/common/rx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_MULTICAST_TRANSPORT == 1 static int8_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, - _z_bytes_t *addr) { + _z_slice_t *addr) { _Z_DEBUG(">> recv session msg"); int8_t ret = _Z_RES_OK; #if Z_FEATURE_MULTI_THREAD == 1 // Acquire the lock - z_mutex_lock(&ztm->_mutex_rx); + _z_mutex_lock(&ztm->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 size_t to_read = 0; @@ -50,9 +51,9 @@ static int8_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_trans break; } } - for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { - to_read |= _z_zbuf_read(&ztm->_zbuf) << (i * (uint8_t)8); - } + // Get stream size + to_read = _z_read_stream_size(&ztm->_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) { @@ -82,17 +83,17 @@ static int8_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_trans } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_rx); + _z_mutex_unlock(&ztm->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; } -int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr) { +int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { return _z_multicast_recv_t_msg_na(ztm, t_msg, addr); } #else -int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr) { +int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { _ZP_UNUSED(ztm); _ZP_UNUSED(t_msg); _ZP_UNUSED(addr); @@ -102,7 +103,7 @@ int8_t _z_multicast_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_messa #if Z_FEATURE_MULTICAST_TRANSPORT == 1 || Z_FEATURE_RAWETH_TRANSPORT == 1 -static _z_transport_peer_entry_t *_z_find_peer_entry(_z_transport_peer_entry_list_t *l, _z_bytes_t *remote_addr) { +static _z_transport_peer_entry_t *_z_find_peer_entry(_z_transport_peer_entry_list_t *l, _z_slice_t *remote_addr) { _z_transport_peer_entry_t *ret = NULL; _z_transport_peer_entry_list_t *xs = l; @@ -121,11 +122,11 @@ static _z_transport_peer_entry_t *_z_find_peer_entry(_z_transport_peer_entry_lis } int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, - _z_bytes_t *addr) { + _z_slice_t *addr) { int8_t ret = _Z_RES_OK; #if Z_FEATURE_MULTI_THREAD == 1 // Acquire and keep the lock - z_mutex_lock(&ztm->_mutex_peer); + _z_mutex_lock(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 // Mark the session that we have received data from this peer @@ -269,7 +270,7 @@ int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_t } if (ret == _Z_RES_OK) { - entry->_remote_addr = _z_bytes_duplicate(addr); + entry->_remote_addr = _z_slice_duplicate(addr); entry->_remote_zid = t_msg->_body._join._zid; _z_conduit_sn_list_copy(&entry->_sn_rx_sns, &t_msg->_body._join._next_sn); @@ -341,14 +342,14 @@ int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_t } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_peer); + _z_mutex_unlock(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; } #else int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, - _z_bytes_t *addr) { + _z_slice_t *addr) { _ZP_UNUSED(ztm); _ZP_UNUSED(t_msg); _ZP_UNUSED(addr); diff --git a/src/transport/multicast/transport.c b/src/transport/multicast/transport.c index 6f6057fd8..3630a5f30 100644 --- a/src/transport/multicast/transport.c +++ b/src/transport/multicast/transport.c @@ -52,17 +52,17 @@ int8_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, } #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = z_mutex_init(&ztm->_mutex_tx); + ret = _z_mutex_init(&ztm->_mutex_tx); if (ret == _Z_RES_OK) { - ret = z_mutex_init(&ztm->_mutex_rx); + ret = _z_mutex_init(&ztm->_mutex_rx); if (ret == _Z_RES_OK) { - ret = z_mutex_init(&ztm->_mutex_peer); + ret = _z_mutex_init(&ztm->_mutex_peer); if (ret != _Z_RES_OK) { - z_mutex_free(&ztm->_mutex_tx); - z_mutex_free(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_mutex_tx); + _z_mutex_drop(&ztm->_mutex_rx); } } else { - z_mutex_free(&ztm->_mutex_tx); + _z_mutex_drop(&ztm->_mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 @@ -79,9 +79,9 @@ int8_t _z_multicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_free(&ztm->_mutex_tx); - z_mutex_free(&ztm->_mutex_rx); - z_mutex_free(&ztm->_mutex_peer); + _z_mutex_drop(&ztm->_mutex_tx); + _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 _z_wbuf_clear(&ztm->_wbuf); @@ -184,17 +184,17 @@ void _z_multicast_transport_clear(_z_transport_t *zt) { #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); + _z_task_join(ztm->_read_task); + _z_task_free(&ztm->_read_task); } if (ztm->_lease_task != NULL) { - z_task_join(ztm->_lease_task); - z_task_free(&ztm->_lease_task); + _z_task_join(ztm->_lease_task); + _z_task_free(&ztm->_lease_task); } // Clean up the mutexes - z_mutex_free(&ztm->_mutex_tx); - z_mutex_free(&ztm->_mutex_rx); - z_mutex_free(&ztm->_mutex_peer); + _z_mutex_drop(&ztm->_mutex_tx); + _z_mutex_drop(&ztm->_mutex_rx); + _z_mutex_drop(&ztm->_mutex_peer); #endif // Z_FEATURE_MULTI_THREAD == 1 // Clean up the buffers diff --git a/src/transport/multicast/tx.c b/src/transport/multicast/tx.c index 5de35fe4f..3f7726db0 100644 --- a/src/transport/multicast/tx.c +++ b/src/transport/multicast/tx.c @@ -46,7 +46,7 @@ int8_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport #if Z_FEATURE_MULTI_THREAD == 1 // Acquire the lock - z_mutex_lock(&ztm->_mutex_tx); + _z_mutex_lock(&ztm->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 // Prepare the buffer eventually reserving space for the message length @@ -65,7 +65,7 @@ int8_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_tx); + _z_mutex_unlock(&ztm->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; @@ -82,11 +82,11 @@ int8_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_m _Bool drop = false; if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&ztm->_mutex_tx); + _z_mutex_lock(&ztm->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 } else { #if Z_FEATURE_MULTI_THREAD == 1 - int8_t locked = z_mutex_trylock(&ztm->_mutex_tx); + int8_t locked = _z_mutex_try_lock(&ztm->_mutex_tx); if (locked != (int8_t)0) { _Z_INFO("Dropping zenoh message because of congestion control"); // We failed to acquire the lock, drop the message @@ -153,7 +153,7 @@ int8_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_m } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_tx); + _z_mutex_unlock(&ztm->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 } diff --git a/src/transport/peer_entry.c b/src/transport/peer_entry.c index 599660fcc..013c8c6de 100644 --- a/src/transport/peer_entry.c +++ b/src/transport/peer_entry.c @@ -23,7 +23,7 @@ void _z_transport_peer_entry_clear(_z_transport_peer_entry_t *src) { #endif src->_remote_zid = _z_id_empty(); - _z_bytes_clear(&src->_remote_addr); + _z_slice_clear(&src->_remote_addr); } void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_transport_peer_entry_t *src) { @@ -40,7 +40,7 @@ void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_trans dst->_received = src->_received; dst->_remote_zid = src->_remote_zid; - _z_bytes_copy(&dst->_remote_addr, &src->_remote_addr); + _z_slice_copy(&dst->_remote_addr, &src->_remote_addr); } size_t _z_transport_peer_entry_size(const _z_transport_peer_entry_t *src) { diff --git a/src/transport/raweth/link.c b/src/transport/raweth/link.c index 63aa74705..4c6a82b85 100644 --- a/src/transport/raweth/link.c +++ b/src/transport/raweth/link.c @@ -45,6 +45,9 @@ #define RAWETH_CONFIG_WHITELIST_KEY 0x04 #define RAWETH_CONFIG_WHITELIST_STR "whitelist" +// Ethtype must be at least 0x600 in network order +#define RAWETH_ETHTYPE_MIN_VALUE 0x600U + #define RAWETH_CONFIG_MAPPING_BUILD \ _z_str_intmapping_t args[RAWETH_CONFIG_ARGC]; \ args[0]._key = RAWETH_CONFIG_IFACE_KEY; \ @@ -60,7 +63,7 @@ const uint16_t _ZP_RAWETH_DEFAULT_ETHTYPE = 0x72e0; const char *_ZP_RAWETH_DEFAULT_INTERFACE = "lo"; const uint8_t _ZP_RAWETH_DEFAULT_SMAC[_ZP_MAC_ADDR_LENGTH] = {0x30, 0x03, 0xc8, 0x37, 0x25, 0xa1}; const _zp_raweth_mapping_entry_t _ZP_RAWETH_DEFAULT_MAPPING = { - {0, {0}, ""}, 0x0000, {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, false}; + {0, {0}, {{0, NULL, {NULL, NULL}}}}, 0x0000, {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}, false}; static _Bool _z_valid_iface_raweth(_z_str_intmap_t *config); static const char *_z_get_iface_raweth(_z_str_intmap_t *config); @@ -72,6 +75,7 @@ static size_t _z_valid_whitelist_raweth(_z_str_intmap_t *config); static int8_t _z_get_whitelist_raweth(_z_str_intmap_t *config, _zp_raweth_whitelist_array_t *array, size_t size); static int8_t _z_get_mapping_entry(char *entry, _zp_raweth_mapping_entry_t *storage); static _Bool _z_valid_mapping_entry(char *entry); +static _Bool _z_valid_address_raweth_inner(const _z_string_t *address); static _Bool _z_valid_address_raweth(const char *address); static uint8_t *_z_parse_address_raweth(const char *address); static int8_t _z_f_link_open_raweth(_z_link_t *self); @@ -80,8 +84,8 @@ static void _z_f_link_close_raweth(_z_link_t *self); static void _z_f_link_free_raweth(_z_link_t *self); static size_t _z_f_link_write_raweth(const _z_link_t *self, const uint8_t *ptr, size_t len); static size_t _z_f_link_write_all_raweth(const _z_link_t *self, const uint8_t *ptr, size_t len); -static size_t _z_f_link_read_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr); -static size_t _z_f_link_read_exact_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr); +static size_t _z_f_link_read_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr); +static size_t _z_f_link_read_exact_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr); static uint16_t _z_get_link_mtu_raweth(void); static _Bool _z_valid_iface_raweth(_z_str_intmap_t *config) { @@ -99,7 +103,7 @@ static _Bool _z_valid_ethtype_raweth(_z_str_intmap_t *config) { return false; } long ethtype = strtol(s_ethtype, NULL, 16); - return (_z_raweth_htons(ethtype) > 0x600); // Ethtype must be at least 0x600 in network order + return (_z_raweth_htons((uint16_t)ethtype) > RAWETH_ETHTYPE_MIN_VALUE); } static long _z_get_ethtype_raweth(_z_str_intmap_t *config) { @@ -113,7 +117,7 @@ static size_t _z_valid_mapping_raweth(_z_str_intmap_t *config) { if (cfg_str == NULL) { return 0; } - char *s_mapping = zp_malloc(strlen(cfg_str)); + char *s_mapping = z_malloc(strlen(cfg_str)); if (s_mapping == NULL) { return 0; } @@ -125,14 +129,14 @@ static size_t _z_valid_mapping_raweth(_z_str_intmap_t *config) { while (entry != NULL) { // Check entry if (!_z_valid_mapping_entry(entry)) { - zp_free(s_mapping); + z_free(s_mapping); return 0; } size++; entry = strtok(NULL, delim); } // Clean up - zp_free(s_mapping); + z_free(s_mapping); return size; } @@ -143,7 +147,7 @@ static int8_t _z_get_mapping_raweth(_z_str_intmap_t *config, _zp_raweth_mapping_ return _Z_ERR_GENERIC; } // Copy data - char *s_mapping = zp_malloc(strlen(cfg_str)); + char *s_mapping = z_malloc(strlen(cfg_str)); if (s_mapping == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -160,24 +164,24 @@ static int8_t _z_get_mapping_raweth(_z_str_intmap_t *config, _zp_raweth_mapping_ while ((entry != NULL) && (idx < _zp_raweth_mapping_array_len(array))) { // Copy data into array _Z_CLEAN_RETURN_IF_ERR(_z_get_mapping_entry(entry, _zp_raweth_mapping_array_get(array, idx)), - zp_free(s_mapping)); + z_free(s_mapping)); // Next iteration idx++; entry = strtok(NULL, delim); } // Clean up - zp_free(s_mapping); + z_free(s_mapping); return _Z_RES_OK; } -static const size_t _z_valid_whitelist_raweth(_z_str_intmap_t *config) { +static size_t _z_valid_whitelist_raweth(_z_str_intmap_t *config) { // Retrieve data const char *cfg_str = _z_str_intmap_get(config, RAWETH_CONFIG_WHITELIST_KEY); if (cfg_str == NULL) { return 0; } // Copy data - char *s_whitelist = zp_malloc(strlen(cfg_str)); + char *s_whitelist = z_malloc(strlen(cfg_str)); if (s_whitelist == NULL) { return 0; } @@ -189,7 +193,7 @@ static const size_t _z_valid_whitelist_raweth(_z_str_intmap_t *config) { while (entry != NULL) { // Check entry if (!_z_valid_address_raweth(entry)) { - zp_free(s_whitelist); + z_free(s_whitelist); return 0; } size++; @@ -198,7 +202,7 @@ static const size_t _z_valid_whitelist_raweth(_z_str_intmap_t *config) { // Parse last entry // Clean up - zp_free(s_whitelist); + z_free(s_whitelist); return size; } @@ -209,7 +213,7 @@ static int8_t _z_get_whitelist_raweth(_z_str_intmap_t *config, _zp_raweth_whitel return _Z_ERR_GENERIC; } // Copy data - char *s_whitelist = zp_malloc(strlen(cfg_str)); + char *s_whitelist = z_malloc(strlen(cfg_str)); if (s_whitelist == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -232,13 +236,13 @@ static int8_t _z_get_whitelist_raweth(_z_str_intmap_t *config, _zp_raweth_whitel // Copy address to entry _zp_raweth_whitelist_entry_t *elem = _zp_raweth_whitelist_array_get(array, idx); memcpy(elem->_mac, addr, _ZP_MAC_ADDR_LENGTH); - zp_free(addr); + z_free(addr); // Next iteration idx++; entry = strtok(NULL, delim); } // Clean up - zp_free(s_whitelist); + z_free(s_whitelist); return _Z_RES_OK; } @@ -250,7 +254,7 @@ static int8_t _z_get_mapping_entry(char *entry, _zp_raweth_mapping_entry_t *stor char *p_start = &entry[0]; char *p_end = strchr(p_start, RAWETH_CFG_TUPLE_SEPARATOR); size_t ke_len = (uintptr_t)p_end - (uintptr_t)p_start; - char *ke_suffix = (char *)zp_malloc(ke_len); + char *ke_suffix = (char *)z_malloc(ke_len); if (ke_suffix == NULL) { return _Z_ERR_SYSTEM_OUT_OF_MEMORY; } @@ -264,7 +268,7 @@ static int8_t _z_get_mapping_entry(char *entry, _zp_raweth_mapping_entry_t *stor *p_end = '\0'; uint8_t *addr = _z_parse_address_raweth(p_start); memcpy(storage->_dmac, addr, _ZP_MAC_ADDR_LENGTH); - zp_free(addr); + z_free(addr); *p_end = RAWETH_CFG_TUPLE_SEPARATOR; // Check optional third entry (vlan id) @@ -307,22 +311,23 @@ static _Bool _z_valid_mapping_entry(char *entry) { return true; } -static _Bool _z_valid_address_raweth(const char *address) { +static _Bool _z_valid_address_raweth_inner(const _z_string_t *address) { // Check if the string has the correct length - size_t len = strlen(address); + size_t len = _z_string_len(address); + const char *str_data = _z_string_data(address); if (len != 17) { // 6 pairs of hexadecimal digits and 5 colons return false; } // Check if the colons are at the correct positions - for (int i = 2; i < len; i += 3) { - if (address[i] != ':') { + for (size_t i = 2; i < len; i += 3) { + if (str_data[i] != ':') { return false; } } // Check if each character is a valid hexadecimal digit - for (int i = 0; i < len; ++i) { + for (size_t i = 0; i < len; ++i) { if (i % 3 != 2) { - char c = address[i]; + char c = str_data[i]; if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))) { return false; } @@ -331,8 +336,12 @@ static _Bool _z_valid_address_raweth(const char *address) { return true; } +static _Bool _z_valid_address_raweth(const char *address) { + _z_string_t addr_str = _z_string_alias_str(address); + return _z_valid_address_raweth_inner(&addr_str); +} + static uint8_t *_z_parse_address_raweth(const char *address) { - size_t len = strlen(address); // Allocate data uint8_t *ret = (uint8_t *)z_malloc(_ZP_MAC_ADDR_LENGTH); if (ret == NULL) { @@ -354,8 +363,8 @@ static int8_t _z_f_link_open_raweth(_z_link_t *self) { self->_socket._raweth._mapping = _zp_raweth_mapping_array_empty(); self->_socket._raweth._whitelist = _zp_raweth_whitelist_array_empty(); // Init socket smac - if (_z_valid_address_raweth(self->_endpoint._locator._address)) { - uint8_t *addr = _z_parse_address_raweth(self->_endpoint._locator._address); + if (_z_valid_address_raweth_inner(&self->_endpoint._locator._address)) { + uint8_t *addr = _z_parse_address_raweth(_z_string_data(&self->_endpoint._locator._address)); memcpy(&self->_socket._raweth._smac, addr, _ZP_MAC_ADDR_LENGTH); z_free(addr); } else { @@ -402,7 +411,15 @@ static int8_t _z_f_link_open_raweth(_z_link_t *self) { static int8_t _z_f_link_listen_raweth(_z_link_t *self) { return _z_f_link_open_raweth(self); } -static void _z_f_link_close_raweth(_z_link_t *self) { _z_close_raweth(&self->_socket._raweth._sock); } +static void _z_f_link_close_raweth(_z_link_t *self) { + // Close connection + _z_close_raweth(&self->_socket._raweth._sock); + // Clear config + _zp_raweth_mapping_array_clear(&self->_socket._raweth._mapping); + if (_zp_raweth_whitelist_array_len(&self->_socket._raweth._whitelist) != 0) { + _zp_raweth_whitelist_array_clear(&self->_socket._raweth._whitelist); + } +} static void _z_f_link_free_raweth(_z_link_t *self) { _ZP_UNUSED(self); } @@ -420,7 +437,7 @@ static size_t _z_f_link_write_all_raweth(const _z_link_t *self, const uint8_t *p return SIZE_MAX; } -static size_t _z_f_link_read_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +static size_t _z_f_link_read_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { _ZP_UNUSED(self); _ZP_UNUSED(ptr); _ZP_UNUSED(len); @@ -428,7 +445,7 @@ static size_t _z_f_link_read_raweth(const _z_link_t *self, uint8_t *ptr, size_t return SIZE_MAX; } -static size_t _z_f_link_read_exact_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_bytes_t *addr) { +static size_t _z_f_link_read_exact_raweth(const _z_link_t *self, uint8_t *ptr, size_t len, _z_slice_t *addr) { _ZP_UNUSED(self); _ZP_UNUSED(ptr); _ZP_UNUSED(len); @@ -442,7 +459,8 @@ int8_t _z_endpoint_raweth_valid(_z_endpoint_t *endpoint) { int8_t ret = _Z_RES_OK; // Check the root - if (!_z_str_eq(endpoint->_locator._protocol, RAWETH_SCHEMA)) { + _z_string_t str_cmp = _z_string_alias_str(RAWETH_SCHEMA); + if (!_z_string_equals(&endpoint->_locator._protocol, &str_cmp)) { ret = _Z_ERR_CONFIG_LOCATOR_INVALID; } return ret; diff --git a/src/transport/raweth/read.c b/src/transport/raweth/read.c index 781e34e7a..81cf0fd3d 100644 --- a/src/transport/raweth/read.c +++ b/src/transport/raweth/read.c @@ -29,13 +29,14 @@ int8_t _zp_raweth_read(_z_transport_multicast_t *ztm) { int8_t ret = _Z_RES_OK; - _z_bytes_t addr; + _z_slice_t addr; _z_transport_message_t t_msg; ret = _z_raweth_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); } + _z_slice_clear(&addr); return ret; } #else @@ -51,7 +52,7 @@ int8_t _zp_raweth_read(_z_transport_multicast_t *ztm) { void *_zp_raweth_read_task(void *ztm_arg) { _z_transport_multicast_t *ztm = (_z_transport_multicast_t *)ztm_arg; _z_transport_message_t t_msg; - _z_bytes_t addr = _z_bytes_wrap(NULL, 0); + _z_slice_t addr = _z_slice_alias_buf(NULL, 0); // Task loop while (ztm->_read_task_running == true) { @@ -63,33 +64,36 @@ void *_zp_raweth_read_task(void *ztm_arg) { break; case _Z_ERR_TRANSPORT_RX_FAILED: // Drop message + _z_slice_clear(&addr); continue; break; default: // Drop message & stop task _Z_ERROR("Connection closed due to malformed message"); ztm->_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; + _z_slice_clear(&addr); continue; } _z_t_msg_clear(&t_msg); - _z_bytes_clear(&addr); + _z_slice_clear(&addr); } return NULL; } -int8_t _zp_raweth_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task) { +int8_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._raweth._read_task_running = true; // Init before z_task_init for concurrency issue + (void)memset(task, 0, sizeof(_z_task_t)); + zt->_transport._unicast._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._raweth._read_task_running = false; + if (_z_task_init(task, attr, _zp_raweth_read_task, &zt->_transport._raweth) != _Z_RES_OK) { + zt->_transport._unicast._lease_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task diff --git a/src/transport/raweth/rx.c b/src/transport/raweth/rx.c index 6732532ab..a1fdb9d1e 100644 --- a/src/transport/raweth/rx.c +++ b/src/transport/raweth/rx.c @@ -27,7 +27,7 @@ #if Z_FEATURE_RAWETH_TRANSPORT == 1 -static size_t _z_raweth_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z_bytes_t *addr) { +static size_t _z_raweth_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z_slice_t *addr) { uint8_t *buff = _z_zbuf_get_wptr(zbf); size_t rb = _z_receive_raweth(&link->_socket._raweth._sock, buff, _z_zbuf_space_left(zbf), addr, &link->_socket._raweth._whitelist); @@ -47,9 +47,9 @@ static size_t _z_raweth_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z } size_t data_length = 0; if (has_vlan) { - _zp_eth_vlan_header_t *header = (_zp_eth_vlan_header_t *)buff; + _zp_eth_vlan_header_t *vlan_header = (_zp_eth_vlan_header_t *)buff; // Retrieve data length - data_length = _z_raweth_ntohs(header->data_length); + data_length = _z_raweth_ntohs(vlan_header->data_length); if (rb < (data_length + sizeof(_zp_eth_vlan_header_t))) { // Invalid data_length return SIZE_MAX; @@ -58,7 +58,7 @@ static size_t _z_raweth_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z _z_zbuf_set_wpos(zbf, _z_zbuf_get_wpos(zbf) + sizeof(_zp_eth_vlan_header_t) + data_length); _z_zbuf_set_rpos(zbf, _z_zbuf_get_rpos(zbf) + sizeof(_zp_eth_vlan_header_t)); } else { - _zp_eth_header_t *header = (_zp_eth_header_t *)buff; + header = (_zp_eth_header_t *)buff; // Retrieve data length data_length = _z_raweth_ntohs(header->data_length); if (rb < (data_length + sizeof(_zp_eth_header_t))) { @@ -73,13 +73,13 @@ static size_t _z_raweth_link_recv_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, _z } /*------------------ Reception helper ------------------*/ -int8_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr) { +int8_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { _Z_DEBUG(">> recv session msg"); int8_t ret = _Z_RES_OK; #if Z_FEATURE_MULTI_THREAD == 1 // Acquire the lock - z_mutex_lock(&ztm->_mutex_rx); + _z_mutex_lock(&ztm->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 // Prepare the buffer @@ -107,18 +107,18 @@ int8_t _z_raweth_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_messa } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_rx); + _z_mutex_unlock(&ztm->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; } -int8_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr) { +int8_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { return _z_raweth_recv_t_msg_na(ztm, t_msg, addr); } #else -int8_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_bytes_t *addr) { +int8_t _z_raweth_recv_t_msg(_z_transport_multicast_t *ztm, _z_transport_message_t *t_msg, _z_slice_t *addr) { _ZP_UNUSED(ztm); _ZP_UNUSED(t_msg); _ZP_UNUSED(addr); diff --git a/src/transport/raweth/tx.c b/src/transport/raweth/tx.c index a3cf15a8d..7e21ff6a6 100644 --- a/src/transport/raweth/tx.c +++ b/src/transport/raweth/tx.c @@ -31,19 +31,19 @@ #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); } +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 (int i = 0; i < _zp_raweth_mapping_array_len(&sock->_mapping); i++) { + for (size_t i = 0; i < _zp_raweth_mapping_array_len(&sock->_mapping); i++) { // Find matching keyexpr const _zp_raweth_mapping_entry_t *entry = _zp_raweth_mapping_array_get(&sock->_mapping, i); - if (zp_keyexpr_intersect_null_terminated(keyexpr->_suffix, entry->_keyexpr._suffix) != _Z_RES_OK) { + if (z_keyexpr_intersects(keyexpr, &entry->_keyexpr) != _Z_RES_OK) { continue; } - return i; + return (int)i; } return -1; } @@ -69,10 +69,11 @@ static int8_t _zp_raweth_set_socket(const _z_keyexpr_t *keyexpr, _z_raweth_socke // Key not found case if (idx < 0) { idx = 0; // Set to default entry - _Z_DEBUG("Key '%s' wasn't found in config mapping, sending to default address", keyexpr->_suffix); + _Z_DEBUG("Key '%.*s' wasn't found in config mapping, sending to default address", + (int)_z_string_len(&keyexpr->_suffix), _z_string_data(&keyexpr->_suffix)); } // Store data into socket - const _zp_raweth_mapping_entry_t *entry = _zp_raweth_mapping_array_get(&sock->_mapping, idx); + const _zp_raweth_mapping_entry_t *entry = _zp_raweth_mapping_array_get(&sock->_mapping, (size_t)idx); memcpy(&sock->_dmac, &entry->_dmac, _ZP_MAC_ADDR_LENGTH); uint16_t vlan = entry->_vlan; sock->_has_vlan = entry->_has_vlan; @@ -130,7 +131,7 @@ static int8_t __unsafe_z_raweth_write_header(_z_link_t *zl, _z_wbuf_t *wbf) { header.vlan_type = _ZP_ETH_TYPE_VLAN; header.tag = resocket->_vlan; header.ethtype = resocket->_ethtype; - header.data_length = _z_raweth_htons(wpos - sizeof(header)); + header.data_length = _z_raweth_htons((uint16_t)(wpos - sizeof(header))); // Write header _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, (uint8_t *)&header, 0, sizeof(header))); } else { @@ -139,7 +140,7 @@ static int8_t __unsafe_z_raweth_write_header(_z_link_t *zl, _z_wbuf_t *wbf) { memcpy(&header.dmac, &resocket->_dmac, _ZP_MAC_ADDR_LENGTH); memcpy(&header.smac, &resocket->_smac, _ZP_MAC_ADDR_LENGTH); header.ethtype = resocket->_ethtype; - header.data_length = _z_raweth_htons(wpos - sizeof(header)); + header.data_length = _z_raweth_htons((uint16_t)(wpos - sizeof(header))); // Write header _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, (uint8_t *)&header, 0, sizeof(header))); } @@ -151,7 +152,7 @@ static int8_t __unsafe_z_raweth_write_header(_z_link_t *zl, _z_wbuf_t *wbf) { static int8_t _z_raweth_link_send_wbuf(const _z_link_t *zl, const _z_wbuf_t *wbf) { int8_t ret = _Z_RES_OK; for (size_t i = 0; (i < _z_wbuf_len_iosli(wbf)) && (ret == _Z_RES_OK); i++) { - _z_bytes_t bs = _z_iosli_to_bytes(_z_wbuf_get_iosli(wbf, i)); + _z_slice_t bs = _z_iosli_to_bytes(_z_wbuf_get_iosli(wbf, i)); size_t n = bs.len; do { @@ -196,7 +197,7 @@ int8_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_me _Z_DEBUG(">> send session message"); #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&ztm->_mutex_tx); + _z_mutex_lock(&ztm->_mutex_tx); #endif // Reset wbuf _z_wbuf_reset(&ztm->_wbuf); @@ -214,7 +215,7 @@ int8_t _z_raweth_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_me ztm->_transmitted = true; #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_tx); + _z_mutex_unlock(&ztm->_mutex_tx); #endif return ret; @@ -229,9 +230,9 @@ int8_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, // 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); + _z_mutex_lock(&ztm->_mutex_tx); } else { - if (z_mutex_trylock(&ztm->_mutex_tx) != (int8_t)0) { + if (_z_mutex_try_lock(&ztm->_mutex_tx) != (int8_t)0) { _Z_INFO("Dropping zenoh message because of congestion control"); // We failed to acquire the lock, drop the message return ret; @@ -241,7 +242,7 @@ int8_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, _ZP_UNUSED(cong_ctrl); #endif // Z_FEATURE_MULTI_THREAD == 1 - const z_keyexpr_t *keyexpr = NULL; + const _z_keyexpr_t *keyexpr = NULL; switch (n_msg->_tag) { case _Z_N_PUSH: keyexpr = &n_msg->_body._push._key; @@ -314,7 +315,7 @@ int8_t _z_raweth_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, #endif } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztm->_mutex_tx); + _z_mutex_unlock(&ztm->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; } diff --git a/src/transport/unicast.c b/src/transport/unicast.c index 02ddc9e5c..dca9ae0ea 100644 --- a/src/transport/unicast.c +++ b/src/transport/unicast.c @@ -31,7 +31,7 @@ #include "zenoh-pico/utils/logging.h" #if Z_FEATURE_UNICAST_TRANSPORT == 1 -void _zp_unicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *callback) { +void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { void *ctx = callback->context; z_id_t id = zt->_transport._unicast._remote_zid; callback->call(&id, ctx); @@ -39,12 +39,14 @@ void _zp_unicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *call 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_bytes_t remote_zidbytes = _z_bytes_wrap(remote_zid.id, _z_id_len(remote_zid)); - _zp_config_insert(ps, Z_INFO_ROUTER_PID_KEY, _z_string_from_bytes(&remote_zidbytes)); + _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_clear(&remote_zid_str); } #else -void _zp_unicast_fetch_zid(const _z_transport_t *zt, z_owned_closure_zid_t *callback) { +void _zp_unicast_fetch_zid(const _z_transport_t *zt, _z_closure_zid_t *callback) { _ZP_UNUSED(zt); _ZP_UNUSED(callback); } diff --git a/src/transport/unicast/lease.c b/src/transport/unicast/lease.c index c18d63467..3555d251c 100644 --- a/src/transport/unicast/lease.c +++ b/src/transport/unicast/lease.c @@ -44,10 +44,11 @@ void *_zp_unicast_lease_task(void *ztu_arg) { ztu->_received = false; ztu->_transmitted = false; - _z_zint_t next_lease = ztu->_lease; - _z_zint_t next_keep_alive = (_z_zint_t)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + int next_lease = (int)ztu->_lease; + int next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); while (ztu->_lease_task_running == true) { - if (next_lease == 0) { + // Next lease process + if (next_lease <= 0) { // Check if received data if (ztu->_received == true) { // Reset the lease parameters @@ -58,10 +59,9 @@ void *_zp_unicast_lease_task(void *ztu_arg) { _z_unicast_transport_close(ztu, _Z_CLOSE_EXPIRED); break; } - - next_lease = ztu->_lease; + next_lease = (int)ztu->_lease; } - + // Next keep alive process if (next_keep_alive <= 0) { // Check if need to send a keep alive if (ztu->_transmitted == false) { @@ -72,11 +72,11 @@ void *_zp_unicast_lease_task(void *ztu_arg) { // Reset the keep alive parameters ztu->_transmitted = false; - next_keep_alive = (_z_zint_t)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); + next_keep_alive = (int)(ztu->_lease / Z_TRANSPORT_LEASE_EXPIRE_FACTOR); } // Compute the target interval - _z_zint_t interval; + int interval; if (next_lease == 0) { interval = next_keep_alive; } else { @@ -87,7 +87,7 @@ void *_zp_unicast_lease_task(void *ztu_arg) { } // The keep alive and lease intervals are expressed in milliseconds - z_sleep_ms(interval); + z_sleep_ms((size_t)interval); next_lease = next_lease - interval; next_keep_alive = next_keep_alive - interval; @@ -95,13 +95,12 @@ void *_zp_unicast_lease_task(void *ztu_arg) { return 0; } -int8_t _zp_unicast_start_lease_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task) { +int8_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)); + (void)memset(task, 0, sizeof(_z_task_t)); zt->_transport._unicast._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) { - zt->_transport._unicast._lease_task_running = false; + if (_z_task_init(task, attr, _zp_unicast_lease_task, &zt->_transport._unicast) != _Z_RES_OK) { return _Z_ERR_SYSTEM_TASK_FAILED; } // Attach task diff --git a/src/transport/unicast/read.c b/src/transport/unicast/read.c index f179ba840..77d782595 100644 --- a/src/transport/unicast/read.c +++ b/src/transport/unicast/read.c @@ -18,6 +18,7 @@ #include "zenoh-pico/config.h" #include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/transport/common/rx.h" #include "zenoh-pico/transport/unicast/rx.h" #include "zenoh-pico/utils/logging.h" @@ -49,7 +50,7 @@ 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->_mutex_rx); // Prepare the buffer _z_zbuf_reset(&ztu->_zbuf); @@ -66,11 +67,9 @@ void *_zp_unicast_read_task(void *ztu_arg) { continue; } } - - for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { - to_read |= _z_zbuf_read(&ztu->_zbuf) << (i * (uint8_t)8); - } - + // Get stream size + to_read = _z_read_stream_size(&ztu->_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) { @@ -117,16 +116,16 @@ void *_zp_unicast_read_task(void *ztu_arg) { // Move the read position of the read buffer _z_zbuf_set_rpos(&ztu->_zbuf, _z_zbuf_get_rpos(&ztu->_zbuf) + to_read); } - z_mutex_unlock(&ztu->_mutex_rx); + _z_mutex_unlock(&ztu->_mutex_rx); return NULL; } -int8_t _zp_unicast_start_read_task(_z_transport_t *zt, z_task_attr_t *attr, z_task_t *task) { +int8_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)); + (void)memset(task, 0, sizeof(_z_task_t)); zt->_transport._unicast._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) { + if (_z_task_init(task, attr, _zp_unicast_read_task, &zt->_transport._unicast) != _Z_RES_OK) { zt->_transport._unicast._read_task_running = false; return _Z_ERR_SYSTEM_TASK_FAILED; } diff --git a/src/transport/unicast/rx.c b/src/transport/unicast/rx.c index 6278ca735..1046f214f 100644 --- a/src/transport/unicast/rx.c +++ b/src/transport/unicast/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/common/rx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -32,7 +33,7 @@ int8_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_messag int8_t ret = _Z_RES_OK; #if Z_FEATURE_MULTI_THREAD == 1 // Acquire the lock - z_mutex_lock(&ztu->_mutex_rx); + _z_mutex_lock(&ztu->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 size_t to_read = 0; @@ -48,9 +49,9 @@ int8_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_messag continue; } } - for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { - to_read |= _z_zbuf_read(&ztu->_zbuf) << (i * (uint8_t)8); - } + // Get stream size + to_read = _z_read_stream_size(&ztu->_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) { @@ -85,7 +86,7 @@ int8_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_messag } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztu->_mutex_rx); + _z_mutex_unlock(&ztu->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; @@ -164,7 +165,7 @@ int8_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_trans _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); // Convert the defragmentation buffer into a decoding buffer _z_zenoh_message_t zm; - int8_t ret = _z_network_message_decode(&zm, &zbf); + ret = _z_network_message_decode(&zm, &zbf); 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 diff --git a/src/transport/unicast/transport.c b/src/transport/unicast/transport.c index 11e7467e6..7003e3055 100644 --- a/src/transport/unicast/transport.c +++ b/src/transport/unicast/transport.c @@ -38,38 +38,27 @@ int8_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transpo #if Z_FEATURE_MULTI_THREAD == 1 // Initialize the mutexes - ret = z_mutex_init(&zt->_transport._unicast._mutex_tx); + ret = _z_mutex_init(&zt->_transport._unicast._mutex_tx); if (ret == _Z_RES_OK) { - ret = z_mutex_init(&zt->_transport._unicast._mutex_rx); + ret = _z_mutex_init(&zt->_transport._unicast._mutex_rx); if (ret != _Z_RES_OK) { - z_mutex_free(&zt->_transport._unicast._mutex_tx); + _z_mutex_drop(&zt->_transport._unicast._mutex_tx); } } #endif // Z_FEATURE_MULTI_THREAD == 1 // Initialize the read and write buffers if (ret == _Z_RES_OK) { - uint16_t mtu = (zl->_mtu < Z_BATCH_UNICAST_SIZE) ? zl->_mtu : Z_BATCH_UNICAST_SIZE; + uint16_t mtu = (zl->_mtu < param->_batch_size) ? zl->_mtu : param->_batch_size; size_t dbuf_size = 0; - size_t wbuf_size = 0; - size_t zbuf_size = 0; + size_t wbuf_size = mtu; + size_t zbuf_size = param->_batch_size; _Bool expandable = false; - switch (zl->_cap._flow) { - case Z_LINK_CAP_FLOW_STREAM: - // Add stream length field to buffer size - wbuf_size = mtu + _Z_MSG_LEN_ENC_SIZE; - zbuf_size = Z_BATCH_UNICAST_SIZE + _Z_MSG_LEN_ENC_SIZE; - expandable = true; - break; - case Z_LINK_CAP_FLOW_DATAGRAM: - default: - wbuf_size = mtu; - zbuf_size = Z_BATCH_UNICAST_SIZE; - expandable = false; - break; + // 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; @@ -86,8 +75,8 @@ int8_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transpo _Z_ERROR("Not enough memory to allocate transport tx rx buffers!"); #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_free(&zt->_transport._unicast._mutex_tx); - z_mutex_free(&zt->_transport._unicast._mutex_rx); + _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); @@ -115,8 +104,8 @@ int8_t _z_unicast_transport_create(_z_transport_t *zt, _z_link_t *zl, _z_transpo _z_wbuf_clear(&zt->_transport._unicast._dbuf_best_effort); #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_free(&zt->_transport._unicast._mutex_tx); - z_mutex_free(&zt->_transport._unicast._mutex_rx); + _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); @@ -224,8 +213,8 @@ int8_t _z_unicast_open_client(_z_transport_unicast_establish_param_t *param, con // Create the OpenSyn message _z_zint_t lease = Z_TRANSPORT_LEASE; _z_zint_t initial_sn = param->_initial_sn_tx; - _z_bytes_t cookie; - _z_bytes_copy(&cookie, &iam._body._init._cookie); + _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); @@ -290,17 +279,17 @@ void _z_unicast_transport_clear(_z_transport_t *zt) { #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); + _z_task_join(ztu->_read_task); + _z_task_free(&ztu->_read_task); } if (ztu->_lease_task != NULL) { - z_task_join(ztu->_lease_task); - z_task_free(&ztu->_lease_task); + _z_task_join(ztu->_lease_task); + _z_task_free(&ztu->_lease_task); } // Clean up the mutexes - z_mutex_free(&ztu->_mutex_tx); - z_mutex_free(&ztu->_mutex_rx); + _z_mutex_drop(&ztu->_mutex_tx); + _z_mutex_drop(&ztu->_mutex_rx); #endif // Z_FEATURE_MULTI_THREAD == 1 // Clean up the buffers diff --git a/src/transport/unicast/tx.c b/src/transport/unicast/tx.c index 3eb220e56..78c8bb125 100644 --- a/src/transport/unicast/tx.c +++ b/src/transport/unicast/tx.c @@ -12,7 +12,7 @@ // ZettaScale Zenoh Team, // -#include "zenoh-pico/transport/unicast/tx.h" +#include "zenoh-pico/transport/common/tx.h" #include @@ -20,7 +20,7 @@ #include "zenoh-pico/protocol/codec/network.h" #include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/protocol/iobuf.h" -#include "zenoh-pico/transport/common/tx.h" +#include "zenoh-pico/transport/unicast/tx.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -49,7 +49,7 @@ int8_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_mes #if Z_FEATURE_MULTI_THREAD == 1 // Acquire the lock - z_mutex_lock(&ztu->_mutex_tx); + _z_mutex_lock(&ztu->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 // Prepare the buffer eventually reserving space for the message length @@ -68,7 +68,7 @@ int8_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_mes } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztu->_mutex_tx); + _z_mutex_unlock(&ztu->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 return ret; @@ -85,11 +85,11 @@ int8_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg _Bool drop = false; if (cong_ctrl == Z_CONGESTION_CONTROL_BLOCK) { #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_lock(&ztu->_mutex_tx); + _z_mutex_lock(&ztu->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 } else { #if Z_FEATURE_MULTI_THREAD == 1 - int8_t locked = z_mutex_trylock(&ztu->_mutex_tx); + int8_t locked = _z_mutex_try_lock(&ztu->_mutex_tx); if (locked != (int8_t)0) { _Z_INFO("Dropping zenoh message because of congestion control"); // We failed to acquire the lock, drop the message @@ -163,7 +163,7 @@ int8_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg } #if Z_FEATURE_MULTI_THREAD == 1 - z_mutex_unlock(&ztu->_mutex_tx); + _z_mutex_unlock(&ztu->_mutex_tx); #endif // Z_FEATURE_MULTI_THREAD == 1 } diff --git a/src/utils/encoding.c b/src/utils/encoding.c index 085511bdf..0fb93f978 100644 --- a/src/utils/encoding.c +++ b/src/utils/encoding.c @@ -51,7 +51,7 @@ size_t _z_cobs_decode(const uint8_t *input, size_t input_len, uint8_t *output) { uint8_t *pos = output; uint8_t code = (uint8_t)0xFF; - const uint8_t *input_end_ptr = _z_cptr_u8_offset(input, input_len); + const uint8_t *input_end_ptr = _z_cptr_u8_offset(input, (ptrdiff_t)input_len); for (uint8_t block = (uint8_t)0x00; byte < input_end_ptr; block--) { if (block != (uint8_t)0x00) { *pos = *byte; diff --git a/src/utils/endianness.c b/src/utils/endianness.c new file mode 100644 index 000000000..46be4a7c2 --- /dev/null +++ b/src/utils/endianness.c @@ -0,0 +1,134 @@ +// +// Copyright (c) 2024 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/utils/endianness.h" + +#if !defined(ZENOH_ENDIANNNESS_BIG) && !defined(ZENOH_ENDIANNNESS_LITTLE) +// Gcc/clang test +#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define ZENOH_ENDIANNNESS_BIG +#else +#define ZENOH_ENDIANNNESS_LITTLE +#endif +#endif + +// *** Little endian *** +uint16_t _z_le_load16(const uint8_t *src) { return (uint16_t)(src[0] << 0) | (uint16_t)(src[1] << 8); } + +uint32_t _z_le_load32(const uint8_t *src) { + return ((uint32_t)src[0] << 0) | ((uint32_t)src[1] << 8) | ((uint32_t)src[2] << 16) | ((uint32_t)src[3] << 24); +} + +uint64_t _z_le_load64(const uint8_t *src) { + return ((uint64_t)src[0] << 0) | ((uint64_t)src[1] << 8) | ((uint64_t)src[2] << 16) | ((uint64_t)src[3] << 24) | + ((uint64_t)src[4] << 32) | ((uint64_t)src[5] << 40) | ((uint64_t)src[6] << 48) | ((uint64_t)src[7] << 56); +} + +#define _Z_LE_STORE_IMPL(SIZE) \ + size_t _z_le_store##SIZE(uint##SIZE##_t val, uint8_t *dst) { \ + size_t len = 1; \ + for (size_t i = 0; i < sizeof(val); ++i) { \ + if (val != 0) { \ + len = i + 1; \ + } \ + dst[i] = (uint8_t)val; \ + val = val >> 8; \ + } \ + return len; \ + } + +_Z_LE_STORE_IMPL(16) +_Z_LE_STORE_IMPL(32) +_Z_LE_STORE_IMPL(64) + +// *** Big endian *** +uint16_t _z_be_load16(const uint8_t *src) { return (uint16_t)(src[0] << 8) | (uint16_t)(src[1] << 0); } + +uint32_t _z_be_load32(const uint8_t *src) { + return ((uint32_t)src[0] << 24) | ((uint32_t)src[1] << 16) | ((uint32_t)src[2] << 8) | ((uint32_t)src[3] << 0); +} + +uint64_t _z_be_load64(const uint8_t *src) { + return ((uint64_t)src[0] << 56) | ((uint64_t)src[1] << 48) | ((uint64_t)src[2] << 40) | ((uint64_t)src[3] << 32) | + ((uint64_t)src[4] << 24) | ((uint64_t)src[5] << 16) | ((uint64_t)src[6] << 8) | ((uint64_t)src[7] << 0); +} + +#define _Z_BE_STORE_IMPL(SIZE) \ + size_t _z_be_store##SIZE(uint##SIZE##_t val, uint8_t *dst) { \ + size_t len = 1; \ + for (size_t i = 0; i < sizeof(val); ++i) { \ + if (val != 0) { \ + len = i + 1; \ + } \ + dst[sizeof(val) - 1 - i] = (uint8_t)val; \ + val = val >> 8; \ + } \ + return len; \ + } + +_Z_BE_STORE_IMPL(16) +_Z_BE_STORE_IMPL(32) +_Z_BE_STORE_IMPL(64) + +// *** Host *** +uint16_t _z_host_le_load16(const uint8_t *src) { +#if defined(ZENOH_ENDIANNNESS_BIG) + return _z_be_load16(src); +#elif defined(ZENOH_ENDIANNNESS_LITTLE) + return _z_le_load16(src); +#endif +} + +uint32_t _z_host_le_load32(const uint8_t *src) { +#if defined(ZENOH_ENDIANNNESS_BIG) + return _z_be_load32(src); +#elif defined(ZENOH_ENDIANNNESS_LITTLE) + return _z_le_load32(src); +#endif +} + +uint64_t _z_host_le_load64(const uint8_t *src) { +#if defined(ZENOH_ENDIANNNESS_BIG) + return _z_be_load64(src); +#elif defined(ZENOH_ENDIANNNESS_LITTLE) + return _z_le_load64(src); +#endif +} + +size_t _z_host_le_store16(const uint16_t val, uint8_t *dst) { +#if defined(ZENOH_ENDIANNNESS_BIG) + return _z_be_store16(val, dst); +#elif defined(ZENOH_ENDIANNNESS_LITTLE) + return _z_le_store16(val, dst); +#endif +} +size_t _z_host_le_store32(const uint32_t val, uint8_t *dst) { +#if defined(ZENOH_ENDIANNNESS_BIG) + return _z_be_store32(val, dst); +#elif defined(ZENOH_ENDIANNNESS_LITTLE) + return _z_le_store32(val, dst); +#endif +} + +size_t _z_host_le_store64(const uint64_t val, uint8_t *dst) { +#if defined(ZENOH_ENDIANNNESS_BIG) + return _z_be_store64(val, dst); +#elif defined(ZENOH_ENDIANNNESS_LITTLE) + return _z_le_store64(val, dst); +#endif +} + +uint8_t _z_get_u16_lsb(uint_fast16_t val) { return (uint8_t)(val >> 0); } + +uint8_t _z_get_u16_msb(uint_fast16_t val) { return (uint8_t)(val >> 8); } diff --git a/src/utils/pointers.c b/src/utils/pointers.c index 2e1bd4b08..77c05628f 100644 --- a/src/utils/pointers.c +++ b/src/utils/pointers.c @@ -14,13 +14,13 @@ #include "zenoh-pico/utils/pointers.h" -size_t _z_ptr_u8_diff(const uint8_t *l_ptr, const uint8_t *r_ptr) { return l_ptr - r_ptr; } +size_t _z_ptr_u8_diff(const uint8_t *l_ptr, const uint8_t *r_ptr) { return (size_t)(l_ptr - r_ptr); } const uint8_t *_z_cptr_u8_offset(const uint8_t *ptr, const ptrdiff_t off) { return ptr + off; } uint8_t *_z_ptr_u8_offset(uint8_t *ptr, const ptrdiff_t off) { return ptr + off; } -size_t _z_ptr_char_diff(const char *l_ptr, const char *r_ptr) { return l_ptr - r_ptr; } +size_t _z_ptr_char_diff(const char *l_ptr, const char *r_ptr) { return (size_t)(l_ptr - r_ptr); } const char *_z_cptr_char_offset(const char *ptr, const ptrdiff_t off) { return ptr + off; } diff --git a/src/utils/string.c b/src/utils/string.c index e95e3ab07..512ae2310 100644 --- a/src/utils/string.c +++ b/src/utils/string.c @@ -26,7 +26,7 @@ char const *_z_rstrstr(char const *haystack_start, char const *haystack_end, con char const *he = haystack_end; const char *needle_end = strchr(needle_start, 0); - hs = _z_cptr_char_offset(hs, _z_ptr_char_diff(needle_end, needle_start)); + hs = _z_cptr_char_offset(hs, (ptrdiff_t)_z_ptr_char_diff(needle_end, needle_start)); char const *result = NULL; while ((result == false) && (he >= hs)) { char found = 1; @@ -50,7 +50,7 @@ char const *_z_rstrstr(char const *haystack_start, char const *haystack_end, con } char const *_z_bstrstr(_z_str_se_t haystack, _z_str_se_t needle) { - haystack.end = _z_cptr_char_offset(haystack.end, -1 * _z_ptr_char_diff(needle.end, needle.start)); + haystack.end = _z_cptr_char_offset(haystack.end, -1 * (ptrdiff_t)_z_ptr_char_diff(needle.end, needle.start)); char const *result = NULL; for (; (result == false) && (haystack.start <= haystack.end); haystack.start = _z_cptr_char_offset(haystack.start, 1)) { @@ -86,7 +86,7 @@ char const *_z_strstr_skipneedle(char const *haystack_start, char const *haystac char const *_z_bstrstr_skipneedle(_z_str_se_t haystack, _z_str_se_t needle) { char const *result = _z_bstrstr(haystack, needle); if (result != NULL) { - result = _z_cptr_char_offset(result, _z_ptr_char_diff(needle.end, needle.start)); + result = _z_cptr_char_offset(result, (ptrdiff_t)_z_ptr_char_diff(needle.end, needle.start)); } return result; } @@ -102,7 +102,7 @@ _z_str_se_t _z_splitstr_next(_z_splitstr_t *str) { if (result.end == str->s.end) { str->s = (_z_str_se_t){.start = NULL, .end = NULL}; } else { - str->s.start = _z_cptr_char_offset(result.end, strlen(str->delimiter)); + str->s.start = _z_cptr_char_offset(result.end, (ptrdiff_t)strlen(str->delimiter)); } } return result; @@ -122,7 +122,7 @@ _z_str_se_t _z_splitstr_nextback(_z_splitstr_t *str) { if (result.start == str->s.start) { str->s = (_z_str_se_t){.start = NULL, .end = NULL}; } else { - str->s.end = _z_cptr_char_offset(result.start, -1 * strlen(str->delimiter)); + str->s.end = _z_cptr_char_offset(result.start, -1 * (ptrdiff_t)strlen(str->delimiter)); } } return result; diff --git a/tests/attachment.py b/tests/attachment.py new file mode 100644 index 000000000..05c97c613 --- /dev/null +++ b/tests/attachment.py @@ -0,0 +1,252 @@ +import argparse +import os +from signal import SIGINT +import subprocess +import sys +import time +import re + +# Specify the directory for the binaries +DIR_EXAMPLES = "build/examples" + + +def pub_and_sub(): + print("*** Pub & sub test ***") + test_status = 0 + + # Expected z_pub output & status + z_pub_expected_status = 0 + z_pub_expected_output = '''Opening session... +Declaring publisher for 'demo/example/zenoh-pico-pub'... +Press CTRL-C to quit... +Putting Data ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 1] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 2] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 3] Pub from Pico!')... +Putting Data ('demo/example/zenoh-pico-pub': '[ 4] Pub from Pico!')...''' + + # Expected z_sub output & status + z_sub_expected_status = 0 + z_sub_expected_output = '''Opening session... +Declaring Subscriber on 'demo/example/**'... +Press CTRL-C to quit... +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!') + with encoding: zenoh/string;utf8 + with timestamp: + with attachment: + 0: source, C + 1: index, 0 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 1] Pub from Pico!') + with encoding: zenoh/string;utf8 + with timestamp: + with attachment: + 0: source, C + 1: index, 1 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 2] Pub from Pico!') + with encoding: zenoh/string;utf8 + with timestamp: + with attachment: + 0: source, C + 1: index, 2 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 3] Pub from Pico!') + with encoding: zenoh/string;utf8 + with timestamp: + with attachment: + 0: source, C + 1: index, 3 +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 4] Pub from Pico!') + with encoding: zenoh/string;utf8 + with timestamp: + with attachment: + 0: source, C + 1: index, 4''' + + print("Start subscriber") + # Start z_sub in the background + z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub_attachment -n 5" + + z_sub_process = subprocess.Popen( + z_sub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + + # Introduce a delay to ensure z_sub starts + time.sleep(2) + + print("Start publisher") + # Start z_pub + z_pub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_pub_attachment -n 5" + z_pub_process = subprocess.Popen( + z_pub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + + # Wait for z_pub to finish + z_pub_process.wait() + + print("Stop subscriber") + time.sleep(2) + if z_sub_process.poll() is None: + # send SIGINT to group + z_sub_process_gid = os.getpgid(z_sub_process.pid) + os.killpg(z_sub_process_gid, SIGINT) + + # Wait for z_sub to finish + z_sub_process.wait() + + print("Check publisher status & output") + # Check the exit status of z_pub + z_pub_status = z_pub_process.returncode + if z_pub_status == z_pub_expected_status: + print("z_pub status valid") + else: + print(f"z_pub status invalid, expected: {z_pub_expected_status}, received: {z_pub_status}") + test_status = 1 + + # Check output of z_pub + z_pub_output = z_pub_process.stdout.read() + if z_pub_expected_output in z_pub_output: + print("z_pub output valid") + else: + print("z_pub output invalid:") + print(f"Expected: \"{z_pub_expected_output}\"") + print(f"Received: \"{z_pub_output}\"") + test_status = 1 + + 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: + print("z_sub status valid") + else: + print(f"z_sub status invalid, expected: {z_sub_expected_status}, received: {z_sub_status}") + test_status = 1 + + # Check output of z_sub + z_sub_output = re.sub(r' with timestamp: \d+\n', ' with timestamp: \n', z_sub_process.stdout.read()) + if z_sub_expected_output in z_sub_output: + print("z_sub output valid") + else: + print("z_sub output invalid:") + print(f"Expected: \"{z_sub_expected_output}\"") + print(f"Received: \"{z_sub_output}\"") + test_status = 1 + # Return value + return test_status + + +def query_and_queryable(): + print("*** Query & queryable test ***") + test_status = 0 + + # Expected z_query output & status + + z_query_expected_status = 0 + z_query_expected_output = """Opening session... +Sending Query 'demo/example/**'... +>> Received ('demo/example/**': 'Queryable from Pico!') + with encoding: zenoh/string;utf8 + with attachment: + 0: reply_key, reply_value +>> Received query final notification""" + + # Expected z_queryable output & status + z_queryable_expected_status = 0 + 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/**' + with encoding: zenoh/string;utf8 + with attachment: + 0: test_key, test_value""" + + print("Start queryable") + # Start z_queryable in the background + z_queryable_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_queryable_attachment -n 1" + z_queryable_process = subprocess.Popen( + z_queryable_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + + # Introduce a delay to ensure z_queryable starts + time.sleep(2) + + print("Start query") + # Start z_query + z_query_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_get_attachment" + z_query_process = subprocess.Popen( + z_query_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + + # Wait for z_query to finish + z_query_process.wait() + + print("Stop queryable") + time.sleep(2) + if z_queryable_process.poll() is None: + # send SIGINT to group + z_quaryable_process_gid = os.getpgid(z_queryable_process.pid) + os.killpg(z_quaryable_process_gid, SIGINT) + + # Wait for z_queryable to finish + z_queryable_process.wait() + + print("Check query status & output") + # Check the exit status of z_query + z_query_status = z_query_process.returncode + if z_query_status == z_query_expected_status: + print("z_query status valid") + else: + print(f"z_query status invalid, expected: {z_query_expected_status}," f" received: {z_query_status}") + test_status = 1 + + # Check output of z_query + z_query_output = z_query_process.stdout.read() + if z_query_expected_output in z_query_output: + print("z_query output valid") + else: + print("z_query output invalid:") + print(f'Expected: "{z_query_expected_output}"') + print(f'Received: "{z_query_output}"') + test_status = 1 + + 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: + print("z_queryable status valid") + else: + print(f"z_queryable status invalid, expected: {z_queryable_expected_status}," f" received: {z_queryable_status}") + test_status = 1 + + # Check output of z_queryable + z_queryable_output = z_queryable_process.stdout.read() + if z_queryable_expected_output in z_queryable_output: + print("z_queryable output valid") + else: + print("z_queryable output invalid:") + print(f'Expected: "{z_queryable_expected_output}"') + print(f'Received: "{z_queryable_output}"') + test_status = 1 + # Return status + return test_status + + +if __name__ == "__main__": + EXIT_STATUS = 0 + + # Test pub and sub examples + if pub_and_sub() == 1: + EXIT_STATUS = 1 + # Test query and queryable examples + if query_and_queryable() == 1: + EXIT_STATUS = 1 + # Exit + sys.exit(EXIT_STATUS) diff --git a/tests/modularity.py b/tests/modularity.py index 000b6b90a..7350ae70a 100644 --- a/tests/modularity.py +++ b/tests/modularity.py @@ -4,10 +4,23 @@ import subprocess import sys import time +import difflib # Specify the directory for the binaries DIR_EXAMPLES = "build/examples" + +def print_string_diff(str_a, str_b): + for i, s in enumerate(difflib.ndiff(str_a, str_b)): + if s[0] == " ": + continue + elif s[0] == "-": + print('Delete "{}" from position {}'.format(s[-1], i)) + elif s[0] == "+": + print('Add "{}" to position {}'.format(s[-1], i)) + print() + + def pub_and_sub(args): print("*** Pub & sub test ***") test_status = 0 @@ -15,7 +28,7 @@ def pub_and_sub(args): # Expected z_pub output & status if args.pub == 1: z_pub_expected_status = 0 - z_pub_expected_output = '''Opening session... + z_pub_expected_output = """Opening session... Declaring publisher for 'demo/example/zenoh-pico-pub'... Press CTRL-C to quit... Putting Data ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!')... @@ -27,17 +40,16 @@ def pub_and_sub(args): Putting Data ('demo/example/zenoh-pico-pub': '[ 6] Pub from Pico!')... Putting Data ('demo/example/zenoh-pico-pub': '[ 7] Pub from Pico!')... Putting Data ('demo/example/zenoh-pico-pub': '[ 8] Pub from Pico!')... -Putting Data ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')...''' - else : +Putting Data ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')...""" + else: z_pub_expected_status = 254 - z_pub_expected_output = ("ERROR: Zenoh pico was compiled without " - "Z_FEATURE_PUBLICATION but this example requires it.") + z_pub_expected_output = "ERROR: Zenoh pico was compiled without " "Z_FEATURE_PUBLICATION but this example requires it." # Expected z_sub output & status if args.sub == 1: z_sub_expected_status = -2 if args.pub == 1: - z_sub_expected_output = '''Opening session... + z_sub_expected_output = """Opening session... Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit... >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!') @@ -49,26 +61,27 @@ def pub_and_sub(args): >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 6] Pub from Pico!') >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 7] Pub from Pico!') >> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 8] Pub from Pico!') ->> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')''' +>> [Subscriber] Received ('demo/example/zenoh-pico-pub': '[ 9] Pub from Pico!')""" else: - z_sub_expected_output = '''Opening session... + z_sub_expected_output = """Opening session... Declaring Subscriber on 'demo/example/**'... -Press CTRL-C to quit...''' - else : +Press CTRL-C to quit...""" + else: z_sub_expected_status = 254 - z_sub_expected_output = ("ERROR: Zenoh pico was compiled without " - "Z_FEATURE_SUBSCRIPTION but this example requires it.") + 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_process = subprocess.Popen(z_sub_command, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - start_new_session=True, - text=True) + z_sub_process = subprocess.Popen( + z_sub_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + start_new_session=True, + text=True, + ) # Introduce a delay to ensure z_sub starts time.sleep(2) @@ -76,12 +89,14 @@ def pub_and_sub(args): print("Start publisher") # Start z_pub z_pub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_pub -n 10" - z_pub_process = subprocess.Popen(z_pub_command, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True) + z_pub_process = subprocess.Popen( + z_pub_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) # Wait for z_pub to finish z_pub_process.wait() @@ -110,8 +125,8 @@ def pub_and_sub(args): print("z_pub output valid") else: print("z_pub output invalid:") - print(f"Expected: \"{z_pub_expected_output}\"") - print(f"Received: \"{z_pub_output}\"") + print(f'Expected: "{z_pub_expected_output}"') + print(f'Received: "{z_pub_output}"') test_status = 1 print("Check subscriber status & output") @@ -129,12 +144,13 @@ def pub_and_sub(args): print("z_sub output valid") else: print("z_sub output invalid:") - print(f"Expected: \"{z_sub_expected_output}\"") - print(f"Received: \"{z_sub_output}\"") + print(f'Expected: "{z_sub_expected_output}"') + print(f'Received: "{z_sub_output}"') test_status = 1 # Return value return test_status + def query_and_queryable(args): print("*** Query & queryable test ***") test_status = 0 @@ -143,46 +159,49 @@ def query_and_queryable(args): if args.query == 1: z_query_expected_status = 0 if args.queryable == 1: - z_query_expected_output = '''Opening session... + z_query_expected_output = """Opening session... Sending Query 'demo/example/**'... ->> Received ('demo/example/zenoh-pico-queryable': 'Queryable from Pico!') ->> Received query final notification''' +>> Received PUT ('demo/example/**': 'Queryable from Pico!') +>> Received query final notification""" else: - z_query_expected_output = '''Opening session... + z_query_expected_output = """Opening session... Sending Query 'demo/example/**'... ->> Received query final notification''' - else : +>> Received query final notification""" + else: z_query_expected_status = 254 - z_query_expected_output = ("ERROR: Zenoh pico was compiled without " - "Z_FEATURE_QUERY or Z_FEATURE_MULTI_THREAD but this example requires them.") + z_query_expected_output = ( + "ERROR: Zenoh pico was compiled without " "Z_FEATURE_QUERY or Z_FEATURE_MULTI_THREAD but this example requires them." + ) # Expected z_queryable output & status if args.queryable == 1: z_queryable_expected_status = -2 if args.query == 1: - z_queryable_expected_output = '''Opening session... + 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/**?''' + >> [Queryable handler] Received Query 'demo/example/**' +""" else: - z_queryable_expected_output = '''Opening session... + z_queryable_expected_output = """Opening session... Creating Queryable on 'demo/example/zenoh-pico-queryable'... -Press CTRL-C to quit...''' - else : +Press CTRL-C to quit...""" + else: z_queryable_expected_status = 254 - z_queryable_expected_output = ("ERROR: Zenoh pico was compiled without " - "Z_FEATURE_QUERYABLE but this example requires it.") + 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_process = subprocess.Popen(z_queryable_command, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - start_new_session=True, - text=True) + z_queryable_process = subprocess.Popen( + z_queryable_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + start_new_session=True, + text=True, + ) # Introduce a delay to ensure z_queryable starts time.sleep(2) @@ -190,12 +209,14 @@ def query_and_queryable(args): print("Start query") # Start z_query z_query_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_get" - z_query_process = subprocess.Popen(z_query_command, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True) + z_query_process = subprocess.Popen( + z_query_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) # Wait for z_query to finish z_query_process.wait() @@ -215,8 +236,7 @@ def query_and_queryable(args): if z_query_status == z_query_expected_status: print("z_query status valid") else: - print(f"z_query status invalid, expected: {z_query_expected_status}," - f" received: {z_query_status}") + print(f"z_query status invalid, expected: {z_query_expected_status}," f" received: {z_query_status}") test_status = 1 # Check output of z_query @@ -225,8 +245,8 @@ def query_and_queryable(args): print("z_query output valid") else: print("z_query output invalid:") - print(f"Expected: \"{z_query_expected_output}\"") - print(f"Received: \"{z_query_output}\"") + print(f'Expected: "{z_query_expected_output}"') + print(f'Received: "{z_query_output}"') test_status = 1 print("Check queryable status & output") @@ -235,8 +255,7 @@ def query_and_queryable(args): if z_queryable_status == 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}") + print(f"z_queryable status invalid, expected: {z_queryable_expected_status}," f" received: {z_queryable_status}") test_status = 1 # Check output of z_queryable @@ -245,25 +264,25 @@ def query_and_queryable(args): print("z_queryable output valid") else: print("z_queryable output invalid:") - print(f"Expected: \"{z_queryable_expected_output}\"") - print(f"Received: \"{z_queryable_output}\"") + print(f'Expected: "{z_queryable_expected_output}"') + print(f'Received: "{z_queryable_output}"') + print_string_diff(z_queryable_expected_output, z_queryable_output) test_status = 1 # Return status return test_status + if __name__ == "__main__": - parser = argparse.ArgumentParser(description="This script runs zenoh-pico examples" - " and checks them according to the given configuration") + parser = argparse.ArgumentParser( + description="This script runs zenoh-pico examples" " and checks them according to the given configuration" + ) parser.add_argument("--pub", type=int, choices=[0, 1], help="Z_FEATURE_PUBLICATION (0 or 1)") parser.add_argument("--sub", type=int, choices=[0, 1], help="Z_FEATURE_SUBSCRIPTION (0 or 1)") - parser.add_argument("--queryable", type=int, choices=[0, 1], - help="Z_FEATURE_QUERYABLE (0 or 1)") + parser.add_argument("--queryable", type=int, choices=[0, 1], help="Z_FEATURE_QUERYABLE (0 or 1)") parser.add_argument("--query", type=int, choices=[0, 1], help="Z_FEATURE_QUERY (0 or 1)") - EXIT_STATUS = 0 prog_args = parser.parse_args() - print(f"Args value, pub:{prog_args.pub}, sub:{prog_args.sub}, " - f"queryable:{prog_args.queryable}, query:{prog_args.query}") + print(f"Args value, pub:{prog_args.pub}, sub:{prog_args.sub}, " f"queryable:{prog_args.queryable}, query:{prog_args.query}") # Test pub and sub examples if pub_and_sub(prog_args) == 1: diff --git a/tests/no_router.py b/tests/no_router.py new file mode 100644 index 000000000..0e1d2c5a5 --- /dev/null +++ b/tests/no_router.py @@ -0,0 +1,155 @@ +import argparse +import os +from signal import SIGINT +import subprocess +import sys +import time + +# Specify the directory for the binaries +DIR_EXAMPLES = "build/examples" + + +def test_all(): + print("*** Pub & sub test ***") + test_status = 0 + + # Expected output & status + z_expected_status = 255 + z_expected_output = '''Opening session... +Unable to open session!''' + + print("Start subscriber") + # Start z_sub + z_sub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub" + z_sub_process = subprocess.Popen( + z_sub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + # Wait for z_sub to finish + z_sub_process.wait() + + print("Start publisher") + # Start z_pub + z_pub_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_pub" + z_pub_process = subprocess.Popen( + z_pub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True + ) + # Wait for z_pub to finish + z_pub_process.wait() + + print("Start queryable") + # Start z_queryable + z_queryable_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_queryable" + z_queryable_process = subprocess.Popen( + z_queryable_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + # Wait for z_queryable to finish + z_queryable_process.wait() + + print("Start query") + # Start z_query + z_query_command = f"stdbuf -oL -eL ./{DIR_EXAMPLES}/z_get" + z_query_process = subprocess.Popen( + z_query_command, + shell=True, + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + ) + # Wait for z_query to finish + z_query_process.wait() + + print("Check publisher status & output") + # Check the exit status of z_pub + z_pub_status = z_pub_process.returncode + if z_pub_status == z_expected_status: + print("z_pub status valid") + else: + print(f"z_pub status invalid, expected: {z_expected_status}, received: {z_pub_status}") + test_status = 1 + + # Check output of z_pub + z_pub_output = z_pub_process.stdout.read() + if z_expected_output in z_pub_output: + print("z_pub output valid") + else: + print("z_pub output invalid:") + print(f"Expected: \"{z_expected_output}\"") + print(f"Received: \"{z_pub_output}\"") + test_status = 1 + + print("Check subscriber status & output") + # Check the exit status of z_sub + z_sub_status = z_sub_process.returncode + if z_sub_status == z_expected_status: + print("z_sub status valid") + else: + print(f"z_sub status invalid, expected: {z_expected_status}, received: {z_sub_status}") + test_status = 1 + + # Check output of z_sub + z_sub_output = z_sub_process.stdout.read() + if z_expected_output in z_sub_output: + print("z_sub output valid") + else: + print("z_sub output invalid:") + print(f"Expected: \"{z_expected_output}\"") + print(f"Received: \"{z_sub_output}\"") + test_status = 1 + + print("Check query status & output") + # Check the exit status of z_query + z_query_status = z_query_process.returncode + if z_query_status == z_expected_status: + print("z_query status valid") + else: + print(f"z_query status invalid, expected: {z_expected_status}," f" received: {z_query_status}") + test_status = 1 + + # Check output of z_query + z_query_output = z_query_process.stdout.read() + if z_expected_output in z_query_output: + print("z_query output valid") + else: + print("z_query output invalid:") + print(f'Expected: "{z_expected_output}"') + print(f'Received: "{z_query_output}"') + test_status = 1 + + print("Check queryable status & output") + # Check the exit status of z_queryable + z_queryable_status = z_queryable_process.returncode + if z_queryable_status == z_expected_status: + print("z_queryable status valid") + else: + print(f"z_queryable status invalid, expected: {z_expected_status}," f" received: {z_queryable_status}") + test_status = 1 + + # Check output of z_queryable + z_queryable_output = z_queryable_process.stdout.read() + if z_expected_output in z_queryable_output: + print("z_queryable output valid") + else: + print("z_queryable output invalid:") + print(f'Expected: "{z_expected_output}"') + print(f'Received: "{z_queryable_output}"') + test_status = 1 + + # Return value + return test_status + + +if __name__ == "__main__": + EXIT_STATUS = 0 + + # Test all examples + if test_all() == 1: + EXIT_STATUS = 1 + + # Exit + sys.exit(EXIT_STATUS) diff --git a/tests/raweth.py b/tests/raweth.py index 930b20908..c70231c2d 100644 --- a/tests/raweth.py +++ b/tests/raweth.py @@ -16,6 +16,7 @@ def pub_and_sub(args): if args.reth == 1: z_pub_expected_status = 0 z_pub_expected_output = '''Opening session... +Waiting for joins... Declaring publisher for 'demo/example/zenoh-pico-pub'... Press CTRL-C to quit... Putting Data ('demo/example/zenoh-pico-pub': '[ 0] Pub from Pico!')... @@ -35,7 +36,7 @@ def pub_and_sub(args): # Expected z_sub output & status if args.reth == 1: - z_sub_expected_status = -2 + z_sub_expected_status = 0 z_sub_expected_output = '''Opening session... Declaring Subscriber on 'demo/example/**'... Press CTRL-C to quit... @@ -56,13 +57,14 @@ def pub_and_sub(args): print("Start subscriber") # Start z_sub in the background - z_sub_command = f"sudo stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub -m \"peer\" -l \"reth/0\"s" + z_sub_command = f"sudo stdbuf -oL -eL ./{DIR_EXAMPLES}/z_sub -n 10 -m \"peer\" -l \ + \"reth/30:03:8c:c8:00:a2#iface=lo;whitelist=30:03:8c:c8:00:a1,\"s" + z_sub_process = subprocess.Popen(z_sub_command, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, - start_new_session=True, text=True) # Introduce a delay to ensure z_sub starts @@ -70,7 +72,8 @@ def pub_and_sub(args): print("Start publisher") # Start z_pub - z_pub_command = f"sudo stdbuf -oL -eL ./{DIR_EXAMPLES}/z_pub -n 10 -m \"peer\" -l \"reth/0\"s" + z_pub_command = f"sudo stdbuf -oL -eL ./{DIR_EXAMPLES}/z_pub -n 10 -m \"peer\" -l \ + \"reth/30:03:8c:c8:00:a1#iface=lo;whitelist=30:03:8c:c8:00:a2,\"s" z_pub_process = subprocess.Popen(z_pub_command, shell=True, stdin=subprocess.PIPE, @@ -82,6 +85,7 @@ def pub_and_sub(args): z_pub_process.wait() print("Stop subscriber") + time.sleep(2) if z_sub_process.poll() is None: # send SIGINT to group z_sub_process_gid = os.getpgid(z_sub_process.pid) diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index dd0be80da..c90a27238 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -19,9 +19,9 @@ #undef NDEBUG #include +#define URI "demo/example/**/*" #if defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__) #include -#define sleep(x) Sleep(x * 1000) #else #include #endif @@ -52,72 +52,73 @@ void zid_handler(const z_id_t *id, void *arg) { } volatile unsigned int hellos = 0; -void hello_handler(z_owned_hello_t *hello, void *arg) { +void hello_handler(const z_loaned_hello_t *hello, void *arg) { + (void)hello; (void)(arg); printf("%s\n", __func__); hellos++; - z_hello_null(); - z_drop(hello); // validate double-drop safety: caller drops hello if it's not dropped by the handler } volatile unsigned int queries = 0; -void query_handler(const z_query_t *query, void *arg) { +void query_handler(const z_loaned_query_t *query, void *arg) { printf("%s\n", __func__); queries++; - z_owned_str_t k_str = z_keyexpr_to_string(z_query_keyexpr(query)); -#ifdef ZENOH_PICO - if (z_check(k_str) == false) { - k_str = zp_keyexpr_resolve(*(z_session_t *)arg, z_query_keyexpr(query)); - } -#endif + const z_loaned_keyexpr_t *query_ke = z_query_keyexpr(query); + z_view_string_t k_str; + z_keyexpr_as_view_string(query_ke, &k_str); + (void)arg; + assert(!z_view_string_is_empty(&k_str)); - z_bytes_t pred = z_query_parameters(query); + z_view_string_t pred; + z_query_parameters(query, &pred); (void)(pred); - z_value_t payload_value = z_query_value(query); - (void)(payload_value); - z_query_reply_options_t _ret_qreply_opt = z_query_reply_options_default(); - z_query_reply(query, z_keyexpr(z_loan(k_str)), (const uint8_t *)value, strlen(value), &_ret_qreply_opt); + const z_loaned_bytes_t *payload = z_query_payload(query); + (void)(payload); + z_query_reply_options_t _ret_qreply_opt; + z_query_reply_options_default(&_ret_qreply_opt); + + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_from_static_str(&reply_payload, value); - z_drop(z_move(k_str)); + z_query_reply(query, query_ke, z_move(reply_payload), &_ret_qreply_opt); } volatile unsigned int replies = 0; -void reply_handler(z_owned_reply_t *reply, void *arg) { +void reply_handler(const z_loaned_reply_t *reply, void *arg) { printf("%s\n", __func__); replies++; + (void)arg; if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); + const z_loaned_sample_t *sample = z_reply_ok(reply); - z_owned_str_t k_str = z_keyexpr_to_string(sample.keyexpr); -#ifdef ZENOH_PICO - if (z_check(k_str) == false) { - k_str = zp_keyexpr_resolve(*(z_session_t *)arg, sample.keyexpr); - } -#endif - z_drop(z_move(k_str)); + z_view_string_t k_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &k_str); + (void)arg; + assert(!z_view_string_is_empty(&k_str)); } else { - z_value_t _ret_zvalue = z_reply_err(reply); - (void)(_ret_zvalue); + const z_loaned_reply_err_t *_ret_zerr = z_reply_err(reply); + (void)(_ret_zerr); } - - z_reply_null(); // Does nothing. Just to test compilation - z_drop(reply); // validate double-drop safety: caller drops reply if it's not dropped by the handler } volatile unsigned int datas = 0; -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { printf("%s\n", __func__); datas++; - z_owned_str_t k_str = z_keyexpr_to_string(sample->keyexpr); -#ifdef ZENOH_PICO - if (z_check(k_str) == false) { - k_str = zp_keyexpr_resolve(*(z_session_t *)arg, sample->keyexpr); - } -#endif - z_drop(z_move(k_str)); + z_view_string_t k_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &k_str); + (void)arg; + assert(!z_view_string_is_empty(&k_str)); + const char *encoding_expected = + z_sample_kind(sample) == Z_SAMPLE_KIND_PUT ? "zenoh/bytes;test_encoding" : "zenoh/bytes"; + z_owned_string_t encoding; + z_encoding_to_string(z_sample_encoding(sample), &encoding); + printf("%s\n", z_string_data(z_loan(encoding))); + assert(strncmp(encoding_expected, z_string_data(z_loan(encoding)), strlen(encoding_expected)) == 0); } int main(int argc, char **argv) { @@ -127,100 +128,76 @@ int main(int argc, char **argv) { #ifdef ZENOH_C zc_init_logger(); + const char *encoding_expected = + z_sample_kind(sample) == Z_SAMPLE_KIND_PUT ? "zenoh/bytes" : "zenoh/bytes;test_encoding"; + z_pu #endif - printf("Testing Keyexpr..."); - z_keyexpr_t key = z_keyexpr("demo/example"); - _Bool _ret_bool = z_keyexpr_is_initialized(&key); - assert_eq(_ret_bool, true); - - int8_t _ret_int8 = z_keyexpr_includes(z_keyexpr("demo/example/**"), z_keyexpr("demo/example/a")); - assert_eq(_ret_int8, 0); -#ifdef ZENOH_PICO - _ret_int8 = zp_keyexpr_includes_null_terminated("demo/example/**", "demo/example/a"); - assert_eq(_ret_int8, 0); -#endif - _ret_int8 = z_keyexpr_intersects(z_keyexpr("demo/example/**"), z_keyexpr("demo/example/a")); - assert_eq(_ret_int8, 0); -#ifdef ZENOH_PICO - _ret_int8 = zp_keyexpr_intersect_null_terminated("demo/example/**", "demo/example/a"); - assert_eq(_ret_int8, 0); -#endif - _ret_int8 = z_keyexpr_equals(z_keyexpr("demo/example/**"), z_keyexpr("demo/example")); - assert_eq(_ret_int8, -1); -#ifdef ZENOH_PICO - _ret_int8 = zp_keyexpr_equals_null_terminated("demo/example/**", "demo/example"); - assert_eq(_ret_int8, -1); -#endif - - sleep(SLEEP); + 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/**"); + + _Bool _ret_bool = z_keyexpr_includes(z_loan(key_demo_example_starstar), z_loan(key_demo_example_a)); + assert(_ret_bool); + _ret_bool = z_keyexpr_intersects(z_loan(key_demo_example_starstar), z_loan(key_demo_example_a)); + assert(_ret_bool); + _ret_bool = z_keyexpr_equals(z_loan(key_demo_example_starstar), z_loan(key_demo_example)); + assert(!_ret_bool); + z_sleep_s(SLEEP); - size_t keyexpr_len = strlen("demo/example/**/*"); - char *keyexpr_str = (char *)malloc(keyexpr_len + 1); - memcpy(keyexpr_str, "demo/example/**/*", keyexpr_len); + size_t keyexpr_len = strlen(URI); + char *keyexpr_str = (char *)z_malloc(keyexpr_len + 1); + memcpy(keyexpr_str, URI, keyexpr_len); keyexpr_str[keyexpr_len] = '\0'; - _ret_int8 = z_keyexpr_is_canon(keyexpr_str, keyexpr_len); + int8_t _ret_int8 = z_keyexpr_is_canon(keyexpr_str, keyexpr_len); assert(_ret_int8 < 0); -#ifdef ZENOH_PICO - _ret_int8 = zp_keyexpr_is_canon_null_terminated(keyexpr_str); - assert(_ret_int8 < 0); -#endif _ret_int8 = z_keyexpr_canonize(keyexpr_str, &keyexpr_len); assert_eq(_ret_int8, 0); - assert_eq(strlen("demo/example/**/*"), keyexpr_len); -#ifdef ZENOH_PICO - _ret_int8 = zp_keyexpr_canonize_null_terminated(keyexpr_str); - assert_eq(_ret_int8, 0); - assert_eq(strlen("demo/example/**/*"), keyexpr_len); -#endif + assert_eq(strlen(URI), keyexpr_len); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); printf("Testing Configs..."); - z_owned_config_t _ret_config = z_config_new(); - assert(z_check(_ret_config)); + z_owned_config_t _ret_config; + z_config_new(&_ret_config); + assert(!z_internal_check(_ret_config)); // null config corresponds to empty one z_drop(z_move(_ret_config)); - _ret_config = z_config_default(); - assert(z_check(_ret_config)); + z_config_default(&_ret_config); + assert(z_internal_check(_ret_config)); #ifdef ZENOH_PICO - _ret_int8 = zp_config_insert(z_loan(_ret_config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[1])); + _ret_int8 = zp_config_insert(z_loan_mut(_ret_config), Z_CONFIG_CONNECT_KEY, argv[1]); assert_eq(_ret_int8, 0); const char *_ret_cstr = zp_config_get(z_loan(_ret_config), Z_CONFIG_CONNECT_KEY); assert_eq(strlen(_ret_cstr), strlen(argv[1])); assert_eq(strncmp(_ret_cstr, argv[1], strlen(_ret_cstr)), 0); #endif - z_owned_scouting_config_t _ret_sconfig = z_scouting_config_default(); - assert(z_check(_ret_sconfig)); -#ifdef ZENOH_PICO - _ret_int8 = - zp_scouting_config_insert(z_loan(_ret_sconfig), Z_CONFIG_SCOUTING_TIMEOUT_KEY, z_string_make(SCOUTING_TIMEOUT)); - assert_eq(_ret_int8, 0); - _ret_cstr = zp_scouting_config_get(z_loan(_ret_sconfig), Z_CONFIG_SCOUTING_TIMEOUT_KEY); - assert_eq(strlen(_ret_cstr), strlen(SCOUTING_TIMEOUT)); - assert_eq(strncmp(_ret_cstr, SCOUTING_TIMEOUT, strlen(_ret_cstr)), 0); -#endif - z_drop(z_move(_ret_sconfig)); + z_owned_config_t _ret_sconfig; + z_config_default(&_ret_sconfig); + assert(z_internal_check(_ret_sconfig)); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); printf("Testing Scouting..."); - _ret_sconfig = z_scouting_config_from(z_loan(_ret_config)); - z_owned_closure_hello_t _ret_closure_hello = z_closure(hello_handler, NULL, NULL); - _ret_int8 = z_scout(z_move(_ret_sconfig), z_move(_ret_closure_hello)); + z_owned_closure_hello_t _ret_closure_hello; + z_closure(&_ret_closure_hello, hello_handler, NULL, NULL); + _ret_int8 = z_scout(z_move(_ret_sconfig), z_move(_ret_closure_hello), NULL); assert_eq(_ret_int8, 0); assert(hellos >= 1); - uint32_t _scouting_timeout = strtoul(SCOUTING_TIMEOUT, NULL, 10); + uint32_t _scouting_timeout = (uint32_t)strtoul(SCOUTING_TIMEOUT, NULL, 10); z_sleep_ms(_scouting_timeout); printf("Ok\n"); z_sleep_s(SLEEP); - z_owned_session_t s1 = z_open(z_move(_ret_config)); - assert(z_check(s1)); + z_owned_session_t s1; + z_open(&s1, z_move(_ret_config)); + 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++) { @@ -228,38 +205,43 @@ int main(int argc, char **argv) { } printf("\n"); - z_owned_closure_zid_t _ret_closure_zid = z_closure(zid_handler, NULL, NULL); + z_owned_closure_zid_t _ret_closure_zid; + z_closure(&_ret_closure_zid, zid_handler, NULL, NULL); _ret_int8 = z_info_peers_zid(z_loan(s1), z_move(_ret_closure_zid)); assert_eq(_ret_int8, 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(zids, 0); + z_closure(&_ret_closure_zid, zid_handler, NULL, NULL); _ret_int8 = z_info_routers_zid(z_loan(s1), z_move(_ret_closure_zid)); assert_eq(_ret_int8, 0); - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(zids, 1); #ifdef ZENOH_PICO - zp_task_read_options_t _ret_read_opt = zp_task_read_options_default(); - zp_start_read_task(z_loan(s1), &_ret_read_opt); - zp_task_lease_options_t _ret_lease_opt = zp_task_lease_options_default(); - zp_start_lease_task(z_loan(s1), &_ret_lease_opt); + zp_task_read_options_t _ret_read_opt; + zp_task_read_options_default(&_ret_read_opt); + zp_start_read_task(z_loan_mut(s1), &_ret_read_opt); + zp_task_lease_options_t _ret_lease_opt; + zp_task_lease_options_default(&_ret_lease_opt); + zp_start_lease_task(z_loan_mut(s1), &_ret_lease_opt); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); - _ret_config = z_config_default(); + z_config_default(&_ret_config); #ifdef ZENOH_PICO - _ret_int8 = zp_config_insert(z_loan(_ret_config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[1])); + _ret_int8 = zp_config_insert(z_loan_mut(_ret_config), Z_CONFIG_CONNECT_KEY, argv[1]); assert_eq(_ret_int8, 0); _ret_cstr = zp_config_get(z_loan(_ret_config), Z_CONFIG_CONNECT_KEY); assert_eq(strlen(_ret_cstr), strlen(argv[1])); assert_eq(strncmp(_ret_cstr, argv[1], strlen(_ret_cstr)), 0); #endif - z_owned_session_t s2 = z_open(z_move(_ret_config)); - assert(z_check(s2)); + z_owned_session_t s2; + z_open(&s2, z_move(_ret_config)); + 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++) { @@ -268,139 +250,146 @@ int main(int argc, char **argv) { printf("\n"); #ifdef ZENOH_PICO - zp_start_read_task(z_loan(s2), NULL); - zp_start_lease_task(z_loan(s2), NULL); + zp_start_read_task(z_loan_mut(s2), NULL); + zp_start_lease_task(z_loan_mut(s2), NULL); #endif - sleep(SLEEP); + z_sleep_s(SLEEP); - z_session_t ls1 = z_loan(s1); + const z_loaned_session_t *ls1 = z_loan(s1); printf("Declaring Subscriber..."); - z_owned_closure_sample_t _ret_closure_sample = z_closure(data_handler, NULL, &ls1); - z_subscriber_options_t _ret_sub_opt = z_subscriber_options_default(); - z_owned_subscriber_t _ret_sub = - z_declare_subscriber(z_loan(s2), z_keyexpr(keyexpr_str), z_move(_ret_closure_sample), &_ret_sub_opt); - assert(z_check(_ret_sub)); + z_owned_closure_sample_t _ret_closure_sample; + z_closure(&_ret_closure_sample, data_handler, NULL, &ls1); + z_subscriber_options_t _ret_sub_opt; + z_subscriber_options_default(&_ret_sub_opt); + + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr_str); + z_owned_subscriber_t _ret_sub; + _ret_int8 = z_declare_subscriber(&_ret_sub, z_loan(s2), z_loan(ke), z_move(_ret_closure_sample), &_ret_sub_opt); + assert(_ret_int8 == _Z_RES_OK); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); - printf("Declaring Keyexpr..."); - char *s1_res = (char *)malloc(64); - snprintf(s1_res, 64, "%s/chunk/%d", keyexpr_str, 1); - z_owned_keyexpr_t _ret_expr = z_declare_keyexpr(z_loan(s1), z_keyexpr(s1_res)); - assert(z_check(_ret_expr)); + char s1_res[64]; + sprintf(s1_res, "%s/chunk/%d", keyexpr_str, 1); + z_view_keyexpr_t s1_key; + z_view_keyexpr_from_str(&s1_key, s1_res); + z_owned_keyexpr_t _ret_expr; + z_declare_keyexpr(&_ret_expr, z_loan(s1), z_loan(s1_key)); + assert(z_internal_check(_ret_expr)); printf("Ok\n"); printf("Session Put..."); - z_put_options_t _ret_put_opt = z_put_options_default(); + z_put_options_t _ret_put_opt; + z_put_options_default(&_ret_put_opt); + z_owned_encoding_t encoding; + z_encoding_from_str(&encoding, "test_encoding"); + _ret_put_opt.encoding = z_move(encoding); _ret_put_opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_encoding_t _ret_encoding = z_encoding_default(); - (void)(_ret_encoding); - _ret_encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - _ret_put_opt.encoding = _ret_encoding; - _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), (const uint8_t *)value, strlen(value), &_ret_put_opt); + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_str(&payload, (char *)value, NULL, NULL); + + _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), z_move(payload), &_ret_put_opt); assert_eq(_ret_int8, 0); + assert(!z_internal_check(encoding)); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(datas, 1); printf("Session delete..."); - z_delete_options_t _ret_delete_opt = z_delete_options_default(); + z_delete_options_t _ret_delete_opt; + z_delete_options_default(&_ret_delete_opt); + _ret_delete_opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; _ret_int8 = z_delete(z_loan(s1), z_loan(_ret_expr), &_ret_delete_opt); assert_eq(_ret_int8, 0); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(datas, 2); printf("Undeclaring Keyexpr..."); - _ret_int8 = z_undeclare_keyexpr(z_loan(s1), z_move(_ret_expr)); + _ret_int8 = z_undeclare_keyexpr(z_move(_ret_expr), z_loan(s1)); printf(" %02x\n", _ret_int8); assert_eq(_ret_int8, 0); - assert(!z_check(_ret_expr)); - printf("Ok\n"); - - _ret_int8 = z_undeclare_subscriber(z_move(_ret_sub)); - assert_eq(_ret_int8, 0); - - printf("Declaring Pull Subscriber..."); - z_owned_closure_sample_t _ret_closure_sample2 = z_closure(data_handler, NULL, &ls1); - z_pull_subscriber_options_t _ret_psub_opt = z_pull_subscriber_options_default(); - z_owned_pull_subscriber_t _ret_psub = - z_declare_pull_subscriber(z_loan(s2), z_keyexpr(keyexpr_str), z_move(_ret_closure_sample2), &_ret_psub_opt); - assert(z_check(_ret_psub)); + assert(!z_internal_check(_ret_expr)); printf("Ok\n"); printf("Declaring Publisher..."); - z_publisher_options_t _ret_pub_opt = z_publisher_options_default(); + z_publisher_options_t _ret_pub_opt; + z_publisher_options_default(&_ret_pub_opt); + z_encoding_from_str(&encoding, "test_encoding"); + _ret_pub_opt.encoding = z_move(encoding); _ret_pub_opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_owned_publisher_t _ret_pub = z_declare_publisher(z_loan(s1), z_keyexpr(keyexpr_str), &_ret_pub_opt); - assert(z_check(_ret_pub)); + z_owned_publisher_t _ret_pub; + _ret_int8 = z_declare_publisher(&_ret_pub, z_loan(s1), z_loan(s1_key), &_ret_pub_opt); + assert(_ret_int8 == _Z_RES_OK); + assert(!z_internal_check(encoding)); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); printf("Publisher Put..."); - z_publisher_put_options_t _ret_pput_opt = z_publisher_put_options_default(); - _ret_int8 = z_publisher_put(z_loan(_ret_pub), (const uint8_t *)value, strlen(value), &_ret_pput_opt); - assert_eq(_ret_int8, 0); - printf("Ok\n"); - - sleep(SLEEP); + // Create payload + z_bytes_serialize_from_str(&payload, value); - printf("Pull Subscriber Pulling data..."); - _ret_int8 = z_subscriber_pull(z_loan(_ret_psub)); + z_publisher_put_options_t _ret_pput_opt; + z_publisher_put_options_default(&_ret_pput_opt); + _ret_int8 = z_publisher_put(z_loan(_ret_pub), z_move(payload), &_ret_pput_opt); assert_eq(_ret_int8, 0); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(datas, 3); printf("Publisher Delete..."); - z_publisher_delete_options_t _ret_pdelete_opt = z_publisher_delete_options_default(); + z_publisher_delete_options_t _ret_pdelete_opt; + z_publisher_delete_options_default(&_ret_pdelete_opt); _ret_int8 = z_publisher_delete(z_loan(_ret_pub), &_ret_pdelete_opt); assert_eq(_ret_int8, 0); printf("Ok\n"); - sleep(SLEEP); - - printf("Pull Subscriber Pulling data..."); - _ret_int8 = z_subscriber_pull(z_loan(_ret_psub)); - assert_eq(_ret_int8, 0); - printf("Ok\n"); - - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(datas, 4); printf("Undeclaring Publisher..."); _ret_int8 = z_undeclare_publisher(z_move(_ret_pub)); assert_eq(_ret_int8, 0); - assert(!z_check(_ret_pub)); + assert(!z_internal_check(_ret_pub)); printf("Ok\n"); - printf("Undeclaring Pull Subscriber..."); - _ret_int8 = z_undeclare_pull_subscriber(z_move(_ret_psub)); + z_sleep_s(SLEEP); + + printf("Undeclaring Subscriber..."); + _ret_int8 = z_undeclare_subscriber(z_move(_ret_sub)); assert_eq(_ret_int8, 0); + assert(!z_internal_check(_ret_sub)); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); printf("Declaring Queryable..."); - z_owned_closure_query_t _ret_closure_query = z_closure(query_handler, NULL, &ls1); - z_queryable_options_t _ret_qle_opt = z_queryable_options_default(); - z_owned_queryable_t qle = - z_declare_queryable(z_loan(s1), z_keyexpr(s1_res), z_move(_ret_closure_query), &_ret_qle_opt); - assert(z_check(qle)); + z_owned_closure_query_t _ret_closure_query; + z_closure(&_ret_closure_query, query_handler, NULL, &ls1); + z_queryable_options_t _ret_qle_opt; + z_queryable_options_default(&_ret_qle_opt); + z_owned_queryable_t qle; + assert(z_declare_queryable(&qle, z_loan(s1), z_loan(s1_key), z_move(_ret_closure_query), &_ret_qle_opt) == + _Z_RES_OK); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); printf("Testing Consolidations..."); - z_session_t ls2 = z_loan(s2); - z_owned_closure_reply_t _ret_closure_reply = z_closure(reply_handler, NULL, &ls2); - z_get_options_t _ret_get_opt = z_get_options_default(); + const z_loaned_session_t *ls2 = z_loan(s2); + z_owned_closure_reply_t _ret_closure_reply; + z_closure(&_ret_closure_reply, reply_handler, NULL, &ls2); + z_get_options_t _ret_get_opt; + z_get_options_default(&_ret_get_opt); _ret_get_opt.target = z_query_target_default(); _ret_get_opt.consolidation = z_query_consolidation_auto(); (void)(_ret_get_opt.consolidation); @@ -415,11 +404,11 @@ int main(int argc, char **argv) { printf("Ok\n"); printf("Testing Get..."); - _ret_int8 = z_get(z_loan(s2), z_keyexpr(s1_res), "", z_move(_ret_closure_reply), &_ret_get_opt); + _ret_int8 = z_get(z_loan(s2), z_loan(s1_key), "", z_move(_ret_closure_reply), &_ret_get_opt); assert_eq(_ret_int8, 0); printf("Ok\n"); - sleep(SLEEP); + z_sleep_s(SLEEP); assert_eq(queries, 1); assert_eq(replies, 1); @@ -429,8 +418,8 @@ int main(int argc, char **argv) { printf("Ok\n"); #ifdef ZENOH_PICO - zp_stop_read_task(z_loan(s1)); - zp_stop_lease_task(z_loan(s1)); + zp_stop_read_task(z_loan_mut(s1)); + zp_stop_lease_task(z_loan_mut(s1)); #endif printf("Close sessions..."); @@ -438,17 +427,16 @@ int main(int argc, char **argv) { assert_eq(_ret_int8, 0); #ifdef ZENOH_PICO - zp_stop_read_task(z_loan(s2)); - zp_stop_lease_task(z_loan(s2)); + zp_stop_read_task(z_loan_mut(s2)); + zp_stop_lease_task(z_loan_mut(s2)); #endif _ret_int8 = z_close(z_move(s2)); assert_eq(_ret_int8, 0); printf("Ok\n"); - sleep(SLEEP * 5); + z_sleep_s(SLEEP * 5); - free(s1_res); - free(keyexpr_str); + z_free(keyexpr_str); return 0; } diff --git a/tests/z_api_bytes_test.c b/tests/z_api_bytes_test.c new file mode 100644 index 000000000..cbf0c9610 --- /dev/null +++ b/tests/z_api_bytes_test.c @@ -0,0 +1,312 @@ +// +// Copyright (c) 2024 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 +#include +#include + +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" + +#undef NDEBUG +#include + +void test_reader_seek(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, 10, NULL, NULL); + + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + assert(z_bytes_reader_tell(&reader) == 0); + + assert(0 == z_bytes_reader_seek(&reader, 5, SEEK_CUR)); + assert(z_bytes_reader_tell(&reader) == 5); + + assert(0 == z_bytes_reader_seek(&reader, 7, SEEK_SET)); + assert(z_bytes_reader_tell(&reader) == 7); + + assert(0 == z_bytes_reader_seek(&reader, -1, SEEK_END)); + assert(z_bytes_reader_tell(&reader) == 9); + + assert(z_bytes_reader_seek(&reader, 20, SEEK_SET) < 0); + + assert(0 == z_bytes_reader_seek(&reader, 5, SEEK_SET)); + assert(z_bytes_reader_tell(&reader) == 5); + + assert(z_bytes_reader_seek(&reader, 10, SEEK_CUR) < 0); + assert(z_bytes_reader_seek(&reader, 10, SEEK_END) < 0); + assert(z_bytes_reader_seek(&reader, -20, SEEK_END) < 0); + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_reader_read(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {0}; + + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, 10, NULL, NULL); + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + + assert(5 == z_bytes_reader_read(&reader, data_out, 5)); + + z_bytes_reader_seek(&reader, 2, SEEK_CUR); + assert(2 == z_bytes_reader_read(&reader, data_out + 7, 2)); + + z_bytes_reader_seek(&reader, 5, SEEK_SET); + assert(2 == z_bytes_reader_read(&reader, data_out + 5, 2)); + + z_bytes_reader_seek(&reader, -1, SEEK_END); + assert(1 == z_bytes_reader_read(&reader, data_out + 9, 10)); + + assert(0 == z_bytes_reader_read(&reader, data_out, 10)); + + assert(!memcmp(data, data_out, 10)); + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_writer(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {0}; + + z_owned_bytes_t payload; + z_bytes_empty(&payload); + + z_bytes_writer_t writer = z_bytes_get_writer(z_bytes_loan_mut(&payload)); + + assert(z_bytes_writer_write_all(&writer, data, 3) == 0); + assert(z_bytes_writer_write_all(&writer, data + 3, 5) == 0); + assert(z_bytes_writer_write_all(&writer, data + 8, 2) == 0); + + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + + assert(10 == z_bytes_reader_read(&reader, data_out, 10)); + assert(0 == memcmp(data, data_out, 10)); + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_bounded(void) { + uint32_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint32_t data_out[10] = {0}; + + z_owned_bytes_t payload; + z_bytes_empty(&payload); + + z_bytes_writer_t writer = z_bytes_get_writer(z_bytes_loan_mut(&payload)); + for (size_t i = 0; i < 10; ++i) { + z_owned_bytes_t b; + z_bytes_serialize_from_uint32(&b, data[i]); + assert(z_bytes_writer_append_bounded(&writer, z_bytes_move(&b)) == 0); + } + { + z_owned_bytes_t b; + z_bytes_serialize_from_str(&b, "test"); + assert(z_bytes_writer_append_bounded(&writer, z_bytes_move(&b)) == 0); + } + + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + + for (size_t i = 0; i < 10; ++i) { + z_owned_bytes_t b; + assert(z_bytes_reader_read_bounded(&reader, &b) == 0); + assert(z_bytes_deserialize_into_uint32(z_bytes_loan(&b), &data_out[i]) == 0); + z_bytes_drop(z_bytes_move(&b)); + } + assert(!memcmp(data, data_out, 10)); + { + z_owned_string_t s; + z_owned_bytes_t b; + assert(z_bytes_reader_read_bounded(&reader, &b) == 0); + z_bytes_deserialize_into_string(z_bytes_loan(&b), &s); + assert(strncmp("test", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_bytes_drop(z_bytes_move(&b)); + z_string_drop(z_string_move(&s)); + } + uint8_t d; + assert(0 == z_bytes_reader_read(&reader, &d, 1)); // we reached the end of the payload + + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_append(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {0}; + + z_owned_bytes_t payload; + z_bytes_empty(&payload); + + z_bytes_writer_t writer = z_bytes_get_writer(z_bytes_loan_mut(&payload)); + z_bytes_writer_write_all(&writer, data, 5); + { + z_owned_bytes_t b; + z_bytes_serialize_from_buf(&b, data + 5, 5); + assert(z_bytes_writer_append(&writer, z_bytes_move(&b)) == 0); + } + + z_bytes_reader_t reader = z_bytes_get_reader(z_bytes_loan(&payload)); + z_bytes_reader_read(&reader, data_out, 10); + + assert(!memcmp(data, data_out, 10)); + + uint8_t d; + assert(0 == z_bytes_reader_read(&reader, &d, 1)); // we reached the end of the payload + + z_bytes_drop(z_bytes_move(&payload)); +} + +void custom_deleter(void *data, void *context) { + (void)data; + size_t *cnt = (size_t *)context; + (*cnt)++; +} + +_Bool z_check_and_drop_payload(z_owned_bytes_t *payload, uint8_t *data, size_t len) { + z_owned_slice_t out; + z_bytes_deserialize_into_slice(z_bytes_loan(payload), &out); + z_bytes_drop(z_bytes_move(payload)); + _Bool res = memcmp(data, z_slice_data(z_slice_loan(&out)), len) == 0; + z_slice_drop(z_slice_move(&out)); + + return res; +} + +void test_slice(void) { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + size_t cnt = 0; + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, data, 10, custom_deleter, (void *)&cnt); + + z_owned_slice_t out; + z_bytes_deserialize_into_slice(z_bytes_loan(&payload), &out); + + assert(cnt == 0); + z_bytes_drop(z_bytes_move(&payload)); + assert(cnt == 1); + + assert(!memcmp(data, z_slice_data(z_slice_loan(&out)), 10)); + z_slice_drop(z_slice_move(&out)); + + z_owned_bytes_t payload2; + z_owned_slice_t s; + z_slice_copy_from_buf(&s, data, 10); + z_bytes_serialize_from_slice(&payload2, z_slice_loan(&s)); + assert(z_internal_slice_check(&s)); + z_slice_drop(z_slice_move(&s)); + assert(z_check_and_drop_payload(&payload2, data, 10)); + + z_owned_bytes_t payload3; + z_slice_copy_from_buf(&s, data, 10); + z_bytes_from_slice(&payload3, z_slice_move(&s)); + assert(!z_internal_slice_check(&s)); + assert(z_check_and_drop_payload(&payload3, data, 10)); + + z_owned_bytes_t payload4; + z_bytes_serialize_from_buf(&payload4, data, 10); + assert(z_check_and_drop_payload(&payload4, data, 10)); + + z_owned_bytes_t payload5; + z_bytes_from_static_buf(&payload5, data, 10); + assert(z_check_and_drop_payload(&payload5, data, 10)); +} + +#define TEST_ARITHMETIC(TYPE, EXT, VAL) \ + { \ + TYPE in = VAL, out; \ + z_owned_bytes_t payload; \ + z_bytes_serialize_from_##EXT(&payload, in); \ + z_bytes_deserialize_into_##EXT(z_bytes_loan(&payload), &out); \ + assert(in == out); \ + z_bytes_drop(z_bytes_move(&payload)); \ + } + +void test_arithmetic(void) { + TEST_ARITHMETIC(uint8_t, uint8, 5); + TEST_ARITHMETIC(uint16_t, uint16, 1000); + TEST_ARITHMETIC(uint32_t, uint32, 51000000); + TEST_ARITHMETIC(uint64_t, uint64, 1000000000005); + + TEST_ARITHMETIC(int8_t, int8, 5); + TEST_ARITHMETIC(int16_t, int16, -1000); + TEST_ARITHMETIC(int32_t, int32, 51000000); + TEST_ARITHMETIC(int64_t, int64, -1000000000005); + + TEST_ARITHMETIC(float, float, 10.1f); + TEST_ARITHMETIC(double, double, -105.001); +} + +bool iter_body(z_owned_bytes_t *b, void *context) { + uint8_t *val = (uint8_t *)context; + if (*val >= 10) { + return false; + } else { + z_bytes_serialize_from_uint8(b, *val); + } + *val = *val + 1; + return true; +} + +void test_iter(void) { + uint8_t data_out[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + + z_owned_bytes_t payload; + uint8_t context = 0; + z_bytes_from_iter(&payload, iter_body, (void *)(&context)); + + z_bytes_iterator_t it = z_bytes_get_iterator(z_bytes_loan(&payload)); + + size_t i = 0; + z_owned_bytes_t out; + while (z_bytes_iterator_next(&it, &out)) { + uint8_t res; + z_bytes_deserialize_into_uint8(z_bytes_loan(&out), &res); + assert(res == data_out[i]); + i++; + z_bytes_drop(z_bytes_move(&out)); + } + assert(i == 10); + z_bytes_drop(z_bytes_move(&payload)); +} + +void test_pair(void) { + z_owned_bytes_t payload, payload1, payload2, payload1_out, payload2_out; + z_bytes_serialize_from_int16(&payload1, -500); + z_bytes_serialize_from_double(&payload2, 123.45); + z_bytes_from_pair(&payload, z_bytes_move(&payload1), z_bytes_move(&payload2)); + + z_bytes_deserialize_into_pair(z_bytes_loan(&payload), &payload1_out, &payload2_out); + + int16_t i; + double d; + z_bytes_deserialize_into_int16(z_bytes_loan(&payload1_out), &i); + z_bytes_deserialize_into_double(z_bytes_loan(&payload2_out), &d); + + assert(i == -500); + assert(d == 123.45); +} + +int main(void) { + test_reader_seek(); + test_reader_read(); + test_writer(); + test_slice(); + test_arithmetic(); + test_bounded(); + test_append(); + test_iter(); + test_pair(); +} diff --git a/tests/z_api_config_test.c b/tests/z_api_config_test.c new file mode 100644 index 000000000..534edd317 --- /dev/null +++ b/tests/z_api_config_test.c @@ -0,0 +1,49 @@ +// +// Copyright (c) 2024 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 +#include +#include + +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" + +#undef NDEBUG +#include + +void config_client(void) { + const char *locator = "tcp/127.0.0.1"; + z_owned_config_t config; + assert(0 == z_config_client(&config, locator)); + assert(z_internal_config_check(&config)); + assert(strcmp(zp_config_get(z_config_loan(&config), Z_CONFIG_MODE_KEY), Z_CONFIG_MODE_CLIENT) == 0); + assert(strcmp(zp_config_get(z_config_loan(&config), Z_CONFIG_CONNECT_KEY), locator) == 0); + z_config_drop(z_config_move(&config)); +} + +void config_peer(void) { + const char *locator = "udp/228.0.0.4:7447#iface=en0"; + z_owned_config_t config; + assert(0 == z_config_peer(&config, locator)); + assert(z_internal_config_check(&config)); + assert(strcmp(zp_config_get(z_config_loan(&config), Z_CONFIG_MODE_KEY), Z_CONFIG_MODE_PEER) == 0); + assert(strcmp(zp_config_get(z_config_loan(&config), Z_CONFIG_CONNECT_KEY), locator) == 0); + z_config_drop(z_config_move(&config)); + assert(0 != z_config_peer(&config, NULL)); + assert(!z_internal_config_check(&config)); +} + +int main(void) { + config_client(); + config_peer(); +} diff --git a/tests/z_api_double_drop_test.c b/tests/z_api_double_drop_test.c index 776848b2a..7de607c24 100644 --- a/tests/z_api_double_drop_test.c +++ b/tests/z_api_double_drop_test.c @@ -23,35 +23,27 @@ #define URL "demo/example" void test_keyexpr(void) { - z_owned_keyexpr_t keyexpr = z_keyexpr_new(URL); - assert(z_check(keyexpr)); + z_owned_keyexpr_t keyexpr; + z_keyexpr_from_str(&keyexpr, URL); + assert(z_internal_check(keyexpr)); z_drop(z_move(keyexpr)); - assert(!z_check(keyexpr)); + assert(!z_internal_check(keyexpr)); z_drop(z_move(keyexpr)); - assert(!z_check(keyexpr)); + assert(!z_internal_check(keyexpr)); } void test_config(void) { - z_owned_config_t config = z_config_default(); - assert(z_check(config)); + z_owned_config_t config; + z_config_default(&config); + assert(z_internal_check(config)); z_drop(z_move(config)); - assert(!z_check(config)); + assert(!z_internal_check(config)); z_drop(z_move(config)); - assert(!z_check(config)); -} - -void test_scouting_config(void) { - z_owned_scouting_config_t config = z_scouting_config_default(); - assert(z_check(config)); - z_drop(z_move(config)); - assert(!z_check(config)); - z_drop(z_move(config)); - assert(!z_check(config)); + assert(!z_internal_check(config)); } int main(void) { test_keyexpr(); test_config(); - test_scouting_config(); return 0; } diff --git a/tests/z_api_encoding_test.c b/tests/z_api_encoding_test.c new file mode 100644 index 000000000..8f3577085 --- /dev/null +++ b/tests/z_api_encoding_test.c @@ -0,0 +1,102 @@ +#include +#include +#include + +#include "zenoh-pico/api/primitives.h" +#include "zenoh-pico/api/types.h" + +#undef NDEBUG +#include + +void test_null_encoding(void) { + z_owned_encoding_t e; + z_internal_encoding_null(&e); + assert(!z_internal_encoding_check(&e)); + z_encoding_drop(z_encoding_move(&e)); +} + +void test_encoding_without_id(void) { + z_owned_encoding_t e1; + z_encoding_from_str(&e1, "my_encoding"); + assert(z_internal_encoding_check(&e1)); + z_owned_string_t s; + z_encoding_to_string(z_encoding_loan(&e1), &s); + assert(strncmp("zenoh/bytes;my_encoding", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e1)); + z_string_drop(z_string_move(&s)); + + z_owned_encoding_t e2; + z_encoding_from_substr(&e2, "my_encoding", 4); + assert(z_internal_encoding_check(&e2)); + + z_encoding_to_string(z_encoding_loan(&e2), &s); + assert(strncmp("zenoh/bytes;my_e", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e2)); + z_string_drop(z_string_move(&s)); +} + +void test_encoding_with_id(void) { + z_owned_encoding_t e1; + z_encoding_from_str(&e1, "zenoh/string;utf8"); + assert(z_internal_encoding_check(&e1)); + z_owned_string_t s; + z_encoding_to_string(z_encoding_loan(&e1), &s); + assert(strncmp("zenoh/string;utf8", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e1)); + z_string_drop(z_string_move(&s)); + + z_owned_encoding_t e2; + z_encoding_from_substr(&e2, "zenoh/string;utf8", 15); + assert(z_internal_encoding_check(&e2)); + + z_encoding_to_string(z_encoding_loan(&e2), &s); + assert(strncmp("zenoh/string;utf8", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e2)); + z_string_drop(z_string_move(&s)); + + z_owned_encoding_t e3; + z_encoding_from_str(&e3, "custom_id;custom_schema"); + assert(z_internal_encoding_check(&e3)); + + z_encoding_to_string(z_encoding_loan(&e3), &s); + assert(strncmp("zenoh/bytes;custom_id;custom_schema", z_string_data(z_string_loan(&s)), + z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e3)); + z_string_drop(z_string_move(&s)); + + z_owned_encoding_t e4; + z_encoding_from_substr(&e4, "custom_id;custom_schema", 16); + assert(z_internal_encoding_check(&e2)); + + z_encoding_to_string(z_encoding_loan(&e4), &s); + assert(strncmp("zenoh/bytes;custom_id;custom", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == + 0); + z_encoding_drop(z_encoding_move(&e4)); + z_string_drop(z_string_move(&s)); +} + +void test_with_schema(void) { + z_owned_encoding_t e; + z_internal_encoding_null(&e); + z_encoding_set_schema_from_str(z_encoding_loan_mut(&e), "my_schema"); + + z_owned_string_t s; + z_encoding_to_string(z_encoding_loan_mut(&e), &s); + assert(strncmp("zenoh/bytes;my_schema", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e)); + + z_encoding_from_str(&e, "zenoh/string;"); + z_encoding_set_schema_from_substr(z_encoding_loan_mut(&e), "my_schema", 3); + + z_encoding_to_string(z_encoding_loan(&e), &s); + assert(strncmp("zenoh/string;my_", z_string_data(z_string_loan(&s)), z_string_len(z_string_loan(&s))) == 0); + z_encoding_drop(z_encoding_move(&e)); + z_string_drop(z_string_move(&s)); +} + +int main(void) { + test_null_encoding(); + test_encoding_without_id(); + test_encoding_with_id(); + test_with_schema(); +} diff --git a/tests/z_api_null_drop_test.c b/tests/z_api_null_drop_test.c index a3c0f74cf..8168af075 100644 --- a/tests/z_api_null_drop_test.c +++ b/tests/z_api_null_drop_test.c @@ -20,150 +20,64 @@ #include "zenoh-pico.h" -int main(void) { - // - // Check that all null functions exists - // - z_owned_session_t session_null_1 = z_session_null(); - z_owned_keyexpr_t keyexpr_null_1 = z_keyexpr_null(); - z_owned_config_t config_null_1 = z_config_null(); - z_owned_scouting_config_t scouting_config_null_1 = z_scouting_config_null(); - z_owned_hello_t hello_null_1 = z_hello_null(); - z_owned_closure_sample_t closure_sample_null_1 = z_closure_sample_null(); - z_owned_closure_query_t closure_query_null_1 = z_closure_query_null(); - z_owned_closure_reply_t closure_reply_null_1 = z_closure_reply_null(); - z_owned_closure_hello_t closure_hello_null_1 = z_closure_hello_null(); - z_owned_closure_zid_t closure_zid_null_1 = z_closure_zid_null(); - z_owned_str_t str_null_1 = z_str_null(); - - // - // Test that they actually make invalid value (where applicable) - // - assert(!z_check(session_null_1)); - assert(!z_check(keyexpr_null_1)); - assert(!z_check(config_null_1)); - assert(!z_check(scouting_config_null_1)); - assert(!z_check(hello_null_1)); - assert(!z_check(str_null_1)); - - // - // Test that z_null macro defined for all types - // - z_owned_session_t session_null_2; - z_owned_keyexpr_t keyexpr_null_2; - z_owned_config_t config_null_2; - z_owned_scouting_config_t scouting_config_null_2; - z_owned_hello_t hello_null_2; - z_owned_closure_sample_t closure_sample_null_2; - z_owned_closure_query_t closure_query_null_2; - z_owned_closure_reply_t closure_reply_null_2; - z_owned_closure_hello_t closure_hello_null_2; - z_owned_closure_zid_t closure_zid_null_2; - z_owned_str_t str_null_2; - - z_null(&session_null_2); - z_null(&keyexpr_null_2); - z_null(&config_null_2); - z_null(&scouting_config_null_2); - z_null(&hello_null_2); - z_null(&closure_sample_null_2); - z_null(&closure_query_null_2); - z_null(&closure_reply_null_2); - z_null(&closure_hello_null_2); - z_null(&closure_zid_null_2); - z_null(&str_null_2); - -#if Z_FEATURE_PUBLICATION == 1 - z_owned_publisher_t publisher_null_1 = z_publisher_null(); - assert(!z_check(publisher_null_1)); - z_owned_publisher_t publisher_null_2; - z_null(&publisher_null_2); - assert(!z_check(publisher_null_2)); -#endif -#if Z_FEATURE_SUBSCRIPTION == 1 - z_owned_pull_subscriber_t pull_subscriber_null_1 = z_pull_subscriber_null(); - z_owned_subscriber_t subscriber_null_1 = z_subscriber_null(); - assert(!z_check(pull_subscriber_null_1)); - assert(!z_check(subscriber_null_1)); - z_owned_pull_subscriber_t pull_subscriber_null_2; - z_owned_subscriber_t subscriber_null_2; - z_null(&pull_subscriber_null_2); - z_null(&subscriber_null_2); - assert(!z_check(pull_subscriber_null_2)); - assert(!z_check(subscriber_null_2)); -#endif -#if Z_FEATURE_QUERYABLE == 1 - z_owned_queryable_t queryable_null_1 = z_queryable_null(); - assert(!z_check(queryable_null_1)); - z_owned_queryable_t queryable_null_2; - z_null(&queryable_null_2); - assert(!z_check(queryable_null_2)); -#endif -#if Z_FEATURE_QUERY == 1 - z_owned_reply_t reply_null_1 = z_reply_null(); - assert(!z_check(reply_null_1)); - z_owned_reply_t reply_null_2; - z_null(&reply_null_2); - assert(!z_check(reply_null_2)); -#endif - - // - // Test that null macro works the same as direct call - // - assert(!z_check(session_null_2)); - assert(!z_check(keyexpr_null_2)); - assert(!z_check(config_null_2)); - assert(!z_check(scouting_config_null_2)); - assert(!z_check(hello_null_2)); - assert(!z_check(str_null_2)); - - // - // Test drop null and double drop it - // - for (int i = 0; i < 2; ++i) { - z_drop(z_move(session_null_1)); - z_drop(z_move(keyexpr_null_1)); - z_drop(z_move(config_null_1)); - z_drop(z_move(scouting_config_null_1)); - z_drop(z_move(hello_null_1)); - z_drop(z_move(closure_sample_null_1)); - z_drop(z_move(closure_query_null_1)); - z_drop(z_move(closure_reply_null_1)); - z_drop(z_move(closure_hello_null_1)); - z_drop(z_move(closure_zid_null_1)); - z_drop(z_move(str_null_1)); - - z_drop(z_move(session_null_2)); - z_drop(z_move(keyexpr_null_2)); - z_drop(z_move(config_null_2)); - z_drop(z_move(scouting_config_null_2)); - z_drop(z_move(hello_null_2)); - z_drop(z_move(closure_sample_null_2)); - z_drop(z_move(closure_query_null_2)); - z_drop(z_move(closure_reply_null_2)); - z_drop(z_move(closure_hello_null_2)); - z_drop(z_move(closure_zid_null_2)); - z_drop(z_move(str_null_2)); +// fill v with invalid values +// set v to null +// check if v it is null +// make sure that drop on null does not crash +// make sure that double drop on null does not crash +// fill v with invalid values again +// +// set v1 to null +// move v to v1 +// make sure that v is null now +#define TEST(name) \ + { \ + z_owned_##name##_t v; \ + memset(&v, -1, sizeof(v)); \ + z_internal_null(&v); \ + assert(!z_internal_check(v)); \ + z_drop(z_move(v)); \ + z_drop(z_move(v)); \ + z_owned_##name##_t v1; \ + z_internal_null(&v1); \ + memset(&v, -1, sizeof(v)); \ + z_take(&v1, z_move(v)); \ + assert(!z_internal_check(v)); \ + } +int main(void) { + TEST(session) + TEST(keyexpr) + TEST(config) + TEST(hello) + TEST(closure_sample) + TEST(closure_query) + TEST(closure_reply) + TEST(closure_hello) + TEST(closure_zid) + TEST(string) + TEST(string_array) + TEST(sample) + TEST(slice) + TEST(bytes) + TEST(encoding) #if Z_FEATURE_PUBLICATION == 1 - z_drop(z_move(publisher_null_1)); - z_drop(z_move(publisher_null_2)); + TEST(publisher) #endif #if Z_FEATURE_SUBSCRIPTION == 1 - z_drop(z_move(pull_subscriber_null_1)); - z_drop(z_move(subscriber_null_1)); - z_drop(z_move(pull_subscriber_null_2)); - z_drop(z_move(subscriber_null_2)); + TEST(subscriber) #endif #if Z_FEATURE_QUERYABLE == 1 - z_drop(z_move(queryable_null_1)); - z_drop(z_move(queryable_null_2)); + TEST(query) + TEST(queryable) #endif #if Z_FEATURE_QUERY == 1 - z_drop(z_move(reply_null_1)); - z_drop(z_move(reply_null_2)); + TEST(reply) #endif - } + // Double drop not supported for these types + // TEST(task) + // TEST(mutex) + // TEST(condvar) return 0; } diff --git a/tests/z_bytes_test.c b/tests/z_bytes_test.c new file mode 100644 index 000000000..cc1373d20 --- /dev/null +++ b/tests/z_bytes_test.c @@ -0,0 +1,224 @@ +// +// Copyright (c) 2024 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 +#include +#include + +#include "zenoh-pico/collections/bytes.h" + +#undef NDEBUG +#include + +void test_null_bytes(void) { + _z_bytes_t b = _z_bytes_null(); + assert(_z_bytes_len(&b) == 0); + assert(_z_bytes_is_empty(&b)); + assert(!_z_bytes_check(&b)); + assert(_z_bytes_num_slices(&b) == 0); + _z_bytes_drop(&b); // no crush +} + +void test_slice(void) { + uint8_t data[5] = {1, 2, 3, 4, 5}; + uint8_t data_out[5] = {0}; + _z_slice_t s = _z_slice_copy_from_buf(data, 5); + _z_bytes_t b; + _z_bytes_from_slice(&b, s); + + assert(_z_bytes_len(&b) == 5); + assert(!_z_bytes_is_empty(&b)); + assert(_z_bytes_check(&b)); + assert(_z_bytes_num_slices(&b) == 1); + assert(_z_slice_eq(_Z_RC_IN_VAL(&_z_bytes_get_slice(&b, 0)->slice), &s)); + + assert(_z_bytes_to_buf(&b, data_out, 5) == 5); + assert(memcmp(data, data_out, 5) == 0); + + _z_bytes_drop(&b); +} + +void test_append(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + uint8_t data_in[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint8_t data_out[10] = {0}; + _z_arc_slice_t s1 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data1, 5), 0, 5); + _z_arc_slice_t s2 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data2, 5), 2, 3); + _z_arc_slice_t s3 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data3, 3), 1, 2); + + _z_bytes_t b = _z_bytes_null(); + + _z_bytes_append_slice(&b, &s1); + _z_bytes_append_slice(&b, &s2); + _z_bytes_append_slice(&b, &s3); + + assert(_z_bytes_len(&b) == 10); + assert(!_z_bytes_is_empty(&b)); + assert(_z_bytes_check(&b)); + assert(_z_bytes_num_slices(&b) == 3); + assert(_z_slice_eq(_Z_RC_IN_VAL(&_z_bytes_get_slice(&b, 0)->slice), _Z_RC_IN_VAL(&s1.slice))); + assert(_z_slice_eq(_Z_RC_IN_VAL(&_z_bytes_get_slice(&b, 1)->slice), _Z_RC_IN_VAL(&s2.slice))); + assert(_z_slice_eq(_Z_RC_IN_VAL(&_z_bytes_get_slice(&b, 2)->slice), _Z_RC_IN_VAL(&s3.slice))); + + assert(_z_bytes_to_buf(&b, data_out, 15) == 10); + assert(memcmp(data_in, data_out, 10) == 0); + + _z_bytes_drop(&b); +} + +void test_reader_read(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + uint8_t data_in[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; + uint8_t data_out[10] = {0}; + _z_arc_slice_t s1 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data1, 5), 0, 5); + _z_arc_slice_t s2 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data2, 5), 2, 3); + _z_arc_slice_t s3 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data3, 3), 1, 2); + + _z_bytes_t b = _z_bytes_null(); + + _z_bytes_append_slice(&b, &s1); + _z_bytes_append_slice(&b, &s2); + _z_bytes_append_slice(&b, &s3); + + _z_bytes_reader_t reader = _z_bytes_get_reader(&b); + + uint8_t out; + assert(_z_bytes_reader_tell(&reader) == 0); + _z_bytes_reader_read(&reader, &out, 1); + assert(_z_bytes_reader_tell(&reader) == 1); + assert(out == 1); + + _z_bytes_reader_read(&reader, data_out, 3); + assert(_z_bytes_reader_tell(&reader) == 4); + assert(memcmp(data_out, data_in + 1, 3) == 0); + + _z_bytes_reader_read(&reader, data_out, 6); + assert(_z_bytes_reader_tell(&reader) == 10); + assert(memcmp(data_out, data_in + 4, 6) == 0); + + _z_bytes_drop(&b); +} + +void test_reader_seek(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + _z_arc_slice_t s1 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data1, 5), 0, 5); + _z_arc_slice_t s2 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data2, 5), 2, 3); + _z_arc_slice_t s3 = _z_arc_slice_wrap(_z_slice_copy_from_buf(data3, 3), 1, 2); + + _z_bytes_t b = _z_bytes_null(); + + _z_bytes_append_slice(&b, &s1); + _z_bytes_append_slice(&b, &s2); + _z_bytes_append_slice(&b, &s3); + + _z_bytes_reader_t reader = _z_bytes_get_reader(&b); + + assert(_z_bytes_reader_tell(&reader) == 0); + assert(_z_bytes_reader_seek(&reader, 3, SEEK_CUR) == 0); + assert(_z_bytes_reader_tell(&reader) == 3); + assert(_z_bytes_reader_seek(&reader, 5, SEEK_CUR) == 0); + assert(_z_bytes_reader_tell(&reader) == 8); + assert(_z_bytes_reader_seek(&reader, 10, SEEK_CUR) != 0); + + assert(_z_bytes_reader_seek(&reader, 0, SEEK_SET) == 0); + assert(_z_bytes_reader_tell(&reader) == 0); + + assert(_z_bytes_reader_seek(&reader, 3, SEEK_SET) == 0); + assert(_z_bytes_reader_tell(&reader) == 3); + assert(_z_bytes_reader_seek(&reader, 8, SEEK_SET) == 0); + assert(_z_bytes_reader_tell(&reader) == 8); + assert(_z_bytes_reader_seek(&reader, 20, SEEK_SET) != 0); + assert(_z_bytes_reader_seek(&reader, -20, SEEK_SET) != 0); + + assert(_z_bytes_reader_seek(&reader, 0, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 10); + assert(_z_bytes_reader_seek(&reader, -3, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 7); + assert(_z_bytes_reader_seek(&reader, -8, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 2); + assert(_z_bytes_reader_seek(&reader, -10, SEEK_END) == 0); + assert(_z_bytes_reader_tell(&reader) == 0); + assert(_z_bytes_reader_seek(&reader, -20, SEEK_END) != 0); + assert(_z_bytes_reader_seek(&reader, 5, SEEK_END) != 0); + + _z_bytes_drop(&b); +} + +void test_writer_no_cache(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + + _z_bytes_t b = _z_bytes_null(); + _z_bytes_writer_t writer = _z_bytes_get_writer(&b, 0); + + _z_bytes_writer_write_all(&writer, data1, 5); + assert(_z_bytes_len(&b) == 5); + assert(_z_bytes_num_slices(&b) == 1); + _z_bytes_writer_write_all(&writer, data2, 5); + assert(_z_bytes_len(&b) == 10); + assert(_z_bytes_num_slices(&b) == 2); + _z_bytes_writer_write_all(&writer, data3, 3); + assert(_z_bytes_len(&b) == 13); + assert(_z_bytes_num_slices(&b) == 3); + + assert(memcmp(data1, _z_arc_slice_data(_z_bytes_get_slice(&b, 0)), 5) == 0); + assert(memcmp(data2, _z_arc_slice_data(_z_bytes_get_slice(&b, 1)), 5) == 0); + assert(memcmp(data3, _z_arc_slice_data(_z_bytes_get_slice(&b, 2)), 3) == 0); + _z_bytes_drop(&b); +} + +void test_writer_with_cache(void) { + uint8_t data1[5] = {1, 2, 3, 4, 5}; + uint8_t data2[5] = {1, 2, 6, 7, 8}; + uint8_t data3[3] = {3, 9, 10}; + + uint8_t data1_out[7] = {1, 2, 3, 4, 5, 1, 2}; + uint8_t data2_out[6] = {6, 7, 8, 3, 9, 10}; + _z_bytes_t b = _z_bytes_null(); + _z_bytes_writer_t writer = _z_bytes_get_writer(&b, 7); + + _z_bytes_writer_write_all(&writer, data1, 5); + assert(_z_bytes_len(&b) == 5); + assert(_z_bytes_num_slices(&b) == 1); + _z_bytes_writer_write_all(&writer, data2, 5); + assert(_z_bytes_len(&b) == 10); + assert(_z_bytes_num_slices(&b) == 2); + _z_bytes_writer_write_all(&writer, data3, 3); + assert(_z_bytes_len(&b) == 13); + assert(_z_bytes_num_slices(&b) == 2); + + assert(_z_arc_slice_len(_z_bytes_get_slice(&b, 0)) == 7); + assert(_z_arc_slice_len(_z_bytes_get_slice(&b, 1)) == 6); + assert(memcmp(data1_out, _z_arc_slice_data(_z_bytes_get_slice(&b, 0)), 7) == 0); + assert(memcmp(data2_out, _z_arc_slice_data(_z_bytes_get_slice(&b, 1)), 6) == 0); + _z_bytes_drop(&b); +} + +int main(void) { + test_null_bytes(); + test_slice(); + test_append(); + test_reader_read(); + test_reader_seek(); + test_writer_no_cache(); + test_writer_with_cache(); + return 0; +} diff --git a/tests/z_channels_test.c b/tests/z_channels_test.c new file mode 100644 index 000000000..76574ff8d --- /dev/null +++ b/tests/z_channels_test.c @@ -0,0 +1,208 @@ +// +// Copyright (c) 2024 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 +#include +#include +#include + +#include "zenoh-pico/api/handlers.h" +#include "zenoh-pico/api/macros.h" +#include "zenoh-pico/net/sample.h" + +#undef NDEBUG +#include + +#define SEND(closure, v) \ + do { \ + _z_bytes_t payload; \ + _z_bytes_from_slice(&payload, (_z_slice_t){.start = (const uint8_t *)v, .len = strlen(v)}); \ + z_loaned_sample_t sample = { \ + .keyexpr = _z_rname("key"), \ + .payload = payload, \ + .timestamp = _z_timestamp_null(), \ + .encoding = _z_encoding_null(), \ + .kind = 0, \ + .qos = {0}, \ + .attachment = _z_bytes_null(), \ + }; \ + z_call(*z_loan(closure), &sample); \ + } while (0); + +#define _RECV(handler, method, buf) \ + do { \ + z_owned_sample_t sample; \ + int8_t res = method(z_loan(handler), &sample); \ + if (res == Z_CHANNEL_DISCONNECTED) { \ + strcpy(buf, "closed"); \ + } else if (res == Z_OK) { \ + z_owned_slice_t value; \ + z_bytes_deserialize_into_slice(z_sample_payload(z_loan(sample)), &value); \ + size_t value_len = z_slice_len(z_loan(value)); \ + strncpy(buf, (const char *)z_slice_data(z_loan(value)), value_len); \ + buf[value_len] = '\0'; \ + z_drop(z_move(sample)); \ + z_drop(z_move(value)); \ + } else if (res == Z_CHANNEL_NODATA) { \ + strcpy(buf, "nodata"); \ + } \ + } while (0); + +#define RECV(handler, buf) _RECV(handler, z_recv, buf) +#define TRY_RECV(handler, buf) _RECV(handler, z_try_recv, buf) + +void sample_fifo_channel_test(void) { + z_owned_closure_sample_t closure; + z_owned_fifo_handler_sample_t handler; + z_fifo_channel_sample_new(&closure, &handler, 10); + + SEND(closure, "v1") + SEND(closure, "v22") + SEND(closure, "v333") + SEND(closure, "v4444") + + char buf[100]; + + RECV(handler, buf) + assert(strcmp(buf, "v1") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v22") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v333") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v4444") == 0); + + z_drop(z_move(closure)); + + RECV(handler, buf) + assert(strcmp(buf, "closed") == 0); + + z_drop(z_move(handler)); +} + +void sample_fifo_channel_test_try_recv(void) { + z_owned_closure_sample_t closure; + z_owned_fifo_handler_sample_t handler; + z_fifo_channel_sample_new(&closure, &handler, 10); + + char buf[100]; + + TRY_RECV(handler, buf) + assert(strcmp(buf, "nodata") == 0); + + SEND(closure, "v1") + SEND(closure, "v22") + SEND(closure, "v333") + SEND(closure, "v4444") + + TRY_RECV(handler, buf) + assert(strcmp(buf, "v1") == 0); + TRY_RECV(handler, buf) + assert(strcmp(buf, "v22") == 0); + TRY_RECV(handler, buf) + assert(strcmp(buf, "v333") == 0); + TRY_RECV(handler, buf) + assert(strcmp(buf, "v4444") == 0); + TRY_RECV(handler, buf) + assert(strcmp(buf, "nodata") == 0); + + z_drop(z_move(closure)); + TRY_RECV(handler, buf) + assert(strcmp(buf, "closed") == 0); + + z_drop(z_move(handler)); +} + +void sample_ring_channel_test_in_size(void) { + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, 10); + + char buf[100]; + + TRY_RECV(handler, buf) + assert(strcmp(buf, "nodata") == 0); + + SEND(closure, "v1") + SEND(closure, "v22") + SEND(closure, "v333") + SEND(closure, "v4444") + + RECV(handler, buf) + assert(strcmp(buf, "v1") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v22") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v333") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v4444") == 0); + TRY_RECV(handler, buf) + assert(strcmp(buf, "nodata") == 0); + + z_drop(z_move(closure)); + RECV(handler, buf) + assert(strcmp(buf, "closed") == 0); + + z_drop(z_move(handler)); +} + +void sample_ring_channel_test_over_size(void) { + z_owned_closure_sample_t closure; + z_owned_ring_handler_sample_t handler; + z_ring_channel_sample_new(&closure, &handler, 3); + + char buf[100]; + TRY_RECV(handler, buf) + assert(strcmp(buf, "nodata") == 0); + + SEND(closure, "v1") + SEND(closure, "v22") + SEND(closure, "v333") + SEND(closure, "v4444") + + RECV(handler, buf) + assert(strcmp(buf, "v22") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v333") == 0); + RECV(handler, buf) + assert(strcmp(buf, "v4444") == 0); + TRY_RECV(handler, buf) + assert(strcmp(buf, "nodata") == 0); + z_drop(z_move(closure)); + TRY_RECV(handler, buf) + assert(strcmp(buf, "closed") == 0); + + z_drop(z_move(handler)); +} + +void zero_size_test(void) { + z_owned_closure_sample_t closure; + + z_owned_fifo_handler_sample_t fifo_handler; + assert(z_fifo_channel_sample_new(&closure, &fifo_handler, 0) != Z_OK); + assert(z_fifo_channel_sample_new(&closure, &fifo_handler, 1) == Z_OK); + z_drop(z_move(fifo_handler)); + + z_owned_ring_handler_sample_t ring_handler; + assert(z_ring_channel_sample_new(&closure, &ring_handler, 0) != Z_OK); + assert(z_ring_channel_sample_new(&closure, &ring_handler, 1) == Z_OK); + z_drop(z_move(ring_handler)); +} + +int main(void) { + sample_fifo_channel_test(); + sample_fifo_channel_test_try_recv(); + sample_ring_channel_test_in_size(); + sample_ring_channel_test_over_size(); + zero_size_test(); +} diff --git a/tests/z_client_test.c b/tests/z_client_test.c index 023798062..9713163cd 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -11,6 +11,7 @@ // Contributors: // ZettaScale Zenoh Team, +#include #include #include #include @@ -47,40 +48,48 @@ z_owned_keyexpr_t rids2[SET]; volatile unsigned int total = 0; volatile unsigned int queries = 0; -void query_handler(const z_query_t *query, void *arg) { +void query_handler(const z_loaned_query_t *query, void *arg) { char *res = (char *)malloc(64); snprintf(res, 64, "%s%u", uri, *(unsigned int *)arg); printf(">> Received query: %s\t(%u/%u)\n", res, queries, total); - z_owned_str_t k_str = z_keyexpr_to_string(z_query_keyexpr(query)); - assert(_z_str_eq(z_loan(k_str), res) == true); + z_view_string_t k_str, res_str; + z_keyexpr_as_view_string(z_query_keyexpr(query), &k_str); + z_view_string_from_str(&res_str, res); + assert(_z_string_equals(z_loan(k_str), z_loan(res_str))); - z_bytes_t pred = z_query_parameters(query); - assert(pred.len == strlen("")); - assert(strncmp((const char *)pred.start, "", strlen("")) == 0); + z_view_string_t pred; + z_query_parameters(query, &pred); + assert(z_string_len(z_loan(pred)) == 0); - z_query_reply(query, z_keyexpr(res), (const uint8_t *)res, strlen(res), NULL); + // Reply value encoding + z_owned_bytes_t reply_payload; + z_bytes_serialize_from_str(&reply_payload, res); + z_query_reply(query, z_query_keyexpr(query), z_move(reply_payload), NULL); queries++; - z_drop(z_move(k_str)); free(res); } volatile unsigned int replies = 0; -void reply_handler(z_owned_reply_t *reply, void *arg) { +void reply_handler(const z_loaned_reply_t *reply, void *arg) { char *res = (char *)malloc(64); snprintf(res, 64, "%s%u", uri, *(unsigned int *)arg); if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); + const z_loaned_sample_t *sample = z_reply_ok(reply); printf(">> Received reply data: %s\t(%u/%u)\n", res, replies, total); - z_owned_str_t k_str = z_keyexpr_to_string(sample.keyexpr); - assert(sample.payload.len == strlen(res)); - assert(strncmp(res, (const char *)sample.payload.start, strlen(res)) == 0); - assert(_z_str_eq(z_loan(k_str), res) == true); + z_view_string_t k_str, res_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &k_str); + z_owned_string_t value; + z_bytes_deserialize_into_string(z_sample_payload(sample), &value); + assert(z_string_len(z_loan(value)) == strlen(res)); + assert(strncmp(res, z_string_data(z_loan(value)), strlen(res)) == 0); + z_view_string_from_str(&res_str, res); + assert(_z_string_equals(z_loan(k_str), z_loan(res_str))); replies++; - z_drop(z_move(k_str)); + z_drop(z_move(value)); } else { printf(">> Received an error\n"); } @@ -88,23 +97,28 @@ void reply_handler(z_owned_reply_t *reply, void *arg) { } volatile unsigned int datas = 0; -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { char *res = (char *)malloc(64); snprintf(res, 64, "%s%u", uri, *(unsigned int *)arg); printf(">> Received data: %s\t(%u/%u)\n", res, datas, total); - z_owned_str_t k_str = z_keyexpr_to_string(sample->keyexpr); - assert((sample->payload.len == MSG_LEN) || (sample->payload.len == FRAGMENT_MSG_LEN)); - assert(_z_str_eq(z_loan(k_str), res) == true); + _z_string_t res_str = _z_string_alias_str(res); + z_view_string_t k_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &k_str); + z_owned_slice_t value; + z_bytes_deserialize_into_slice(z_sample_payload(sample), &value); + size_t payload_len = z_slice_len(z_loan(value)); + assert((payload_len == MSG_LEN) || (payload_len == FRAGMENT_MSG_LEN)); + assert(_z_string_equals(z_loan(k_str), &res_str)); datas++; - z_drop(z_move(k_str)); + z_drop(z_move(value)); free(res); } -z_string_t format_id(const z_id_t *id) { - _z_bytes_t id_as_bytes = _z_bytes_wrap(id->id, _z_id_len(*id)); - return _z_string_from_bytes(&id_as_bytes); +_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) { @@ -115,35 +129,37 @@ int main(int argc, char **argv) { int is_reliable = strncmp(argv[1], "tcp", 3) == 0; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[1])); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]); for (unsigned int i = 0; i < SET; i++) idx[i] = i; - z_owned_session_t s1 = z_open(z_move(config)); - assert(z_check(s1)); - z_string_t zid1 = format_id(&z_loan(s1)._val.in->val._local_zid); - printf("Session 1 with PID: %s\n", zid1.val); + z_owned_session_t s1; + assert(z_open(&s1, z_move(config)) == 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_clear(&zid1); // Start the read session session lease loops - zp_start_read_task(z_loan(s1), NULL); - zp_start_lease_task(z_loan(s1), NULL); + zp_start_read_task(z_loan_mut(s1), NULL); + zp_start_lease_task(z_loan_mut(s1), NULL); z_sleep_s(SLEEP); - config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[1])); + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, argv[1]); - z_owned_session_t s2 = z_open(z_move(config)); - assert(z_check(s2)); - z_string_t zid2 = format_id(&z_loan(s2)._val.in->val._local_zid); - printf("Session 2 with PID: %s\n", zid2.val); + z_owned_session_t s2; + assert(z_open(&s2, z_move(config)) == 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_clear(&zid2); // Start the read session session lease loops - zp_start_read_task(z_loan(s2), NULL); - zp_start_lease_task(z_loan(s2), NULL); + zp_start_read_task(z_loan_mut(s2), NULL); + zp_start_lease_task(z_loan_mut(s2), NULL); z_sleep_s(SLEEP); @@ -151,8 +167,12 @@ int main(int argc, char **argv) { char *s1_res = (char *)malloc(64); for (unsigned int i = 0; i < SET; i++) { snprintf(s1_res, 64, "%s%u", uri, i); - z_owned_keyexpr_t expr = z_declare_keyexpr(z_loan(s1), z_keyexpr(s1_res)); - printf("Declared resource on session 1: %u %s\n", z_loan(expr)._id, z_loan(expr)._suffix); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, s1_res); + z_owned_keyexpr_t expr; + z_declare_keyexpr(&expr, z_loan(s1), z_loan(ke)); + printf("Declared resource on session 1: %u %.*s\n", z_loan(expr)->_id, + (int)z_string_len(&z_loan(expr)->_suffix), z_string_data(&z_loan(expr)->_suffix)); rids1[i] = expr; } @@ -160,8 +180,12 @@ int main(int argc, char **argv) { for (unsigned int i = 0; i < SET; i++) { snprintf(s1_res, 64, "%s%u", uri, i); - z_owned_keyexpr_t expr = z_declare_keyexpr(z_loan(s2), z_keyexpr(s1_res)); - printf("Declared resource on session 2: %u %s\n", z_loan(expr)._id, z_loan(expr)._suffix); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, s1_res); + z_owned_keyexpr_t expr; + z_declare_keyexpr(&expr, z_loan(s2), z_loan(ke)); + printf("Declared resource on session 2: %u %.*s\n", z_loan(expr)->_id, + (int)z_string_len(&z_loan(expr)->_suffix), z_string_data(&z_loan(expr)->_suffix)); rids2[i] = expr; } @@ -169,12 +193,13 @@ int main(int argc, char **argv) { // Declare subscribers and queryabales on second session for (unsigned int i = 0; i < SET; i++) { - z_owned_closure_sample_t callback = z_closure(data_handler, NULL, &idx[i]); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler, NULL, &idx[i]); z_owned_subscriber_t *sub = (z_owned_subscriber_t *)z_malloc(sizeof(z_owned_subscriber_t)); - *sub = z_declare_subscriber(z_loan(s2), z_loan(rids2[i]), &callback, NULL); - assert(z_check(*sub)); - printf("Declared subscription on session 2: %ju %u %s\n", (uintmax_t)z_subscriber_loan(sub)._val->_entity_id, - z_loan(rids2[i])._id, ""); + int8_t res = z_declare_subscriber(sub, z_loan(s2), z_loan(rids2[i]), z_move(callback), NULL); + assert(res == _Z_RES_OK); + printf("Declared subscription on session 2: %ju %u %s\n", (uintmax_t)z_subscriber_loan(sub)->_entity_id, + z_loan(rids2[i])->_id, ""); subs2 = _z_list_push(subs2, sub); } @@ -182,12 +207,13 @@ int main(int argc, char **argv) { for (unsigned int i = 0; i < SET; i++) { snprintf(s1_res, 64, "%s%u", uri, i); - z_owned_closure_query_t callback = z_closure(query_handler, NULL, &idx[i]); + z_owned_closure_query_t callback; + z_closure(&callback, query_handler, NULL, &idx[i]); z_owned_queryable_t *qle = (z_owned_queryable_t *)z_malloc(sizeof(z_owned_queryable_t)); - *qle = z_declare_queryable(z_loan(s2), z_keyexpr(s1_res), &callback, NULL); - assert(z_check(*qle)); - printf("Declared queryable on session 2: %ju %zu %s\n", (uintmax_t)qle->_value->_entity_id, (z_zint_t)0, - s1_res); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, s1_res); + assert(z_declare_queryable(qle, z_loan(s2), 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); qles2 = _z_list_push(qles2, qle); } @@ -196,8 +222,9 @@ int main(int argc, char **argv) { // Declare publisher on first session for (unsigned int i = 0; i < SET; i++) { z_owned_publisher_t *pub = (z_owned_publisher_t *)z_malloc(sizeof(z_owned_publisher_t)); - *pub = z_declare_publisher(z_loan(s1), z_loan(rids1[i]), NULL); - if (!z_check(*pub)) printf("Declared publisher on session 1: %zu\n", z_loan(*pub)._val->_id); + if (z_declare_publisher(pub, z_loan(s1), z_loan(rids1[i]), NULL) < 0) { + printf("Declared publisher on session 1: %zu\n", z_loan(*pub)->_id); + } pubs1 = _z_list_push(pubs1, pub); } @@ -205,16 +232,22 @@ int main(int argc, char **argv) { // Write data from first session size_t len = MSG_LEN; - uint8_t *payload = (uint8_t *)z_malloc(len); - memset(payload, 1, MSG_LEN); + uint8_t *value = (uint8_t *)z_malloc(len); + memset(value, 1, MSG_LEN); total = MSG * SET; for (unsigned int n = 0; n < MSG; n++) { for (unsigned int i = 0; i < SET; i++) { - z_put_options_t opt = z_put_options_default(); + z_put_options_t opt; + z_put_options_default(&opt); opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_put(z_loan(s1), z_loan(rids1[i]), (const uint8_t *)payload, len, &opt); - printf("Wrote data from session 1: %u %zu b\t(%u/%u)\n", z_loan(rids1[i])._id, len, n * SET + (i + 1), + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, len, NULL, NULL); + + z_put(z_loan(s1), z_loan(rids1[i]), z_move(payload), &opt); + printf("Wrote data from session 1: %u %zu b\t(%u/%u)\n", z_loan(rids1[i])->_id, len, n * SET + (i + 1), total); } } @@ -237,18 +270,24 @@ int main(int argc, char **argv) { // Write fragment data from first session if (is_reliable) { - z_free((uint8_t *)payload); + z_free((uint8_t *)value); len = FRAGMENT_MSG_LEN; - payload = (uint8_t *)z_malloc(len); - memset(payload, 1, FRAGMENT_MSG_LEN); + value = (uint8_t *)z_malloc(len); + memset(value, 1, FRAGMENT_MSG_LEN); total = FRAGMENT_MSG_NB * SET; for (unsigned int n = 0; n < FRAGMENT_MSG_NB; n++) { for (unsigned int i = 0; i < SET; i++) { - z_put_options_t opt = z_put_options_default(); + z_put_options_t opt; + z_put_options_default(&opt); opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_put(z_loan(s1), z_loan(rids1[i]), (const uint8_t *)payload, len, &opt); - printf("Wrote fragment data from session 1: %u %zu b\t(%u/%u)\n", z_loan(rids1[i])._id, len, + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, len, NULL, NULL); + + z_put(z_loan(s1), z_loan(rids1[i]), z_move(payload), &opt); + printf("Wrote fragment data from session 1: %u %zu b\t(%u/%u)\n", z_loan(rids1[i])->_id, len, n * SET + (i + 1), total); } } @@ -271,8 +310,11 @@ int main(int argc, char **argv) { for (unsigned int n = 0; n < QRY; n++) { for (unsigned int i = 0; i < SET; i++) { snprintf(s1_res, 64, "%s%u", uri, i); - z_owned_closure_reply_t callback = z_closure(reply_handler, NULL, &idx[i]); - z_get(z_loan(s1), z_keyexpr(s1_res), "", &callback, NULL); + z_owned_closure_reply_t callback; + z_closure(&callback, reply_handler, NULL, &idx[i]); + 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); } } @@ -309,7 +351,7 @@ int main(int argc, char **argv) { // Undeclare publishers on first session while (pubs1) { z_owned_publisher_t *pub = _z_list_head(pubs1); - printf("Undeclared publisher on session 2: %zu\n", z_loan(*pub)._val->_id); + printf("Undeclared publisher on session 2: %zu\n", z_loan(*pub)->_id); z_undeclare_publisher(z_move(*pub)); pubs1 = _z_list_pop(pubs1, _z_noop_elem_free, NULL); } @@ -319,7 +361,7 @@ int main(int argc, char **argv) { // Undeclare subscribers and queryables on second session while (subs2) { z_owned_subscriber_t *sub = _z_list_head(subs2); - printf("Undeclared subscriber on session 2: %ju\n", (uintmax_t)sub->_value->_entity_id); + printf("Undeclared subscriber on session 2: %ju\n", (uintmax_t)sub->_val._entity_id); z_undeclare_subscriber(z_move(*sub)); subs2 = _z_list_pop(subs2, _z_noop_elem_free, NULL); } @@ -328,7 +370,7 @@ int main(int argc, char **argv) { while (qles2) { z_owned_queryable_t *qle = _z_list_head(qles2); - printf("Undeclared queryable on session 2: %ju\n", (uintmax_t)qle->_value->_entity_id); + printf("Undeclared queryable on session 2: %ju\n", (uintmax_t)qle->_val._entity_id); z_undeclare_queryable(z_move(*qle)); qles2 = _z_list_pop(qles2, _z_noop_elem_free, NULL); } @@ -337,27 +379,25 @@ int main(int argc, char **argv) { // Undeclare resources on both sessions for (unsigned int i = 0; i < SET; i++) { - printf("Undeclared resource on session 1: %u\n", z_loan(rids1[i])._id); - z_undeclare_keyexpr(z_loan(s1), z_move(rids1[i])); + printf("Undeclared resource on session 1: %u\n", z_loan(rids1[i])->_id); + z_undeclare_keyexpr(z_move(rids1[i]), z_loan(s1)); } z_sleep_s(SLEEP); for (unsigned int i = 0; i < SET; i++) { - printf("Undeclared resource on session 2: %u\n", z_loan(rids2[i])._id); - z_undeclare_keyexpr(z_loan(s2), z_move(rids2[i])); + printf("Undeclared resource on session 2: %u\n", z_loan(rids2[i])->_id); + z_undeclare_keyexpr(z_move(rids2[i]), z_loan(s2)); } z_sleep_s(SLEEP); - // Stop both sessions - printf("Stopping threads on session 1\n"); - zp_stop_read_task(z_loan(s1)); - zp_stop_lease_task(z_loan(s1)); + // Stop read and lease tasks for zenoh-pico + zp_stop_read_task(z_loan_mut(s1)); + zp_stop_lease_task(z_loan_mut(s1)); - printf("Stopping threads on session 2\n"); - zp_stop_read_task(z_loan(s2)); - zp_stop_lease_task(z_loan(s2)); + zp_stop_read_task(z_loan_mut(s2)); + zp_stop_lease_task(z_loan_mut(s2)); // Close both sessions printf("Closing session 1\n"); @@ -368,8 +408,8 @@ int main(int argc, char **argv) { printf("Closing session 2\n"); z_close(z_move(s2)); - z_free((uint8_t *)payload); - payload = NULL; + z_free((uint8_t *)value); + value = NULL; free(s1_res); diff --git a/tests/z_collections_test.c b/tests/z_collections_test.c new file mode 100644 index 000000000..ec103b444 --- /dev/null +++ b/tests/z_collections_test.c @@ -0,0 +1,318 @@ +// +// 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 +#include +#include +#include + +#include "zenoh-pico/collections/fifo.h" +#include "zenoh-pico/collections/lifo.h" +#include "zenoh-pico/collections/ring.h" +#include "zenoh-pico/collections/string.h" + +#undef NDEBUG +#include + +char *a = "a"; +char *b = "b"; +char *c = "c"; +char *d = "d"; + +// RING +_Z_RING_DEFINE(_z_str, char) + +void print_ring(_z_str_ring_t *r) { + printf("Ring { capacity: %zu, r_idx: %zu, w_idx: %zu, len: %zu }\n", _z_str_ring_capacity(r), r->_r_idx, r->_w_idx, + _z_str_ring_len(r)); +} + +void ring_test(void) { + _z_str_ring_t r = _z_str_ring_make(3); + print_ring(&r); + assert(_z_str_ring_is_empty(&r)); + + // One + char *s = _z_str_ring_push(&r, a); + print_ring(&r); + assert(s == NULL); + assert(_z_str_ring_len(&r) == 1); + + s = _z_str_ring_pull(&r); + print_ring(&r); + assert(strcmp(a, s) == 0); + assert(_z_str_ring_is_empty(&r)); + + s = _z_str_ring_pull(&r); + print_ring(&r); + assert(s == NULL); + assert(_z_str_ring_is_empty(&r)); + + // Two + s = _z_str_ring_push(&r, a); + print_ring(&r); + assert(s == NULL); + assert(_z_str_ring_len(&r) == 1); + + s = _z_str_ring_push(&r, b); + print_ring(&r); + assert(s == NULL); + assert(_z_str_ring_len(&r) == 2); + + s = _z_str_ring_push(&r, c); + print_ring(&r); + assert(s == NULL); + assert(_z_str_ring_len(&r) == 3); + assert(_z_str_ring_is_full(&r)); + + s = _z_str_ring_push(&r, d); + print_ring(&r); + printf("%s == %s\n", d, s); + assert(strcmp(d, s) == 0); + assert(_z_str_ring_len(&r) == 3); + assert(_z_str_ring_is_full(&r)); + + s = _z_str_ring_push_force(&r, d); + print_ring(&r); + printf("%s == %s\n", a, s); + assert(strcmp(a, s) == 0); + assert(_z_str_ring_len(&r) == 3); + assert(_z_str_ring_is_full(&r)); + + s = _z_str_ring_push_force(&r, d); + print_ring(&r); + printf("%s == %s\n", b, s); + assert(strcmp(b, s) == 0); + assert(_z_str_ring_len(&r) == 3); + assert(_z_str_ring_is_full(&r)); + + s = _z_str_ring_push_force(&r, d); + print_ring(&r); + printf("%s == %s\n", c, s); + assert(strcmp(c, s) == 0); + assert(_z_str_ring_len(&r) == 3); + assert(_z_str_ring_is_full(&r)); + + s = _z_str_ring_pull(&r); + print_ring(&r); + printf("%s == %s\n", d, s); + assert(strcmp(d, s) == 0); + assert(_z_str_ring_len(&r) == 2); + + s = _z_str_ring_pull(&r); + print_ring(&r); + printf("%s == %s\n", d, s); + assert(strcmp(d, s) == 0); + assert(_z_str_ring_len(&r) == 1); + + s = _z_str_ring_pull(&r); + print_ring(&r); + printf("%s == %s\n", d, s); + assert(strcmp(d, s) == 0); + assert(_z_str_ring_is_empty(&r)); + + _z_str_ring_clear(&r); +} + +void ring_test_init_free(void) { + _z_str_ring_t *r = (_z_str_ring_t *)malloc(sizeof(_z_str_ring_t)); + _z_str_ring_init(r, 1); + assert(r != NULL); + + char *str = (char *)calloc(1, sizeof(char)); + _z_str_ring_push_force_drop(r, str); + + _z_str_ring_free(&r); + assert(r == NULL); +} + +// LIFO +_Z_LIFO_DEFINE(_z_str, char) + +void print_lifo(_z_str_lifo_t *r) { + printf("Lifo { capacity: %zu, len: %zu }\n", _z_str_lifo_capacity(r), _z_str_lifo_len(r)); +} + +void lifo_test(void) { + _z_str_lifo_t r = _z_str_lifo_make(3); + print_lifo(&r); + assert(_z_str_lifo_is_empty(&r)); + + // One + char *s = _z_str_lifo_push(&r, a); + print_lifo(&r); + assert(s == NULL); + assert(_z_str_lifo_len(&r) == 1); + + s = _z_str_lifo_pull(&r); + print_lifo(&r); + printf("%s == %s\n", a, s); + assert(strcmp(a, s) == 0); + assert(_z_str_lifo_is_empty(&r)); + + s = _z_str_lifo_pull(&r); + print_lifo(&r); + assert(s == NULL); + assert(_z_str_lifo_is_empty(&r)); + + // Two + s = _z_str_lifo_push(&r, a); + print_lifo(&r); + assert(s == NULL); + assert(_z_str_lifo_len(&r) == 1); + + s = _z_str_lifo_push(&r, b); + print_lifo(&r); + assert(s == NULL); + assert(_z_str_lifo_len(&r) == 2); + + s = _z_str_lifo_push(&r, c); + print_lifo(&r); + assert(s == NULL); + assert(_z_str_lifo_len(&r) == 3); + assert(_z_str_lifo_is_full(&r)); + + s = _z_str_lifo_push(&r, d); + print_lifo(&r); + printf("%s == %s\n", d, s); + assert(strcmp(d, s) == 0); + assert(_z_str_lifo_len(&r) == 3); + assert(_z_str_lifo_is_full(&r)); + + s = _z_str_lifo_pull(&r); + print_lifo(&r); + printf("%s == %s\n", c, s); + assert(strcmp(c, s) == 0); + assert(_z_str_lifo_len(&r) == 2); + + s = _z_str_lifo_pull(&r); + print_lifo(&r); + printf("%s == %s\n", b, s); + assert(strcmp(b, s) == 0); + assert(_z_str_lifo_len(&r) == 1); + + s = _z_str_lifo_pull(&r); + print_lifo(&r); + printf("%s == %s\n", a, s); + assert(strcmp(a, s) == 0); + assert(_z_str_lifo_is_empty(&r)); + + _z_str_lifo_clear(&r); +} + +void lifo_test_init_free(void) { + _z_str_lifo_t *r = (_z_str_lifo_t *)malloc(sizeof(_z_str_lifo_t)); + _z_str_lifo_init(r, 1); + assert(r != NULL); + + char *str = (char *)calloc(1, sizeof(char)); + _z_str_lifo_push_drop(r, str); + + _z_str_lifo_free(&r); + assert(r == NULL); +} + +// FIFO +_Z_FIFO_DEFINE(_z_str, char) + +void print_fifo(_z_str_fifo_t *r) { + printf("Fifo { capacity: %zu, len: %zu }\n", _z_str_fifo_capacity(r), _z_str_fifo_len(r)); +} + +void fifo_test(void) { + _z_str_fifo_t r = _z_str_fifo_make(3); + print_fifo(&r); + assert(_z_str_fifo_is_empty(&r)); + + // One + char *s = _z_str_fifo_push(&r, a); + print_fifo(&r); + assert(s == NULL); + assert(_z_str_fifo_len(&r) == 1); + + s = _z_str_fifo_pull(&r); + print_fifo(&r); + printf("%s == %s\n", a, s); + assert(strcmp(a, s) == 0); + assert(_z_str_fifo_is_empty(&r)); + + s = _z_str_fifo_pull(&r); + print_fifo(&r); + assert(s == NULL); + assert(_z_str_fifo_is_empty(&r)); + + // Two + s = _z_str_fifo_push(&r, a); + print_fifo(&r); + assert(s == NULL); + assert(_z_str_fifo_len(&r) == 1); + + s = _z_str_fifo_push(&r, b); + print_fifo(&r); + assert(s == NULL); + assert(_z_str_fifo_len(&r) == 2); + + s = _z_str_fifo_push(&r, c); + print_fifo(&r); + assert(s == NULL); + assert(_z_str_fifo_len(&r) == 3); + assert(_z_str_fifo_is_full(&r)); + + s = _z_str_fifo_push(&r, d); + print_fifo(&r); + printf("%s == %s\n", d, s); + assert(strcmp(d, s) == 0); + assert(_z_str_fifo_len(&r) == 3); + assert(_z_str_fifo_is_full(&r)); + + s = _z_str_fifo_pull(&r); + print_fifo(&r); + printf("%s == %s\n", a, s); + assert(strcmp(a, s) == 0); + assert(_z_str_fifo_len(&r) == 2); + + s = _z_str_fifo_pull(&r); + print_fifo(&r); + printf("%s == %s\n", b, s); + assert(strcmp(b, s) == 0); + assert(_z_str_fifo_len(&r) == 1); + + s = _z_str_fifo_pull(&r); + print_fifo(&r); + printf("%s == %s\n", c, s); + assert(strcmp(c, s) == 0); + assert(_z_str_fifo_is_empty(&r)); + + _z_str_fifo_clear(&r); +} + +void fifo_test_init_free(void) { + _z_str_fifo_t *r = (_z_str_fifo_t *)malloc(sizeof(_z_str_fifo_t)); + _z_str_fifo_init(r, 1); + assert(r != NULL); + + char *str = (char *)calloc(1, sizeof(char)); + _z_str_fifo_push_drop(r, str); + + _z_str_fifo_free(&r); + assert(r == NULL); +} + +int main(void) { + ring_test(); + ring_test_init_free(); + lifo_test(); + lifo_test_init_free(); + fifo_test(); + fifo_test_init_free(); +} diff --git a/tests/z_data_struct_test.c b/tests/z_data_struct_test.c index 461ee92ca..2e18098dd 100644 --- a/tests/z_data_struct_test.c +++ b/tests/z_data_struct_test.c @@ -48,8 +48,7 @@ void entry_list_test(void) { _z_transport_peer_entry_list_free(&root); } -int main(void) { - entry_list_test(); +void str_vec_list_intmap_test(void) { char *s = (char *)malloc(64); size_t len = 128; @@ -140,6 +139,38 @@ int main(void) { _z_str_intmap_clear(&map); assert(_z_str_intmap_is_empty(&map) == true); +} + +void _z_slice_custom_deleter(void *data, void *context) { + _ZP_UNUSED(data); + size_t *cnt = (size_t *)context; + (*cnt)++; +} + +void z_slice_custom_delete_test(void) { + size_t counter = 0; + uint8_t data[5] = {1, 2, 3, 4, 5}; + _z_delete_context_t dc = (_z_delete_context_t){.deleter = _z_slice_custom_deleter, .context = &counter}; + _z_slice_t s1 = _z_slice_from_buf_custom_deleter(data, 5, dc); + _z_slice_t s2 = _z_slice_from_buf_custom_deleter(data, 5, dc); + _z_slice_t s3 = _z_slice_copy_from_buf(data, 5); + _z_slice_t s4 = _z_slice_alias_buf(data, 5); + assert(_z_slice_is_alloced(&s1)); + assert(_z_slice_is_alloced(&s2)); + assert(_z_slice_is_alloced(&s3)); + assert(!_z_slice_is_alloced(&s4)); + + _z_slice_clear(&s1); + _z_slice_clear(&s2); + _z_slice_clear(&s3); + _z_slice_clear(&s4); + assert(counter == 2); +} + +int main(void) { + entry_list_test(); + str_vec_list_intmap_test(); + z_slice_custom_delete_test(); return 0; } diff --git a/tests/z_endpoint_test.c b/tests/z_endpoint_test.c index 621955c9d..4252b0665 100644 --- a/tests/z_endpoint_test.c +++ b/tests/z_endpoint_test.c @@ -25,116 +25,88 @@ #include int main(void) { - char *s = (char *)malloc(64); - // Locator printf(">>> Testing locators...\n"); - int8_t ret = _Z_RES_OK; _z_locator_t lc; - snprintf(s, 64, "tcp/127.0.0.1:7447"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_RES_OK); - assert(_z_str_eq(lc._protocol, "tcp") == true); - assert(_z_str_eq(lc._address, "127.0.0.1:7447") == true); + _z_string_t str = _z_string_alias_str("tcp/127.0.0.1:7447"); + assert(_z_locator_from_string(&lc, &str) == _Z_RES_OK); + + str = _z_string_alias_str("tcp"); + assert(_z_string_equals(&lc._protocol, &str) == true); + str = _z_string_alias_str("127.0.0.1:7447"); + assert(_z_string_equals(&lc._address, &str) == true); assert(_z_str_intmap_is_empty(&lc._metadata) == true); _z_locator_clear(&lc); - s[0] = '\0'; // snprintf(s, ""); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str(""); + assert(_z_locator_from_string(&lc, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "/"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, "/"); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("/"); + assert(_z_locator_from_string(&lc, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "tcp"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("tcp"); + assert(_z_locator_from_string(&lc, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "tcp/"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("tcp/"); + assert(_z_locator_from_string(&lc, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "127.0.0.1:7447"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("127.0.0.1:7447"); + assert(_z_locator_from_string(&lc, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "tcp/127.0.0.1:7447?"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_RES_OK); + str = _z_string_alias_str("tcp/127.0.0.1:7447?"); + assert(_z_locator_from_string(&lc, &str) == _Z_RES_OK); // No metadata defined so far... but this is a valid syntax in principle - snprintf(s, 64, "tcp/127.0.0.1:7447?invalid=ctrl"); - printf("- %s\n", s); - ret = _z_locator_from_str(&lc, s); - assert(ret == _Z_RES_OK); + str = _z_string_alias_str("tcp/127.0.0.1:7447?invalid=ctrl"); + assert(_z_locator_from_string(&lc, &str) == _Z_RES_OK); // Endpoint printf(">>> Testing endpoints...\n"); _z_endpoint_t ep; - snprintf(s, 64, "tcp/127.0.0.1:7447"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); - assert(_z_str_eq(ep._locator._protocol, "tcp") == true); - assert(_z_str_eq(ep._locator._address, "127.0.0.1:7447") == true); + str = _z_string_alias_str("tcp/127.0.0.1:7447"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); + + str = _z_string_alias_str("tcp"); + assert(_z_string_equals(&ep._locator._protocol, &str) == true); + str = _z_string_alias_str("127.0.0.1:7447"); + assert(_z_string_equals(&ep._locator._address, &str) == true); assert(_z_str_intmap_is_empty(&ep._locator._metadata) == true); assert(_z_str_intmap_is_empty(&ep._config) == true); _z_endpoint_clear(&ep); - s[0] = '\0'; // snprintf(s, ""); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str(""); + assert(_z_endpoint_from_string(&ep, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "/"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("/"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "tcp"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("tcp"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "tcp"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("tcp/"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "127.0.0.1:7447"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_ERR_MESSAGE_DESERIALIZATION_FAILED); + str = _z_string_alias_str("127.0.0.1:7447"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_ERR_CONFIG_LOCATOR_INVALID); - snprintf(s, 64, "tcp/127.0.0.1:7447?"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); + str = _z_string_alias_str("tcp/127.0.0.1:7447?"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); // No metadata defined so far... but this is a valid syntax in principle - snprintf(s, 64, "tcp/127.0.0.1:7447?invalid=ctrl"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); - - snprintf(s, 64, "udp/127.0.0.1:7447#%s=eth0", UDP_CONFIG_IFACE_STR); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); - assert(_z_str_eq(ep._locator._protocol, "udp") == true); - assert(_z_str_eq(ep._locator._address, "127.0.0.1:7447") == true); + str = _z_string_alias_str("tcp/127.0.0.1:7447?invalid=ctrl"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); + + str = _z_string_alias_str("udp/127.0.0.1:7447#iface=eth0"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); + + str = _z_string_alias_str("udp"); + assert(_z_string_equals(&ep._locator._protocol, &str) == true); + str = _z_string_alias_str("127.0.0.1:7447"); + assert(_z_string_equals(&ep._locator._address, &str) == true); assert(_z_str_intmap_is_empty(&ep._locator._metadata) == true); assert(_z_str_intmap_len(&ep._config) == 1); char *p = _z_str_intmap_get(&ep._config, UDP_CONFIG_IFACE_KEY); @@ -142,20 +114,14 @@ int main(void) { (void)(p); _z_endpoint_clear(&ep); - snprintf(s, 64, "udp/127.0.0.1:7447#invalid=eth0"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); + str = _z_string_alias_str("udp/127.0.0.1:7447#invalid=eth0"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); - snprintf(s, 64, "udp/127.0.0.1:7447?invalid=ctrl#%s=eth0", UDP_CONFIG_IFACE_STR); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); + str = _z_string_alias_str("udp/127.0.0.1:7447?invalid=ctrl#iface=eth0"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); - snprintf(s, 64, "udp/127.0.0.1:7447?invalid=ctrl#invalid=eth0"); - printf("- %s\n", s); - ret = _z_endpoint_from_str(&ep, s); - assert(ret == _Z_RES_OK); + str = _z_string_alias_str("udp/127.0.0.1:7447?invalid=ctrl#invalid=eth0"); + assert(_z_endpoint_from_string(&ep, &str) == _Z_RES_OK); return 0; } diff --git a/tests/z_keyexpr_test.c b/tests/z_keyexpr_test.c index 1539b75a5..ff5a01a86 100644 --- a/tests/z_keyexpr_test.c +++ b/tests/z_keyexpr_test.c @@ -20,269 +20,187 @@ #undef NDEBUG #include -int main(void) { - assert(_z_keyexpr_intersects("a", strlen("a"), "a", strlen("a"))); - assert(_z_keyexpr_intersects("a/b", strlen("a/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("*", strlen("*"), "abc", strlen("abc"))); - assert(_z_keyexpr_intersects("*", strlen("*"), "abc", strlen("abc"))); - assert(_z_keyexpr_intersects("*", strlen("*"), "abc", strlen("abc"))); - assert(_z_keyexpr_intersects("*", strlen("*"), "xxx", strlen("xxx"))); - assert(_z_keyexpr_intersects("ab$*", strlen("ab$*"), "abcd", strlen("abcd"))); - assert(_z_keyexpr_intersects("ab$*d", strlen("ab$*d"), "abcd", strlen("abcd"))); - assert(!_z_keyexpr_intersects("ab$*d", strlen("ab$*d"), "abcde", strlen("abcde"))); - assert(_z_keyexpr_intersects("ab$*", strlen("ab$*"), "ab", strlen("ab"))); - assert(!_z_keyexpr_intersects("ab/*", strlen("ab/*"), "ab", strlen("ab"))); - assert(_z_keyexpr_intersects("a/*/c/*/e", strlen("a/*/c/*/e"), "a/b/c/d/e", strlen("a/b/c/d/e"))); - assert(_z_keyexpr_intersects("a/**/d/**/l", strlen("a/**/d/**/l"), "a/b/c/d/e/f/g/h/i/l", - strlen("a/b/c/d/e/f/g/h/i/l"))); - assert(_z_keyexpr_intersects("a/**/d/**/l", strlen("a/**/d/**/l"), "a/d/foo/l", strlen("a/d/foo/l"))); - assert(_z_keyexpr_intersects("a/$*b/c/$*d/e", strlen("a/$*b/c/$*d/e"), "a/xb/c/xd/e", strlen("a/xb/c/xd/e"))); - assert(!_z_keyexpr_intersects("a/*/c/*/e", strlen("a/*/c/*/e"), "a/c/e", strlen("a/c/e"))); - assert(!_z_keyexpr_intersects("a/*/c/*/e", strlen("a/*/c/*/e"), "a/b/c/d/x/e", strlen("a/b/c/d/x/e"))); - assert(!_z_keyexpr_intersects("ab$*cd", strlen("ab$*cd"), "abxxcxxd", strlen("abxxcxxd"))); - assert(_z_keyexpr_intersects("ab$*cd", strlen("ab$*cd"), "abxxcxxcd", strlen("abxxcxxcd"))); - assert(!_z_keyexpr_intersects("ab$*cd", strlen("ab$*cd"), "abxxcxxcdx", strlen("abxxcxxcdx"))); - assert(_z_keyexpr_intersects("**", strlen("**"), "abc", strlen("abc"))); - assert(_z_keyexpr_intersects("**", strlen("**"), "a/b/c", strlen("a/b/c"))); - assert(_z_keyexpr_intersects("ab/**", strlen("ab/**"), "ab", strlen("ab"))); - assert(_z_keyexpr_intersects("**/xyz", strlen("**/xyz"), "a/b/xyz/d/e/f/xyz", strlen("a/b/xyz/d/e/f/xyz"))); - assert( - !_z_keyexpr_intersects("**/xyz$*xyz", strlen("**/xyz$*xyz"), "a/b/xyz/d/e/f/xyz", strlen("a/b/xyz/d/e/f/xyz"))); - assert( - _z_keyexpr_intersects("a/**/c/**/e", strlen("a/**/c/**/e"), "a/b/b/b/c/d/d/d/e", strlen("a/b/b/b/c/d/d/d/e"))); - assert(_z_keyexpr_intersects("a/**/c/**/e", strlen("a/**/c/**/e"), "a/c/e", strlen("a/c/e"))); - assert(_z_keyexpr_intersects("a/**/c/*/e/*", strlen("a/**/c/*/e/*"), "a/b/b/b/c/d/d/c/d/e/f", - strlen("a/b/b/b/c/d/d/c/d/e/f"))); - assert(!_z_keyexpr_intersects("a/**/c/*/e/*", strlen("a/**/c/*/e/*"), "a/b/b/b/c/d/d/c/d/d/e/f", - strlen("a/b/b/b/c/d/d/c/d/d/e/f"))); - assert(!_z_keyexpr_intersects("ab$*cd", strlen("ab$*cd"), "abxxcxxcdx", strlen("abxxcxxcdx"))); - assert(_z_keyexpr_intersects("x/abc", strlen("x/abc"), "x/abc", strlen("x/abc"))); - assert(!_z_keyexpr_intersects("x/abc", strlen("x/abc"), "abc", strlen("abc"))); - assert(_z_keyexpr_intersects("x/*", strlen("x/*"), "x/abc", strlen("x/abc"))); - assert(!_z_keyexpr_intersects("x/*", strlen("x/*"), "abc", strlen("abc"))); - assert(!_z_keyexpr_intersects("*", strlen("*"), "x/abc", strlen("x/abc"))); - assert(_z_keyexpr_intersects("x/*", strlen("x/*"), "x/abc$*", strlen("x/abc$*"))); - assert(_z_keyexpr_intersects("x/$*abc", strlen("x/$*abc"), "x/abc$*", strlen("x/abc$*"))); - assert(_z_keyexpr_intersects("x/a$*", strlen("x/a$*"), "x/abc$*", strlen("x/abc$*"))); - assert(_z_keyexpr_intersects("x/a$*de", strlen("x/a$*de"), "x/abc$*de", strlen("x/abc$*de"))); - assert(_z_keyexpr_intersects("x/a$*d$*e", strlen("x/a$*d$*e"), "x/a$*e", strlen("x/a$*e"))); - assert(_z_keyexpr_intersects("x/a$*d$*e", strlen("x/a$*d$*e"), "x/a$*c$*e", strlen("x/a$*c$*e"))); - assert(_z_keyexpr_intersects("x/a$*d$*e", strlen("x/a$*d$*e"), "x/ade", strlen("x/ade"))); - assert(!_z_keyexpr_intersects("x/c$*", strlen("x/c$*"), "x/abc$*", strlen("x/abc$*"))); - assert(!_z_keyexpr_intersects("x/$*d", strlen("x/$*d"), "x/$*e", strlen("x/$*e"))); - assert(_z_keyexpr_intersects("a", strlen("a"), "a", strlen("a"))); - assert(_z_keyexpr_intersects("a/b", strlen("a/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("*", strlen("*"), "a", strlen("a"))); - assert(_z_keyexpr_intersects("a", strlen("a"), "*", strlen("*"))); - assert(_z_keyexpr_intersects("*", strlen("*"), "aaaaa", strlen("aaaaa"))); - assert(_z_keyexpr_intersects("**", strlen("**"), "a", strlen("a"))); - assert(_z_keyexpr_intersects("a", strlen("a"), "**", strlen("**"))); - assert(_z_keyexpr_intersects("**", strlen("**"), "a", strlen("a"))); - assert(_z_keyexpr_intersects("a/a/a/a", strlen("a/a/a/a"), "**", strlen("**"))); - assert(_z_keyexpr_intersects("a/*", strlen("a/*"), "a/b", strlen("a/b"))); - assert(!_z_keyexpr_intersects("a/*/b", strlen("a/*/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/**/b", strlen("a/**/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/b$*", strlen("a/b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/$*b$*", strlen("a/$*b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/$*b", strlen("a/$*b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/b$*", strlen("a/b$*"), "a/bc", strlen("a/bc"))); - assert(_z_keyexpr_intersects("a/$*b$*", strlen("a/$*b$*"), "a/ebc", strlen("a/ebc"))); - assert(_z_keyexpr_intersects("a/$*b", strlen("a/$*b"), "a/cb", strlen("a/cb"))); - assert(!_z_keyexpr_intersects("a/b$*", strlen("a/b$*"), "a/ebc", strlen("a/ebc"))); - assert(!_z_keyexpr_intersects("a/$*b", strlen("a/$*b"), "a/cbc", strlen("a/cbc"))); - assert(_z_keyexpr_intersects("a/**/b$*", strlen("a/**/b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/**/$*b$*", strlen("a/**/$*b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/**/$*b", strlen("a/**/$*b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_intersects("a/**/b$*", strlen("a/**/b$*"), "a/bc", strlen("a/bc"))); - assert(_z_keyexpr_intersects("a/**/$*b$*", strlen("a/**/$*b$*"), "a/ebc", strlen("a/ebc"))); - assert(_z_keyexpr_intersects("a/**/$*b", strlen("a/**/$*b"), "a/cb", strlen("a/cb"))); - assert(_z_keyexpr_intersects("a/**/b/c/**/d", strlen("a/**/b/c/**/d"), "a/b/b/b/c/d", strlen("a/b/b/b/c/d"))); - assert( - !_z_keyexpr_intersects("a/**/b/c/**/d", strlen("a/**/b/c/**/d"), "a/b/b/b/c/@c/d", strlen("a/b/b/b/c/@c/d"))); - assert(!_z_keyexpr_intersects("a/**/b/c/**/d", strlen("a/**/b/c/**/d"), "a/b/@b/b/c/d", strlen("a/b/@b/b/c/d"))); - assert(_z_keyexpr_intersects("a/**/b/@b/**/b/c/**/d", strlen("a/**/b/@b/**/b/c/**/d"), "a/b/@b/b/c/d", - strlen("a/b/@b/b/c/d"))); - assert(!_z_keyexpr_intersects("a/**/b$*", strlen("a/**/b$*"), "a/ebc", strlen("a/ebc"))); - assert(!_z_keyexpr_intersects("a/**/$*b", strlen("a/**/$*b"), "a/cbc", strlen("a/cbc"))); - - assert(zp_keyexpr_intersect_null_terminated("a", "a") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/b", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("*", "abc") == 0); - assert(zp_keyexpr_intersect_null_terminated("*", "abc") == 0); - assert(zp_keyexpr_intersect_null_terminated("*", "abc") == 0); - assert(zp_keyexpr_intersect_null_terminated("*", "xxx") == 0); - assert(zp_keyexpr_intersect_null_terminated("ab$*", "abcd") == 0); - assert(zp_keyexpr_intersect_null_terminated("ab$*d", "abcd") == 0); - assert(zp_keyexpr_intersect_null_terminated("ab$*", "ab") == 0); - assert(zp_keyexpr_intersect_null_terminated("ab/*", "ab") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/*/c/*/e", "a/b/c/d/e") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/d/**/l", "a/b/c/d/e/f/g/h/i/l") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/d/**/l", "a/d/foo/l") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/$*b/c/$*d/e", "a/xb/c/xd/e") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/*/c/*/e", "a/c/e") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/*/c/*/e", "a/b/c/d/x/e") == -1); - assert(zp_keyexpr_intersect_null_terminated("ab$*cd", "abxxcxxd") == -1); - assert(zp_keyexpr_intersect_null_terminated("ab$*cd", "abxxcxxcd") == 0); - assert(zp_keyexpr_intersect_null_terminated("ab$*cd", "abxxcxxcdx") == -1); - assert(zp_keyexpr_intersect_null_terminated("**", "abc") == 0); - assert(zp_keyexpr_intersect_null_terminated("**", "a/b/c") == 0); - assert(zp_keyexpr_intersect_null_terminated("ab/**", "ab") == 0); - assert(zp_keyexpr_intersect_null_terminated("**/xyz", "a/b/xyz/d/e/f/xyz") == 0); - assert(zp_keyexpr_intersect_null_terminated("**/xyz$*xyz", "a/b/xyz/d/e/f/xyz") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/**/c/**/e", "a/b/b/b/c/d/d/d/e") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/c/**/e", "a/c/e") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/c/*/e/*", "a/b/b/b/c/d/d/c/d/e/f") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/c/*/e/*", "a/b/b/b/c/d/d/c/d/d/e/f") == -1); - assert(zp_keyexpr_intersect_null_terminated("ab$*cd", "abxxcxxcdx") == -1); - assert(zp_keyexpr_intersect_null_terminated("x/abc", "x/abc") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/abc", "abc") == -1); - assert(zp_keyexpr_intersect_null_terminated("x/*", "x/abc") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/*", "abc") == -1); - assert(zp_keyexpr_intersect_null_terminated("*", "x/abc") == -1); - assert(zp_keyexpr_intersect_null_terminated("x/*", "x/abc$*") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/$*abc", "x/abc$*") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/a$*", "x/abc$*") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/a$*de", "x/abc$*de") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/a$*d$*e", "x/a$*e") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/a$*d$*e", "x/a$*c$*e") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/a$*d$*e", "x/ade") == 0); - assert(zp_keyexpr_intersect_null_terminated("x/c$*", "x/abc$*") == -1); - assert(zp_keyexpr_intersect_null_terminated("x/$*d", "x/$*e") == -1); - assert(zp_keyexpr_intersect_null_terminated("a", "a") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/b", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("*", "a") == 0); - assert(zp_keyexpr_intersect_null_terminated("a", "*") == 0); - assert(zp_keyexpr_intersect_null_terminated("*", "aaaaa") == 0); - assert(zp_keyexpr_intersect_null_terminated("**", "a") == 0); - assert(zp_keyexpr_intersect_null_terminated("a", "**") == 0); - assert(zp_keyexpr_intersect_null_terminated("**", "a") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/a/a/a", "**") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/*", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/*/b", "a/b") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/**/b", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/b$*", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/$*b$*", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/$*b", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/b$*", "a/bc") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/$*b$*", "a/ebc") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/$*b", "a/cb") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/b$*", "a/ebc") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/$*b", "a/cbc") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/**/b$*", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/$*b$*", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/$*b", "a/b") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/b$*", "a/bc") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/$*b$*", "a/ebc") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/$*b", "a/cb") == 0); - assert(zp_keyexpr_intersect_null_terminated("a/**/b$*", "a/ebc") == -1); - assert(zp_keyexpr_intersect_null_terminated("a/**/$*b", "a/cbc") == -1); - - assert((zp_keyexpr_intersect_null_terminated("@a", "@a") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a", "@ab") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a", "@a/b") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a", "@a/*") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a", "@a/*/**") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a", "@a$*/**") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a", "@a/**") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("**/xyz$*xyz", "@a/b/xyzdefxyz") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a/**/c/**/e", "@a/@b/b/b/c/d/d/d/e") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/@c/**/e", "@a/b/b/b/@c/d/d/d/e") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/e", "@a/b/b/d/d/d/e") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/e", "@a/b/b/b/d/d/d/e") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/e", "@a/b/b/c/d/d/d/e") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a/**/e", "@a/b/b/@c/b/d/d/d/e") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a/*", "@a/@b") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a/**", "@a/@b") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/@b", "@a/@b") == 0)); - assert(!(zp_keyexpr_intersect_null_terminated("@a/**/@b", "@a/**/@c/**/@b") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/@b/**", "@a/@b") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/@c/@b", "@a/**/@c/**/@b") == 0)); - assert((zp_keyexpr_intersect_null_terminated("@a/**/@c/**/@b", "@a/**/@c/@b") == 0)); - - assert(_z_keyexpr_includes("a", strlen("a"), "a", strlen("a"))); - assert(_z_keyexpr_includes("a/b", strlen("a/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("*", strlen("*"), "a", strlen("a"))); - assert(!_z_keyexpr_includes("a", strlen("a"), "*", strlen("*"))); - assert(_z_keyexpr_includes("*", strlen("*"), "aaaaa", strlen("aaaaa"))); - assert(_z_keyexpr_includes("**", strlen("**"), "a", strlen("a"))); - assert(!_z_keyexpr_includes("a", strlen("a"), "**", strlen("**"))); - assert(_z_keyexpr_includes("**", strlen("**"), "a", strlen("a"))); - assert(_z_keyexpr_includes("**", strlen("**"), "a/a/a/a", strlen("a/a/a/a"))); - assert(_z_keyexpr_includes("**", strlen("**"), "*/**", strlen("*/**"))); - assert(_z_keyexpr_includes("*/**", strlen("*/**"), "*/**", strlen("*/**"))); - assert(!_z_keyexpr_includes("*/**", strlen("*/**"), "**", strlen("**"))); - assert(!_z_keyexpr_includes("a/a/a/a", strlen("a/a/a/a"), "**", strlen("**"))); - assert(_z_keyexpr_includes("a/*", strlen("a/*"), "a/b", strlen("a/b"))); - assert(!_z_keyexpr_includes("a/*/b", strlen("a/*/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/**/b", strlen("a/**/b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/b$*", strlen("a/b$*"), "a/b", strlen("a/b"))); - assert(!_z_keyexpr_includes("a/b", strlen("a/b"), "a/b$*", strlen("a/b$*"))); - assert(_z_keyexpr_includes("a/$*b$*", strlen("a/$*b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/$*b", strlen("a/$*b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/b$*", strlen("a/b$*"), "a/bc", strlen("a/bc"))); - assert(_z_keyexpr_includes("a/$*b$*", strlen("a/$*b$*"), "a/ebc", strlen("a/ebc"))); - assert(_z_keyexpr_includes("a/$*b", strlen("a/$*b"), "a/cb", strlen("a/cb"))); - assert(!_z_keyexpr_includes("a/b$*", strlen("a/b$*"), "a/ebc", strlen("a/ebc"))); - assert(!_z_keyexpr_includes("a/$*b", strlen("a/$*b"), "a/cbc", strlen("a/cbc"))); - assert(_z_keyexpr_includes("a/**/b$*", strlen("a/**/b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/**/$*b$*", strlen("a/**/$*b$*"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/**/$*b", strlen("a/**/$*b"), "a/b", strlen("a/b"))); - assert(_z_keyexpr_includes("a/**/b$*", strlen("a/**/b$*"), "a/bc", strlen("a/bc"))); - assert(_z_keyexpr_includes("a/**/$*b$*", strlen("a/**/$*b$*"), "a/ebc", strlen("a/ebc"))); - assert(_z_keyexpr_includes("a/**/$*b", strlen("a/**/$*b"), "a/cb", strlen("a/cb"))); - assert(!_z_keyexpr_includes("a/**/b$*", strlen("a/**/b$*"), "a/ebc", strlen("a/ebc"))); - assert(!_z_keyexpr_includes("a/**/$*b", strlen("a/**/$*b"), "a/cbc", strlen("a/cbc"))); - - assert(zp_keyexpr_includes_null_terminated("a", "a") == 0); - assert(zp_keyexpr_includes_null_terminated("a/b", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("*", "a") == 0); - assert(zp_keyexpr_includes_null_terminated("a", "*") == -1); - assert(zp_keyexpr_includes_null_terminated("*", "aaaaa") == 0); - assert(zp_keyexpr_includes_null_terminated("**", "a") == 0); - assert(zp_keyexpr_includes_null_terminated("a", "**") == -1); - assert(zp_keyexpr_includes_null_terminated("**", "a") == 0); - assert(zp_keyexpr_includes_null_terminated("**", "a/a/a/a") == 0); - assert(zp_keyexpr_includes_null_terminated("**", "*/**") == 0); - assert(zp_keyexpr_includes_null_terminated("*/**", "*/**") == 0); - assert(zp_keyexpr_includes_null_terminated("*/**", "**") == -1); - assert(zp_keyexpr_includes_null_terminated("a/a/a/a", "**") == -1); - assert(zp_keyexpr_includes_null_terminated("a/*", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/*/b", "a/b") == -1); - assert(zp_keyexpr_includes_null_terminated("a/**/b", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/b$*", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/b", "a/b$*") == -1); - assert(zp_keyexpr_includes_null_terminated("a/$*b$*", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/$*b", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/b$*", "a/bc") == 0); - assert(zp_keyexpr_includes_null_terminated("a/$*b$*", "a/ebc") == 0); - assert(zp_keyexpr_includes_null_terminated("a/$*b", "a/cb") == 0); - assert(zp_keyexpr_includes_null_terminated("a/b$*", "a/ebc") == -1); - assert(zp_keyexpr_includes_null_terminated("a/$*b", "a/cbc") == -1); - assert(zp_keyexpr_includes_null_terminated("a/**/b$*", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/**/$*b$*", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/**/$*b", "a/b") == 0); - assert(zp_keyexpr_includes_null_terminated("a/**/b$*", "a/bc") == 0); - assert(zp_keyexpr_includes_null_terminated("a/**/$*b$*", "a/ebc") == 0); - assert(zp_keyexpr_includes_null_terminated("a/**/$*b", "a/cb") == 0); - assert(zp_keyexpr_includes_null_terminated("a/**/b$*", "a/ebc") == -1); - assert(zp_keyexpr_includes_null_terminated("a/**/$*b", "a/cbc") == -1); - - assert((zp_keyexpr_includes_null_terminated("@a", "@a") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a", "@ab") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/b") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/*") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/*/**") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a$*/**", "@a") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a", "@a/**") == 0)); - assert((zp_keyexpr_includes_null_terminated("@a/**", "@a") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("**/xyz$*xyz", "@a/b/xyzdefxyz") == 0)); - assert((zp_keyexpr_includes_null_terminated("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a/*", "@a/@b") == 0)); - assert(!(zp_keyexpr_includes_null_terminated("@a/**", "@a/@b") == 0)); - assert((zp_keyexpr_includes_null_terminated("@a/**/@b", "@a/@b") == 0)); - assert((zp_keyexpr_includes_null_terminated("@a/@b/**", "@a/@b") == 0)); +#define TEST_TRUE_INTERSECT(a, b) \ + ke_a = _z_rname(a); \ + ke_b = _z_rname(b); \ + assert(_z_keyexpr_suffix_intersects(&ke_a, &ke_b)); + +#define TEST_FALSE_INTERSECT(a, b) \ + ke_a = _z_rname(a); \ + ke_b = _z_rname(b); \ + assert(!_z_keyexpr_suffix_intersects(&ke_a, &ke_b)); + +#define TEST_TRUE_INCLUDE(a, b) \ + ke_a = _z_rname(a); \ + ke_b = _z_rname(b); \ + assert(_z_keyexpr_suffix_includes(&ke_a, &ke_b)); + +#define TEST_FALSE_INCLUDE(a, b) \ + ke_a = _z_rname(a); \ + ke_b = _z_rname(b); \ + assert(!_z_keyexpr_suffix_includes(&ke_a, &ke_b)); + +#define TEST_TRUE_EQUAL(a, b) \ + ke_a = _z_rname(a); \ + ke_b = _z_rname(b); \ + assert(_z_keyexpr_suffix_equals(&ke_a, &ke_b)); + +#define TEST_FALSE_EQUAL(a, b) \ + ke_a = _z_rname(a); \ + ke_b = _z_rname(b); \ + assert(!_z_keyexpr_suffix_equals(&ke_a, &ke_b)); + +void test_intersects(void) { + _z_keyexpr_t ke_a, ke_b; + TEST_TRUE_INTERSECT("a", "a") + TEST_TRUE_INTERSECT("a/b", "a/b") + TEST_TRUE_INTERSECT("*", "abc") + TEST_TRUE_INTERSECT("*", "abc") + TEST_TRUE_INTERSECT("*", "abc") + TEST_TRUE_INTERSECT("*", "xxx") + TEST_TRUE_INTERSECT("ab$*", "abcd") + TEST_TRUE_INTERSECT("ab$*d", "abcd") + TEST_TRUE_INTERSECT("ab$*", "ab") + TEST_FALSE_INTERSECT("ab/*", "ab") + TEST_TRUE_INTERSECT("a/*/c/*/e", "a/b/c/d/e") + TEST_TRUE_INTERSECT("a/**/d/**/l", "a/b/c/d/e/f/g/h/i/l") + TEST_TRUE_INTERSECT("a/**/d/**/l", "a/d/foo/l") + TEST_TRUE_INTERSECT("a/$*b/c/$*d/e", "a/xb/c/xd/e") + TEST_FALSE_INTERSECT("a/*/c/*/e", "a/c/e") + TEST_FALSE_INTERSECT("a/*/c/*/e", "a/b/c/d/x/e") + TEST_FALSE_INTERSECT("ab$*cd", "abxxcxxd") + TEST_TRUE_INTERSECT("ab$*cd", "abxxcxxcd") + TEST_FALSE_INTERSECT("ab$*cd", "abxxcxxcdx") + TEST_TRUE_INTERSECT("**", "abc") + TEST_TRUE_INTERSECT("**", "a/b/c") + TEST_TRUE_INTERSECT("ab/**", "ab") + TEST_TRUE_INTERSECT("**/xyz", "a/b/xyz/d/e/f/xyz") + TEST_FALSE_INTERSECT("**/xyz$*xyz", "a/b/xyz/d/e/f/xyz") + TEST_TRUE_INTERSECT("a/**/c/**/e", "a/b/b/b/c/d/d/d/e") + TEST_TRUE_INTERSECT("a/**/c/**/e", "a/c/e") + TEST_TRUE_INTERSECT("a/**/c/*/e/*", "a/b/b/b/c/d/d/c/d/e/f") + TEST_FALSE_INTERSECT("a/**/c/*/e/*", "a/b/b/b/c/d/d/c/d/d/e/f") + TEST_FALSE_INTERSECT("ab$*cd", "abxxcxxcdx") + TEST_TRUE_INTERSECT("x/abc", "x/abc") + TEST_FALSE_INTERSECT("x/abc", "abc") + TEST_TRUE_INTERSECT("x/*", "x/abc") + TEST_FALSE_INTERSECT("x/*", "abc") + TEST_FALSE_INTERSECT("*", "x/abc") + TEST_TRUE_INTERSECT("x/*", "x/abc$*") + TEST_TRUE_INTERSECT("x/$*abc", "x/abc$*") + TEST_TRUE_INTERSECT("x/a$*", "x/abc$*") + TEST_TRUE_INTERSECT("x/a$*de", "x/abc$*de") + TEST_TRUE_INTERSECT("x/a$*d$*e", "x/a$*e") + TEST_TRUE_INTERSECT("x/a$*d$*e", "x/a$*c$*e") + TEST_TRUE_INTERSECT("x/a$*d$*e", "x/ade") + TEST_FALSE_INTERSECT("x/c$*", "x/abc$*") + TEST_FALSE_INTERSECT("x/$*d", "x/$*e") + TEST_TRUE_INTERSECT("a", "a") + TEST_TRUE_INTERSECT("a/b", "a/b") + TEST_TRUE_INTERSECT("*", "a") + TEST_TRUE_INTERSECT("a", "*") + TEST_TRUE_INTERSECT("*", "aaaaa") + TEST_TRUE_INTERSECT("**", "a") + TEST_TRUE_INTERSECT("a", "**") + TEST_TRUE_INTERSECT("**", "a") + TEST_TRUE_INTERSECT("a/a/a/a", "**") + TEST_TRUE_INTERSECT("a/*", "a/b") + TEST_FALSE_INTERSECT("a/*/b", "a/b") + TEST_TRUE_INTERSECT("a/**/b", "a/b") + TEST_TRUE_INTERSECT("a/b$*", "a/b") + TEST_TRUE_INTERSECT("a/$*b$*", "a/b") + TEST_TRUE_INTERSECT("a/$*b", "a/b") + TEST_TRUE_INTERSECT("a/b$*", "a/bc") + TEST_TRUE_INTERSECT("a/$*b$*", "a/ebc") + TEST_TRUE_INTERSECT("a/$*b", "a/cb") + TEST_FALSE_INTERSECT("a/b$*", "a/ebc") + TEST_FALSE_INTERSECT("a/$*b", "a/cbc") + TEST_TRUE_INTERSECT("a/**/b$*", "a/b") + TEST_TRUE_INTERSECT("a/**/$*b$*", "a/b") + TEST_TRUE_INTERSECT("a/**/$*b", "a/b") + TEST_TRUE_INTERSECT("a/**/b$*", "a/bc") + TEST_TRUE_INTERSECT("a/**/$*b$*", "a/ebc") + TEST_TRUE_INTERSECT("a/**/$*b", "a/cb") + TEST_FALSE_INTERSECT("a/**/b$*", "a/ebc") + TEST_FALSE_INTERSECT("a/**/$*b", "a/cbc") + + TEST_TRUE_INTERSECT("@a", "@a") + TEST_FALSE_INTERSECT("@a", "@ab") + TEST_FALSE_INTERSECT("@a", "@a/b") + TEST_FALSE_INTERSECT("@a", "@a/*") + TEST_FALSE_INTERSECT("@a", "@a/*/**") + TEST_FALSE_INTERSECT("@a", "@a$*/**") + TEST_TRUE_INTERSECT("@a", "@a/**") + TEST_FALSE_INTERSECT("**/xyz$*xyz", "@a/b/xyzdefxyz") + TEST_TRUE_INTERSECT("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e") + TEST_FALSE_INTERSECT("@a/**/c/**/e", "@a/@b/b/b/c/d/d/d/e") + TEST_TRUE_INTERSECT("@a/**/@c/**/e", "@a/b/b/b/@c/d/d/d/e") + TEST_TRUE_INTERSECT("@a/**/e", "@a/b/b/d/d/d/e") + TEST_TRUE_INTERSECT("@a/**/e", "@a/b/b/b/d/d/d/e") + TEST_TRUE_INTERSECT("@a/**/e", "@a/b/b/c/d/d/d/e") + TEST_FALSE_INTERSECT("@a/**/e", "@a/b/b/@c/b/d/d/d/e") + TEST_FALSE_INTERSECT("@a/*", "@a/@b") + TEST_FALSE_INTERSECT("@a/**", "@a/@b") + TEST_TRUE_INTERSECT("@a/**/@b", "@a/@b") + TEST_FALSE_INTERSECT("@a/**/@b", "@a/**/@c/**/@b") + TEST_TRUE_INTERSECT("@a/@b/**", "@a/@b") + TEST_TRUE_INTERSECT("@a/**/@c/@b", "@a/**/@c/**/@b") + TEST_TRUE_INTERSECT("@a/**/@c/**/@b", "@a/**/@c/@b") +} + +void test_includes(void) { + _z_keyexpr_t ke_a, ke_b; + TEST_TRUE_INCLUDE("a", "a") + TEST_TRUE_INCLUDE("a/b", "a/b") + TEST_TRUE_INCLUDE("*", "a") + TEST_FALSE_INCLUDE("a", "*") + TEST_TRUE_INCLUDE("*", "aaaaa") + TEST_TRUE_INCLUDE("**", "a") + TEST_FALSE_INCLUDE("a", "**") + TEST_TRUE_INCLUDE("**", "a") + TEST_TRUE_INCLUDE("**", "a/a/a/a") + TEST_TRUE_INCLUDE("**", "*/**") + TEST_TRUE_INCLUDE("*/**", "*/**") + TEST_FALSE_INCLUDE("*/**", "**") + TEST_FALSE_INCLUDE("a/a/a/a", "**") + TEST_TRUE_INCLUDE("a/*", "a/b") + TEST_FALSE_INCLUDE("a/*/b", "a/b") + TEST_TRUE_INCLUDE("a/**/b", "a/b") + TEST_TRUE_INCLUDE("a/b$*", "a/b") + TEST_FALSE_INCLUDE("a/b", "a/b$*") + TEST_TRUE_INCLUDE("a/$*b$*", "a/b") + TEST_TRUE_INCLUDE("a/$*b", "a/b") + TEST_TRUE_INCLUDE("a/b$*", "a/bc") + TEST_TRUE_INCLUDE("a/$*b$*", "a/ebc") + TEST_TRUE_INCLUDE("a/$*b", "a/cb") + TEST_FALSE_INCLUDE("a/b$*", "a/ebc") + TEST_FALSE_INCLUDE("a/$*b", "a/cbc") + TEST_TRUE_INCLUDE("a/**/b$*", "a/b") + TEST_TRUE_INCLUDE("a/**/$*b$*", "a/b") + TEST_TRUE_INCLUDE("a/**/$*b", "a/b") + TEST_TRUE_INCLUDE("a/**/b$*", "a/bc") + TEST_TRUE_INCLUDE("a/**/$*b$*", "a/ebc") + TEST_TRUE_INCLUDE("a/**/$*b", "a/cb") + TEST_FALSE_INCLUDE("a/**/b$*", "a/ebc") + TEST_FALSE_INCLUDE("a/**/$*b", "a/cbc") + TEST_TRUE_INCLUDE("@a", "@a") + TEST_FALSE_INCLUDE("@a", "@ab") + TEST_FALSE_INCLUDE("@a", "@a/b") + TEST_FALSE_INCLUDE("@a", "@a/*") + TEST_FALSE_INCLUDE("@a", "@a/*/**") + TEST_FALSE_INCLUDE("@a$*/**", "@a") + TEST_FALSE_INCLUDE("@a", "@a/**") + TEST_TRUE_INCLUDE("@a/**", "@a") + TEST_FALSE_INCLUDE("**/xyz$*xyz", "@a/b/xyzdefxyz") + TEST_TRUE_INCLUDE("@a/**/c/**/e", "@a/b/b/b/c/d/d/d/e") + TEST_FALSE_INCLUDE("@a/*", "@a/@b") + TEST_FALSE_INCLUDE("@a/**", "@a/@b") + TEST_TRUE_INCLUDE("@a/**/@b", "@a/@b") + TEST_TRUE_INCLUDE("@a/@b/**", "@a/@b") +} + +void test_canonize(void) { // clang-format off #define N 31 @@ -404,20 +322,120 @@ int main(void) { memset(canon, 0, 128); strncpy(canon, ke, 128); size_t canon_len = strlen(canon); - zp_keyexpr_canon_status_t status = zp_keyexpr_canonize_null_terminated(canon); + zp_keyexpr_canon_status_t status = z_keyexpr_canonize(canon, &canon_len); printf("%s ", ke); printf(" Status: %d : %d", status, expected[i]); assert(status == expected[i]); if (status == Z_KEYEXPR_CANON_SUCCESS) { printf(" Match: %.*s : %s", (int)canon_len, canon, canonized[i]); - assert(strcmp(canonized[i], canon) == 0); + assert(strncmp(canonized[i], canon, canon_len) == 0); } printf("\n"); } +} + +void test_equals(void) { + _z_keyexpr_t ke_a, ke_b; + TEST_FALSE_EQUAL("a/**/$*b", "a/cb"); + TEST_FALSE_EQUAL("a/bc", "a/cb"); + TEST_TRUE_EQUAL("greetings/hello/there", "greetings/hello/there"); +} + +_Bool keyexpr_equals_string(const z_loaned_keyexpr_t *ke, const char *s) { + z_view_string_t vs; + z_keyexpr_as_view_string(ke, &vs); + _z_string_t str = _z_string_alias_str(s); + return _z_string_equals(z_view_string_loan(&vs), &str); +} + +void test_keyexpr_constructor(void) { + z_owned_keyexpr_t ke; + z_keyexpr_from_str(&ke, "a/b/c"); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke), "a/b/c")); + z_keyexpr_drop(z_keyexpr_move(&ke)); - assert(zp_keyexpr_equals_null_terminated("a/**/$*b", "a/cb") == -1); - assert(zp_keyexpr_equals_null_terminated("a/bc", "a/cb") == -1); - assert(zp_keyexpr_equals_null_terminated("greetings/hello/there", "greetings/hello/there") == 0); + z_keyexpr_from_substr(&ke, "a/b/c/d/e", 5); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke), "a/b/c")); + z_keyexpr_drop(z_keyexpr_move(&ke)); + + assert(0 == z_keyexpr_from_str_autocanonize(&ke, "a/**/**")); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke), "a/**")); + z_keyexpr_drop(z_keyexpr_move(&ke)); + + size_t len = 9; + assert(0 == z_keyexpr_from_substr_autocanonize(&ke, "a/**/**/m/b/c", &len)); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke), "a/**/m")); + assert(len == 6); + z_keyexpr_drop(z_keyexpr_move(&ke)); + + z_view_keyexpr_t vke; + z_view_keyexpr_from_str(&vke, "a/b/c"); + assert(keyexpr_equals_string(z_view_keyexpr_loan(&vke), "a/b/c")); + + char s[] = "a/**/**"; + z_view_keyexpr_from_str_autocanonize(&vke, s); + assert(keyexpr_equals_string(z_view_keyexpr_loan(&vke), "a/**")); +} + +void test_concat(void) { + z_owned_keyexpr_t ke1, ke2; + z_keyexpr_from_str(&ke1, "a/b/c/*"); + assert(0 == z_keyexpr_concat(&ke2, z_keyexpr_loan(&ke1), "/d/e/*", 4)); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke2), "a/b/c/*/d/e")); + z_keyexpr_drop(z_keyexpr_move(&ke2)); + + assert(0 != z_keyexpr_concat(&ke2, z_keyexpr_loan(&ke1), "*/e/*", 3)); + assert(!z_internal_keyexpr_check(&ke2)); + + z_keyexpr_drop(z_keyexpr_move(&ke1)); +} + +void test_join(void) { + z_owned_keyexpr_t ke1, ke2, ke3; + z_keyexpr_from_str(&ke1, "a/b/c/*"); + z_keyexpr_from_str(&ke2, "d/e/*"); + assert(0 == z_keyexpr_join(&ke3, z_keyexpr_loan(&ke1), z_keyexpr_loan(&ke2))); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke3), "a/b/c/*/d/e/*")); + z_keyexpr_drop(z_keyexpr_move(&ke1)); + z_keyexpr_drop(z_keyexpr_move(&ke2)); + z_keyexpr_drop(z_keyexpr_move(&ke3)); + + z_keyexpr_from_str(&ke1, "a/*/**"); + z_keyexpr_from_str(&ke2, "**/d/e/c"); + + assert(0 == z_keyexpr_join(&ke3, z_keyexpr_loan(&ke1), z_keyexpr_loan(&ke2))); + assert(keyexpr_equals_string(z_keyexpr_loan(&ke3), "a/*/**/d/e/c")); + + z_keyexpr_drop(z_keyexpr_move(&ke1)); + z_keyexpr_drop(z_keyexpr_move(&ke2)); + z_keyexpr_drop(z_keyexpr_move(&ke3)); +} + +void test_relation_to(void) { + z_view_keyexpr_t foobar, foostar, barstar; + z_view_keyexpr_from_str(&foobar, "foo/bar"); + z_view_keyexpr_from_str(&foostar, "foo/*"); + z_view_keyexpr_from_str(&barstar, "bar/*"); + + assert(z_keyexpr_relation_to(z_view_keyexpr_loan(&foostar), z_view_keyexpr_loan(&foobar)) == + Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES); + assert(z_keyexpr_relation_to(z_view_keyexpr_loan(&foobar), z_view_keyexpr_loan(&foostar)) == + Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS); + assert(z_keyexpr_relation_to(z_view_keyexpr_loan(&foostar), z_view_keyexpr_loan(&foostar)) == + Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS); + assert(z_keyexpr_relation_to(z_view_keyexpr_loan(&barstar), z_view_keyexpr_loan(&foobar)) == + Z_KEYEXPR_INTERSECTION_LEVEL_DISJOINT); +} + +int main(void) { + test_intersects(); + test_includes(); + test_canonize(); + test_equals(); + test_keyexpr_constructor(); + test_concat(); + test_join(); + test_relation_to(); return 0; } diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index db4347f41..810489dec 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -26,14 +26,16 @@ #include #include -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/protocol/codec/core.h" #include "zenoh-pico/protocol/codec/declarations.h" #include "zenoh-pico/protocol/codec/ext.h" +#include "zenoh-pico/protocol/codec/interest.h" #include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/definitions/declarations.h" +#include "zenoh-pico/protocol/definitions/interest.h" #include "zenoh-pico/protocol/definitions/network.h" #include "zenoh-pico/protocol/ext.h" #include "zenoh-pico/protocol/iobuf.h" @@ -78,7 +80,7 @@ void print_wbuf(_z_wbuf_t *wbf) { void print_zbuf(_z_zbuf_t *zbf) { print_iosli(&zbf->_ios); } -void print_uint8_array(_z_bytes_t *arr) { +void print_uint8_array(_z_slice_t *arr) { printf("Length: %zu, Buffer: [", arr->len); for (size_t i = 0; i < arr->len; i++) { printf("%02x", arr->start[i]); @@ -145,7 +147,7 @@ uint64_t gen_uint64(void) { return ret; } -unsigned int gen_uint(void) { +uint32_t gen_uint32(void) { unsigned int ret = 0; z_random_fill(&ret, sizeof(ret)); return ret; @@ -168,29 +170,31 @@ _z_wbuf_t gen_wbuf(size_t len) { return _z_wbuf_make(len, is_expandable); } -_z_bytes_t gen_payload(size_t len) { - _z_bytes_t pld; - pld._is_alloc = true; - pld.len = len; - pld.start = (uint8_t *)z_malloc(len); - z_random_fill((uint8_t *)pld.start, pld.len); +_z_slice_t gen_slice(size_t len) { + if (len == 0) { + return _z_slice_empty(); + } - return pld; + uint8_t *p = (uint8_t *)z_malloc(sizeof(uint8_t) * len); + for (_z_zint_t i = 0; i < len; i++) { + ((uint8_t *)p)[i] = gen_uint8() & 0x7f; // 0b01111111 + } + return _z_slice_from_buf_custom_deleter(p, len, _z_delete_context_default()); } -_z_bytes_t gen_bytes(size_t len) { - _z_bytes_t arr; - arr._is_alloc = true; - arr.len = len; - arr.start = NULL; - if (len == 0) return arr; +_z_bytes_t gen_payload(size_t len) { + _z_slice_t pld = gen_slice(len); + _z_bytes_t b; + _z_bytes_from_slice(&b, pld); - arr.start = (uint8_t *)z_malloc(sizeof(uint8_t) * len); - for (_z_zint_t i = 0; i < len; i++) { - ((uint8_t *)arr.start)[i] = gen_uint8() & 0x7f; // 0b01111111 - } + return b; +} - return arr; +_z_bytes_t gen_bytes(size_t len) { + _z_slice_t s = gen_slice(len); + _z_bytes_t b; + _z_bytes_from_slice(&b, s); + return b; } _z_id_t gen_zid(void) { @@ -217,36 +221,46 @@ char *gen_str(size_t size) { return str; } -_z_str_array_t gen_str_array(size_t size) { - _z_str_array_t sa = _z_str_array_make(size); - for (size_t i = 0; i < size; i++) ((char **)sa.val)[i] = gen_str(16); +_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); + } return sa; } +_z_string_t gen_string(size_t len) { return _z_string_alias_str(gen_str(len)); } + _z_locator_array_t gen_locator_array(size_t size) { _z_locator_array_t la = _z_locator_array_make(size); for (size_t i = 0; i < size; i++) { _z_locator_t *val = &la._val[i]; - val->_protocol = gen_str(3); - val->_address = gen_str(12); + val->_protocol = gen_string(3); + val->_address = gen_string(12); val->_metadata = _z_str_intmap_make(); // @TODO: generate metadata } return la; } -_z_value_t gen_value(void) { - _z_value_t val; - val.encoding.prefix = gen_zint(); +_z_encoding_t gen_encoding(void) { + _z_encoding_t en; + en.id = gen_uint16(); if (gen_bool()) { - val.encoding.suffix = gen_bytes(8); + en.schema = gen_string(16); } else { - val.encoding.suffix = _z_bytes_empty(); + en.schema = _z_string_null(); } + return en; +} +_z_value_t gen_value(void) { + _z_value_t val; + val.encoding = gen_encoding(); if (gen_bool()) { - val.payload = _z_bytes_empty(); + val.payload = _z_bytes_null(); } else { val.payload = gen_bytes(16); } @@ -276,7 +290,7 @@ void assert_eq_iosli(_z_iosli_t *left, _z_iosli_t *right) { printf(")"); } -void assert_eq_uint8_array(const _z_bytes_t *left, const _z_bytes_t *right) { +void assert_eq_uint8_array(const _z_slice_t *left, const _z_slice_t *right) { printf("Array -> "); printf("Length (%zu:%zu), ", left->len, right->len); @@ -294,20 +308,22 @@ void assert_eq_uint8_array(const _z_bytes_t *left, const _z_bytes_t *right) { printf(")"); } -void assert_eq_str_array(_z_str_array_t *left, _z_str_array_t *right) { +void assert_eq_string_array(_z_string_svec_t *left, _z_string_svec_t *right) { printf("Array -> "); - printf("Length (%zu:%zu), ", left->len, right->len); + printf("Length (%zu:%zu), ", left->_len, right->_len); - assert(left->len == right->len); + assert(left->_len == right->_len); printf("Content ("); - for (size_t i = 0; i < left->len; i++) { - const char *l = left->val[i]; - const char *r = right->val[i]; + for (size_t i = 0; i < left->_len; i++) { + const char *l = _z_string_data(_z_string_svec_get(left, i)); + const char *r = _z_string_data(_z_string_svec_get(right, i)); + size_t l_len = _z_string_len(_z_string_svec_get(left, i)); + size_t r_len = _z_string_len(_z_string_svec_get(right, i)); - printf("%s:%s", l, r); - if (i < left->len - 1) printf(" "); + printf("%.*s:%.*s", (int)l_len, l, (int)r_len, r); + if (i < left->_len - 1) printf(" "); - assert(_z_str_eq(l, r) == true); + assert(_z_string_equals(_z_string_svec_get(left, i), _z_string_svec_get(right, i))); } printf(")"); } @@ -322,20 +338,47 @@ void assert_eq_locator_array(const _z_locator_array_t *left, const _z_locator_ar const _z_locator_t *l = &left->_val[i]; const _z_locator_t *r = &right->_val[i]; - char *ls = _z_locator_to_str(l); - char *rs = _z_locator_to_str(r); + _z_string_t ls = _z_locator_to_string(l); + _z_string_t rs = _z_locator_to_string(r); - printf("%s:%s", ls, rs); + printf("%s:%s", _z_string_data(&ls), _z_string_data(&rs)); if (i < left->_len - 1) printf(" "); - z_free(ls); - z_free(rs); + _z_string_clear(&ls); + _z_string_clear(&rs); assert(_z_locator_eq(l, r) == true); } printf(")"); } +/*=============================*/ +/* Zenoh Core Fields */ +/*=============================*/ +void zint(void) { + printf("\n>> ZINT\n"); + _z_wbuf_t wbf = gen_wbuf(9); + + // Initialize + _z_zint_t e_z = gen_zint(); + + // Encode + int8_t res = _z_zsize_encode(&wbf, e_z); + assert(res == _Z_RES_OK); + (void)(res); + + // Decode + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + _z_zint_t d_z; + res = _z_zsize_decode(&d_z, &zbf); + assert(res == _Z_RES_OK); + assert(e_z == d_z); + + // Free + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + /*=============================*/ /* Zenoh Messages Extensions */ /*=============================*/ @@ -349,7 +392,7 @@ void assert_eq_unit_extension(_z_msg_ext_unit_t *left, _z_msg_ext_unit_t *right) void unit_extension(void) { printf("\n>> UNIT Extension\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_msg_ext_t ext = gen_unit_extension(); @@ -390,7 +433,7 @@ void assert_eq_zint_extension(_z_msg_ext_zint_t *left, _z_msg_ext_zint_t *right) void zint_extension(void) { printf("\n>> ZINT Extension\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_msg_ext_t ext = gen_zint_extension(); @@ -420,7 +463,7 @@ void zint_extension(void) { /*------------------ Unit extension ------------------*/ _z_msg_ext_t gen_zbuf_extension(void) { - _z_bytes_t val = gen_bytes(gen_uint8()); + _z_slice_t val = gen_slice(gen_uint8()); return _z_msg_ext_make_zbuf(_Z_MOCK_EXTENSION_ZBUF, val); } @@ -432,7 +475,7 @@ void assert_eq_zbuf_extension(_z_msg_ext_zbuf_t *left, _z_msg_ext_zbuf_t *right) void zbuf_extension(void) { printf("\n>> ZBUF Extension\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_msg_ext_t ext = gen_zbuf_extension(); @@ -464,11 +507,41 @@ void zbuf_extension(void) { /* Message Fields */ /*=============================*/ /*------------------ Payload field ------------------*/ -void assert_eq_bytes(const _z_bytes_t *left, const _z_bytes_t *right) { assert_eq_uint8_array(left, right); } +void assert_eq_slice(const _z_slice_t *left, const _z_slice_t *right) { assert_eq_uint8_array(left, right); } + +void assert_eq_string(const _z_string_t *left, const _z_string_t *right) { + assert(_z_string_len(left) == _z_string_len(right)); + if (_z_string_len(left) > 0) { + assert(_z_string_equals(left, right)); + } +} + +void assert_eq_bytes(const _z_bytes_t *left, const _z_bytes_t *right) { + size_t len_left = _z_bytes_len(left); + size_t len_right = _z_bytes_len(right); + printf("Array -> "); + printf("Length (%zu:%zu), ", len_left, len_right); + + assert(len_left == len_right); + printf("Content ("); + _z_bytes_reader_t reader_left = _z_bytes_get_reader(left); + _z_bytes_reader_t reader_right = _z_bytes_get_reader(right); + for (size_t i = 0; i < len_left; i++) { + uint8_t l = 0, r = 0; + _z_bytes_reader_read(&reader_left, &l, 1); + _z_bytes_reader_read(&reader_right, &r, 1); + + printf("%02x:%02x", l, r); + if (i < len_left - 1) printf(" "); + + assert(l == r); + } + printf(")"); +} void payload_field(void) { printf("\n>> Payload field\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_bytes_t e_pld = gen_payload(64); @@ -489,8 +562,8 @@ void payload_field(void) { printf("\n"); // Free - _z_bytes_clear(&e_pld); - _z_bytes_clear(&d_pld); + _z_bytes_drop(&e_pld); + _z_bytes_drop(&d_pld); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } @@ -505,10 +578,9 @@ void assert_eq_source_info(const _z_source_info_t *left, const _z_source_info_t assert(left->_entity_id == right->_entity_id); assert(memcmp(left->_id.id, right->_id.id, 16) == 0); } -_z_encoding_t gen_encoding(void) { return (_z_encoding_t){.prefix = gen_uint64(), .suffix = gen_bytes(16)}; } void assert_eq_encoding(const _z_encoding_t *left, const _z_encoding_t *right) { - assert(left->prefix == right->prefix); - assert_eq_bytes(&left->suffix, &right->suffix); + assert(left->id == right->id); + assert_eq_string(&left->schema, &right->schema); } void assert_eq_value(const _z_value_t *left, const _z_value_t *right) { assert_eq_encoding(&left->encoding, &right->encoding); @@ -518,8 +590,9 @@ void assert_eq_value(const _z_value_t *left, const _z_value_t *right) { _z_timestamp_t gen_timestamp(void) { _z_timestamp_t ts; ts.time = gen_uint64(); - _z_bytes_t id = gen_bytes(16); - memcpy(ts.id.id, id.start, id.len); + for (size_t i = 0; i < 16; i++) { + ts.id.id[i] = gen_uint8() & 0x7f; // 0b01111111 + } return ts; } @@ -539,7 +612,7 @@ void assert_eq_timestamp(const _z_timestamp_t *left, const _z_timestamp_t *right void timestamp_field(void) { printf("\n>> Timestamp field\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_timestamp_t e_ts = gen_timestamp(); @@ -572,37 +645,15 @@ void timestamp_field(void) { /*------------------ SubInfo field ------------------*/ _z_subinfo_t gen_subinfo(void) { _z_subinfo_t sm; - sm.mode = gen_bool() ? Z_SUBMODE_PUSH : Z_SUBMODE_PULL; sm.reliability = gen_bool() ? Z_RELIABILITY_RELIABLE : Z_RELIABILITY_BEST_EFFORT; - if (gen_bool()) { - sm.period.origin = gen_uint(); - sm.period.period = gen_uint(); - sm.period.duration = gen_uint(); - } else { - sm.period.origin = 0; - sm.period.period = 0; - sm.period.duration = 0; - } return sm; } void assert_eq_subinfo(_z_subinfo_t *left, _z_subinfo_t *right) { printf("SubInfo -> "); - printf("Mode (%u:%u), ", left->mode, right->mode); - assert(left->mode == right->mode); - printf("Reliable (%u:%u), ", left->reliability, right->reliability); assert(left->reliability == right->reliability); - - printf("Period ("); - printf("<%u:%u,%u>", left->period.origin, left->period.period, left->period.duration); - printf(":"); - printf("<%u:%u,%u>", right->period.origin, right->period.period, right->period.duration); - printf(")"); - assert(left->period.origin == right->period.origin); - assert(left->period.period == right->period.period); - assert(left->period.duration == right->period.duration); } /*------------------ ResKey field ------------------*/ @@ -612,11 +663,13 @@ _z_keyexpr_t gen_keyexpr(void) { key._mapping._val = gen_uint8(); _Bool is_numerical = gen_bool(); if (is_numerical == true) { - key._suffix = NULL; - _z_keyexpr_set_owns_suffix(&key, false); + key._suffix = _z_string_null(); } else { - key._suffix = gen_str(gen_zint() % 16); - _z_keyexpr_set_owns_suffix(&key, true); + size_t len = gen_zint() % 16; + key._suffix = _z_string_preallocate(len); + char *suffix = gen_str(len); + memcpy((char *)_z_string_data(&key._suffix), suffix, len); + z_free(suffix); } return key; } @@ -625,12 +678,13 @@ void assert_eq_keyexpr(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { printf("ResKey -> "); printf("ID (%u:%u), ", left->_id, right->_id); assert(left->_id == right->_id); - assert(!(_z_keyexpr_has_suffix(*left) ^ _z_keyexpr_has_suffix(*right))); + assert(_z_keyexpr_has_suffix(left) == _z_keyexpr_has_suffix(right)); printf("Name ("); - if (_z_keyexpr_has_suffix(*left)) { - printf("%s:%s", left->_suffix, right->_suffix); - assert(_z_str_eq(left->_suffix, right->_suffix) == true); + if (_z_keyexpr_has_suffix(left)) { + printf("%.*s:%.*s", (int)_z_string_len(&left->_suffix), _z_string_data(&left->_suffix), + (int)_z_string_len(&right->_suffix), _z_string_data(&right->_suffix)); + assert(_z_string_equals(&left->_suffix, &right->_suffix) == true); } else { printf("NULL:NULL"); } @@ -639,13 +693,13 @@ void assert_eq_keyexpr(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { void keyexpr_field(void) { printf("\n>> ResKey field\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_keyexpr_t e_rk = gen_keyexpr(); // Encode - uint8_t header = (e_rk._suffix) ? _Z_FLAG_Z_K : 0; + uint8_t header = (_z_keyexpr_has_suffix(&e_rk)) ? _Z_FLAG_Z_K : 0; int8_t res = _z_keyexpr_encode(&wbf, _Z_HAS_FLAG(header, _Z_FLAG_Z_K), &e_rk); assert(res == _Z_RES_OK); (void)(res); @@ -683,7 +737,7 @@ void assert_eq_resource_declaration(const _z_decl_kexpr_t *left, const _z_decl_k void resource_declaration(void) { printf("\n>> Resource declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_decl_kexpr_t e_rd = gen_resource_declaration(); @@ -717,21 +771,19 @@ _z_decl_subscriber_t gen_subscriber_declaration(void) { _z_subinfo_t subinfo = gen_subinfo(); _z_decl_subscriber_t e_sd = {._keyexpr = gen_keyexpr(), ._id = (uint32_t)gen_uint64(), - ._ext_subinfo = {._pull_mode = subinfo.mode == Z_SUBMODE_PULL, - ._reliable = subinfo.reliability == Z_RELIABILITY_RELIABLE}}; + ._ext_subinfo = {._reliable = subinfo.reliability == Z_RELIABILITY_RELIABLE}}; return e_sd; } void assert_eq_subscriber_declaration(const _z_decl_subscriber_t *left, const _z_decl_subscriber_t *right) { assert_eq_keyexpr(&left->_keyexpr, &right->_keyexpr); assert(left->_id == right->_id); - assert(left->_ext_subinfo._pull_mode == right->_ext_subinfo._pull_mode); assert(left->_ext_subinfo._reliable == right->_ext_subinfo._reliable); } void subscriber_declaration(void) { printf("\n>> Subscriber declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_decl_subscriber_t e_sd = gen_subscriber_declaration(); @@ -763,7 +815,7 @@ void subscriber_declaration(void) { _z_decl_queryable_t gen_queryable_declaration(void) { _z_decl_queryable_t e_qd = {._keyexpr = gen_keyexpr(), ._id = (uint32_t)gen_uint64(), - ._ext_queryable_info = {._complete = gen_uint8(), ._distance = (uint32_t)gen_zint()}}; + ._ext_queryable_info = {._complete = gen_uint8(), ._distance = gen_uint16()}}; return e_qd; } @@ -779,7 +831,7 @@ void assert_eq_queryable_declaration(const _z_decl_queryable_t *left, const _z_d void queryable_declaration(void) { printf("\n>> Queryable declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_decl_queryable_t e_qd = gen_queryable_declaration(); @@ -824,7 +876,7 @@ void assert_eq_forget_resource_declaration(const _z_undecl_kexpr_t *left, const void forget_resource_declaration(void) { printf("\n>> Forget resource declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_undecl_kexpr_t e_frd = gen_forget_resource_declaration(); @@ -865,7 +917,7 @@ void assert_eq_forget_subscriber_declaration(const _z_undecl_subscriber_t *left, void forget_subscriber_declaration(void) { printf("\n>> Forget subscriber declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_undecl_subscriber_t e_fsd = gen_forget_subscriber_declaration(); @@ -882,7 +934,6 @@ void forget_subscriber_declaration(void) { _z_uint8_decode(&e_hdr, &zbf); res = _z_undecl_subscriber_decode(&d_fsd, &zbf, e_hdr); assert(res == _Z_RES_OK); - printf(" "); assert_eq_forget_subscriber_declaration(&e_fsd, &d_fsd); printf("\n"); @@ -907,7 +958,7 @@ void assert_eq_forget_queryable_declaration(const _z_undecl_queryable_t *left, c void forget_queryable_declaration(void) { printf("\n>> Forget queryable declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_undecl_queryable_t e_fqd = gen_forget_queryable_declaration(); @@ -1004,19 +1055,24 @@ void assert_eq_declaration(const _z_declaration_t *left, const _z_declaration_t /*------------------ Declare message ------------------*/ _z_network_message_t gen_declare_message(void) { _z_declaration_t declaration = gen_declaration(); - - return _z_n_msg_make_declare(declaration); + _Bool has_id = gen_bool(); + uint32_t id = gen_uint32(); + return _z_n_msg_make_declare(declaration, has_id, id); } void assert_eq_declare_message(_z_n_msg_declare_t *left, _z_n_msg_declare_t *right) { printf(" "); + assert(left->has_interest_id == right->has_interest_id); + if (left->has_interest_id) { + assert(left->_interest_id == right->_interest_id); + } assert_eq_declaration(&left->_decl, &right->_decl); printf("\n"); } void declare_message(void) { printf("\n>> Declare message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_network_message_t n_msg = gen_declare_message(); @@ -1041,6 +1097,79 @@ void declare_message(void) { _z_wbuf_clear(&wbf); } +/*------------------ Interest ------------------*/ +#define _Z_MSGCODEC_INTEREST_BASE_FLAGS_MASK 0x8f // Used to remove R, C & F flags + +_z_interest_t gen_interest(void) { + _z_interest_t i = {0}; + _Bool is_final = gen_bool(); // To determine if interest is final or not + // Generate interest id + i._id = gen_uint32(); + printf("Gen interest %d\n", is_final); + // Add regular interest data + if (!is_final) { + // Generate base flags + i.flags = gen_uint8() & _Z_MSGCODEC_INTEREST_BASE_FLAGS_MASK; + // Generate test cases + _Bool is_restricted = gen_bool(); + uint8_t cf_type = gen_uint8() % 3; // Flags must be c, f or cf + switch (cf_type) { + default: + case 0: + i.flags |= _Z_INTEREST_FLAG_CURRENT; + break; + case 1: + i.flags |= _Z_INTEREST_FLAG_FUTURE; + break; + case 2: + i.flags |= (_Z_INTEREST_FLAG_CURRENT | _Z_INTEREST_FLAG_FUTURE); + break; + } + if (is_restricted) { + i.flags |= _Z_INTEREST_FLAG_RESTRICTED; + // Generate ke + i._keyexpr = gen_keyexpr(); + } + }; + return i; +} + +_z_network_message_t gen_interest_message(void) { + _z_interest_t interest = gen_interest(); + return _z_n_msg_make_interest(interest); +} + +void assert_eq_interest(const _z_interest_t *left, const _z_interest_t *right) { + printf("Interest: 0x%x, 0x%x, %u, %u\n", left->flags, right->flags, left->_id, right->_id); + printf("Interest ke: %d, %d, %d, %d, %.*s, %.*s\n", left->_keyexpr._id, right->_keyexpr._id, + left->_keyexpr._mapping._val, right->_keyexpr._mapping._val, (int)_z_string_len(&left->_keyexpr._suffix), + _z_string_data(&left->_keyexpr._suffix), (int)_z_string_len(&right->_keyexpr._suffix), + _z_string_data(&right->_keyexpr._suffix)); + assert(left->flags == right->flags); + assert(left->_id == right->_id); + assert_eq_keyexpr(&left->_keyexpr, &right->_keyexpr); +} +void interest_message(void) { + printf("\n>> Interest message\n"); + // Init + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_network_message_t expected = gen_interest_message(); + // Encode + assert(_z_n_interest_encode(&wbf, &expected._body._interest) == _Z_RES_OK); + // Decode + _z_n_msg_interest_t decoded; + _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); + // Check + assert_eq_interest(&expected._body._interest._interest, &decoded._interest); + // Clean-up + _z_n_msg_interest_clear(&decoded); + _z_n_msg_interest_clear(&expected._body._interest); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + /*=============================*/ /* Zenoh Messages */ /*=============================*/ @@ -1077,7 +1206,7 @@ void assert_eq_push_body(const _z_push_body_t *left, const _z_push_body_t *right void push_body_message(void) { printf("\n>> Put/Del message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); // Initialize _z_push_body_t e_da = gen_push_body(); @@ -1103,46 +1232,19 @@ void push_body_message(void) { _z_wbuf_clear(&wbf); } -/*------------------ Pull message ------------------*/ -_z_msg_pull_t gen_pull_message(void) { return (_z_msg_pull_t){._ext_source_info = _z_source_info_null()}; } - -void assert_eq_pull_message(_z_msg_pull_t *left, _z_msg_pull_t *right) { - assert_eq_source_info(&left->_ext_source_info, &right->_ext_source_info); -} - -void pull_message(void) { - printf("\n>> Pull message\n"); - _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); - _z_msg_pull_t e_pull_msg = gen_pull_message(); - - assert(_z_pull_encode(&wbf, &e_pull_msg) == _Z_RES_OK); - - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - uint8_t header = _z_zbuf_read(&zbf); - - _z_msg_pull_t d_pull_msg; - assert(_z_pull_decode(&d_pull_msg, &zbf, header) == _Z_RES_OK); - assert_eq_pull_message(&e_pull_msg, &d_pull_msg); - - _z_msg_pull_clear(&e_pull_msg); - _z_msg_pull_clear(&d_pull_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - _z_msg_query_t gen_query(void) { return (_z_msg_query_t){ - ._ext_consolidation = (gen_uint8() % 4) - 1, + ._consolidation = (gen_uint8() % 4) - 1, ._ext_info = gen_source_info(), - ._parameters = gen_bytes(16), + ._parameters = gen_slice(16), ._ext_value = gen_bool() ? gen_value() : _z_value_null(), }; } void assert_eq_query(const _z_msg_query_t *left, const _z_msg_query_t *right) { - assert(left->_ext_consolidation == right->_ext_consolidation); + assert(left->_consolidation == right->_consolidation); assert_eq_source_info(&left->_ext_info, &right->_ext_info); - assert_eq_bytes(&left->_parameters, &right->_parameters); + assert_eq_slice(&left->_parameters, &right->_parameters); assert_eq_value(&left->_ext_value, &right->_ext_value); } @@ -1164,21 +1266,18 @@ void query_message(void) { } _z_msg_err_t gen_err(void) { + size_t len = 1 + gen_uint8(); return (_z_msg_err_t){ - ._code = gen_uint16(), - ._is_infrastructure = gen_bool(), - ._timestamp = gen_timestamp(), + ._encoding = gen_encoding(), ._ext_source_info = gen_bool() ? gen_source_info() : _z_source_info_null(), - ._ext_value = gen_bool() ? gen_value() : _z_value_null(), + ._payload = gen_payload(len), // Hangs if 0 }; } void assert_eq_err(const _z_msg_err_t *left, const _z_msg_err_t *right) { - assert(left->_code == right->_code); - assert(left->_is_infrastructure == right->_is_infrastructure); - assert_eq_timestamp(&left->_timestamp, &right->_timestamp); + assert_eq_encoding(&left->_encoding, &right->_encoding); assert_eq_source_info(&left->_ext_source_info, &right->_ext_source_info); - assert_eq_value(&left->_ext_value, &right->_ext_value); + assert_eq_bytes(&left->_payload, &right->_payload); } void err_message(void) { @@ -1197,46 +1296,16 @@ void err_message(void) { _z_wbuf_clear(&wbf); } -_z_msg_ack_t gen_ack(void) { - return (_z_msg_ack_t){ - ._ext_source_info = gen_bool() ? gen_source_info() : _z_source_info_null(), - ._timestamp = gen_timestamp(), - }; -} - -void assert_eq_ack(const _z_msg_ack_t *left, const _z_msg_ack_t *right) { - assert_eq_timestamp(&left->_timestamp, &right->_timestamp); - assert_eq_source_info(&left->_ext_source_info, &right->_ext_source_info); -} - -void ack_message(void) { - printf("\n>> Ack message\n"); - _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); - _z_msg_ack_t expected = gen_ack(); - assert(_z_ack_encode(&wbf, &expected) == _Z_RES_OK); - _z_msg_ack_t decoded; - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - uint8_t header = _z_zbuf_read(&zbf); - assert(_Z_RES_OK == _z_ack_decode(&decoded, &zbf, header)); - assert_eq_ack(&expected, &decoded); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - _z_msg_reply_t gen_reply(void) { return (_z_msg_reply_t){ - ._ext_source_info = gen_bool() ? gen_source_info() : _z_source_info_null(), - ._timestamp = gen_timestamp(), - ._ext_consolidation = (gen_uint8() % 4) - 1, - ._value = gen_value(), + ._consolidation = (gen_uint8() % 4) - 1, + ._body = gen_push_body(), }; } void assert_eq_reply(const _z_msg_reply_t *left, const _z_msg_reply_t *right) { - assert_eq_timestamp(&left->_timestamp, &right->_timestamp); - assert_eq_source_info(&left->_ext_source_info, &right->_ext_source_info); - assert(left->_ext_consolidation == right->_ext_consolidation); - assert_eq_value(&left->_value, &right->_value); + assert(left->_consolidation == right->_consolidation); + assert_eq_push_body(&left->_body, &right->_body); } void reply_message(void) { @@ -1297,16 +1366,12 @@ _z_n_msg_request_t gen_request(void) { ._ext_budget = gen_bool() ? (uint32_t)gen_uint64() : 0, ._ext_timeout_ms = gen_bool() ? (uint32_t)gen_uint64() : 0, }; - switch (gen_uint8() % 4) { + switch (gen_uint8() % 2) { case 0: { request._tag = _Z_REQUEST_QUERY; request._body._query = gen_query(); } break; - case 1: { - request._tag = _Z_REQUEST_PULL; - request._body._pull = - (_z_msg_pull_t){._ext_source_info = gen_bool() ? gen_source_info() : _z_source_info_null()}; - } break; + case 1: default: { _z_push_body_t body = gen_push_body(); if (body._is_put) { @@ -1342,9 +1407,6 @@ void assert_eq_request(const _z_n_msg_request_t *left, const _z_n_msg_request_t assert_eq_push_body(&(_z_push_body_t){._is_put = false, ._body._del = left->_body._del}, &(_z_push_body_t){._is_put = false, ._body._del = right->_body._del}); } break; - case _Z_REQUEST_PULL: { - assert_eq_source_info(&left->_body._pull._ext_source_info, &right->_body._pull._ext_source_info); - } break; } } @@ -1373,28 +1435,15 @@ _z_n_msg_response_t gen_response(void) { ._ext_timestamp = gen_bool() ? gen_timestamp() : _z_timestamp_null(), ._ext_responder = {._eid = gen_uint16(), ._zid = gen_zid()}, }; - switch (gen_uint() % 5) { + switch (gen_uint32() % 2) { case 0: { - ret._tag = _Z_RESPONSE_BODY_ACK; - ret._body._ack = gen_ack(); - } break; - case 1: { ret._tag = _Z_RESPONSE_BODY_ERR; ret._body._err = gen_err(); } break; - case 2: { - ret._tag = _Z_RESPONSE_BODY_ACK; - ret._body._reply = gen_reply(); - } break; + case 1: default: { - _z_push_body_t body = gen_push_body(); - if (body._is_put) { - ret._tag = _Z_RESPONSE_BODY_PUT; - ret._body._put = body._body._put; - } else { - ret._tag = _Z_RESPONSE_BODY_DEL; - ret._body._del = body._body._del; - } + ret._tag = _Z_RESPONSE_BODY_REPLY; + ret._body._reply = gen_reply(); } break; } return ret; @@ -1414,17 +1463,7 @@ void assert_eq_response(const _z_n_msg_response_t *left, const _z_n_msg_response } break; case _Z_RESPONSE_BODY_ERR: { assert_eq_err(&left->_body._err, &right->_body._err); - } break; - case _Z_RESPONSE_BODY_ACK: { - assert_eq_ack(&left->_body._ack, &right->_body._ack); - } break; - case _Z_RESPONSE_BODY_PUT: { - assert_eq_push_body(&(_z_push_body_t){._is_put = true, ._body._put = left->_body._put}, - &(_z_push_body_t){._is_put = true, ._body._put = right->_body._put}); - } break; - case _Z_RESPONSE_BODY_DEL: { - assert_eq_push_body(&(_z_push_body_t){._is_put = false, ._body._del = left->_body._del}, - &(_z_push_body_t){._is_put = false, ._body._del = right->_body._del}); + } break; } } @@ -1478,7 +1517,7 @@ _z_transport_message_t gen_join(void) { conduit._val._plain._best_effort = gen_uint64(); conduit._val._plain._reliable = gen_uint64(); } - return _z_t_msg_make_join(gen_uint8() % 3, gen_uint64(), gen_zid(), conduit); + return _z_t_msg_make_join(_z_whatami_from_uint8((gen_uint8() % 3)), gen_uint64(), gen_zid(), conduit); } void assert_eq_join(const _z_t_msg_join_t *left, const _z_t_msg_join_t *right) { assert(memcmp(left->_zid.id, right->_zid.id, 16) == 0); @@ -1517,16 +1556,16 @@ void join_message(void) { _z_transport_message_t gen_init(void) { if (gen_bool()) { - return _z_t_msg_make_init_syn(gen_uint8() % 3, gen_zid()); + return _z_t_msg_make_init_syn(_z_whatami_from_uint8((gen_uint8() % 3)), gen_zid()); } else { - return _z_t_msg_make_init_ack(gen_uint8() % 3, gen_zid(), gen_bytes(16)); + return _z_t_msg_make_init_ack(_z_whatami_from_uint8((gen_uint8() % 3)), gen_zid(), gen_slice(16)); } } void assert_eq_init(const _z_t_msg_init_t *left, const _z_t_msg_init_t *right) { assert(left->_batch_size == right->_batch_size); assert(left->_req_id_res == right->_req_id_res); assert(left->_seq_num_res == right->_seq_num_res); - assert_eq_bytes(&left->_cookie, &right->_cookie); + assert_eq_slice(&left->_cookie, &right->_cookie); assert(memcmp(left->_zid.id, right->_zid.id, 16) == 0); assert(left->_version == right->_version); assert(left->_whatami == right->_whatami); @@ -1549,13 +1588,13 @@ void init_message(void) { _z_transport_message_t gen_open(void) { if (gen_bool()) { - return _z_t_msg_make_open_syn(gen_uint(), gen_uint(), gen_bytes(16)); + return _z_t_msg_make_open_syn(gen_uint32(), gen_uint32(), gen_slice(16)); } else { - return _z_t_msg_make_open_ack(gen_uint(), gen_uint()); + return _z_t_msg_make_open_ack(gen_uint32(), gen_uint32()); } } void assert_eq_open(const _z_t_msg_open_t *left, const _z_t_msg_open_t *right) { - assert_eq_bytes(&left->_cookie, &right->_cookie); + assert_eq_slice(&left->_cookie, &right->_cookie); assert(left->_initial_sn == right->_initial_sn); assert(left->_lease == right->_lease); } @@ -1616,7 +1655,8 @@ void keep_alive_message(void) { _z_wbuf_clear(&wbf); } _z_network_message_t gen_net_msg(void) { - switch (gen_uint8() % 5) { + switch (gen_uint8() % 6) { + default: case 0: { return gen_declare_message(); } break; @@ -1629,10 +1669,12 @@ _z_network_message_t gen_net_msg(void) { case 3: { return (_z_network_message_t){._tag = _Z_N_RESPONSE, ._body._response = gen_response()}; } break; - case 4: - default: { + case 4: { return (_z_network_message_t){._tag = _Z_N_RESPONSE_FINAL, ._body._response_final = gen_response_final()}; } break; + case 5: { + return (_z_network_message_t){._tag = _Z_N_INTEREST, ._body._interest._interest = gen_interest()}; + } break; } } void assert_eq_net_msg(const _z_network_message_t *left, const _z_network_message_t *right) { @@ -1655,12 +1697,19 @@ void assert_eq_net_msg(const _z_network_message_t *left, const _z_network_messag case _Z_N_RESPONSE_FINAL: { assert_eq_response_final(&left->_body._response_final, &right->_body._response_final); } break; + case _Z_N_INTEREST: { + assert_eq_interest(&left->_body._interest._interest, &right->_body._interest._interest); + } break; + default: + assert(false); + break; } } _z_network_message_vec_t gen_net_msgs(size_t n) { _z_network_message_vec_t ret = _z_network_message_vec_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)); + memset(msg, 0, sizeof(_z_network_message_t)); *msg = gen_net_msg(); _z_network_message_vec_append(&ret, msg); } @@ -1668,7 +1717,7 @@ _z_network_message_vec_t gen_net_msgs(size_t n) { } _z_transport_message_t gen_frame(void) { - return _z_t_msg_make_frame(gen_uint(), gen_net_msgs(gen_uint8() % 16), gen_bool()); + return _z_t_msg_make_frame(gen_uint32(), gen_net_msgs(gen_uint8() % 16), gen_bool()); } void assert_eq_frame(const _z_t_msg_frame_t *left, const _z_t_msg_frame_t *right) { assert(left->_sn == right->_sn); @@ -1694,11 +1743,11 @@ void frame_message(void) { } _z_transport_message_t gen_fragment(void) { - return _z_t_msg_make_fragment(gen_uint(), gen_bytes(gen_uint8()), gen_bool(), gen_bool()); + return _z_t_msg_make_fragment(gen_uint32(), gen_slice(gen_uint8()), gen_bool(), gen_bool()); } void assert_eq_fragment(const _z_t_msg_fragment_t *left, const _z_t_msg_fragment_t *right) { assert(left->_sn == right->_sn); - assert_eq_bytes(&left->_payload, &right->_payload); + assert_eq_slice(&left->_payload, &right->_payload); } void fragment_message(void) { printf("\n>> fragment message\n"); @@ -1788,9 +1837,10 @@ void transport_message(void) { _z_scouting_message_t gen_scouting(void) { if (gen_bool()) { - return _z_s_msg_make_scout(gen_uint8() % 3, gen_zid()); + return _z_s_msg_make_scout((z_what_t)_z_whatami_from_uint8((gen_uint8() % 3)), gen_zid()); } else { - return _z_s_msg_make_hello(gen_uint8() % 3, gen_zid(), gen_locator_array((gen_uint8() % 16) + 1)); + return _z_s_msg_make_hello(_z_whatami_from_uint8((gen_uint8() % 3)), gen_zid(), + gen_locator_array((gen_uint8() % 16) + 1)); } } void assert_eq_scouting(const _z_scouting_message_t *left, const _z_scouting_message_t *right) { @@ -1836,6 +1886,9 @@ int main(void) { for (unsigned int i = 0; i < RUNS; i++) { printf("\n\n== RUN %u", i); + // Core + zint(); + // Message fields payload_field(); timestamp_field(); @@ -1852,11 +1905,10 @@ int main(void) { // Zenoh messages declare_message(); push_body_message(); - pull_message(); query_message(); err_message(); - ack_message(); reply_message(); + interest_message(); // Network messages push_message(); diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index cd8b28f05..25fa2d72b 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -18,7 +18,7 @@ #include #include "zenoh-pico.h" -#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/collections/slice.h" #include "zenoh-pico/protocol/core.h" #undef NDEBUG @@ -41,19 +41,21 @@ _z_list_t *subs2 = NULL; volatile unsigned int total = 0; volatile unsigned int datas = 0; -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { char *res = (char *)malloc(64); snprintf(res, 64, "%s%u", uri, *(unsigned int *)arg); printf(">> Received data: %s\t(%u/%u)\n", res, datas, total); - - z_owned_str_t k_str = z_keyexpr_to_string(sample->keyexpr); - assert(sample->payload.len == MSG_LEN); - assert(strlen(z_loan(k_str)) == strlen(res)); - assert(strncmp(res, z_loan(k_str), strlen(res)) == 0); + z_view_string_t k_str; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &k_str); + z_owned_slice_t value; + z_bytes_deserialize_into_slice(z_sample_payload(sample), &value); + assert(z_slice_len(z_loan(value)) == MSG_LEN); + assert(z_string_len(z_loan(k_str)) == strlen(res)); + assert(strncmp(res, z_string_data(z_loan(k_str)), strlen(res)) == 0); (void)(sample); datas++; - z_drop(z_move(k_str)); + z_drop(z_move(value)); free(res); } @@ -65,40 +67,43 @@ int main(int argc, char **argv) { _Bool is_reliable = strncmp(argv[1], "tcp", 3) == 0; - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make("peer")); - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(argv[1])); + z_owned_config_t config; + 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_LISTEN_KEY, argv[1]); for (unsigned int i = 0; i < SET; i++) idx[i] = i; - z_owned_session_t s1 = z_open(z_move(config)); - assert(z_check(s1)); - _z_bytes_t id_as_bytes = - _z_bytes_wrap(z_loan(s1)._val.in->val._local_zid.id, _z_id_len(z_loan(s1)._val.in->val._local_zid)); - z_string_t zid1 = _z_string_from_bytes(&id_as_bytes); - printf("Session 1 with PID: %s\n", zid1.val); + z_owned_session_t s1; + assert(z_open(&s1, z_move(config)) == 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_clear(&zid1); // Start the read session session lease loops - zp_start_read_task(z_loan(s1), NULL); - zp_start_lease_task(z_loan(s1), NULL); + zp_start_read_task(z_loan_mut(s1), NULL); + zp_start_lease_task(z_loan_mut(s1), NULL); z_sleep_s(SLEEP); - config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make("peer")); - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(argv[1])); + 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]); + + z_owned_session_t s2; + assert(z_open(&s2, z_move(config)) == Z_OK); - z_owned_session_t s2 = z_open(z_move(config)); - assert(z_check(s2)); - id_as_bytes = _z_bytes_wrap(z_loan(s2)._val.in->val._local_zid.id, _z_id_len(z_loan(s2)._val.in->val._local_zid)); - z_string_t zid2 = _z_string_from_bytes(&id_as_bytes); - printf("Session 2 with PID: %s\n", zid2.val); + 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_clear(&zid2); // Start the read session session lease loops - zp_start_read_task(z_loan(s2), NULL); - zp_start_lease_task(z_loan(s2), NULL); + zp_start_read_task(z_loan_mut(s2), NULL); + zp_start_lease_task(z_loan_mut(s2), NULL); z_sleep_s(SLEEP * 5); @@ -107,28 +112,39 @@ int main(int argc, char **argv) { for (unsigned int i = 0; i < SET; i++) { memset(s1_res, 0, 64); snprintf(s1_res, 64, "%s%u", uri, i); - z_owned_closure_sample_t callback = z_closure(data_handler, NULL, &idx[i]); + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler, NULL, &idx[i]); z_owned_subscriber_t *sub = (z_owned_subscriber_t *)z_malloc(sizeof(z_owned_subscriber_t)); - *sub = z_declare_subscriber(z_loan(s2), z_keyexpr(s1_res), &callback, NULL); - assert(z_check(*sub)); - printf("Declared subscription on session 2: %ju %zu %s\n", (uintmax_t)z_subscriber_loan(sub)._val->_entity_id, + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, s1_res); + int8_t res = z_declare_subscriber(sub, z_loan(s2), 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); subs2 = _z_list_push(subs2, sub); } // Write data from first session size_t len = MSG_LEN; - uint8_t *payload = (uint8_t *)z_malloc(len); - memset(payload, 1, MSG_LEN); + uint8_t *value = (uint8_t *)z_malloc(len); + memset(value, 1, MSG_LEN); total = MSG * SET; for (unsigned int n = 0; n < MSG; n++) { for (unsigned int i = 0; i < SET; i++) { memset(s1_res, 0, 64); snprintf(s1_res, 64, "%s%u", uri, i); - z_put_options_t opt = z_put_options_default(); + z_put_options_t opt; + z_put_options_default(&opt); opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_put(z_loan(s1), z_keyexpr(s1_res), (const uint8_t *)payload, len, &opt); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, s1_res); + + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, len, NULL, NULL); + + z_put(z_loan(s1), z_loan(ke), z_move(payload), &opt); printf("Wrote data from session 1: %s %zu b\t(%u/%u)\n", s1_res, len, n * SET + (i + 1), total); } } @@ -153,21 +169,19 @@ int main(int argc, char **argv) { // Undeclare subscribers and queryables on second session while (subs2) { z_owned_subscriber_t *sub = _z_list_head(subs2); - printf("Undeclared subscriber on session 2: %ju\n", (uintmax_t)z_subscriber_loan(sub)._val->_entity_id); + printf("Undeclared subscriber on session 2: %ju\n", (uintmax_t)z_subscriber_loan(sub)->_entity_id); z_undeclare_subscriber(z_move(*sub)); subs2 = _z_list_pop(subs2, _z_noop_elem_free, NULL); } z_sleep_s(SLEEP); - // Stop both sessions - printf("Stopping threads on session 1\n"); - zp_stop_read_task(z_loan(s1)); - zp_stop_lease_task(z_loan(s1)); + // Stop read and lease tasks for zenoh-pico + zp_stop_read_task(z_loan_mut(s1)); + zp_stop_lease_task(z_loan_mut(s1)); - printf("Stopping threads on session 2\n"); - zp_stop_read_task(z_loan(s2)); - zp_stop_lease_task(z_loan(s2)); + zp_stop_read_task(z_loan_mut(s2)); + zp_stop_lease_task(z_loan_mut(s2)); // Close both sessions printf("Closing session 1\n"); @@ -178,8 +192,8 @@ int main(int argc, char **argv) { printf("Closing session 2\n"); z_close(z_move(s2)); - z_free((uint8_t *)payload); - payload = NULL; + z_free((uint8_t *)value); + value = NULL; free(s1_res); diff --git a/tests/z_perf_rx.c b/tests/z_perf_rx.c index 58d5959c1..b46feb136 100644 --- a/tests/z_perf_rx.c +++ b/tests/z_perf_rx.c @@ -39,15 +39,18 @@ void z_stats_stop(z_stats_t *stats) { stats->count = 0; } -void on_sample(const z_sample_t *sample, void *context) { +void on_sample(const z_loaned_sample_t *sample, void *context) { z_stats_t *stats = (z_stats_t *)context; + z_owned_slice_t value; + z_bytes_deserialize_into_slice(z_sample_payload(sample), &value); + unsigned long data_len = (unsigned long)z_slice_len(z_loan(value)); - if (stats->curr_len != sample->payload.len) { + if (stats->curr_len != data_len) { // End previous measurement z_stats_stop(stats); // Check for end packet - stats->curr_len = (unsigned long)sample->payload.len; - if (sample->payload.len == 1) { + stats->curr_len = data_len; + if (data_len == 1) { test_end = true; return; } @@ -55,6 +58,7 @@ void on_sample(const z_sample_t *sample, void *context) { printf("Starting test for pkt len: %lu\n", stats->curr_len); stats->start = z_clock_now(); } + z_drop(z_move(value)); stats->count++; } @@ -74,32 +78,36 @@ int main(int argc, char **argv) { clocator = "tcp/127.0.0.1:7447"; } // Set config - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (mode != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } // Open session - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); exit(-1); } // Declare Subscriber/resource - z_owned_closure_sample_t callback = z_closure(on_sample, NULL, (void *)&test_stats); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t callback; + z_closure(&callback, on_sample, NULL, (void *)&test_stats); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to create subscriber.\n"); exit(-1); } @@ -112,13 +120,12 @@ int main(int argc, char **argv) { z_sleep_s(1); // Clean up z_undeclare_subscriber(z_move(sub)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); exit(0); } #else int main(void) { + (void)test_stats; printf("ERROR: Zenoh pico was compiled without Z_FEATURE_SUBSCRIPTION but this test requires it.\n"); return -2; } diff --git a/tests/z_perf_tx.c b/tests/z_perf_tx.c index 1852ecf37..4c8c7cd0a 100644 --- a/tests/z_perf_tx.c +++ b/tests/z_perf_tx.c @@ -26,7 +26,11 @@ int send_packets(unsigned long pkt_len, z_owned_publisher_t *pub, uint8_t *value z_clock_t test_start = z_clock_now(); unsigned long elapsed_us = 0; while (elapsed_us < TEST_DURATION_US) { - z_publisher_put(z_loan(*pub), (const uint8_t *)value, pkt_len, NULL); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, pkt_len, NULL, NULL); + + z_publisher_put(z_loan(*pub), z_move(payload), NULL); elapsed_us = z_clock_elapsed_us(&test_start); } return 0; @@ -52,31 +56,34 @@ int main(int argc, char **argv) { clocator = "tcp/127.0.0.1:7447"; } // Set config - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (mode != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); } if (clocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_CONNECT_KEY, z_string_make(clocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } // Open session - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); exit(-1); } // Declare publisher - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { + z_owned_publisher_t pub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_publisher(&pub, z_loan(s), z_loan(ke), NULL) < 0) { printf("Unable to declare publisher for key expression!\n"); exit(-1); } @@ -94,11 +101,18 @@ int main(int argc, char **argv) { } // Send end packet printf("Sending end pkt\n"); - z_publisher_put(z_loan(pub), (const uint8_t *)value, 1, NULL); + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, 1, NULL, NULL); + + z_publisher_put(z_loan(pub), z_move(payload), NULL); + + // Stop read and lease tasks for zenoh-pico + zp_stop_read_task(z_loan_mut(s)); + zp_stop_lease_task(z_loan_mut(s)); + // Clean up z_undeclare_publisher(z_move(pub)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); free(value); exit(0); diff --git a/tests/z_refcount_test.c b/tests/z_refcount_test.c new file mode 100644 index 000000000..82271f48e --- /dev/null +++ b/tests/z_refcount_test.c @@ -0,0 +1,272 @@ +// +// Copyright (c) 2024 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 +#include +#include +#include + +#include "zenoh-pico/collections/refcount.h" +#include "zenoh-pico/system/platform-common.h" + +#undef NDEBUG +#include + +#define FOO_CLEARED_VALUE -1 + +typedef struct _dummy_t { + int foo; +} _dummy_t; + +void _dummy_clear(_dummy_t *val) { + val->foo = FOO_CLEARED_VALUE; + return; +} + +_Z_REFCOUNT_DEFINE(_dummy, _dummy) + +void test_rc_null(void) { + _dummy_rc_t drc = _dummy_rc_null(); + assert(drc._cnt == NULL); + assert(drc._val == NULL); +} + +void test_rc_size(void) { assert(_dummy_rc_size(NULL) == sizeof(_dummy_rc_t)); } + +void test_rc_drop(void) { + _dummy_rc_t drc = _dummy_rc_null(); + assert(!_dummy_rc_drop(NULL)); + assert(!_dummy_rc_drop(&drc)); +} + +void test_rc_new(void) { + _dummy_t *val = z_malloc(sizeof(_dummy_t)); + val->foo = 42; + _dummy_rc_t drc = _dummy_rc_new(val); + assert(!_Z_RC_IS_NULL(&drc)); + assert(_z_rc_strong_count(drc._cnt) == 1); + assert(_z_rc_weak_count(drc._cnt) == 1); + assert(drc._val->foo == 42); + drc._val->foo = 0; + assert(val->foo == 0); + assert(_dummy_rc_drop(&drc)); +} + +void test_rc_new_from_val(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc = _dummy_rc_new_from_val(&val); + assert(!_Z_RC_IS_NULL(&drc)); + assert(_z_rc_strong_count(drc._cnt) == 1); + assert(_z_rc_weak_count(drc._cnt) == 1); + assert(drc._val->foo == 42); + drc._val->foo = 0; + assert(val.foo == 42); + assert(_dummy_rc_drop(&drc)); +} + +void test_rc_clone(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + assert(_z_rc_strong_count(drc1._cnt) == 1); + assert(_z_rc_weak_count(drc1._cnt) == 1); + + _dummy_rc_t drc2 = _dummy_rc_clone(&drc1); + assert(!_Z_RC_IS_NULL(&drc2)); + assert(_z_rc_strong_count(drc2._cnt) == 2); + assert(_z_rc_weak_count(drc2._cnt) == 2); + assert(_z_rc_strong_count(drc2._cnt) == _z_rc_strong_count(drc1._cnt)); + assert(_z_rc_weak_count(drc2._cnt) == _z_rc_weak_count(drc1._cnt)); + assert(drc2._val->foo == drc1._val->foo); + + assert(!_dummy_rc_drop(&drc1)); + assert(_z_rc_strong_count(drc2._cnt) == 1); + assert(_z_rc_weak_count(drc2._cnt) == 1); + assert(drc2._val->foo == 42); + assert(_dummy_rc_drop(&drc2)); +} + +void test_rc_eq(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_rc_t drc2 = _dummy_rc_clone(&drc1); + assert(_dummy_rc_eq(&drc1, &drc2)); + assert(!_dummy_rc_drop(&drc1)); + assert(_dummy_rc_drop(&drc2)); +} + +void test_rc_clone_as_ptr(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_rc_t *drc2 = _dummy_rc_clone_as_ptr(&drc1); + assert(drc2->_val != NULL); + assert(!_Z_RC_IS_NULL(drc2)); + assert(_z_rc_strong_count(drc2->_cnt) == 2); + assert(_z_rc_weak_count(drc2->_cnt) == 2); + assert(_dummy_rc_eq(&drc1, drc2)); + assert(!_dummy_rc_drop(&drc1)); + assert(_dummy_rc_drop(drc2)); + z_free(drc2); +} + +void test_rc_copy(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_rc_t drc2 = _dummy_rc_null(); + assert(!_dummy_rc_eq(&drc1, &drc2)); + _dummy_rc_copy(&drc2, &drc1); + assert(_z_rc_strong_count(drc2._cnt) == 2); + assert(_z_rc_weak_count(drc2._cnt) == 2); + assert(_dummy_rc_eq(&drc1, &drc2)); + assert(!_dummy_rc_drop(&drc2)); + assert(_dummy_rc_drop(&drc1)); +} + +void test_rc_clone_as_weak(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_weak_t dwk1 = _dummy_rc_clone_as_weak(&drc1); + assert(!_Z_RC_IS_NULL(&dwk1)); + assert(_z_rc_strong_count(dwk1._cnt) == 1); + assert(_z_rc_weak_count(dwk1._cnt) == 2); + + assert(dwk1._val->foo == 42); + assert(!_dummy_rc_drop(&drc1)); + assert(_z_rc_strong_count(dwk1._cnt) == 0); + assert(_z_rc_weak_count(dwk1._cnt) == 1); + assert(_dummy_weak_drop(&dwk1)); +} + +void test_rc_clone_as_weak_ptr(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_weak_t *dwk1 = _dummy_rc_clone_as_weak_ptr(&drc1); + assert(dwk1 != NULL); + assert(!_Z_RC_IS_NULL(dwk1)); + assert(_z_rc_strong_count(dwk1->_cnt) == 1); + assert(_z_rc_weak_count(dwk1->_cnt) == 2); + + assert(!_dummy_rc_drop(&drc1)); + assert(_z_rc_strong_count(dwk1->_cnt) == 0); + assert(_z_rc_weak_count(dwk1->_cnt) == 1); + assert(_dummy_weak_drop(dwk1)); + z_free(dwk1); +} + +void test_weak_null(void) { + _dummy_weak_t dwk = _dummy_weak_null(); + assert(dwk._val == NULL); + assert(dwk._cnt == NULL); +} + +void test_weak_clone(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_weak_t dwk1 = _dummy_rc_clone_as_weak(&drc1); + assert(_z_rc_strong_count(dwk1._cnt) == 1); + assert(_z_rc_weak_count(dwk1._cnt) == 2); + + _dummy_weak_t dwk2 = _dummy_weak_clone(&dwk1); + assert(_z_rc_strong_count(dwk2._cnt) == 1); + assert(_z_rc_weak_count(dwk2._cnt) == 3); + + assert(!_dummy_rc_drop(&drc1)); + assert(_z_rc_strong_count(dwk2._cnt) == 0); + assert(_z_rc_weak_count(dwk2._cnt) == 2); + + assert(_dummy_weak_eq(&dwk1, &dwk2)); + assert(!_dummy_weak_drop(&dwk2)); + assert(_dummy_weak_drop(&dwk1)); +} + +void test_weak_copy(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_weak_t dwk1 = _dummy_rc_clone_as_weak(&drc1); + _dummy_weak_t dwk2 = _dummy_weak_null(); + assert(!_dummy_weak_eq(&dwk1, &dwk2)); + + _dummy_weak_copy(&dwk2, &dwk1); + assert(_dummy_weak_eq(&dwk1, &dwk2)); + assert(_z_rc_strong_count(dwk2._cnt) == 1); + assert(_z_rc_weak_count(dwk2._cnt) == 3); + + assert(!_dummy_weak_drop(&dwk1)); + assert(!_dummy_weak_drop(&dwk2)); + assert(_dummy_rc_drop(&drc1)); +} + +void test_weak_upgrade(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new(&val); + _dummy_weak_t dwk1 = _dummy_rc_clone_as_weak(&drc1); + + // Valid upgrade + _dummy_rc_t drc2 = _dummy_weak_upgrade(&dwk1); + assert(!_Z_RC_IS_NULL(&drc2)); + assert(_z_rc_strong_count(drc2._cnt) == 2); + assert(_z_rc_weak_count(drc2._cnt) == 3); + assert(!_dummy_rc_drop(&drc1)); + assert(!_dummy_rc_drop(&drc2)); + + // Failed upgrade + _dummy_rc_t drc3 = _dummy_weak_upgrade(&dwk1); + assert(_Z_RC_IS_NULL(&drc3)); + assert(_z_rc_strong_count(dwk1._cnt) == 0); + assert(_z_rc_weak_count(dwk1._cnt) == 1); + assert(_dummy_weak_drop(&dwk1)); +} + +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_rc_t drc2 = _dummy_rc_clone(&drc1); + assert(_Z_RC_IS_NULL(&drc2)); + + _dummy_weak_t dwk1 = _dummy_rc_clone_as_weak(&drc1); + assert(_Z_RC_IS_NULL(&dwk1)); +} + +void test_decr(void) { + _dummy_t val = {.foo = 42}; + _dummy_rc_t drc1 = _dummy_rc_new_from_val(&val); + _dummy_rc_t drc2 = _dummy_rc_clone(&drc1); + assert(!_dummy_rc_decr(&drc2)); + assert(_dummy_rc_decr(&drc1)); +} + +int main(void) { + test_rc_null(); + test_rc_size(); + test_rc_drop(); + test_rc_new(); + test_rc_new_from_val(); + test_rc_clone(); + test_rc_eq(); + test_rc_clone_as_ptr(); + test_rc_copy(); + test_rc_clone_as_weak(); + test_rc_clone_as_weak_ptr(); + test_weak_null(); + test_weak_clone(); + test_weak_copy(); + test_weak_upgrade(); + test_overflow(); + test_decr(); + return 0; +} diff --git a/tests/z_session_test.c b/tests/z_session_test.c index 40058e102..15ca0f6b3 100644 --- a/tests/z_session_test.c +++ b/tests/z_session_test.c @@ -17,23 +17,25 @@ #include #include "zenoh-pico.h" +#include "zenoh-pico/api/macros.h" #undef NDEBUG #include int main(void) { - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make("client")); + z_owned_config_t config; + z_config_default(&config); + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, "client"); printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; @@ -43,9 +45,9 @@ int main(void) { // z_sleep_ms(1000); // Stop read and lease tasks for zenoh-pico - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); + zp_stop_read_task(z_loan_mut(s)); + zp_stop_lease_task(z_loan_mut(s)); // Immediately close the session - z_close(&s); + z_close(z_move(s)); } diff --git a/tests/z_test_fragment_rx.c b/tests/z_test_fragment_rx.c index 5f2e248ae..056b9f5ba 100644 --- a/tests/z_test_fragment_rx.c +++ b/tests/z_test_fragment_rx.c @@ -18,56 +18,73 @@ #include #if Z_FEATURE_SUBSCRIPTION == 1 -void data_handler(const z_sample_t *sample, void *ctx) { +void data_handler(const z_loaned_sample_t *sample, void *ctx) { (void)(ctx); - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_view_string_t keystr; + z_keyexpr_as_view_string(z_sample_keyexpr(sample), &keystr); bool is_valid = true; - const uint8_t *data = sample->payload.start; - for (size_t i = 0; i < sample->payload.len; i++) { + z_owned_slice_t value; + z_bytes_deserialize_into_slice(z_sample_payload(sample), &value); + const uint8_t *data = z_slice_data(z_loan(value)); + size_t data_len = z_slice_len(z_loan(value)); + for (size_t i = 0; i < data_len; i++) { if (data[i] != (uint8_t)i) { is_valid = false; break; } } - printf("[rx]: Received packet on %s, len: %d, validity: %d, qos {priority: %d, cong_ctrl: %d}\n", z_loan(keystr), - (int)sample->payload.len, is_valid, z_qos_get_priority(sample->qos), - z_qos_get_congestion_control(sample->qos)); - z_drop(z_move(keystr)); + printf("[rx]: Received packet on %.*s, len: %d, validity: %d, qos {priority: %d, cong_ctrl: %d}\n", + (int)z_string_len(z_loan(keystr)), z_string_data(z_loan(keystr)), (int)data_len, is_valid, + z_sample_priority(sample), z_sample_congestion_control(sample)); + z_drop(z_move(value)); } int main(int argc, char **argv) { const char *keyexpr = "test/zenoh-pico-fragment"; - const char *mode = "client"; + const char *mode = NULL; char *llocator = NULL; + char *clocator = NULL; (void)argv; // Check if peer mode if (argc > 1) { mode = "peer"; llocator = "udp/224.0.0.224:7447#iface=lo"; + } else { + mode = "client"; + clocator = "tcp/127.0.0.1:7447"; } // Set config - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + if (mode != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } // Open session - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } // Declare subscriber - z_owned_closure_sample_t callback = z_closure(data_handler); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_closure_sample_t callback; + z_closure(&callback, data_handler); + z_owned_subscriber_t sub; + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + if (z_declare_subscriber(&sub, z_loan(s), z_loan(ke), z_move(callback), NULL) < 0) { printf("Unable to declare subscriber.\n"); return -1; } @@ -80,8 +97,6 @@ int main(int argc, char **argv) { } // Clean up z_undeclare_subscriber(z_move(sub)); - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); return 0; } diff --git a/tests/z_test_fragment_tx.c b/tests/z_test_fragment_tx.c index 70b24968e..bf12b18dc 100644 --- a/tests/z_test_fragment_tx.c +++ b/tests/z_test_fragment_tx.c @@ -15,22 +15,20 @@ #include #include #include -#include +#include + +#include "zenoh-pico.h" #if Z_FEATURE_PUBLICATION == 1 int main(int argc, char **argv) { const char *keyexpr = "test/zenoh-pico-fragment"; - const char *mode = "client"; + const char *mode = NULL; char *llocator = NULL; + char *clocator = NULL; uint8_t *value = NULL; size_t size = 10000; (void)argv; - // Check if peer mode - if (argc > 1) { - mode = "peer"; - llocator = "udp/224.0.0.224:7447#iface=lo"; - } // Init value value = malloc(size); if (value == NULL) { @@ -39,38 +37,64 @@ int main(int argc, char **argv) { for (size_t i = 0; i < size; i++) { value[i] = (uint8_t)i; } + // Check if peer or client mode + if (argc > 1) { + mode = "peer"; + llocator = "udp/224.0.0.224:7447#iface=lo"; + } else { + mode = "client"; + clocator = "tcp/127.0.0.1:7447"; + } // Set config - z_owned_config_t config = z_config_default(); - zp_config_insert(z_loan(config), Z_CONFIG_MODE_KEY, z_string_make(mode)); + z_owned_config_t config; + z_config_default(&config); + if (mode != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_MODE_KEY, mode); + } if (llocator != NULL) { - zp_config_insert(z_loan(config), Z_CONFIG_LISTEN_KEY, z_string_make(llocator)); + zp_config_insert(z_loan_mut(config), Z_CONFIG_LISTEN_KEY, llocator); + } + if (clocator != NULL) { + zp_config_insert(z_loan_mut(config), Z_CONFIG_CONNECT_KEY, clocator); } // Open session - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); return -1; } // Start read and lease tasks for zenoh-pico - if (zp_start_read_task(z_loan(s), NULL) < 0 || zp_start_lease_task(z_loan(s), NULL) < 0) { + 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_close(z_session_move(&s)); return -1; } + // Wait for joins + if (strcmp(mode, "peer") == 0) { + z_sleep_s(3); + } // Put data - z_put_options_t options = z_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); + z_view_keyexpr_t ke; + z_view_keyexpr_from_str(&ke, keyexpr); + + z_put_options_t options; + z_put_options_default(&options); options.priority = Z_PRIORITY_DATA_HIGH; options.congestion_control = Z_CONGESTION_CONTROL_BLOCK; + for (int i = 0; i < 5; i++) { + // Create payload + z_owned_bytes_t payload; + z_bytes_from_buf(&payload, value, size, NULL, NULL); + printf("[tx]: Sending packet on %s, len: %d\n", keyexpr, (int)size); - if (z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)value, size, &options) < 0) { + if (z_put(z_loan(s), z_loan(ke), z_move(payload), &options) < 0) { printf("Oh no! Put has failed...\n"); + return -1; } + z_sleep_s(1); } // Clean up - zp_stop_read_task(z_loan(s)); - zp_stop_lease_task(z_loan(s)); z_close(z_move(s)); free(value); return 0; diff --git a/tools/z_keyexpr_canonizer.c b/tools/z_keyexpr_canonizer.c index 239152648..3ffd19105 100644 --- a/tools/z_keyexpr_canonizer.c +++ b/tools/z_keyexpr_canonizer.c @@ -33,7 +33,7 @@ int main(int argc, char **argv) { buffer = realloc(buffer, len + 1); strncpy(buffer, argv[i], len); buffer[len] = '\0'; - zp_keyexpr_canon_status_t status = zp_keyexpr_canonize_null_terminated(buffer); + zp_keyexpr_canon_status_t status = z_keyexpr_canonize(buffer, &len); switch (status) { case Z_KEYEXPR_CANON_SUCCESS: diff --git a/version.txt b/version.txt index 6e5d683f0..bd2666abb 100644 --- a/version.txt +++ b/version.txt @@ -1 +1 @@ -0.11.0.0 \ No newline at end of file +1.0.0.0 \ No newline at end of file diff --git a/zenohpico.pc b/zenohpico.pc index 7433e1cc5..45f37d7e1 100644 --- a/zenohpico.pc +++ b/zenohpico.pc @@ -3,6 +3,6 @@ prefix=/usr/local Name: zenohpico Description: URL: -Version: 0.11.20240411dev +Version: 1.0.20240830dev Cflags: -I${prefix}/include Libs: -L${prefix}/lib -lzenohpico diff --git a/zephyr/CMakeLists.txt b/zephyr/CMakeLists.txt index a3e7f145a..3559a1c90 100644 --- a/zephyr/CMakeLists.txt +++ b/zephyr/CMakeLists.txt @@ -31,7 +31,6 @@ configure_zenoh_feature(CONFIG_ZENOH_PICO_LINK_WS) file(GLOB_RECURSE Sources "../src/api/*.c" "../src/collections/*.c" - "../src/deprecated/*.c" "../src/link/*.c" "../src/net/*.c" "../src/protocol/*.c"