diff --git a/.clang-format b/.clang-format index a777cf13a..f36aab3ab 100644 --- a/.clang-format +++ b/.clang-format @@ -1,3 +1,4 @@ BasedOnStyle: Google IndentWidth: 4 ColumnLimit: 120 +PointerAlignment: Left \ No newline at end of file diff --git a/.github/workflows/arduino_esp32.yaml b/.github/workflows/arduino_esp32.yaml index d54477ee0..197ce7776 100644 --- a/.github/workflows/arduino_esp32.yaml +++ b/.github/workflows/arduino_esp32.yaml @@ -15,129 +15,129 @@ name: arduino_esp32 on: push: - branches: [ '**' ] + branches: ["**"] pull_request: - branches: [ '**' ] + branches: ["**"] jobs: build: - name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 - - - name: Install requirements - run: | - echo "No requirements need to be installed" - - - name: Install PlatformIO - run: | - python3 -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" - . $HOME/.platformio/penv/bin/activate - platformio update - - - name: Set up project - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - mkdir -p $ARDUINO_BASE - cd $ARDUINO_BASE - platformio init -b esp32thing_plus --project-option="build_flags=-DZ_LINK_BLUETOOTH=1 -DZENOH_DEBUG=3" - - cd $ARDUINO_BASE/lib - ln -s $ZENOH_PICO_BASE - - cd $ARDUINO_BASE - - - name: Build z_pub example - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ARDUINO_BASE/src/* - cd $ARDUINO_BASE/src - ln -s $ZENOH_PICO_BASE/examples/arduino/z_pub.ino - - cd $ARDUINO_BASE - platformio run - - - name: Build z_sub example - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ARDUINO_BASE/src/* - cd $ARDUINO_BASE/src - ln -s $ZENOH_PICO_BASE/examples/arduino/z_sub.ino - - cd $ARDUINO_BASE - platformio run - - - name: Build z_pull example - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ARDUINO_BASE/src/* - cd $ARDUINO_BASE/src - ln -s $ZENOH_PICO_BASE/examples/arduino/z_pull.ino - - cd $ARDUINO_BASE - platformio run - - - name: Build z_get example - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ARDUINO_BASE/src/* - cd $ARDUINO_BASE/src - ln -s $ZENOH_PICO_BASE/examples/arduino/z_get.ino - - cd $ARDUINO_BASE - platformio run - - - name: Build z_queryable example - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ARDUINO_BASE/src/* - cd $ARDUINO_BASE/src - ln -s $ZENOH_PICO_BASE/examples/arduino/z_queryable.ino - - cd $ARDUINO_BASE - platformio run - - - name: Build z_scout example - run: | - cd $HOME - export ARDUINO_BASE=$HOME/work/arduino_esp32project/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ARDUINO_BASE/src/* - cd $ARDUINO_BASE/src - ln -s $ZENOH_PICO_BASE/examples/arduino/z_scout.ino - - cd $ARDUINO_BASE - platformio run + - uses: actions/checkout@v2 + + - name: Install requirements + run: | + echo "No requirements need to be installed" + + - name: Install PlatformIO + run: | + curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py + python3 get-platformio.py + . $HOME/.platformio/penv/bin/activate + platformio update + + - name: Set up project + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + mkdir -p $ARDUINO_BASE + cd $ARDUINO_BASE + platformio init -b esp32thing_plus --project-option="build_flags=-DZ_LINK_BLUETOOTH=1 -DZENOH_DEBUG=3" + + cd $ARDUINO_BASE/lib + ln -s $ZENOH_PICO_BASE + + cd $ARDUINO_BASE + + - name: Build z_pub example + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ARDUINO_BASE/src/* + cd $ARDUINO_BASE/src + ln -s $ZENOH_PICO_BASE/examples/arduino/z_pub.ino + + cd $ARDUINO_BASE + platformio run + + - name: Build z_sub example + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ARDUINO_BASE/src/* + cd $ARDUINO_BASE/src + ln -s $ZENOH_PICO_BASE/examples/arduino/z_sub.ino + + cd $ARDUINO_BASE + platformio run + + - name: Build z_pull example + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ARDUINO_BASE/src/* + cd $ARDUINO_BASE/src + ln -s $ZENOH_PICO_BASE/examples/arduino/z_pull.ino + + cd $ARDUINO_BASE + platformio run + + - name: Build z_get example + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ARDUINO_BASE/src/* + cd $ARDUINO_BASE/src + ln -s $ZENOH_PICO_BASE/examples/arduino/z_get.ino + + cd $ARDUINO_BASE + platformio run + + - name: Build z_queryable example + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ARDUINO_BASE/src/* + cd $ARDUINO_BASE/src + ln -s $ZENOH_PICO_BASE/examples/arduino/z_queryable.ino + + cd $ARDUINO_BASE + platformio run + + - name: Build z_scout example + run: | + cd $HOME + export ARDUINO_BASE=$HOME/work/arduino_esp32project/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ARDUINO_BASE/src/* + cd $ARDUINO_BASE/src + ln -s $ZENOH_PICO_BASE/examples/arduino/z_scout.ino + + cd $ARDUINO_BASE + platformio run diff --git a/.github/workflows/espidf.yaml b/.github/workflows/espidf.yaml index 181b60af4..6f46eb0e4 100644 --- a/.github/workflows/espidf.yaml +++ b/.github/workflows/espidf.yaml @@ -15,129 +15,129 @@ name: espidf on: push: - branches: [ '**' ] + branches: ["**"] pull_request: - branches: [ '**' ] + branches: ["**"] jobs: build: - name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 - - - name: Install requirements - run: | - echo "No requirements need to be installed" - - - name: Install PlatformIO - run: | - python3 -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" - . $HOME/.platformio/penv/bin/activate - platformio update - - - name: Set up project - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - mkdir -p $ESPIDF_BASE - cd $ESPIDF_BASE - platformio init -b az-delivery-devkit-v4 --project-option="framework=espidf" --project-option="build_flags=-DZENOH_ESPIDF -DZENOH_DEBUG=3" - - cd $ESPIDF_BASE/lib - ln -s $ZENOH_PICO_BASE - - cd $ESPIDF_BASE - - - name: Build z_pub example - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ESPIDF_BASE/src/* - cd $ESPIDF_BASE/src - ln -s $ZENOH_PICO_BASE/examples/espidf/z_pub.c - - cd $ESPIDF_BASE - platformio run - - - name: Build z_sub example - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ESPIDF_BASE/src/* - cd $ESPIDF_BASE/src - ln -s $ZENOH_PICO_BASE/examples/espidf/z_sub.c - - cd $ESPIDF_BASE - platformio run - - - name: Build z_pull example - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ESPIDF_BASE/src/* - cd $ESPIDF_BASE/src - ln -s $ZENOH_PICO_BASE/examples/espidf/z_pull.c - - cd $ESPIDF_BASE - platformio run - - - name: Build z_get example - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ESPIDF_BASE/src/* - cd $ESPIDF_BASE/src - ln -s $ZENOH_PICO_BASE/examples/espidf/z_get.c - - cd $ESPIDF_BASE - platformio run - - - name: Build z_queryable example - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ESPIDF_BASE/src/* - cd $ESPIDF_BASE/src - ln -s $ZENOH_PICO_BASE/examples/espidf/z_queryable.c - - cd $ESPIDF_BASE - platformio run - - - name: Build z_scout example - run: | - cd $HOME - export ESPIDF_BASE=$HOME/work/espidfproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ESPIDF_BASE/src/* - cd $ESPIDF_BASE/src - ln -s $ZENOH_PICO_BASE/examples/espidf/z_scout.c - - cd $ESPIDF_BASE - platformio run + - uses: actions/checkout@v2 + + - name: Install requirements + run: | + echo "No requirements need to be installed" + + - name: Install PlatformIO + run: | + curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py + python3 get-platformio.py + . $HOME/.platformio/penv/bin/activate + platformio update + + - name: Set up project + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + mkdir -p $ESPIDF_BASE + cd $ESPIDF_BASE + platformio init -b az-delivery-devkit-v4 --project-option="framework=espidf" --project-option="build_flags=-DZENOH_ESPIDF -DZENOH_DEBUG=3" + + cd $ESPIDF_BASE/lib + ln -s $ZENOH_PICO_BASE + + cd $ESPIDF_BASE + + - name: Build z_pub example + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ESPIDF_BASE/src/* + cd $ESPIDF_BASE/src + ln -s $ZENOH_PICO_BASE/examples/espidf/z_pub.c + + cd $ESPIDF_BASE + platformio run + + - name: Build z_sub example + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ESPIDF_BASE/src/* + cd $ESPIDF_BASE/src + ln -s $ZENOH_PICO_BASE/examples/espidf/z_sub.c + + cd $ESPIDF_BASE + platformio run + + - name: Build z_pull example + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ESPIDF_BASE/src/* + cd $ESPIDF_BASE/src + ln -s $ZENOH_PICO_BASE/examples/espidf/z_pull.c + + cd $ESPIDF_BASE + platformio run + + - name: Build z_get example + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ESPIDF_BASE/src/* + cd $ESPIDF_BASE/src + ln -s $ZENOH_PICO_BASE/examples/espidf/z_get.c + + cd $ESPIDF_BASE + platformio run + + - name: Build z_queryable example + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ESPIDF_BASE/src/* + cd $ESPIDF_BASE/src + ln -s $ZENOH_PICO_BASE/examples/espidf/z_queryable.c + + cd $ESPIDF_BASE + platformio run + + - name: Build z_scout example + run: | + cd $HOME + export ESPIDF_BASE=$HOME/work/espidfproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ESPIDF_BASE/src/* + cd $ESPIDF_BASE/src + ln -s $ZENOH_PICO_BASE/examples/espidf/z_scout.c + + cd $ESPIDF_BASE + platformio run diff --git a/.github/workflows/integration.yaml b/.github/workflows/integration.yaml index 5015e4757..888b9d72e 100644 --- a/.github/workflows/integration.yaml +++ b/.github/workflows/integration.yaml @@ -32,28 +32,28 @@ jobs: os: [ ubuntu-latest, macOS-latest ] steps: - - uses: actions/checkout@v2 - - - name: Install latest stable - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - components: rustfmt, clippy + - uses: actions/checkout@v2 - - name: Compile debug - run: make all - env: - BUILD_TYPE: Debug - BUILD_TESTING: OFF - BUILD_MULTICAST: OFF - BUILD_INTEGRATION: ON + - name: Install latest stable + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy - - name: Test debug - run: make test - env: - BUILD_TYPE: Debug # Workaround for Windows as it seems the previous step is being ignored - BUILD_TESTING: OFF # Workaround for Windows as it seems the previous step is being ignored - BUILD_MULTICAST: OFF # Workaround for Windows as it seems the previous step is being ignored - BUILD_INTEGRATION: ON # Workaround for Windows as it seems the previous step is being ignored - ZENOH_BRANCH: master + - name: Compile debug + run: make all + env: + BUILD_TYPE: Debug + BUILD_TESTING: OFF + BUILD_MULTICAST: OFF + BUILD_INTEGRATION: ON + + - name: Test debug + run: make test + env: + BUILD_TYPE: Debug # Workaround for Windows as it seems the previous step is being ignored + BUILD_TESTING: OFF # Workaround for Windows as it seems the previous step is being ignored + BUILD_MULTICAST: OFF # Workaround for Windows as it seems the previous step is being ignored + BUILD_INTEGRATION: ON # Workaround for Windows as it seems the previous step is being ignored + ZENOH_BRANCH: new-protocol diff --git a/.github/workflows/mbed.yaml b/.github/workflows/mbed.yaml index 3c691cd5e..03386d06e 100644 --- a/.github/workflows/mbed.yaml +++ b/.github/workflows/mbed.yaml @@ -15,129 +15,129 @@ name: mbed on: push: - branches: [ '**' ] + branches: ["**"] pull_request: - branches: [ '**' ] + branches: ["**"] jobs: build: - name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 - - - name: Install requirements - run: | - echo "No requirements need to be installed" - - - name: Install PlatformIO - run: | - python3 -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" - . $HOME/.platformio/penv/bin/activate - platformio update - - - name: Set up project - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - mkdir -p $MBED_BASE - cd $MBED_BASE - pio init -b nucleo_f767zi --project-option="framework=mbed" --project-option="build_flags=-DZ_LINK_SERIAL=1 -DZENOH_DEBUG=3" - - cd $MBED_BASE/lib - ln -s $ZENOH_PICO_BASE - - cd $MBED_BASE - - - name: Build z_pub example - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $MBED_BASE/src/* - cd $MBED_BASE/src - ln -s $ZENOH_PICO_BASE/examples/mbed/z_pub.cpp - - cd $MBED_BASE - platformio run - - - name: Build z_sub example - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $MBED_BASE/src/* - cd $MBED_BASE/src - ln -s $ZENOH_PICO_BASE/examples/mbed/z_sub.cpp - - cd $MBED_BASE - platformio run - - - name: Build z_pull example - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $MBED_BASE/src/* - cd $MBED_BASE/src - ln -s $ZENOH_PICO_BASE/examples/mbed/z_pull.cpp - - cd $MBED_BASE - platformio run - - - name: Build z_get example - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $MBED_BASE/src/* - cd $MBED_BASE/src - ln -s $ZENOH_PICO_BASE/examples/mbed/z_get.cpp - - cd $MBED_BASE - platformio run - - - name: Build z_queryable example - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $MBED_BASE/src/* - cd $MBED_BASE/src - ln -s $ZENOH_PICO_BASE/examples/mbed/z_queryable.cpp - - cd $MBED_BASE - platformio run - - - name: Build z_scout example - run: | - cd $HOME - export MBED_BASE=$HOME/work/mbedproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $MBED_BASE/src/* - cd $MBED_BASE/src - ln -s $ZENOH_PICO_BASE/examples/mbed/z_scout.cpp - - cd $MBED_BASE - platformio run + - uses: actions/checkout@v2 + + - name: Install requirements + run: | + echo "No requirements need to be installed" + + - name: Install PlatformIO + run: | + curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py + python3 get-platformio.py + . $HOME/.platformio/penv/bin/activate + platformio update + + - name: Set up project + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + mkdir -p $MBED_BASE + cd $MBED_BASE + pio init -b nucleo_f767zi --project-option="framework=mbed" --project-option="build_flags=-DZ_LINK_SERIAL=1 -DZENOH_DEBUG=3" + + cd $MBED_BASE/lib + ln -s $ZENOH_PICO_BASE + + cd $MBED_BASE + + - name: Build z_pub example + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $MBED_BASE/src/* + cd $MBED_BASE/src + ln -s $ZENOH_PICO_BASE/examples/mbed/z_pub.cpp + + cd $MBED_BASE + platformio run + + - name: Build z_sub example + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $MBED_BASE/src/* + cd $MBED_BASE/src + ln -s $ZENOH_PICO_BASE/examples/mbed/z_sub.cpp + + cd $MBED_BASE + platformio run + + - name: Build z_pull example + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $MBED_BASE/src/* + cd $MBED_BASE/src + ln -s $ZENOH_PICO_BASE/examples/mbed/z_pull.cpp + + cd $MBED_BASE + platformio run + + - name: Build z_get example + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $MBED_BASE/src/* + cd $MBED_BASE/src + ln -s $ZENOH_PICO_BASE/examples/mbed/z_get.cpp + + cd $MBED_BASE + platformio run + + - name: Build z_queryable example + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $MBED_BASE/src/* + cd $MBED_BASE/src + ln -s $ZENOH_PICO_BASE/examples/mbed/z_queryable.cpp + + cd $MBED_BASE + platformio run + + - name: Build z_scout example + run: | + cd $HOME + export MBED_BASE=$HOME/work/mbedproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $MBED_BASE/src/* + cd $MBED_BASE/src + ln -s $ZENOH_PICO_BASE/examples/mbed/z_scout.cpp + + cd $MBED_BASE + platformio run diff --git a/.github/workflows/multicast.yaml b/.github/workflows/multicast.yaml index 3c3fd8179..63bc774a1 100644 --- a/.github/workflows/multicast.yaml +++ b/.github/workflows/multicast.yaml @@ -15,34 +15,34 @@ name: multicast on: push: - branches: [ '**' ] + branches: ["**"] pull_request: - branches: [ '**' ] + branches: ["**"] schedule: - - cron: '0 6 * * 1-5' + - cron: "0 6 * * 1-5" jobs: build: - name: Build on macOS-latest runs-on: macOS-latest strategy: fail-fast: false matrix: - os: [ macOS-latest ] + os: [macOS-latest] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v2 - - name: Compile debug - run: make all - env: - BUILD_TYPE: Debug - BUILD_TESTING: OFF - BUILD_MULTICAST: ON - BUILD_INTEGRATION: OFF + - name: Compile debug + run: make all + env: + BUILD_TYPE: Debug + BUILD_TESTING: OFF + BUILD_MULTICAST: ON + BUILD_INTEGRATION: OFF + ZENOH_BRANCH: new-protocol - - name: Test debug - run: make test - env: - ARGS: -V + - name: Test debug + run: make test + env: + ARGS: -V diff --git a/.github/workflows/zephyr.yaml b/.github/workflows/zephyr.yaml index acc52a51d..7ec080212 100644 --- a/.github/workflows/zephyr.yaml +++ b/.github/workflows/zephyr.yaml @@ -15,132 +15,132 @@ name: zephyr on: push: - branches: [ '**' ] + branches: ["**"] pull_request: - branches: [ '**' ] + branches: ["**"] jobs: build: - name: Build on ${{ matrix.os }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - os: [ ubuntu-latest ] + os: [ubuntu-latest] steps: - - uses: actions/checkout@v2 - - - name: Install requirements - run: | - echo "No requirements need to be installed" - - - name: Install PlatformIO - run: | - python3 -c "$(curl -fsSL https://raw.githubusercontent.com/platformio/platformio/master/scripts/get-platformio.py)" - . $HOME/.platformio/penv/bin/activate - platformio update - - - name: Set up project - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - mkdir -p $ZEPHYR_BASE - cd $ZEPHYR_BASE - pio init -b nucleo_f767zi --project-option="framework=zephyr" --project-option="build_flags=-DZ_LINK_SERIAL=1 -DZENOH_DEBUG=3" - - cd $ZEPHYR_BASE/lib - ln -s $ZENOH_PICO_BASE - - mkdir -p $ZEPHYR_BASE/zephyr - cd $ZEPHYR_BASE/zephyr - ln -s $ZENOH_PICO_BASE/docs/zephyr/nucleo_f767zi/prj.conf prj.conf - ln -s $ZENOH_PICO_BASE/docs/zephyr/nucleo_f767zi/CMakeLists.txt CMakeLists.txt - - - name: Build z_pub example - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ZEPHYR_BASE/src/* - cd $ZEPHYR_BASE/src - ln -s $ZENOH_PICO_BASE/examples/zephyr/z_pub.c - - cd $ZEPHYR_BASE - platformio run - - - name: Build z_sub example - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ZEPHYR_BASE/src/* - cd $ZEPHYR_BASE/src - ln -s $ZENOH_PICO_BASE/examples/zephyr/z_sub.c - - cd $ZEPHYR_BASE - platformio run - - - name: Build z_pull example - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ZEPHYR_BASE/src/* - cd $ZEPHYR_BASE/src - ln -s $ZENOH_PICO_BASE/examples/zephyr/z_pull.c - - cd $ZEPHYR_BASE - platformio run - - - name: Build z_get example - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ZEPHYR_BASE/src/* - cd $ZEPHYR_BASE/src - ln -s $ZENOH_PICO_BASE/examples/zephyr/z_get.c - - cd $ZEPHYR_BASE - platformio run - - - name: Build z_queryable example - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ZEPHYR_BASE/src/* - cd $ZEPHYR_BASE/src - ln -s $ZENOH_PICO_BASE/examples/zephyr/z_queryable.c - - cd $ZEPHYR_BASE - platformio run - - - name: Build z_scout example - run: | - cd $HOME - export ZEPHYR_BASE=$HOME/work/zephyrproject/ - export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ - . $HOME/.platformio/penv/bin/activate - - rm -rf $ZEPHYR_BASE/src/* - cd $ZEPHYR_BASE/src - ln -s $ZENOH_PICO_BASE/examples/zephyr/z_scout.c - - cd $ZEPHYR_BASE - platformio run + - uses: actions/checkout@v2 + + - name: Install requirements + run: | + echo "No requirements need to be installed" + + - name: Install PlatformIO + run: | + curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py + python3 get-platformio.py + . $HOME/.platformio/penv/bin/activate + platformio update + + - name: Set up project + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + mkdir -p $ZEPHYR_BASE + cd $ZEPHYR_BASE + pio init -b nucleo_f767zi --project-option="framework=zephyr" --project-option="build_flags=-DZ_LINK_SERIAL=1 -DZENOH_DEBUG=3" + + cd $ZEPHYR_BASE/lib + ln -s $ZENOH_PICO_BASE + + mkdir -p $ZEPHYR_BASE/zephyr + cd $ZEPHYR_BASE/zephyr + ln -s $ZENOH_PICO_BASE/docs/zephyr/nucleo_f767zi/prj.conf prj.conf + ln -s $ZENOH_PICO_BASE/docs/zephyr/nucleo_f767zi/CMakeLists.txt CMakeLists.txt + + - name: Build z_pub example + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ZEPHYR_BASE/src/* + cd $ZEPHYR_BASE/src + ln -s $ZENOH_PICO_BASE/examples/zephyr/z_pub.c + + cd $ZEPHYR_BASE + platformio run + + - name: Build z_sub example + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ZEPHYR_BASE/src/* + cd $ZEPHYR_BASE/src + ln -s $ZENOH_PICO_BASE/examples/zephyr/z_sub.c + + cd $ZEPHYR_BASE + platformio run + + - name: Build z_pull example + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ZEPHYR_BASE/src/* + cd $ZEPHYR_BASE/src + ln -s $ZENOH_PICO_BASE/examples/zephyr/z_pull.c + + cd $ZEPHYR_BASE + platformio run + + - name: Build z_get example + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ZEPHYR_BASE/src/* + cd $ZEPHYR_BASE/src + ln -s $ZENOH_PICO_BASE/examples/zephyr/z_get.c + + cd $ZEPHYR_BASE + platformio run + + - name: Build z_queryable example + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ZEPHYR_BASE/src/* + cd $ZEPHYR_BASE/src + ln -s $ZENOH_PICO_BASE/examples/zephyr/z_queryable.c + + cd $ZEPHYR_BASE + platformio run + + - name: Build z_scout example + run: | + cd $HOME + export ZEPHYR_BASE=$HOME/work/zephyrproject/ + export ZENOH_PICO_BASE=$HOME/work/zenoh-pico/zenoh-pico/ + . $HOME/.platformio/penv/bin/activate + + rm -rf $ZEPHYR_BASE/src/* + cd $ZEPHYR_BASE/src + ln -s $ZENOH_PICO_BASE/examples/zephyr/z_scout.c + + cd $ZEPHYR_BASE + platformio run diff --git a/BSDmakefile b/BSDmakefile index 5dc504035..790a7288e 100644 --- a/BSDmakefile +++ b/BSDmakefile @@ -62,8 +62,9 @@ CMAKE_OPT=-DZENOH_DEBUG=$(ZENOH_DEBUG) -DBUILD_EXAMPLES=$(BUILD_EXAMPLES) -DCMAK all: make -$(BUILD_DIR)/Makefile: CMakeLists.txt +$(BUILD_DIR)/Makefile: mkdir -p $(BUILD_DIR) + echo $(CMAKE_OPT) cmake $(CMAKE_OPT) -B$(BUILD_DIR) make: $(BUILD_DIR)/Makefile diff --git a/CMakeLists.txt b/CMakeLists.txt index 332bf0411..d1e86848a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -129,41 +129,28 @@ elseif(CMAKE_BUILD_TYPE MATCHES "RELEASE") endif() endif() -file(GLOB PublicHeaders "include/*.h" - "include/zenoh-pico/*.h" + +file(GLOB_RECURSE PublicHeaders "include/zenoh-pico/api/*.h" "include/zenoh-pico/collections/*.h" "include/zenoh-pico/link/*.h" - "include/zenoh-pico/link/config/*.h" + "include/zenoh-pico/net/*.h" "include/zenoh-pico/protocol/*.h" "include/zenoh-pico/session/*.h" - "include/zenoh-pico/system/*.h" - "include/zenoh-pico/system/link/*.h" "include/zenoh-pico/transport/*.h" "include/zenoh-pico/utils/*.h" + "include/zenoh-pico/config.h" ) target_include_directories(${Libname} PUBLIC ${PROJECT_SOURCE_DIR}/include) -file(GLOB Sources "src/*.c" +file(GLOB_RECURSE Sources "src/api/*.c" - "src/net/*.c" "src/collections/*.c" "src/link/*.c" - "src/link/config/*.c" - "src/link/unicast/*.c" - "src/link/multicast/*.c" + "src/net/*.c" "src/protocol/*.c" - "src/protocol/keyexpr/*.c" "src/session/*.c" - "src/system/*.c" "src/transport/*.c" - "src/transport/common/*.c" - "src/transport/unicast/*.c" - "src/transport/unicast/link/*.c" - "src/transport/unicast/link/task/*.c" - "src/transport/multicast/*.c" - "src/transport/multicast/link/*.c" - "src/transport/multicast/link/task/*.c" "src/utils/*.c" ) diff --git a/GNUmakefile b/GNUmakefile index 6ea060ed9..cf4512a1b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -62,8 +62,9 @@ CMAKE_OPT=-DZENOH_DEBUG=$(ZENOH_DEBUG) -DBUILD_EXAMPLES=$(BUILD_EXAMPLES) -DCMAK all: make -$(BUILD_DIR)/Makefile: CMakeLists.txt +$(BUILD_DIR)/Makefile: mkdir -p $(BUILD_DIR) + echo $(CMAKE_OPT) cmake $(CMAKE_OPT) -B $(BUILD_DIR) make: $(BUILD_DIR)/Makefile diff --git a/examples/arduino/z_scout.ino b/examples/arduino/z_scout.ino index bc7e2f17d..632b50295 100644 --- a/examples/arduino/z_scout.ino +++ b/examples/arduino/z_scout.ino @@ -20,13 +20,25 @@ #define SSID "SSID" #define PASS "PASS" -void fprintzid(z_bytes_t zid) { - if (zid.start == NULL) { +uint8_t zid_len(z_id_t id) { + uint8_t len = 16; + while (len > 0) { + --len; + if (id.id[len] != 0) { + ++len; + break; + } + } + return len; +} +void fprintzid(z_id_t zid) { + unsigned int zidlen = zid_len(zid); + if (zidlen == 0) { Serial.print("None"); } else { Serial.print("Some("); - for (unsigned int i = 0; i < zid.len; i++) { - Serial.print(zid.start[i], HEX); + for (unsigned int i = 0; i < zidlen; i++) { + Serial.print(zid.id[i], HEX); } Serial.print(")"); } diff --git a/examples/espidf/z_scout.c b/examples/espidf/z_scout.c index 96be38a7e..3b45a5a6a 100644 --- a/examples/espidf/z_scout.c +++ b/examples/espidf/z_scout.c @@ -86,13 +86,14 @@ void wifi_init_sta(void) { vEventGroupDelete(s_event_group_handler); } -void fprintzid(FILE *stream, z_bytes_t zid) { - if (zid.start == NULL) { +void fprintzid(FILE *stream, z_id_t zid) { + unsigned int zidlen = _z_id_len(zid); + if (zidlen == 0) { fprintf(stream, "None"); } else { fprintf(stream, "Some("); - for (unsigned int i = 0; i < zid.len; i++) { - fprintf(stream, "%02X", (int)zid.start[i]); + for (unsigned int i = 0; i < zidlen; i++) { + fprintf(stream, "%02X", (int)zid.id[i]); } fprintf(stream, ")"); } diff --git a/examples/mbed/z_scout.cpp b/examples/mbed/z_scout.cpp index 8d3ee55cc..c3cdf5d41 100644 --- a/examples/mbed/z_scout.cpp +++ b/examples/mbed/z_scout.cpp @@ -16,13 +16,26 @@ #include #include -void fprintzid(FILE *stream, z_bytes_t zid) { - if (zid.start == NULL) { +uint8_t zid_len(z_id_t id) { + uint8_t len = 16; + while (len > 0) { + --len; + if (id.id[len] != 0) { + ++len; + break; + } + } + return len; +} + +void fprintzid(FILE *stream, z_id_t zid) { + unsigned int zidlen = zid_len(zid); + if (zidlen == 0) { fprintf(stream, "None"); } else { fprintf(stream, "Some("); - for (unsigned int i = 0; i < zid.len; i++) { - fprintf(stream, "%02X", (int)zid.start[i]); + for (unsigned int i = 0; i < zidlen; i++) { + fprintf(stream, "%02X", (int)zid.id[i]); } fprintf(stream, ")"); } diff --git a/examples/unix/c11/z_ping.c b/examples/unix/c11/z_ping.c index d4ff47adb..4db578c7e 100644 --- a/examples/unix/c11/z_ping.c +++ b/examples/unix/c11/z_ping.c @@ -150,4 +150,4 @@ struct args_t parse_args(int argc, char** argv) { .number_of_pings = number_of_pings, .warmup_ms = warmup_ms, }; -} \ No newline at end of file +} diff --git a/examples/unix/c11/z_pong.c b/examples/unix/c11/z_pong.c index c0d1cd0b0..503c37e25 100644 --- a/examples/unix/c11/z_pong.c +++ b/examples/unix/c11/z_pong.c @@ -53,4 +53,4 @@ int main(int argc, char** argv) { zp_stop_lease_task(z_loan(session)); z_close(z_move(session)); -} \ No newline at end of file +} diff --git a/examples/unix/c11/z_pub.c b/examples/unix/c11/z_pub.c index add4332f3..3516dfb43 100644 --- a/examples/unix/c11/z_pub.c +++ b/examples/unix/c11/z_pub.c @@ -16,17 +16,22 @@ #include #include #include +#include #include #include +#include "zenoh-pico/system/platform.h" + int main(int argc, char **argv) { const char *keyexpr = "demo/example/zenoh-pico-pub"; - const char *value = "Pub from Pico!"; + char *const default_value = "Pub from Pico!"; + char *value = default_value; const char *mode = "client"; char *locator = NULL; + int n = 10; int opt; - while ((opt = getopt(argc, argv, "k:v:e:m:")) != -1) { + while ((opt = getopt(argc, argv, "k:v:e:m:l:n:")) != -1) { switch (opt) { case 'k': keyexpr = optarg; @@ -40,6 +45,18 @@ int main(int argc, char **argv) { case 'm': mode = optarg; break; + case 'l': + opt = atoi(optarg); + value = z_malloc(opt + 1); + memset(value, 'A', opt); + value[opt] = 0; + for (int i = opt - 1; opt > 0; i--, opt /= 10) { + value[i] = '0' + (opt % 10); + } + break; + case 'n': + n = atoi(optarg); + break; case '?': if (optopt == 'k' || optopt == 'v' || optopt == 'e' || optopt == 'm') { fprintf(stderr, "Option -%c requires an argument.\n", optopt); @@ -78,15 +95,15 @@ int main(int argc, char **argv) { return -1; } - char *buf = (char *)malloc(256); - for (int idx = 0; 1; ++idx) { + for (int idx = 0; idx < n; ++idx) { sleep(1); - snprintf(buf, 256, "[%4d] %s", idx, value); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); + (void)idx; + // snprintf(buf, 256, "[%4d] %s", idx, value); + printf("Putting Data ('%s': '%s')...\n", keyexpr, value); 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); + z_publisher_put(z_loan(pub), (const uint8_t *)value, strlen(value), &options); } z_undeclare_publisher(z_move(pub)); @@ -97,6 +114,8 @@ int main(int argc, char **argv) { z_close(z_move(s)); - free(buf); + if (value != default_value) { + free(value); + } return 0; } diff --git a/examples/unix/c11/z_put.c b/examples/unix/c11/z_put.c index 29807cc8d..9a7d70195 100644 --- a/examples/unix/c11/z_put.c +++ b/examples/unix/c11/z_put.c @@ -72,20 +72,20 @@ int main(int argc, char **argv) { } 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"); - return -1; - } + // 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"); + // return -1; + // } 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_keyexpr(keyexpr), (const uint8_t *)value, strlen(value), &options) < 0) { printf("Oh no! Put has failed...\n"); } - z_undeclare_keyexpr(z_loan(s), z_move(ke)); + // z_undeclare_keyexpr(z_loan(s), z_move(ke)); // Stop read and lease tasks for zenoh-pico zp_stop_read_task(z_loan(s)); diff --git a/examples/unix/c11/z_scout.c b/examples/unix/c11/z_scout.c index 84dbfe39e..751609db1 100644 --- a/examples/unix/c11/z_scout.c +++ b/examples/unix/c11/z_scout.c @@ -19,13 +19,14 @@ #include #include -void fprintzid(FILE *stream, z_bytes_t zid) { - if (zid.start == NULL) { +void fprintzid(FILE *stream, z_id_t zid) { + unsigned int zidlen = _z_id_len(zid); + if (zidlen == 0) { fprintf(stream, "None"); } else { fprintf(stream, "Some("); - for (unsigned int i = 0; i < zid.len; i++) { - fprintf(stream, "%02X", (int)zid.start[i]); + for (unsigned int i = 0; i < zidlen; i++) { + fprintf(stream, "%02X", (int)zid.id[i]); } fprintf(stream, ")"); } @@ -68,6 +69,7 @@ void callback(z_owned_hello_t *hello, void *context) { fprinthello(stdout, z_loan(*hello)); fprintf(stdout, "\n"); (*(int *)context)++; + z_drop(hello); } void drop(void *context) { diff --git a/examples/unix/c99/z_scout.c b/examples/unix/c99/z_scout.c index c2eb2096a..5b40a408e 100644 --- a/examples/unix/c99/z_scout.c +++ b/examples/unix/c99/z_scout.c @@ -17,13 +17,14 @@ #include #include -void fprintzid(FILE *stream, z_bytes_t zid) { - if (zid.start == NULL) { +void fprintzid(FILE *stream, z_id_t zid) { + unsigned int zidlen = _z_id_len(zid); + if (zidlen == 0) { fprintf(stream, "None"); } else { fprintf(stream, "Some("); - for (unsigned int i = 0; i < zid.len; i++) { - fprintf(stream, "%02X", (int)zid.start[i]); + for (unsigned int i = 0; i < zidlen; i++) { + fprintf(stream, "%02X", (int)zid.id[i]); } fprintf(stream, ")"); } @@ -66,6 +67,7 @@ void callback(z_owned_hello_t *hello, void *context) { fprinthello(stdout, z_hello_loan(hello)); fprintf(stdout, "\n"); (*(int *)context)++; + z_drop(hello); } void drop(void *context) { diff --git a/examples/windows/z_scout.c b/examples/windows/z_scout.c index 1d1590b02..8d7feea64 100644 --- a/examples/windows/z_scout.c +++ b/examples/windows/z_scout.c @@ -18,13 +18,14 @@ #include #include -void fprintzid(FILE *stream, z_bytes_t zid) { - if (zid.start == NULL) { +void fprintzid(FILE *stream, z_id_t zid) { + unsigned int zidlen = _z_id_len(zid); + if (zidlen == 0) { fprintf(stream, "None"); } else { fprintf(stream, "Some("); - for (unsigned int i = 0; i < zid.len; i++) { - fprintf(stream, "%02X", (int)zid.start[i]); + for (unsigned int i = 0; i < zidlen; i++) { + fprintf(stream, "%02X", (int)zid.id[i]); } fprintf(stream, ")"); } diff --git a/examples/zephyr/z_scout.c b/examples/zephyr/z_scout.c index 1c3e2d101..e9e221194 100644 --- a/examples/zephyr/z_scout.c +++ b/examples/zephyr/z_scout.c @@ -14,13 +14,14 @@ #include #include -void fprintzid(FILE *stream, z_bytes_t zid) { - if (zid.start == NULL) { +void fprintzid(FILE *stream, z_id_t zid) { + unsigned int zidlen = _z_id_len(zid); + if (zidlen == 0) { fprintf(stream, "None"); } else { fprintf(stream, "Some("); - for (unsigned int i = 0; i < zid.len; i++) { - fprintf(stream, "%02X", (int)zid.start[i]); + for (unsigned int i = 0; i < zidlen; i++) { + fprintf(stream, "%02X", (int)zid.id[i]); } fprintf(stream, ")"); } diff --git a/include/zenoh-pico/api/constants.h b/include/zenoh-pico/api/constants.h index 221379489..9e9e095ca 100644 --- a/include/zenoh-pico/api/constants.h +++ b/include/zenoh-pico/api/constants.h @@ -21,6 +21,20 @@ extern "C" { #endif +/** + * What values. + * + * Enumerators: + * Z_WHAT_ROUTER: Router. + * Z_WHAT_PEER: Peer. + * Z_WHAT_CLIENT: Client. + */ +typedef enum { + Z_WHAT_ROUTER = 0x01, // Router + Z_WHAT_PEER = 0x02, // Peer + Z_WHAT_CLIENT = 0x03 // Client +} z_what_t; + /** * Whatami values, defined as a bitmask. * @@ -29,11 +43,7 @@ extern "C" { * Z_WHATAMI_PEER: Bitmask to filter for Zenoh peers. * Z_WHATAMI_CLIENT: Bitmask to filter for Zenoh clients. */ -typedef enum { - Z_WHATAMI_ROUTER = 0x01, // 1 << 0 - Z_WHATAMI_PEER = 0x02, // 1 << 1 - Z_WHATAMI_CLIENT = 0x04 // 1 << 2 -} z_whatami_t; +typedef enum { Z_WHATAMI_ROUTER = 0x00, Z_WHATAMI_PEER = 0x01, Z_WHATAMI_CLIENT = 0x02 } z_whatami_t; #define Z_WHATAMI_DEFAULT Z_WHATAMI_ROUTER /** @@ -154,7 +164,7 @@ typedef enum { * Z_RELIABILITY_BEST_EFFORT: Defines reliability as ``BEST_EFFORT`` * Z_RELIABILITY_RELIABLE: Defines reliability as ``RELIABLE`` */ -typedef enum { Z_RELIABILITY_BEST_EFFORT = 0, Z_RELIABILITY_RELIABLE = 1 } z_reliability_t; +typedef enum { Z_RELIABILITY_BEST_EFFORT = 1, Z_RELIABILITY_RELIABLE = 0 } z_reliability_t; #define Z_RELIABILITY_DEFAULT Z_RELIABILITY_RELIABLE /** diff --git a/include/zenoh-pico/api/macros.h b/include/zenoh-pico/api/macros.h index 23ed7eb21..f6b6077fb 100644 --- a/include/zenoh-pico/api/macros.h +++ b/include/zenoh-pico/api/macros.h @@ -230,7 +230,7 @@ * Returns: * Returns the new closure. */ -#define z_closure(...) _z_closure_overloader(__VA_ARGS__, 0, 0) +#define z_closure(...) _z_closure_overloader(__VA_ARGS__, 0, 0, 0) #else @@ -343,4 +343,4 @@ inline void z_call(const z_owned_closure_zid_t &closure, const z_id_t *zid) #endif /* ZENOH_C_STANDARD != 99 */ -#endif /* ZENOH_PICO_API_MACROS_H */ \ No newline at end of file +#endif /* ZENOH_PICO_API_MACROS_H */ diff --git a/include/zenoh-pico/api/types.h b/include/zenoh-pico/api/types.h index f62d495cd..4e8c48f13 100644 --- a/include/zenoh-pico/api/types.h +++ b/include/zenoh-pico/api/types.h @@ -11,8 +11,8 @@ // Contributors: // ZettaScale Zenoh Team, -#ifndef ZENOH_PICO_API_TYPES_H -#define ZENOH_PICO_API_TYPES_H +#ifndef INCLUDE_ZENOH_PICO_API_TYPES_H +#define INCLUDE_ZENOH_PICO_API_TYPES_H #include "zenoh-pico/net/publish.h" #include "zenoh-pico/net/query.h" @@ -395,7 +395,7 @@ typedef _z_sample_t z_sample_t; * Represents the content of a `hello` message returned by a zenoh entity as a reply to a `scout` message. * * Members: - * uint8_t whatami: The kind of zenoh entity. + * 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. */ @@ -541,4 +541,4 @@ void z_closure_zid_call(const z_owned_closure_zid_t *closure, const z_id_t *id); } #endif -#endif /* ZENOH_PICO_API_TYPES_H */ +#endif /* INCLUDE_ZENOH_PICO_API_TYPES_H */ diff --git a/include/zenoh-pico/collections/bytes.h b/include/zenoh-pico/collections/bytes.h index 8d04e7914..0002bc257 100644 --- a/include/zenoh-pico/collections/bytes.h +++ b/include/zenoh-pico/collections/bytes.h @@ -34,9 +34,11 @@ typedef struct { } _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); _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src); diff --git a/include/zenoh-pico/collections/list.h b/include/zenoh-pico/collections/list.h index b2b913175..339e7c25f 100644 --- a/include/zenoh-pico/collections/list.h +++ b/include/zenoh-pico/collections/list.h @@ -59,8 +59,8 @@ void _z_list_free(_z_list_t **xs, z_element_free_f f_f); static inline type *name##_list_head(const name##_list_t *l) { return (type *)_z_list_head(l); } \ static inline name##_list_t *name##_list_tail(const name##_list_t *l) { return _z_list_tail(l); } \ static inline name##_list_t *name##_list_push(name##_list_t *l, type *e) { return _z_list_push(l, e); } \ - static inline name##_list_t *name##_list_pop(name##_list_t *l, type** x) { \ - return _z_list_pop(l, name##_elem_free, (void**)x); \ + static inline name##_list_t *name##_list_pop(name##_list_t *l, type **x) { \ + return _z_list_pop(l, name##_elem_free, (void **)x); \ } \ static inline name##_list_t *name##_list_find(const name##_list_t *l, name##_eq_f c_f, type *e) { \ return _z_list_find(l, (z_element_eq_f)c_f, e); \ diff --git a/include/zenoh-pico/config.h b/include/zenoh-pico/config.h index 234e66fb3..23a929993 100644 --- a/include/zenoh-pico/config.h +++ b/include/zenoh-pico/config.h @@ -12,8 +12,8 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_CONFIG_H -#define ZENOH_PICO_CONFIG_H +#ifndef INCLUDE_ZENOH_PICO_CONFIG_H +#define INCLUDE_ZENOH_PICO_CONFIG_H /*------------------ Runtime configuration properties ------------------*/ /** @@ -88,6 +88,12 @@ #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`. @@ -114,7 +120,7 @@ * Do not change this value. */ #ifndef Z_PROTO_VERSION -#define Z_PROTO_VERSION 0x07 +#define Z_PROTO_VERSION 0x08 #endif /** @@ -145,13 +151,12 @@ #define Z_CONFIG_SOCKET_TIMEOUT 100 #endif -/** - * The default sequence number resolution takes 4 bytes on the wire. - * Given the VLE encoding of ZInt, 4 bytes result in 28 useful bits. - * 2^28 = 268_435_456 => Max Seq Num = 268_435_455 - */ #ifndef Z_SN_RESOLUTION -#define Z_SN_RESOLUTION 268435455 +#define Z_SN_RESOLUTION 0x02 +#endif + +#ifndef Z_REQ_RESOLUTION +#define Z_REQ_RESOLUTION 0x02 #endif /** @@ -218,21 +223,16 @@ #endif /** - * Defaulf maximum batch size possible to be received. + * Defaulf maximum batch size possible to be received or sent. */ -#ifndef Z_BATCH_SIZE_RX -#define Z_BATCH_SIZE_RX \ - 65535 // Warning: changing this value can break the communication - // with zenohd in the current protocol version. - // In the future, it will be possible to negotiate such value. - // Change it at your own risk. +#ifndef Z_BATCH_UNICAST_SIZE +#define Z_BATCH_UNICAST_SIZE 65535 #endif - /** - * Defaulf maximum batch size possible to be sent. + * Defaulf maximum batch size possible to be received or sent. */ -#ifndef Z_BATCH_SIZE_TX -#define Z_BATCH_SIZE_TX 65535 +#ifndef Z_BATCH_MULTICAST_SIZE +#define Z_BATCH_MULTICAST_SIZE 8192 #endif /** @@ -271,4 +271,4 @@ #endif #endif -#endif /* ZENOH_PICO_CONFIG_H */ +#endif /* INCLUDE_ZENOH_PICO_CONFIG_H */ diff --git a/include/zenoh-pico/link/config/udp.h b/include/zenoh-pico/link/config/udp.h index e7a4dffc9..36e5b08c9 100644 --- a/include/zenoh-pico/link/config/udp.h +++ b/include/zenoh-pico/link/config/udp.h @@ -44,4 +44,4 @@ int8_t _z_udp_config_from_str(_z_str_intmap_t *strint, const char *s); int8_t _z_udp_config_from_strn(_z_str_intmap_t *strint, const char *s, size_t n); #endif -#endif /* ZENOH_PICO_LINK_CONFIG_UDP_H */ \ No newline at end of file +#endif /* ZENOH_PICO_LINK_CONFIG_UDP_H */ diff --git a/include/zenoh-pico/net/primitives.h b/include/zenoh-pico/net/primitives.h index e7fc75839..1ebcf43aa 100644 --- a/include/zenoh-pico/net/primitives.h +++ b/include/zenoh-pico/net/primitives.h @@ -14,6 +14,9 @@ #ifndef ZENOH_PICO_PRIMITIVES_NETAPI_H #define ZENOH_PICO_PRIMITIVES_NETAPI_H +#include + +#include "zenoh-pico/api/constants.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/net/publish.h" #include "zenoh-pico/net/query.h" @@ -28,12 +31,13 @@ * Scout for routers and/or peers. * * Parameters: - * what: A whatami bitmask of zenoh entities kind to scout for. + * what: A what bitmask of zenoh entities kind to scout for. + * zid: The ZenohID of the scouting origin. * locator: The locator where to scout. * timeout: The time that should be spent scouting before returnng the results. */ -void _z_scout(const z_whatami_t what, const char *locator, const uint32_t timeout, _z_hello_handler_t callback, - void *arg_call, _z_drop_handler_t dropper, void *arg_drop); +void _z_scout(const z_what_t what, const _z_id_t zid, const char *locator, const uint32_t timeout, + _z_hello_handler_t callback, void *arg_call, _z_drop_handler_t dropper, void *arg_drop); /*------------------ Declarations ------------------*/ @@ -51,7 +55,7 @@ void _z_scout(const z_whatami_t what, const char *locator, const uint32_t timeou * Returns: * A numerical id of the declared resource. */ -_z_zint_t _z_declare_resource(_z_session_t *zn, _z_keyexpr_t keyexpr); +uint16_t _z_declare_resource(_z_session_t *zn, _z_keyexpr_t keyexpr); /** * Associate a numerical id with the given resource key. @@ -65,7 +69,7 @@ _z_zint_t _z_declare_resource(_z_session_t *zn, _z_keyexpr_t keyexpr); * Returns: * 0 if success, or a negative value identifying the error. */ -int8_t _z_undeclare_resource(_z_session_t *zn, const _z_zint_t rid); +int8_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid); /** * Declare a :c:type:`_z_publisher_t` for the given resource key. @@ -172,7 +176,8 @@ int8_t _z_undeclare_queryable(_z_queryable_t *qle); * ``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); + const _z_encoding_t encoding, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, + z_priority_t priority); /** * Pull data for a pull mode :c:type:`_z_subscriber_t`. The pulled data will be provided @@ -216,9 +221,8 @@ int8_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, * 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. - * len: The length of the value of this reply. + * payload: The value of this reply, the caller keeps ownership. */ -int8_t _z_send_reply(const z_query_t *query, _z_keyexpr_t keyexpr, const uint8_t *payload, const size_t len); +int8_t _z_send_reply(const z_query_t *query, const _z_keyexpr_t keyexpr, const _z_value_t payload); #endif /* ZENOH_PICO_PRIMITIVES_NETAPI_H */ diff --git a/include/zenoh-pico/net/publish.h b/include/zenoh-pico/net/publish.h index 638f015b5..0e6ab763c 100644 --- a/include/zenoh-pico/net/publish.h +++ b/include/zenoh-pico/net/publish.h @@ -12,8 +12,8 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_PUBLISH_NETAPI_H -#define ZENOH_PICO_PUBLISH_NETAPI_H +#ifndef INCLUDE_ZENOH_PICO_NET_PUBLISH_H +#define INCLUDE_ZENOH_PICO_NET_PUBLISH_H #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" @@ -32,4 +32,4 @@ typedef struct { void _z_publisher_clear(_z_publisher_t *pub); void _z_publisher_free(_z_publisher_t **pub); -#endif /* ZENOH_PICO_PUBLISH_NETAPI_H */ +#endif /* INCLUDE_ZENOH_PICO_NET_PUBLISH_H */ diff --git a/include/zenoh-pico/net/query.h b/include/zenoh-pico/net/query.h index 104b98432..cb59f6dd5 100644 --- a/include/zenoh-pico/net/query.h +++ b/include/zenoh-pico/net/query.h @@ -14,6 +14,8 @@ #ifndef ZENOH_PICO_QUERY_NETAPI_H #define ZENOH_PICO_QUERY_NETAPI_H +#include + #include "zenoh-pico/api/constants.h" #include "zenoh-pico/protocol/core.h" @@ -23,7 +25,7 @@ typedef struct { _z_value_t _value; _z_keyexpr_t _key; - _z_zint_t _qid; + uint32_t _request_id; void *_zn; // FIXME: _z_session_t *zn; char *_parameters; _Bool _anyke; @@ -33,7 +35,7 @@ typedef struct { * Return type when declaring a queryable. */ typedef struct { - _z_zint_t _id; + uint32_t _entity_id; void *_zn; // FIXME: _z_session_t *zn; } _z_queryable_t; diff --git a/include/zenoh-pico/net/resource.h b/include/zenoh-pico/net/resource.h deleted file mode 100644 index 566c649d4..000000000 --- a/include/zenoh-pico/net/resource.h +++ /dev/null @@ -1,44 +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_RESOURCE_NETAPI_H -#define ZENOH_PICO_RESOURCE_NETAPI_H - -#include "zenoh-pico/collections/string.h" -#include "zenoh-pico/protocol/core.h" - -/** - * Create a resource key from a resource name. - * - * Parameters: - * rname: The resource name. The caller keeps its ownership. - * - * Returns: - * A :c:type:`_z_keyexpr_t` containing a new resource key. - */ -_z_keyexpr_t _z_rname(const char *rname); - -/** - * Create a resource key from a resource id and a suffix. - * - * Parameters: - * id: The resource id. - * suffix: The suffix. - * - * Returns: - * A :c:type:`_z_keyexpr_t` containing a new resource key. - */ -_z_keyexpr_t _z_rid_with_suffix(_z_zint_t rid, const char *suffix); - -#endif /* ZENOH_PICO_RESOURCE_NETAPI_H */ diff --git a/include/zenoh-pico/net/session.h b/include/zenoh-pico/net/session.h index 76e628692..19c90adee 100644 --- a/include/zenoh-pico/net/session.h +++ b/include/zenoh-pico/net/session.h @@ -12,10 +12,15 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_SESSION_NETAPI_H -#define ZENOH_PICO_SESSION_NETAPI_H +#ifndef INCLUDE_ZENOH_PICO_NET_SESSION_H +#define INCLUDE_ZENOH_PICO_NET_SESSION_H +#include + +#include "zenoh-pico/collections/element.h" +#include "zenoh-pico/collections/list.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/session.h" #include "zenoh-pico/utils/config.h" @@ -31,13 +36,14 @@ typedef struct { _z_transport_t _tp; // Zenoh PID - _z_bytes_t _local_zid; + _z_id_t _local_zid; // Session counters - _z_zint_t _resource_id; - _z_zint_t _entity_id; + uint16_t _resource_id; + uint32_t _entity_id; _z_zint_t _pull_id; _z_zint_t _query_id; + _z_zint_t _interest_id; // Session declarations _z_resource_list_t *_local_resources; @@ -168,4 +174,4 @@ int8_t _zp_start_lease_task(_z_session_t *z); int8_t _zp_stop_lease_task(_z_session_t *z); #endif // Z_MULTI_THREAD == 1 -#endif /* ZENOH_PICO_SESSION_NETAPI_H */ +#endif /* INCLUDE_ZENOH_PICO_NET_SESSION_H */ diff --git a/include/zenoh-pico/net/subscribe.h b/include/zenoh-pico/net/subscribe.h index 48b0465b5..2a8a53c1b 100644 --- a/include/zenoh-pico/net/subscribe.h +++ b/include/zenoh-pico/net/subscribe.h @@ -15,6 +15,8 @@ #ifndef ZENOH_PICO_SUBSCRIBE_NETAPI_H #define ZENOH_PICO_SUBSCRIBE_NETAPI_H +#include + #include "zenoh-pico/net/session.h" #include "zenoh-pico/protocol/core.h" @@ -22,7 +24,7 @@ * Return type when declaring a subscriber. */ typedef struct { - _z_zint_t _id; + uint32_t _entity_id; _z_session_t *_zn; } _z_subscriber_t; diff --git a/include/zenoh-pico/protocol/codec.h b/include/zenoh-pico/protocol/codec.h index 6ed578635..d58d3a66f 100644 --- a/include/zenoh-pico/protocol/codec.h +++ b/include/zenoh-pico/protocol/codec.h @@ -12,52 +12,8 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_PROTOCOL_CODEC_H -#define ZENOH_PICO_PROTOCOL_CODEC_H - -#include - -#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_EC(fn) \ - if (fn != _Z_RES_OK) { \ - return -1; \ - } - -/*------------------ 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); -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); - -int8_t _z_uint8_encode(_z_wbuf_t *buf, uint8_t v); -int8_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *buf); - -int8_t _z_uint64_encode(_z_wbuf_t *buf, uint64_t v); -int8_t _z_uint64_decode(uint64_t *u8, _z_zbuf_t *buf); - -int8_t _z_zint_encode(_z_wbuf_t *buf, _z_zint_t v); -int8_t _z_zint_decode(_z_zint_t *zint, _z_zbuf_t *buf); - -int8_t _z_bytes_encode(_z_wbuf_t *buf, const _z_bytes_t *bs); -int8_t _z_bytes_decode(_z_bytes_t *bs, _z_zbuf_t *buf); -int8_t _z_bytes_decode_na(_z_bytes_t *bs, _z_zbuf_t *buf); - -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_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); - -#endif /* ZENOH_PICO_PROTOCOL_CODEC_H */ +#ifndef INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_H +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/codec/message.h" +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_H */ diff --git a/include/zenoh-pico/protocol/codec/core.h b/include/zenoh-pico/protocol/codec/core.h new file mode 100644 index 000000000..222fb5922 --- /dev/null +++ b/include/zenoh-pico/protocol/codec/core.h @@ -0,0 +1,87 @@ +// +// 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_PROTOCOL_CODEC_CORE_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_CORE_H + +#include +#include + +#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; \ + } \ + } + +/*------------------ 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); +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); + +int8_t _z_uint8_encode(_z_wbuf_t *buf, uint8_t v); +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(_z_zint_t v); +int8_t _z_zint_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_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_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_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); + +int8_t _z_timestamp_encode(_z_wbuf_t *buf, const _z_timestamp_t *ts); +int8_t _z_timestamp_encode_ext(_z_wbuf_t *buf, const _z_timestamp_t *ts); +int8_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *buf); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_CORE_H */ diff --git a/include/zenoh-pico/protocol/codec/declarations.h b/include/zenoh-pico/protocol/codec/declarations.h new file mode 100644 index 000000000..1e4ffa631 --- /dev/null +++ b/include/zenoh-pico/protocol/codec/declarations.h @@ -0,0 +1,60 @@ +// +// 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_PROTOCOL_CODEC_DECLARATIONS_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_DECLARATIONS_H + +#include "zenoh-pico/protocol/definitions/declarations.h" +#include "zenoh-pico/protocol/iobuf.h" +#define _Z_DECL_KEXPR_MID 0 +#define _Z_DECL_KEXPR_FLAG_N 0x20 +#define _Z_UNDECL_KEXPR_MID 1 +#define _Z_DECL_SUBSCRIBER_MID 2 +#define _Z_DECL_SUBSCRIBER_FLAG_N 0x20 +#define _Z_DECL_SUBSCRIBER_FLAG_M 0x40 +#define _Z_UNDECL_SUBSCRIBER_MID 3 +#define _Z_DECL_QUERYABLE_MID 4 +#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 +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); +int8_t _z_undecl_kexpr_decode(_z_undecl_kexpr_t *decl, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_decl_subscriber_encode(_z_wbuf_t *wbf, const _z_decl_subscriber_t *decl); +int8_t _z_decl_subscriber_decode(_z_decl_subscriber_t *decl, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_undecl_subscriber_encode(_z_wbuf_t *wbf, const _z_undecl_subscriber_t *decl); +int8_t _z_undecl_subscriber_decode(_z_undecl_subscriber_t *decl, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_decl_queryable_encode(_z_wbuf_t *wbf, const _z_decl_queryable_t *decl); +int8_t _z_decl_queryable_decode(_z_decl_queryable_t *decl, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_undecl_queryable_encode(_z_wbuf_t *wbf, const _z_undecl_queryable_t *decl); +int8_t _z_undecl_queryable_decode(_z_undecl_queryable_t *decl, _z_zbuf_t *zbf, uint8_t header); +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); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/codec/ext.h b/include/zenoh-pico/protocol/codec/ext.h new file mode 100644 index 000000000..428842aa1 --- /dev/null +++ b/include/zenoh-pico/protocol/codec/ext.h @@ -0,0 +1,69 @@ +// +// 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_PROTOCOL_CODEC_EXTCODEC_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_EXTCODEC_H + +#include + +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/ext.h" +#include "zenoh-pico/protocol/iobuf.h" + +/*------------------ Message Extension ------------------*/ +int8_t _z_msg_ext_encode(_z_wbuf_t *wbf, const _z_msg_ext_t *ext, _Bool has_next); +int8_t _z_msg_ext_decode(_z_msg_ext_t *ext, _z_zbuf_t *zbf, _Bool *has_next); +int8_t _z_msg_ext_decode_na(_z_msg_ext_t *ext, _z_zbuf_t *zbf, _Bool *has_next); +int8_t _z_msg_ext_vec_encode(_z_wbuf_t *wbf, const _z_msg_ext_vec_t *extensions); +int8_t _z_msg_ext_vec_decode(_z_msg_ext_vec_t *extensions, _z_zbuf_t *zbf); +/** + * Iterates through the extensions in `zbf`, assuming at least one is present at its begining + * (calling this function otherwise is UB). Short-circuits if `callback` returns a non-zero value. + * + * `callback` will receive `context` as its second argument, and may "steal" its first argument by + * copying its value and setting it to `_z_msg_ext_make_unit(0)`. + */ +int8_t _z_msg_ext_decode_iter(_z_zbuf_t *zbf, int8_t (*callback)(_z_msg_ext_t *, void *), void *context); +/** + * Iterates through the extensions in `zbf`, assuming at least one is present at its begining. + * Returns `_Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN` if a mandatory extension is found, + * `_Z_RES_OK` otherwise. + */ +int8_t _z_msg_ext_skip_non_mandatories(_z_zbuf_t *zbf, uint8_t trace_id); +/** + * Logs an error to debug the unknown extension, returning `_Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN`. + * + * `trace_id` may be any arbitrary value, but is advised to be unique to its call-site, + * to help debugging should it be necessary. + */ +int8_t _z_msg_ext_unknown_error(_z_msg_ext_t *extension, uint8_t trace_id); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_EXTCODEC_H */ + +// NOTE: the following headers are for unit testing only +#ifdef ZENOH_PICO_TEST_H +// ------------------ Message Fields ------------------ +int8_t _z_msg_ext_encode_unit(_z_wbuf_t *wbf, const _z_msg_ext_unit_t *pld); +int8_t _z_msg_ext_decode_unit(_z_msg_ext_unit_t *pld, _z_zbuf_t *zbf); +int8_t _z_msg_ext_decode_unit_na(_z_msg_ext_unit_t *pld, _z_zbuf_t *zbf); + +int8_t _z_msg_ext_encode_zint(_z_wbuf_t *wbf, const _z_msg_ext_zint_t *pld); +int8_t _z_msg_ext_decode_zint(_z_msg_ext_zint_t *pld, _z_zbuf_t *zbf); +int8_t _z_msg_ext_decode_zint_na(_z_msg_ext_zint_t *pld, _z_zbuf_t *zbf); + +int8_t _z_msg_ext_encode_zbuf(_z_wbuf_t *wbf, const _z_msg_ext_zbuf_t *pld); +int8_t _z_msg_ext_decode_zbuf(_z_msg_ext_zbuf_t *pld, _z_zbuf_t *zbf); +int8_t _z_msg_ext_decode_zbuf_na(_z_msg_ext_zbuf_t *pld, _z_zbuf_t *zbf); + +#endif /* ZENOH_PICO_TEST_H */ diff --git a/include/zenoh-pico/protocol/codec/message.h b/include/zenoh-pico/protocol/codec/message.h new file mode 100644 index 000000000..89080475a --- /dev/null +++ b/include/zenoh-pico/protocol/codec/message.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 INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_MESSAGE_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_MESSAGE_H + +#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_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); + +int8_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del); +int8_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_MESSAGE_H */ diff --git a/include/zenoh-pico/protocol/codec/network.h b/include/zenoh-pico/protocol/codec/network.h new file mode 100644 index 000000000..ef42cc991 --- /dev/null +++ b/include/zenoh-pico/protocol/codec/network.h @@ -0,0 +1,36 @@ +// +// 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_PROTOCOL_CODEC_NETWORK_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_NETWORK_H + +#include + +#include "zenoh-pico/protocol/definitions/network.h" +#include "zenoh-pico/protocol/iobuf.h" +int8_t _z_push_encode(_z_wbuf_t *wbf, const _z_n_msg_push_t *msg); +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 _z_request_decode(_z_n_msg_request_t *msg, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg); +int8_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header); +int8_t _z_response_final_encode(_z_wbuf_t *wbf, const _z_n_msg_response_final_t *msg); +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_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); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_NETWORK_H */ diff --git a/include/zenoh-pico/protocol/codec/transport.h b/include/zenoh-pico/protocol/codec/transport.h new file mode 100644 index 000000000..0feaf1784 --- /dev/null +++ b/include/zenoh-pico/protocol/codec/transport.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 INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_TRANSPORT_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_TRANSPORT_H + +#include "zenoh-pico/protocol/definitions/transport.h" +#include "zenoh-pico/protocol/iobuf.h" +#define _ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE 32 + +int8_t _z_scouting_message_encode(_z_wbuf_t *buf, const _z_scouting_message_t *msg); +int8_t _z_scouting_message_decode(_z_scouting_message_t *msg, _z_zbuf_t *buf); + +int8_t _z_transport_message_encode(_z_wbuf_t *buf, const _z_transport_message_t *msg); +int8_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *buf); + +int8_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg); +int8_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header); + +int8_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t *msg); +int8_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header); + +int8_t _z_open_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_open_t *msg); +int8_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header); + +int8_t _z_close_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_close_t *msg); +int8_t _z_close_decode(_z_t_msg_close_t *msg, _z_zbuf_t *zbf, uint8_t header); + +int8_t _z_keep_alive_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_keep_alive_t *msg); +int8_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header); + +int8_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_t *msg); +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 _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t header); + +int8_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_message_t *msg); +int8_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf); +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CODEC_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/core.h b/include/zenoh-pico/protocol/core.h index 4909c4504..de72c49c7 100644 --- a/include/zenoh-pico/protocol/core.h +++ b/include/zenoh-pico/protocol/core.h @@ -12,9 +12,11 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_PROTOCOL_CORE_H -#define ZENOH_PICO_PROTOCOL_CORE_H +#ifndef INCLUDE_ZENOH_PICO_PROTOCOL_CORE_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_CORE_H +#include +#include #include #include "zenoh-pico/api/constants.h" @@ -22,6 +24,10 @@ #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/system/platform.h" + +#define _Z_OPTIONAL +#define _Z_MOVE(x) x * /** * The reserved resource ID indicating a string-only resource key. @@ -45,6 +51,9 @@ typedef size_t _z_zint_t; typedef struct { uint8_t id[16]; } _z_id_t; +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. @@ -63,9 +72,24 @@ typedef struct { } _z_timestamp_t; _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp); -void _z_timestamp_reset(_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); +/** + * The product of: + * - top-most bit: whether or not the keyexpr containing this mapping owns its suffix (1=true) + * - the mapping for the keyexpr prefix: + * - 0: local mapping. + * - 0x7fff (MAX): unknown remote mapping. + * - x: the mapping associated with the x-th peer. + */ +typedef struct { + uint16_t _val; +} _z_mapping_t; +#define _Z_KEYEXPR_MAPPING_LOCAL 0 +#define _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE 0x7fff + /** * A zenoh-net resource key. * @@ -74,9 +98,58 @@ _Bool _z_timestamp_check(const _z_timestamp_t *stamp); * char *val: A pointer to the string containing the resource name. */ typedef struct { - _z_zint_t _id; - const char *_suffix; + uint16_t _id; + _z_mapping_t _mapping; + char *_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) { + assert(id <= _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + return (_z_mapping_t){._val = (uint16_t)((owns_suffix ? 0x8000 : 0) | id)}; +} +static inline void _z_keyexpr_set_mapping(_z_keyexpr_t *ke, uint16_t id) { + assert(id <= _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + ke->_mapping._val &= 0x8000; + ke->_mapping._val |= id; +} +static inline void _z_keyexpr_fix_mapping(_z_keyexpr_t *ke, uint16_t id) { + if (_z_keyexpr_mapping_id(ke) == _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE) { + _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); } + +/** + * Create a resource key from a resource name. + * + * Parameters: + * rname: The resource name. The caller keeps its ownership. + * + * Returns: + * A :c:type:`_z_keyexpr_t` containing a new resource key. + */ +_z_keyexpr_t _z_rname(const char *rname); + +/** + * Create a resource key from a resource id and a suffix. + * + * Parameters: + * id: The resource id. + * suffix: The suffix. + * + * Returns: + * A :c:type:`_z_keyexpr_t` containing a new resource key. + */ +_z_keyexpr_t _z_rid_with_suffix(uint16_t rid, const char *suffix); /** * A zenoh-net data sample. @@ -107,6 +180,10 @@ typedef struct { _z_bytes_t payload; _z_encoding_t encoding; } _z_value_t; +_z_value_t _z_value_null(void); +_z_value_t _z_value_steal(_z_value_t *value); +void _z_value_clear(_z_value_t *src); +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`. @@ -114,12 +191,13 @@ typedef struct { * 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. - * uint8_t whatami: The kind of zenoh entity. + * z_whatami_t whatami: The kind of zenoh entity. */ typedef struct { - _z_bytes_t zid; + _z_id_t zid; _z_str_array_t locators; - uint8_t whatami; + 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); @@ -159,4 +237,16 @@ typedef struct { z_submode_t mode; } _z_subinfo_t; -#endif /* ZENOH_PICO_PROTOCOL_CORE_H */ +typedef struct { + _z_id_t _id; + uint32_t _entity_id; + uint32_t _source_sn; +} _z_source_info_t; +_z_source_info_t _z_source_info_null(void); + +typedef struct { + uint32_t _request_id; + uint32_t _entity_id; +} _z_reply_context_t; + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_CORE_H */ diff --git a/include/zenoh-pico/protocol/definitions/core.h b/include/zenoh-pico/protocol/definitions/core.h new file mode 100644 index 000000000..58d16a430 --- /dev/null +++ b/include/zenoh-pico/protocol/definitions/core.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 INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_CORE_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_CORE_H + +#include "zenoh-pico/protocol/core.h" + +#define _Z_DEFAULT_UNICAST_BATCH_SIZE 65535 +#define _Z_DEFAULT_MULTICAST_BATCH_SIZE 8192 +#define _Z_DEFAULT_RESOLUTION_SIZE 2 + +#define _Z_DECLARE_CLEAR(layer, name) void _z_##layer##_msg_clear_##name(_z_##name##_t *m, uint8_t header) +#define _Z_DECLARE_CLEAR_NOH(layer, name) void _z_##layer##_msg_clear_##name(_z_##name##_t *m) + +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +#define _Z_MSG_LEN_ENC_SIZE 2 + +/*=============================*/ +/* Message header */ +/*=============================*/ +#define _Z_MID_MASK 0x1f +#define _Z_FLAGS_MASK 0xe0 + +/*=============================*/ +/* Message helpers */ +/*=============================*/ +#define _Z_MID(h) (_Z_MID_MASK & (h)) +#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) + +#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 new file mode 100644 index 000000000..9cb5e05e5 --- /dev/null +++ b/include/zenoh-pico/protocol/definitions/declarations.h @@ -0,0 +1,144 @@ +// +// 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_PROTOCOL_DEFINITIONS_DECLARATIONS_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_DECLARATIONS_H + +#include + +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/keyexpr.h" + +typedef struct { + uint16_t _id; + _z_keyexpr_t _keyexpr; +} _z_decl_kexpr_t; +_z_decl_kexpr_t _z_decl_kexpr_null(void); +typedef struct { + uint16_t _id; +} _z_undecl_kexpr_t; +_z_undecl_kexpr_t _z_undecl_kexpr_null(void); + +typedef struct { + _z_keyexpr_t _keyexpr; + uint32_t _id; + struct { + _Bool _pull_mode; + _Bool _reliable; + } _ext_subinfo; +} _z_decl_subscriber_t; +_z_decl_subscriber_t _z_decl_subscriber_null(void); +typedef struct { + uint32_t _id; + _z_keyexpr_t _ext_keyexpr; +} _z_undecl_subscriber_t; +_z_undecl_subscriber_t _z_undecl_subscriber_null(void); + +typedef struct { + _z_keyexpr_t _keyexpr; + uint32_t _id; + struct { + uint8_t _complete; + uint32_t _distance; + } _ext_queryable_info; +} _z_decl_queryable_t; +_z_decl_queryable_t _z_decl_queryable_null(void); +typedef struct { + uint32_t _id; + _z_keyexpr_t _ext_keyexpr; +} _z_undecl_queryable_t; +_z_undecl_queryable_t _z_undecl_queryable_null(void); + +typedef struct { + _z_keyexpr_t _keyexpr; + uint32_t _id; +} _z_decl_token_t; +_z_decl_token_t _z_decl_token_null(void); +typedef struct { + uint32_t _id; + _z_keyexpr_t _ext_keyexpr; +} _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); + +typedef struct { + enum { + _Z_DECL_KEXPR, + _Z_UNDECL_KEXPR, + _Z_DECL_SUBSCRIBER, + _Z_UNDECL_SUBSCRIBER, + _Z_DECL_QUERYABLE, + _Z_UNDECL_QUERYABLE, + _Z_DECL_TOKEN, + _Z_UNDECL_TOKEN, + _Z_DECL_INTEREST, + _Z_FINAL_INTEREST, + _Z_UNDECL_INTEREST, + } _tag; + union { + _z_decl_kexpr_t _decl_kexpr; + _z_undecl_kexpr_t _undecl_kexpr; + _z_decl_subscriber_t _decl_subscriber; + _z_undecl_subscriber_t _undecl_subscriber; + _z_decl_queryable_t _decl_queryable; + _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; + } _body; +} _z_declaration_t; +void _z_declaration_clear(_z_declaration_t* decl); +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_undecl_subscriber(uint32_t id, _Z_OPTIONAL _Z_MOVE(_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_undecl_queryable(uint32_t id, _Z_OPTIONAL _Z_MOVE(_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 _Z_MOVE(_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 _Z_MOVE(_z_keyexpr_t) key); +_z_declaration_t _z_make_final_decl(uint32_t id); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_DECLARATIONS_H */ diff --git a/include/zenoh-pico/protocol/definitions/message.h b/include/zenoh-pico/protocol/definitions/message.h new file mode 100644 index 000000000..703ed6172 --- /dev/null +++ b/include/zenoh-pico/protocol/definitions/message.h @@ -0,0 +1,184 @@ +// +// 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_PROTOCOL_DEFINITIONS_MESSAGE_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_MESSAGE_H + +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/core.h" +/* Zenoh Messages */ +#define _Z_MID_Z_OAM 0x00 +#define _Z_MID_Z_PUT 0x01 +#define _Z_MID_Z_DEL 0x02 +#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 + +// Flags: +// - T: Timestamp If T==1 then the timestamp if present +// - 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 | +// +-+-+-+---------+ +// ~ 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; +} _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 +// +---------------+ +// ~ [err_exts] ~ if Z==1 +// +---------------+ +#define _Z_FLAG_Z_E_T 0x20 +#define _Z_FLAG_Z_E_I 0x40 +typedef struct { + uint16_t _code; + _Bool _is_infrastructure; + _z_timestamp_t _timestamp; + _z_source_info_t _ext_source_info; + _z_value_t _ext_value; +} _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; +} _z_m_push_commons_t; + +typedef struct { + _z_m_push_commons_t _commons; +} _z_msg_del_t; +static inline void _z_msg_del_clear(_z_msg_del_t *del) { (void)del; } +#define _Z_M_DEL_ID 0x02 +#define _Z_FLAG_Z_D_T 0x20 + +typedef struct { + _z_m_push_commons_t _commons; + _z_bytes_t _payload; + _z_encoding_t _encoding; +} _z_msg_put_t; +void _z_msg_put_clear(_z_msg_put_t *); +#define _Z_M_PUT_ID 0x01 +#define _Z_FLAG_Z_P_E 0x40 +#define _Z_FLAG_Z_P_T 0x20 + +/*------------------ Query Message ------------------*/ +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|C|P| QUERY | +// +-+-+-+---------+ +// ~ params ~ if P==1 -- +// +---------------+ +// ~ consolidation ~ if C==1 -- u8 +// +---------------+ +// ~ [qry_exts] ~ if Z==1 +// +---------------+ +#define _Z_FLAG_Z_Q_P 0x20 // 1 << 6 | Period if P==1 then a period is present +typedef struct { + _z_bytes_t _parameters; + _z_source_info_t _ext_info; + _z_value_t _ext_value; + z_consolidation_mode_t _ext_consolidation; +} _z_msg_query_t; +typedef struct { + _Bool info; + _Bool body; + _Bool consolidation; +} _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); + +#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 new file mode 100644 index 000000000..e439b276a --- /dev/null +++ b/include/zenoh-pico/protocol/definitions/network.h @@ -0,0 +1,240 @@ +// +// 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_PROTOCOL_DEFINITIONS_NETWORK_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_NETWORK_H + +#include + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/collections/bytes.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/ext.h" +#include "zenoh-pico/protocol/keyexpr.h" +/* Network Messages */ +#define _Z_MID_N_OAM 0x1f +#define _Z_MID_N_DECLARE 0x1e +#define _Z_MID_N_PUSH 0x1d +#define _Z_MID_N_REQUEST 0x1c +#define _Z_MID_N_RESPONSE 0x1b +#define _Z_MID_N_RESPONSE_FINAL 0x1a + +/*=============================*/ +/* Network flags */ +/*=============================*/ +#define _Z_FLAG_N_Z 0x80 // 1 << 7 + +// 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 +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_N_PUSH_N 0x20 // 1 << 5 +#define _Z_FLAG_N_PUSH_M 0x40 // 1 << 6 + +// REQUEST 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 +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_N_REQUEST_N 0x20 // 1 << 5 +#define _Z_FLAG_N_REQUEST_M 0x40 // 1 << 6 + +// RESPONSE 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 +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_N_RESPONSE_N 0x20 // 1 << 5 +#define _Z_FLAG_N_RESPONSE_M 0x40 // 1 << 6 + +typedef struct { + uint8_t _val; +} _z_n_qos_t; + +#define _z_n_qos_make(express, nodrop, priority) \ + (_z_n_qos_t) { ._val = ((express << 4) | (nodrop << 3) | priority) } +#define _Z_N_QOS_DEFAULT _z_n_qos_make(0, 0, 5) + +// RESPONSE FINAL message flags: +// Z Extensions if Z==1 then Zenoh extensions are present +// #define _Z_FLAG_N_RESPONSE_X 0x20 // 1 << 5 +// #define _Z_FLAG_N_RESPONSE_X 0x40 // 1 << 6 + +// Flags: +// - N: Named if N==1 then the keyexpr has name/suffix +// - M: Mapping if M==1 then keyexpr mapping is the one declared by the sender, otherwise by the receiver +// - Z: Extension if Z==1 then at least one extension is present +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|M|N| REQUEST | +// +-+-+-+---------+ +// ~ request_id:z32~ +// +---------------+ +// ~ key_scope:z16 ~ +// +---------------+ +// ~ key_suffix ~ if N==1 -- +// +---------------+ +// ~ [req_exts] ~ if Z==1 +// +---------------+ +// ~ ZenohMessage ~ +// +---------------+ +// +typedef struct { + _z_zint_t _rid; + _z_keyexpr_t _key; + _z_timestamp_t _ext_timestamp; + _z_n_qos_t _ext_qos; + 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; + 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 { + _Bool ext_qos; + _Bool ext_tstamp; + _Bool ext_target; + _Bool ext_budget; + _Bool ext_timeout_ms; + uint8_t n; +} _z_n_msg_request_exts_t; +_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; +_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); + +/*------------------ Response Final Message ------------------*/ +// Flags: +// - Z: Extension if Z==1 then at least one extension is present +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|M|N| ResFinal| +// +-+-+-+---------+ +// ~ request_id:z32~ +// +---------------+ +// ~ [reply_exts] ~ if Z==1 +// +---------------+ +// +typedef struct { + _z_zint_t _request_id; +} _z_n_msg_response_final_t; +void _z_n_msg_response_final_clear(_z_n_msg_response_final_t *msg); + +// Flags: +// - N: Named if N==1 then the keyexpr has name/suffix +// - M: Mapping if M==1 then keyexpr mapping is the one declared by the sender, otherwise by the receiver +// - Z: Extension if Z==1 then at least one extension is present +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|M|N| PUSH | +// +-+-+-+---------+ +// ~ key_scope:z? ~ +// +---------------+ +// ~ key_suffix ~ if N==1 -- +// +---------------+ +// ~ [push_exts] ~ if Z==1 +// +---------------+ +// ~ ZenohMessage ~ +// +---------------+ +// +typedef struct { + _z_keyexpr_t _key; + _z_timestamp_t _timestamp; + _z_n_qos_t _qos; + _z_push_body_t _body; +} _z_n_msg_push_t; +void _z_n_msg_push_clear(_z_n_msg_push_t *msg); + +/*------------------ Response Message ------------------*/ +typedef struct { + _z_timestamp_t _ext_timestamp; + _z_zint_t _request_id; + _z_keyexpr_t _key; + _z_n_qos_t _ext_qos; + struct { + _z_id_t _zid; + uint32_t _eid; + } _ext_responder; + 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); + +typedef struct { + _z_declaration_t _decl; + _z_timestamp_t _ext_timestamp; + _z_n_qos_t _ext_qos; +} _z_n_msg_declare_t; +static inline void _z_n_msg_declare_clear(_z_n_msg_declare_t *msg) { _z_declaration_clear(&msg->_decl); } + +/*------------------ Zenoh Message ------------------*/ +typedef union { + _z_n_msg_declare_t _declare; + _z_n_msg_push_t _push; + _z_n_msg_request_t _request; + _z_n_msg_response_t _response; + _z_n_msg_response_final_t _response_final; +} _z_network_body_t; +typedef struct { + enum { _Z_N_DECLARE, _Z_N_PUSH, _Z_N_REQUEST, _Z_N_RESPONSE, _Z_N_RESPONSE_FINAL } _tag; + _z_network_body_t _body; +} _z_network_message_t; +typedef _z_network_message_t _z_zenoh_message_t; +void _z_n_msg_clear(_z_network_message_t *m); +void _z_n_msg_free(_z_network_message_t **m); +inline static void _z_msg_clear(_z_zenoh_message_t *msg) { _z_n_msg_clear(msg); } +inline static void _z_msg_free(_z_zenoh_message_t **msg) { _z_n_msg_free(msg); } +_Z_ELEM_DEFINE(_z_network_message, _z_network_message_t, _z_noop_size, _z_n_msg_clear, _z_noop_copy) +_Z_VEC_DEFINE(_z_network_message, _z_network_message_t) + +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_consolidation_mode_t consolidation, _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_value_t) value); +_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_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_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_push_body_t) body); + +#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 new file mode 100644 index 000000000..32b8dd82a --- /dev/null +++ b/include/zenoh-pico/protocol/definitions/transport.h @@ -0,0 +1,538 @@ +// +// 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_PROTOCOL_DEFINITIONS_TRANSPORT_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_TRANSPORT_H + +/* Scouting Messages */ +#include + +#include "zenoh-pico/link/endpoint.h" +#include "zenoh-pico/protocol/definitions/network.h" + +#define _Z_MID_SCOUT 0x01 +#define _Z_MID_HELLO 0x02 + +/* Transport Messages */ +#define _Z_MID_T_OAM 0x00 +#define _Z_MID_T_INIT 0x01 +#define _Z_MID_T_OPEN 0x02 +#define _Z_MID_T_CLOSE 0x03 +#define _Z_MID_T_KEEP_ALIVE 0x04 +#define _Z_MID_T_FRAME 0x05 +#define _Z_MID_T_FRAGMENT 0x06 +#define _Z_MID_T_JOIN 0x07 + +/*=============================*/ +/* Message flags */ +/*=============================*/ +#define _Z_FLAG_T_Z 0x80 // 1 << 7 + +// Scout message flags: +// I ZenohID if I==1 then the ZenohID is present +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_SCOUT_I 0x08 // 1 << 3 + +// Hello message flags: +// L Locators if L==1 then Locators are present +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_HELLO_L 0x20 // 1 << 5 + +// Join message flags: +// T Lease period if T==1 then the lease period is in seconds else in milliseconds +// S Size params if S==1 then size parameters are exchanged +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_JOIN_T 0x20 // 1 << 5 +#define _Z_FLAG_T_JOIN_S 0x40 // 1 << 6 + +// Init message flags: +// A Ack if A==1 then the message is an acknowledgment (aka InitAck), otherwise InitSyn +// S Size params if S==1 then size parameters are exchanged +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_INIT_A 0x20 // 1 << 5 +#define _Z_FLAG_T_INIT_S 0x40 // 1 << 6 + +// Open message flags: +// A Ack if A==1 then the message is an acknowledgment (aka OpenAck), otherwise OpenSyn +// T Lease period if T==1 then the lease period is in seconds else in milliseconds +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_OPEN_A 0x20 // 1 << 5 +#define _Z_FLAG_T_OPEN_T 0x40 // 1 << 6 + +// Frame message flags: +// R Reliable if R==1 it concerns the reliable channel, else the best-effort channel +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_FRAME_R 0x20 // 1 << 5 + +// Frame message flags: +// R Reliable if R==1 it concerns the reliable channel, else the best-effort channel +// M More if M==1 then other fragments will follow +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_FRAGMENT_R 0x20 // 1 << 5 +#define _Z_FLAG_T_FRAGMENT_M 0x40 // 1 << 6 + +// Close message flags: +// S Session Close if S==1 Session close or S==0 Link close +// Z Extensions if Z==1 then Zenoh extensions are present +#define _Z_FLAG_T_CLOSE_S 0x20 // 1 << 5 + +/*=============================*/ +/* Transport Messages */ +/*=============================*/ +/*------------------ Scout Message ------------------*/ +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// The SCOUT message can be sent at any point in time to solicit HELLO messages from matching parties. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|X|X| SCOUT | +// +-+-+-+---------+ +// | version | +// +---------------+ +// |zid_len|I| what| (#)(*) +// +-+-+-+-+-+-+-+-+ +// ~ [u8] ~ if Flag(I)==1 -- ZenohID +// +---------------+ +// +// (#) ZID length. If Flag(I)==1 it indicates how many bytes are used for the ZenohID bytes. +// A ZenohID is minimum 1 byte and maximum 16 bytes. Therefore, the actual lenght is computed as: +// real_zid_len := 1 + zid_len +// +// (*) What. It indicates a bitmap of WhatAmI interests. +// The valid bitflags are: +// - 0b001: Router +// - 0b010: Peer +// - 0b100: Client +// +typedef struct { + _z_id_t _zid; + z_what_t _what; + uint8_t _version; +} _z_s_msg_scout_t; +void _z_s_msg_scout_clear(_z_s_msg_scout_t *msg); + +/*------------------ Hello Message ------------------*/ +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// The HELLO message is sent in any of the following three cases: +// 1) in response to a SCOUT message; +// 2) to (periodically) advertise (e.g., on multicast) the Peer and the locators it is reachable at; +// 3) in a already established session to update the corresponding peer on the new capabilities +// (i.e., whatmai) and/or new set of locators (i.e., added or deleted). +// Locators are expressed as: +// +// udp/192.168.0.2:1234 +// tcp/192.168.0.2:1234 +// udp/239.255.255.123:5555 +// +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|X|L| HELLO | +// +-+-+-+---------+ +// | version | +// +---------------+ +// |zid_len|X|X|wai| (*) +// +-+-+-+-+-+-+-+-+ +// ~ [u8] ~ -- ZenohID +// +---------------+ +// ~ ~ if Flag(L)==1 -- List of locators +// +---------------+ +// +// (*) WhatAmI. It indicates the role of the zenoh node sending the HELLO message. +// The valid WhatAmI values are: +// - 0b00: Router +// - 0b01: Peer +// - 0b10: Client +// - 0b11: Reserved +// +typedef struct { + _z_id_t _zid; + _z_locator_array_t _locators; + z_whatami_t _whatami; + uint8_t _version; +} _z_s_msg_hello_t; +void _z_s_msg_hello_clear(_z_s_msg_hello_t *msg); + +/*------------------ Join Message ------------------*/ +// # Join message +// +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// The JOIN message is sent on a multicast Locator to advertise the transport parameters. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |O|S|T| JOIN | +// +-+-+-+-+-------+ +// ~ |Q~ if O==1 +// +---------------+ +// | v_maj | v_min | -- Protocol Version VMaj.VMin +// +-------+-------+ +// ~ whatami ~ -- Router, Peer or a combination of them +// +---------------+ +// ~ zenoh_id ~ -- PID of the sender of the JOIN message +// +---------------+ +// ~ lease ~ -- Lease period of the sender of the JOIN message(*) +// +---------------+ +// ~ seq_num_res ~ if S==1(*) -- Otherwise 2^28 is assumed(**) +// +---------------+ +// ~ [next_sn] ~ (***) +// +---------------+ +// +// - if Q==1 then the sender supports QoS. +// +// (*) if T==1 then the lease period is expressed in seconds, otherwise in milliseconds +// (**) if S==0 then 2^28 is assumed. +// (***) if Q==1 then 8 sequence numbers are present: one for each priority. +// if Q==0 then only one sequence number is present. +// +typedef struct { + _z_zint_t _reliable; + _z_zint_t _best_effort; +} _z_coundit_sn_t; +typedef struct { + union { + _z_coundit_sn_t _plain; + _z_coundit_sn_t _qos[Z_PRIORITIES_NUM]; + } _val; + _Bool _is_qos; +} _z_conduit_sn_list_t; +typedef struct { + _z_id_t _zid; + _z_zint_t _lease; + _z_conduit_sn_list_t _next_sn; + uint16_t _batch_size; + z_whatami_t _whatami; + uint8_t _req_id_res; + uint8_t _seq_num_res; + uint8_t _version; +} _z_t_msg_join_t; +void _z_t_msg_join_clear(_z_t_msg_join_t *msg); + +/*------------------ Init Message ------------------*/ +// # Init message +// +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// The INIT message is sent on a specific Locator to initiate a session with the peer associated +// with that Locator. The initiator MUST send an INIT message with the A flag set to 0. If the +// corresponding peer deems appropriate to initialize a session with the initiator, the corresponding +// peer MUST reply with an INIT message with the A flag set to 1. +// +// Flags: +// - A: Ack if A==0 then the message is an InitSyn else it is an InitAck +// - S: Size params if S==1 then size parameters are exchanged +// - Z: Extensions if Z==1 then zenoh extensions will follow. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|S|A| INIT | +// +-+-+-+---------+ +// | version | +// +---------------+ +// |zid_len|x|x|wai| (#)(*) +// +-------+-+-+---+ +// ~ [u8] ~ -- ZenohID of the sender of the INIT message +// +---------------+ +// |x|x|kid|rid|fsn| \ -- SN/ID resolution (+) +// +---------------+ | if Flag(S)==1 +// | u16 | | -- Batch Size ($) +// | | / +// +---------------+ +// ~ ~ -- if Flag(A)==1 -- Cookie +// +---------------+ +// ~ [InitExts] ~ -- if Flag(Z)==1 +// +---------------+ +// +// If A==1 and S==0 then size parameters are (ie. S flag) are accepted. +// +// (*) WhatAmI. It indicates the role of the zenoh node sending the INIT +// message. +// The valid WhatAmI values are: +// - 0b00: Router +// - 0b01: Peer +// - 0b10: Client +// - 0b11: Reserved +// +// (#) ZID length. It indicates how many bytes are used for the ZenohID bytes. +// A ZenohID is minimum 1 byte and maximum 16 bytes. Therefore, the actual +// lenght is computed as: +// real_zid_len := 1 + zid_len +// +// (+) Sequence Number/ID resolution. It indicates the resolution and +// consequently the wire overhead +// of various SN and ID in Zenoh. +// - fsn: frame/fragment sequence number resolution. Used in Frame/Fragment +// messages. +// - rid: request ID resolution. Used in Request/Response messages. +// - kid: key expression ID resolution. Used in Push/Request/Response +// messages. The valid SN/ID resolution values are: +// - 0b00: 8 bits +// - 0b01: 16 bits +// - 0b10: 32 bits +// - 0b11: 64 bits +// +// ($) Batch Size. It indicates the maximum size of a batch the sender of the +// +typedef struct { + _z_id_t _zid; + _z_bytes_t _cookie; + uint16_t _batch_size; + z_whatami_t _whatami; + uint8_t _req_id_res; + uint8_t _seq_num_res; + uint8_t _version; +} _z_t_msg_init_t; +void _z_t_msg_init_clear(_z_t_msg_init_t *msg); + +/*------------------ Open Message ------------------*/ +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total lenght +// in bytes of the message, resulting in the maximum lenght of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the lenght of a message must not exceed 65_535 bytes. +// +// The OPEN message is sent on a link to finally open an initialized session with the peer. +// +// Flags: +// - A Ack if A==1 then the message is an acknowledgment (aka OpenAck), otherwise OpenSyn +// - T Lease period if T==1 then the lease period is in seconds else in milliseconds +// - Z Extensions if Z==1 then Zenoh extensions are present +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|T|A| OPEN | +// +-+-+-+---------+ +// % lease % -- Lease period of the sender of the OPEN message +// +---------------+ +// % initial_sn % -- Initial SN proposed by the sender of the OPEN(*) +// +---------------+ +// ~ ~ if Flag(A)==0 (**) -- Cookie +// +---------------+ +// ~ [OpenExts] ~ if Flag(Z)==1 +// +---------------+ +// +// (*) The initial sequence number MUST be compatible with the sequence number resolution agreed in the +// [`super::InitSyn`]-[`super::InitAck`] message exchange +// (**) The cookie MUST be the same received in the [`super::InitAck`]from the corresponding zenoh node +// +typedef struct { + _z_zint_t _lease; + _z_zint_t _initial_sn; + _z_bytes_t _cookie; +} _z_t_msg_open_t; +void _z_t_msg_open_clear(_z_t_msg_open_t *msg); + +/*------------------ Close Message ------------------*/ +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// The CLOSE message is sent in any of the following two cases: +// 1) in response to an OPEN message which is not accepted; +// 2) at any time to arbitrarly close the session with the corresponding peer. +// +// Flags: +// - S: Session Close if S==1 Session close or S==0 Link close +// - X: Reserved +// - Z: Extensions if Z==1 then zenoh extensions will follow. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|X|S| CLOSE | +// +-+-+-+---------+ +// | Reason | +// +---------------+ +// ~ [CloseExts] ~ if Flag(Z)==1 +// +---------------+ +// +typedef struct { + uint8_t _reason; +} _z_t_msg_close_t; +void _z_t_msg_close_clear(_z_t_msg_close_t *msg); +/*=============================*/ +/* Close reasons */ +/*=============================*/ +#define _Z_CLOSE_GENERIC 0x00 +#define _Z_CLOSE_UNSUPPORTED 0x01 +#define _Z_CLOSE_INVALID 0x02 +#define _Z_CLOSE_MAX_TRANSPORTS 0x03 +#define _Z_CLOSE_MAX_LINKS 0x04 +#define _Z_CLOSE_EXPIRED 0x05 + +/*------------------ Keep Alive Message ------------------*/ +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// The KEEP_ALIVE message can be sent periodically to avoid the expiration of the session lease +// period in case there are no messages to be sent. +// +// Flags: +// - X: Reserved +// - X: Reserved +// - Z: Extensions If Z==1 then Zenoh extensions will follow. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|X|X| KALIVE | +// +-+-+-+---------+ +// ~ [KAliveExts] ~ if Flag(Z)==1 +// +---------------+ +// +typedef struct { + uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior +} _z_t_msg_keep_alive_t; +void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg); + +/*------------------ Frame Message ------------------*/ +// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length +// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. +// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve +// the boundary of the serialized messages. The length is encoded as little-endian. +// In any case, the length of a message must not exceed 65_535 bytes. +// +// Flags: +// - R: Reliable If R==1 it concerns the reliable channel, else the best-effort channel +// - X: Reserved +// - Z: Extensions If Z==1 then zenoh extensions will follow. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|X|R| FRAME | +// +-+-+-+---------+ +// % seq num % +// +---------------+ +// ~ [FrameExts] ~ if Flag(Z)==1 +// +---------------+ +// ~ [NetworkMsg] ~ +// +---------------+ +// +// - if R==1 then the FRAME is sent on the reliable channel, best-effort otherwise. +// +typedef struct { + _z_network_message_vec_t _messages; + _z_zint_t _sn; +} _z_t_msg_frame_t; +void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg); + +/*------------------ Fragment Message ------------------*/ +// The Fragment message is used to transmit on the wire large Zenoh Message that require fragmentation +// because they are larger thatn the maximum batch size (i.e. 2^16-1) and/or the link MTU. +// +// The [`Fragment`] message flow is the following: +// +// Flags: +// - R: Reliable if R==1 it concerns the reliable channel, else the best-effort channel +// - M: More if M==1 then other fragments will follow +// - Z: Extensions if Z==1 then zenoh extensions will follow. +// +// 7 6 5 4 3 2 1 0 +// +-+-+-+-+-+-+-+-+ +// |Z|M|R| FRAGMENT| +// +-+-+-+---------+ +// % seq num % +// +---------------+ +// ~ [FragExts] ~ if Flag(Z)==1 +// +---------------+ +// ~ [u8] ~ +// +---------------+ +// +typedef struct { + _z_bytes_t _payload; + _z_zint_t _sn; +} _z_t_msg_fragment_t; +void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg); + +/*------------------ Transport Message ------------------*/ +typedef union { + _z_t_msg_join_t _join; + _z_t_msg_init_t _init; + _z_t_msg_open_t _open; + _z_t_msg_close_t _close; + _z_t_msg_keep_alive_t _keep_alive; + _z_t_msg_frame_t _frame; + _z_t_msg_fragment_t _fragment; +} _z_transport_body_t; + +typedef struct { + _z_transport_body_t _body; + uint8_t _header; +} _z_transport_message_t; +void _z_t_msg_clear(_z_transport_message_t *msg); + +/*------------------ Builders ------------------*/ +_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_open_ack(_z_zint_t lease, _z_zint_t initial_sn); +_z_transport_message_t _z_t_msg_make_close(uint8_t reason, _Bool link_only); +_z_transport_message_t _z_t_msg_make_keep_alive(void); +_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages, _Bool is_reliable); +_z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, _Bool is_reliable); +_z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, _Bool is_reliable, _Bool is_last); +_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_bytes_t messages, _Bool is_reliable, _Bool is_last); + +/*------------------ Copy ------------------*/ +void _z_t_msg_copy(_z_transport_message_t *clone, _z_transport_message_t *msg); +void _z_t_msg_copy_join(_z_t_msg_join_t *clone, _z_t_msg_join_t *msg); +void _z_t_msg_copy_init(_z_t_msg_init_t *clone, _z_t_msg_init_t *msg); +void _z_t_msg_copy_open(_z_t_msg_open_t *clone, _z_t_msg_open_t *msg); +void _z_t_msg_copy_close(_z_t_msg_close_t *clone, _z_t_msg_close_t *msg); +void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_t *msg); +void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg); + +typedef union { + _z_s_msg_scout_t _scout; + _z_s_msg_hello_t _hello; +} _z_scouting_body_t; + +typedef struct { + _z_scouting_body_t _body; + uint8_t _header; +} _z_scouting_message_t; +void _z_s_msg_clear(_z_scouting_message_t *msg); + +_z_scouting_message_t _z_s_msg_make_scout(z_what_t what, _z_id_t zid); +_z_scouting_message_t _z_s_msg_make_hello(z_whatami_t whatami, _z_id_t zid, _z_locator_array_t locators); + +void _z_s_msg_copy(_z_scouting_message_t *clone, _z_scouting_message_t *msg); +void _z_s_msg_copy_scout(_z_s_msg_scout_t *clone, _z_s_msg_scout_t *msg); +void _z_s_msg_copy_hello(_z_s_msg_hello_t *clone, _z_s_msg_hello_t *msg); + +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_DEFINITIONS_TRANSPORT_H */ diff --git a/include/zenoh-pico/protocol/ext.h b/include/zenoh-pico/protocol/ext.h new file mode 100644 index 000000000..118c1ed14 --- /dev/null +++ b/include/zenoh-pico/protocol/ext.h @@ -0,0 +1,102 @@ +// +// 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_PROTOCOL_EXTENSION_H +#define ZENOH_PICO_PROTOCOL_EXTENSION_H + +#include +#include + +#include "zenoh-pico/protocol/core.h" + +/*=============================*/ +/* Message header */ +/*=============================*/ +#define _Z_EXT_FULL_ID_MASK 0x7F +#define _Z_EXT_ID_MASK 0x0F +#define _Z_EXT_ENC_MASK 0x60 + +/*=============================*/ +/* Message helpers */ +/*=============================*/ +#define _Z_EXT_FULL_ID(h) (_Z_EXT_FULL_ID_MASK & h) +#define _Z_EXT_ID(h) (_Z_EXT_ID_MASK & h) +#define _Z_EXT_ENC(h) (_Z_EXT_ENC_MASK & h) +#define _Z_EXT_HAS_FLAG(h, f) ((h & f) != 0) +#define _Z_EXT_SET_FLAG(h, f) (h |= f) + +/*=============================*/ +/* Extension IDs */ +/*=============================*/ +// #define _Z_MSG_EXT_ID_FOO 0x00 // Hex(ENC|M|ID) + +/*=============================*/ +/* Extension Encodings */ +/*=============================*/ +#define _Z_MSG_EXT_ENC_UNIT 0x00 // 0x00 << 5 +#define _Z_MSG_EXT_ENC_ZINT 0x20 // 0x01 << 5 +#define _Z_MSG_EXT_ENC_ZBUF 0x40 // 0x10 << 5 + +/*=============================*/ +/* Extension flags */ +/*=============================*/ +#define _Z_MSG_EXT_FLAG_M 0x10 +#define _Z_MSG_EXT_IS_MANDATORY(h) ((h & _Z_MSG_EXT_FLAG_M) != 0) +#define _Z_MSG_EXT_FLAG_Z 0x80 + +typedef struct { + uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior +} _z_msg_ext_unit_t; +void _z_msg_ext_clear_unit(_z_msg_ext_unit_t *ext); + +/*------------------ ZID Extension ------------------*/ +typedef struct { + uint64_t _val; +} _z_msg_ext_zint_t; +void _z_msg_ext_clear_zint(_z_msg_ext_zint_t *ext); + +/*------------------ Unknown Extension ------------------*/ +typedef struct { + _z_bytes_t _val; +} _z_msg_ext_zbuf_t; +void _z_msg_ext_clear_zbuf(_z_msg_ext_zbuf_t *ext); + +/*------------------ Message Extensions ------------------*/ +typedef union { + _z_msg_ext_unit_t _unit; + _z_msg_ext_zint_t _zint; + _z_msg_ext_zbuf_t _zbuf; +} _z_msg_ext_body_t; + +typedef struct { + _z_msg_ext_body_t _body; + uint8_t _header; +} _z_msg_ext_t; +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); + +/*------------------ Copy ------------------*/ +void _z_msg_ext_copy(_z_msg_ext_t *clone, const _z_msg_ext_t *ext); +void _z_msg_ext_copy_unit(_z_msg_ext_unit_t *clone, const _z_msg_ext_unit_t *ext); +void _z_msg_ext_copy_zint(_z_msg_ext_zint_t *clone, const _z_msg_ext_zint_t *ext); +void _z_msg_ext_copy_zbuf(_z_msg_ext_zbuf_t *clone, const _z_msg_ext_zbuf_t *ext); + +_Z_ELEM_DEFINE(_z_msg_ext, _z_msg_ext_t, _z_noop_size, _z_msg_ext_clear, _z_msg_ext_copy) +_Z_VEC_DEFINE(_z_msg_ext, _z_msg_ext_t) + +#endif /* ZENOH_PICO_PROTOCOL_EXTENSION_H */ diff --git a/include/zenoh-pico/protocol/iobuf.h b/include/zenoh-pico/protocol/iobuf.h index 0e0b98a97..90af275fe 100644 --- a/include/zenoh-pico/protocol/iobuf.h +++ b/include/zenoh-pico/protocol/iobuf.h @@ -16,6 +16,8 @@ #define ZENOH_PICO_PROTOCOL_IOBUF_H #include +#include +#include #include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" @@ -64,8 +66,11 @@ 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); size_t _z_zbuf_capacity(const _z_zbuf_t *zbf); +uint8_t const *_z_zbuf_start(const _z_zbuf_t *zbf); size_t _z_zbuf_len(const _z_zbuf_t *zbf); _Bool _z_zbuf_can_read(const _z_zbuf_t *zbf); size_t _z_zbuf_space_left(const _z_zbuf_t *zbf); @@ -93,7 +98,7 @@ typedef struct { size_t _r_idx; size_t _w_idx; size_t _capacity; - _Bool _is_expandable; + size_t _expansion_step; } _z_wbuf_t; _z_wbuf_t _z_wbuf_make(size_t capacity, _Bool is_expandable); diff --git a/include/zenoh-pico/protocol/keyexpr.h b/include/zenoh-pico/protocol/keyexpr.h index 1093851dd..05fa45f8d 100644 --- a/include/zenoh-pico/protocol/keyexpr.h +++ b/include/zenoh-pico/protocol/keyexpr.h @@ -11,8 +11,8 @@ // Contributors: // ZettaScale Zenoh Team, -#ifndef ZENOH_PICO_PROTOCOL_KEYEXPR_H -#define ZENOH_PICO_PROTOCOL_KEYEXPR_H +#ifndef INCLUDE_ZENOH_PICO_PROTOCOL_KEYEXPR_H +#define INCLUDE_ZENOH_PICO_PROTOCOL_KEYEXPR_H #include @@ -26,8 +26,14 @@ _Bool _z_keyexpr_intersects(const char *lstart, const size_t llen, const char *r /*------------------ clone/Copy/Free helpers ------------------*/ void _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src); -_z_keyexpr_t _z_keyexpr_duplicate(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); +_z_keyexpr_t _z_keyexpr_steal(_Z_MOVE(_z_keyexpr_t) src); +static inline _z_keyexpr_t _z_keyexpr_null(void) { return (_z_keyexpr_t){._id = 0, ._mapping = {0}, ._suffix = NULL}; } _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp); -void _z_timestamp_reset(_z_timestamp_t *tstamp); +void _z_timestamp_clear(_z_timestamp_t *tstamp); +void _z_keyexpr_clear(_z_keyexpr_t *rk); +void _z_keyexpr_free(_z_keyexpr_t **rk); -#endif /* ZENOH_PICO_PROTOCOL_KEYEXPR_H */ +#endif /* INCLUDE_ZENOH_PICO_PROTOCOL_KEYEXPR_H */ diff --git a/include/zenoh-pico/protocol/msg.h b/include/zenoh-pico/protocol/msg.h deleted file mode 100644 index 597acf6eb..000000000 --- a/include/zenoh-pico/protocol/msg.h +++ /dev/null @@ -1,1007 +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_PROTOCOL_MSG_H -#define ZENOH_PICO_PROTOCOL_MSG_H - -#include - -#include "zenoh-pico/collections/array.h" -#include "zenoh-pico/collections/element.h" -#include "zenoh-pico/collections/string.h" -#include "zenoh-pico/link/endpoint.h" -#include "zenoh-pico/net/query.h" -#include "zenoh-pico/protocol/core.h" - -#define _Z_DECLARE_CLEAR(layer, name) void _z_##layer##_msg_clear_##name(_z_##name##_t *m, uint8_t header) - -#define _Z_DECLARE_CLEAR_NOH(layer, name) void _z_##layer##_msg_clear_##name(_z_##name##_t *m) - -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -#define _Z_MSG_LEN_ENC_SIZE 2 - -/*=============================*/ -/* Message IDs */ -/*=============================*/ -/* Transport Messages */ -#define _Z_MID_JOIN 0x00 -#define _Z_MID_SCOUT 0x01 -#define _Z_MID_HELLO 0x02 -#define _Z_MID_INIT 0x03 -#define _Z_MID_OPEN 0x04 -#define _Z_MID_CLOSE 0x05 -#define _Z_MID_SYNC 0x06 -#define _Z_MID_ACK_NACK 0x07 -#define _Z_MID_KEEP_ALIVE 0x08 -#define _Z_MID_PING_PONG 0x09 -#define _Z_MID_FRAME 0x0a -/* Zenoh Messages */ -#define _Z_MID_DECLARE 0x0b -#define _Z_MID_DATA 0x0c -#define _Z_MID_QUERY 0x0d -#define _Z_MID_PULL 0x0e -#define _Z_MID_UNIT 0x0f -#define _Z_MID_LINK_STATE_LIST 0x10 -/* Message decorators */ -#define _Z_MID_PRIORITY 0x1c -#define _Z_MID_ROUTING_CONTEXT 0x1d -#define _Z_MID_REPLY_CONTEXT 0x1e -#define _Z_MID_ATTACHMENT 0x1f - -/*=============================*/ -/* Message flags */ -/*=============================*/ -/* Transport message flags */ -#define _Z_FLAG_T_A 0x20 // 1 << 5 | Ack if A==1 then the message is an acknowledgment -#define _Z_FLAG_T_C 0x40 // 1 << 6 | Count if C==1 then number of unacknowledged messages is present -#define _Z_FLAG_T_E 0x80 // 1 << 7 | End if E==1 then it is the last FRAME fragment -#define _Z_FLAG_T_F 0x40 // 1 << 6 | Fragment if F==1 then the FRAME is a fragment -#define _Z_FLAG_T_I 0x20 // 1 << 5 | PeerID if I==1 then the PeerID is present or requested -#define _Z_FLAG_T_K 0x40 // 1 << 6 | CloseLink if K==1 then close the transport link only -#define _Z_FLAG_T_L 0x80 // 1 << 7 | Locators if L==1 then Locators are present -#define _Z_FLAG_T_M 0x20 // 1 << 5 | Mask if M==1 then a Mask is present -#define _Z_FLAG_T_O 0x80 // 1 << 7 | Options if O==1 then Options are present -#define _Z_FLAG_T_P 0x20 // 1 << 5 | PingOrPong if P==1 then the message is Ping, otherwise is Pong -#define _Z_FLAG_T_R \ - 0x20 // 1 << 5 | Reliable if R==1 then it concerns the reliable channel, best-effort otherwise -#define _Z_FLAG_T_S 0x40 // 1 << 6 | SN Resolution if S==1 then the SN Resolution is present -#define _Z_FLAG_T_T1 0x20 // 1 << 5 | TimeRes if T==1 then the time resolution is in seconds -#define _Z_FLAG_T_T2 0x40 // 1 << 6 | TimeRes if T==1 then the time resolution is in seconds -#define _Z_FLAG_T_W 0x40 // 1 << 6 | WhatAmI if W==1 then WhatAmI is indicated -#define _Z_FLAG_T_Z \ - 0x20 // 1 << 5 | MixedSlices if Z==1 then the payload contains a mix of raw and shm_info payload -#define _Z_FLAG_T_X 0x00 // Unused flags are set to zero - -/* Zenoh message flags */ -#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 0x80 // 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 - -/* Init option flags */ -#define _Z_OPT_INIT_QOS 0x01 // 1 << 0 | QoS if QOS==1 then the session supports QoS -#define _Z_OPT_JOIN_QOS 0x01 // 1 << 0 | QoS if QOS==1 then the session supports QoS - -/*=============================*/ -/* Message header */ -/*=============================*/ -#define _Z_MID_MASK 0x1f -#define _Z_FLAGS_MASK 0xe0 - -/*=============================*/ -/* Message helpers */ -/*=============================*/ -#define _Z_MID(h) (_Z_MID_MASK & h) -#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) - -/*=============================*/ -/* Declaration IDs */ -/*=============================*/ -#define _Z_DECL_RESOURCE 0x01 -#define _Z_DECL_PUBLISHER 0x02 -#define _Z_DECL_SUBSCRIBER 0x03 -#define _Z_DECL_QUERYABLE 0x04 -#define _Z_DECL_FORGET_RESOURCE 0x11 -#define _Z_DECL_FORGET_PUBLISHER 0x12 -#define _Z_DECL_FORGET_SUBSCRIBER 0x13 -#define _Z_DECL_FORGET_QUERYABLE 0x14 - -/*=============================*/ -/* Close reasons */ -/*=============================*/ -#define _Z_CLOSE_GENERIC 0x00 -#define _Z_CLOSE_UNSUPPORTED 0x01 -#define _Z_CLOSE_INVALID 0x02 -#define _Z_CLOSE_MAX_TRANSPORTS 0x03 -#define _Z_CLOSE_MAX_LINKS 0x04 -#define _Z_CLOSE_EXPIRED 0x05 - -/*=============================*/ -/* DataInfo flags */ -/*=============================*/ -#define _Z_DATA_INFO_SLICED 0x01 // 1 << 0 -#define _Z_DATA_INFO_KIND 0x02 // 1 << 1 -#define _Z_DATA_INFO_ENC 0x04 // 1 << 2 -#define _Z_DATA_INFO_TSTAMP 0x08 // 1 << 3 -// Reserved: bits 4-6 -#define _Z_DATA_INFO_SRC_ID 0x80 // 1 << 7 -#define _Z_DATA_INFO_SRC_SN 0x100 // 1 << 8 - -/*------------------ Payload field ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// ~ Length ~ -// +---------------+ -// ~ Buffer ~ -// +---------------+ -// -typedef _z_bytes_t _z_payload_t; -void _z_payload_clear(_z_payload_t *p); - -/*------------------ Locators Field ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// ~ Num of Locs ~ -// +---------------+ -// ~ [Locator] ~ -// +---------------+ -// -// NOTE: Locators is an array of strings and are encoded as such - -/*=============================*/ -/* Message decorators */ -/*=============================*/ -// # Attachment decorator -// -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The Attachment can decorate any message (i.e., TransportMessage and ZenohMessage) and it allows to -// append to the message any additional information. Since the information contained in the -// Attachement is relevant only to the layer that provided them (e.g., Transport, Zenoh, User) it -// is the duty of that layer to serialize and de-serialize the attachment whenever deemed necessary. -// The attachement always contains serialized properties. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|Z| ATTCH | -// +-+-+-+---------+ -// ~ Attachment ~ -// +---------------+ -// -typedef struct { - _z_payload_t _payload; - uint8_t _header; -} _z_attachment_t; -void _z_t_msg_clear_attachment(_z_attachment_t *a); - -/*------------------ ReplyContext Decorator ------------------*/ -// The ReplyContext is a message decorator for either: -// - the Data messages that results from a query -// - or a Unit message in case the message is a REPLY_FINAL. -// The replier-id (eval or storage id) is represented as a byte-array. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|F| R_CTX | -// +-+-+-+---------+ -// ~ qid ~ -// +---------------+ -// ~ replier_id ~ if F==0 -// +---------------+ -// -// - if F==1 then the message is a REPLY_FINAL -// -typedef struct { - _z_bytes_t _replier_id; - _z_zint_t _qid; - uint8_t _header; -} _z_reply_context_t; -void _z_msg_clear_reply_context(_z_reply_context_t *rc); - -// -- Priority decorator -// -// The Priority is a message decorator containing -// informations related to the priority of the frame/zenoh message. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// | ID | Prio | -// +-+-+-+---------+ -// -// WARNING: zenoh-pico does not support priorities and QoS. - -/*=============================*/ -/* Zenoh Messages */ -/*=============================*/ -/*------------------ ResKey Field ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// ~ RID ~ -// +---------------+ -// ~ Suffix ~ if K==1 -// +---------------+ -// -void _z_keyexpr_clear(_z_keyexpr_t *rk); -void _z_keyexpr_free(_z_keyexpr_t **rk); - -/*------------------ Resource Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|X|X| RES | -// +---------------+ -// ~ RID ~ -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; - _z_zint_t _id; -} _z_res_decl_t; -void _z_msg_clear_declaration_resource(_z_res_decl_t *dcl); - -/*------------------ Forget Resource Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|X| F_RES | -// +---------------+ -// ~ RID ~ -// +---------------+ -// -typedef struct { - _z_zint_t _rid; -} _z_forget_res_decl_t; -void _z_msg_clear_declaration_forget_resource(_z_forget_res_decl_t *dcl); - -/*------------------ Publisher Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|X|X| PUB | -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; -} _z_pub_decl_t; -void _z_msg_clear_declaration_publisher(_z_pub_decl_t *dcl); - -/*------------------ Forget Publisher Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|X|X| F_PUB | -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; -} _z_forget_pub_decl_t; -void _z_msg_clear_declaration_forget_publisher(_z_forget_pub_decl_t *dcl); - -/*------------------ SubInfo Field ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+---------+ -// |P|X|X| SM_ID | -// +---------------+ -// ~ Period ~ if P==1 -// +---------------+ -// -void _z_subinfo_clear(_z_subinfo_t *si); - -/*------------------ Subscriber Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|S|R| SUB | -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// ~ SubInfo ~ if S==1. Otherwise: SubMode=Push -// +---------------+ -// -// - if R==1 then the subscription is reliable, best-effort otherwise. -// -typedef struct { - _z_keyexpr_t _key; - _z_subinfo_t _subinfo; -} _z_sub_decl_t; -void _z_msg_clear_declaration_subscriber(_z_sub_decl_t *dcl); - -/*------------------ Forget Subscriber Message ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|X|X| F_SUB | -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; -} _z_forget_sub_decl_t; -void _z_msg_clear_declaration_forget_subscriber(_z_forget_sub_decl_t *dcl); - -/*------------------ Queryable Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|Q|X| QABLE | -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// ~ QablInfo ~ if Q==1 -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; - _z_zint_t _complete; - _z_zint_t _distance; -} _z_qle_decl_t; -void _z_msg_clear_declaration_queryable(_z_qle_decl_t *dcl); - -/*------------------ Forget Queryable Declaration ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|X|X| F_QABLE | -// +---------------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; -} _z_forget_qle_decl_t; -void _z_msg_clear_declaration_forget_queryable(_z_forget_qle_decl_t *dcl); - -/*------------------ Declaration Message ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|X| DECLARE | -// +-+-+-+---------+ -// ~ Num of Decl ~ -// +---------------+ -// ~ [Declaration] ~ -// +---------------+ -// -typedef struct { - union { - _z_res_decl_t _res; - _z_forget_res_decl_t _forget_res; - _z_pub_decl_t _pub; - _z_forget_pub_decl_t _forget_pub; - _z_sub_decl_t _sub; - _z_forget_sub_decl_t _forget_sub; - _z_qle_decl_t _qle; - _z_forget_qle_decl_t _forget_qle; - } _body; - uint8_t _header; -} _z_declaration_t; - -void _z_msg_clear_declaration(_z_declaration_t *dcl); -_Z_ELEM_DEFINE(_z_declaration, _z_declaration_t, _z_noop_size, _z_msg_clear_declaration, _z_noop_copy) -_Z_ARRAY_DEFINE(_z_declaration, _z_declaration_t) - -typedef struct { - _z_declaration_array_t _declarations; -} _z_msg_declare_t; -void _z_msg_clear_declare(_z_msg_declare_t *dcl); - -/*------------------ Timestamp Field ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+---------+ -// ~ Time ~ Encoded as _z_zint_t -// +---------------+ -// ~ ID ~ -// +---------------+ -// -void _z_timestamp_clear(_z_timestamp_t *ts); - -/*------------------ Data Info Field ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// ~ options ~ -// +---------------+ -// ~ kind ~ if options & (1 << 1) -// +---------------+ -// ~ encoding ~ if options & (1 << 2) -// +---------------+ -// ~ timestamp ~ if options & (1 << 3) -// +---------------+ -// ~ source_id ~ if options & (1 << 7) -// +---------------+ -// ~ source_sn ~ if options & (1 << 8) -// +---------------+ -// -// - if options & (1 << 0) then the payload is sliced -typedef struct { - _z_bytes_t _source_id; - _z_timestamp_t _tstamp; - _z_zint_t _flags; - _z_zint_t _source_sn; - _z_encoding_t _encoding; - uint8_t _kind; -} _z_data_info_t; -void _z_data_info_clear(_z_data_info_t *di); - -/*------------------ Data Message ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|I|D| DATA | -// +-+-+-+---------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// ~ DataInfo ~ if I==1 -// +---------------+ -// ~ Payload ~ -// +---------------+ -// -// - if D==1 then the message can be dropped for congestion control reasons. -// -typedef struct { - _z_data_info_t _info; - _z_keyexpr_t _key; - _z_payload_t _payload; -} _z_msg_data_t; -void _z_msg_clear_data(_z_msg_data_t *msg); - -/*------------------ Unit Message ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|D| UNIT | -// +-+-+-+---------+ -// -// - if D==1 then the message can be dropped for congestion control reasons. -// -typedef struct { - uint8_t __dummy; // Just to avoid empty structures that might cause undefined behavior -} _z_msg_unit_t; -void _z_msg_clear_unit(_z_msg_unit_t *unt); - -/*------------------ Pull Message ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|N|F| PULL | -// +-+-+-+---------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// ~ pullid ~ -// +---------------+ -// ~ max_samples ~ if N==1 -// +---------------+ -// -typedef struct { - _z_keyexpr_t _key; - _z_zint_t _pull_id; - _z_zint_t _max_samples; -} _z_msg_pull_t; -void _z_msg_clear_pull(_z_msg_pull_t *msg); - -/*------------------ Query Message ------------------*/ -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |K|B|T| QUERY | -// +-+-+-+---------+ -// ~ ResKey ~ if K==1 then keyexpr is string -// +---------------+ -// ~ parameters ~ -// +---------------+ -// ~ qid ~ -// +---------------+ -// ~ target ~ if T==1. Otherwise target = Z_TARGET_BEST_MATCHING -// +---------------+ -// ~ consolidation ~ -// +---------------+ -// ~ QueryBody ~ if B==1 -// +---------------+ -// -// where, QueryBody data structure is optionally included in Query messages -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+---------+ -// ~ DataInfo ~ -// +---------------+ -// ~ Payload ~ -// +---------------+ -// ``` - -typedef struct { - _z_keyexpr_t _key; - _z_zint_t _qid; - char *_parameters; - z_query_target_t _target; - z_consolidation_mode_t _consolidation; - _z_data_info_t _info; - _z_payload_t _payload; -} _z_msg_query_t; -void _z_msg_clear_query(_z_msg_query_t *msg); - -/*------------------ Zenoh Message ------------------*/ -typedef union { - _z_msg_declare_t _declare; - _z_msg_data_t _data; - _z_msg_query_t _query; - _z_msg_pull_t _pull; - _z_msg_unit_t _unit; -} _z_zenoh_body_t; -typedef struct { - _z_zenoh_body_t _body; - _z_attachment_t *_attachment; - _z_reply_context_t *_reply_context; - uint8_t _header; -} _z_zenoh_message_t; -void _z_msg_clear(_z_zenoh_message_t *m); -_Z_ELEM_DEFINE(_z_zenoh_message, _z_zenoh_message_t, _z_noop_size, _z_msg_clear, _z_noop_copy) -_Z_VEC_DEFINE(_z_zenoh_message, _z_zenoh_message_t) - -/*------------------ Builders ------------------*/ -_z_reply_context_t *_z_msg_make_reply_context(_z_zint_t qid, _z_bytes_t replier_id, _Bool is_final); -_z_declaration_t _z_msg_make_declaration_resource(_z_zint_t id, _z_keyexpr_t key); -_z_declaration_t _z_msg_make_declaration_forget_resource(_z_zint_t rid); -_z_declaration_t _z_msg_make_declaration_publisher(_z_keyexpr_t key); -_z_declaration_t _z_msg_make_declaration_forget_publisher(_z_keyexpr_t key); -_z_declaration_t _z_msg_make_declaration_subscriber(_z_keyexpr_t key, _z_subinfo_t subinfo); -_z_declaration_t _z_msg_make_declaration_forget_subscriber(_z_keyexpr_t key); -_z_declaration_t _z_msg_make_declaration_queryable(_z_keyexpr_t key, _z_zint_t complete, _z_zint_t distance); -_z_declaration_t _z_msg_make_declaration_forget_queryable(_z_keyexpr_t key); -_z_zenoh_message_t _z_msg_make_declare(_z_declaration_array_t declarations); -_z_zenoh_message_t _z_msg_make_data(_z_keyexpr_t key, _z_data_info_t info, _z_payload_t payload, _Bool can_be_dropped); -_z_zenoh_message_t _z_msg_make_unit(_Bool can_be_dropped); -_z_zenoh_message_t _z_msg_make_pull(_z_keyexpr_t key, _z_zint_t pull_id, _z_zint_t max_samples, _Bool is_final); -_z_zenoh_message_t _z_msg_make_query(_z_keyexpr_t key, char *parameters, _z_zint_t qid, z_query_target_t target, - z_consolidation_mode_t consolidation, _z_value_t value); -_z_zenoh_message_t _z_msg_make_reply(_z_keyexpr_t key, _z_data_info_t info, _z_payload_t payload, _Bool can_be_dropped, - _z_reply_context_t *rctx); - -/*=============================*/ -/* Transport Messages */ -/*=============================*/ -/*------------------ Scout Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The SCOUT message can be sent at any point in time to solicit HELLO messages from matching parties. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|W|I| SCOUT | -// +-+-+-+-+-------+ -// ~ what ~ if W==1 -- Otherwise implicitly scouting for Routers -// +---------------+ -// -// - if I==1 then the sender is asking for hello replies that contain a Zenoh ID. -// -typedef struct { - z_whatami_t _what; -} _z_t_msg_scout_t; -void _z_t_msg_clear_scout(_z_t_msg_scout_t *msg); - -/*------------------ Hello Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The HELLO message is sent in any of the following three cases: -// 1) in response to a SCOUT message; -// 2) to (periodically) advertise (e.g., on multicast) the Peer and the locators it is reachable at; -// 3) in a already established session to update the corresponding peer on the new capabilities -// (i.e., whatmai) and/or new set of locators (i.e., added or deleted). -// Locators are expressed as: -// -// udp/192.168.0.2:1234 -// tcp/192.168.0.2:1234 -// udp/239.255.255.123:5555 -// -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |L|W|I| HELLO | -// +-+-+-+-+-------+ -// ~ zenoh_id ~ if I==1 -// +---------------+ -// ~ whatami ~ if W==1 -- Otherwise it is from a Router -// +---------------+ -// ~ Locators ~ if L==1 -- Otherwise src-address is the locator -// +---------------+ -// -typedef struct { - _z_bytes_t _zid; - _z_locator_array_t _locators; - z_whatami_t _whatami; -} _z_t_msg_hello_t; -void _z_t_msg_clear_hello(_z_t_msg_hello_t *msg); - -/*------------------ Join Message ------------------*/ -// # Join message -// -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The JOIN message is sent on a multicast Locator to advertise the transport parameters. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |O|S|T| JOIN | -// +-+-+-+-+-------+ -// ~ |Q~ if O==1 -// +---------------+ -// | v_maj | v_min | -- Protocol Version VMaj.VMin -// +-------+-------+ -// ~ whatami ~ -- Router, Peer or a combination of them -// +---------------+ -// ~ zenoh_id ~ -- PID of the sender of the JOIN message -// +---------------+ -// ~ lease ~ -- Lease period of the sender of the JOIN message(*) -// +---------------+ -// ~ sn_resolution ~ if S==1(*) -- Otherwise 2^28 is assumed(**) -// +---------------+ -// ~ [next_sn] ~ (***) -// +---------------+ -// -// - if Q==1 then the sender supports QoS. -// -// (*) if T==1 then the lease period is expressed in seconds, otherwise in milliseconds -// (**) if S==0 then 2^28 is assumed. -// (***) if Q==1 then 8 sequence numbers are present: one for each priority. -// if Q==0 then only one sequence number is present. -// -typedef struct { - _z_zint_t _reliable; - _z_zint_t _best_effort; -} _z_coundit_sn_t; -typedef struct { - union { - _z_coundit_sn_t _plain; - _z_coundit_sn_t _qos[Z_PRIORITIES_NUM]; - } _val; - _Bool _is_qos; -} _z_conduit_sn_list_t; -typedef struct { - _z_bytes_t _zid; - _z_zint_t _options; - _z_zint_t _lease; - _z_zint_t _sn_resolution; - _z_conduit_sn_list_t _next_sns; - z_whatami_t _whatami; - uint8_t _version; -} _z_t_msg_join_t; -void _z_t_msg_clear_join(_z_t_msg_join_t *msg); - -/*------------------ Init Message ------------------*/ -// # Init message -// -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The INIT message is sent on a specific Locator to initiate a session with the peer associated -// with that Locator. The initiator MUST send an INIT message with the A flag set to 0. If the -// corresponding peer deems appropriate to initialize a session with the initiator, the corresponding -// peer MUST reply with an INIT message with the A flag set to 1. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |O|S|A| INIT | -// +-+-+-+-+-------+ -// ~ |Q~ if O==1 -// +---------------+ -// | v_maj | v_min | if A==0 -- Protocol Version VMaj.VMin -// +-------+-------+ -// ~ whatami ~ -- Client, Router, Peer or a combination of them -// +---------------+ -// ~ zenoh_id ~ -- PID of the sender of the INIT message -// +---------------+ -// ~ sn_resolution ~ if S==1(*) -- Otherwise 2^28 is assumed(**) -// +---------------+ -// ~ cookie ~ if A==1 -// +---------------+ -// -// (*) if A==0 and S==0 then 2^28 is assumed. -// if A==1 and S==0 then the agreed resolution is the one communicated by the initiator. -// -// - if Q==1 then the initiator/responder supports QoS. -// -typedef struct { - _z_bytes_t _zid; - _z_bytes_t _cookie; - _z_zint_t _options; - _z_zint_t _sn_resolution; - z_whatami_t _whatami; - uint8_t _version; -} _z_t_msg_init_t; -void _z_t_msg_clear_init(_z_t_msg_init_t *msg); - -/*------------------ Open Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total lenght -// in bytes of the message, resulting in the maximum lenght of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the lenght of a message must not exceed 65_535 bytes. -// -// The OPEN message is sent on a link to finally open an initialized session with the peer. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|T|A| OPEN | -// +-+-+-+-+-------+ -// ~ lease_period ~ -- Lease period of the sender of the OPEN message(*) -// +---------------+ -// ~ initial_sn ~ -- Initial SN proposed by the sender of the OPEN(**) -// +---------------+ -// ~ cookie ~ if A==0(*) -// +---------------+ -// -// (*) if T==1 then the lease period is expressed in seconds, otherwise in milliseconds -// (**) the cookie MUST be the same received in the INIT message with A==1 from the corresponding peer -// -typedef struct { - _z_zint_t _lease; - _z_zint_t _initial_sn; - _z_bytes_t _cookie; -} _z_t_msg_open_t; -void _z_t_msg_clear_open(_z_t_msg_open_t *msg); - -/*------------------ Close Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The CLOSE message is sent in any of the following two cases: -// 1) in response to an OPEN message which is not accepted; -// 2) at any time to arbitrarly close the session with the corresponding peer. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|K|I| CLOSE | -// +-+-+-+-+-------+ -// ~ zenoh_id ~ if I==1 -- PID of the target peer. -// +---------------+ -// | reason | -// +---------------+ -// -// - if K==0 then close the whole zenoh session. -// - if K==1 then close the transport link the CLOSE message was sent on (e.g., TCP socket) but -// keep the whole session open. NOTE: the session will be automatically closed when -// the session's lease period expires. -typedef struct { - _z_bytes_t _zid; - uint8_t _reason; -} _z_t_msg_close_t; -void _z_t_msg_clear_close(_z_t_msg_close_t *msg); - -/*------------------ Sync Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The SYNC message allows to signal the corresponding peer the sequence number of the next message -// to be transmitted on the reliable or best-effort channel. In the case of reliable channel, the -// peer can optionally include the number of unacknowledged messages. A SYNC sent on the reliable -// channel triggers the transmission of an ACKNACK message. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|C|R| SYNC | -// +-+-+-+-+-------+ -// ~ sn ~ -- Sequence number of the next message to be transmitted on this channel. -// +---------------+ -// ~ count ~ if R==1 && C==1 -- Number of unacknowledged messages. -// +---------------+ -// -// - if R==1 then the SYNC concerns the reliable channel, otherwise the best-effort channel. -// -typedef struct { - _z_zint_t _sn; - _z_zint_t _count; -} _z_t_msg_sync_t; -void _z_t_msg_clear_sync(_z_t_msg_sync_t *msg); - -/*------------------ AckNack Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The ACKNACK messages is used on the reliable channel to signal the corresponding peer the last -// sequence number received and optionally a bitmask of the non-received messages. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|M| ACKNACK | -// +-+-+-+-+-------+ -// ~ sn ~ -// +---------------+ -// ~ mask ~ if M==1 -// +---------------+ -// -typedef struct { - _z_zint_t _sn; - _z_zint_t _mask; -} _z_t_msg_ack_nack_t; -void _z_t_msg_clear_ack_nack(_z_t_msg_ack_nack_t *msg); - -/*------------------ Keep Alive Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// The KEEP_ALIVE message can be sent periodically to avoid the expiration of the session lease -// period in case there are no messages to be sent. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|I| K_ALIVE | -// +-+-+-+-+-------+ -// ~ zenoh_id ~ if I==1 -- Peer ID of the KEEP_ALIVE sender. -// +---------------+ -// -typedef struct { - _z_bytes_t _zid; -} _z_t_msg_keep_alive_t; -void _z_t_msg_clear_keep_alive(_z_t_msg_keep_alive_t *msg); - -/*------------------ PingPong Messages ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |X|X|P| P_PONG | -// +-+-+-+-+-------+ -// ~ hash ~ -// +---------------+ -// -// - if P==1 then the message is Ping, otherwise is Pong. -// -typedef struct { - _z_zint_t _hash; -} _z_t_msg_ping_pong_t; -void _z_t_msg_clear_ping_pong(_z_t_msg_ping_pong_t *msg); - -/*------------------ Frame Message ------------------*/ -// NOTE: 16 bits (2 bytes) may be prepended to the serialized message indicating the total length -// in bytes of the message, resulting in the maximum length of a message being 65_535 bytes. -// This is necessary in those stream-oriented transports (e.g., TCP) that do not preserve -// the boundary of the serialized messages. The length is encoded as little-endian. -// In any case, the length of a message must not exceed 65_535 bytes. -// -// 7 6 5 4 3 2 1 0 -// +-+-+-+-+-+-+-+-+ -// |E|F|R| FRAME | -// +-+-+-+-+-------+ -// ~ SN ~ -// +---------------+ -// ~ FramePayload ~ -- if F==1 then the payload is a fragment of a single Zenoh Message, a list of complete Zenoh -// Messages otherwise. -// +---------------+ -// -// - if R==1 then the FRAME is sent on the reliable channel, best-effort otherwise. -// - if F==1 then the FRAME is a fragment. -// - if E==1 then the FRAME is the last fragment. E==1 is valid iff F==1. -// -// NOTE: Only one bit would be sufficient to signal fragmentation in a IP-like fashion as follows: -// - if F==1 then this FRAME is a fragment and more fragment will follow; -// - if F==0 then the message is the last fragment if SN-1 had F==1, -// otherwise it's a non-fragmented message. -// However, this would require to always perform a two-steps de-serialization: first -// de-serialize the FRAME and then the Payload. This is due to the fact the F==0 is ambigous -// w.r.t. detecting if the FRAME is a fragment or not before SN re-ordering has occured. -// By using the F bit to only signal whether the FRAME is fragmented or not, it allows to -// de-serialize the payload in one single pass when F==0 since no re-ordering needs to take -// place at this stage. Then, the F bit is used to detect the last fragment during re-ordering. -// -typedef union { - _z_payload_t _fragment; - _z_zenoh_message_vec_t _messages; -} _z_frame_payload_t; -typedef struct { - _z_frame_payload_t _payload; - _z_zint_t _sn; -} _z_t_msg_frame_t; -void _z_t_msg_clear_frame(_z_t_msg_frame_t *msg, uint8_t header); - -/*------------------ Transport Message ------------------*/ -typedef union { - _z_t_msg_scout_t _scout; - _z_t_msg_hello_t _hello; - _z_t_msg_join_t _join; - _z_t_msg_init_t _init; - _z_t_msg_open_t _open; - _z_t_msg_close_t _close; - _z_t_msg_sync_t _sync; - _z_t_msg_ack_nack_t _ack_nack; - _z_t_msg_keep_alive_t _keep_alive; - _z_t_msg_ping_pong_t _ping_pong; - _z_t_msg_frame_t _frame; -} _z_transport_body_t; -typedef struct { - _z_transport_body_t _body; - _z_attachment_t *_attachment; - uint8_t _header; -} _z_transport_message_t; -void _z_t_msg_clear(_z_transport_message_t *msg); - -/*------------------ Builders ------------------*/ -_z_transport_message_t _z_t_msg_make_scout(z_whatami_t what, _Bool request_zid); -_z_transport_message_t _z_t_msg_make_hello(z_whatami_t whatami, _z_bytes_t zid, _z_locator_array_t locators); -_z_transport_message_t _z_t_msg_make_join(uint8_t version, z_whatami_t whatami, _z_zint_t lease, - _z_zint_t sn_resolution, _z_bytes_t zid, _z_conduit_sn_list_t next_sns); -_z_transport_message_t _z_t_msg_make_init_syn(uint8_t version, z_whatami_t whatami, _z_zint_t sn_resolution, - _z_bytes_t zid, _Bool is_qos); -_z_transport_message_t _z_t_msg_make_init_ack(uint8_t version, z_whatami_t whatami, _z_zint_t sn_resolution, - _z_bytes_t zid, _z_bytes_t cookie, _Bool is_qos); -_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_ack(_z_zint_t lease, _z_zint_t initial_sn); -_z_transport_message_t _z_t_msg_make_close(uint8_t reason, _z_bytes_t zid, _Bool link_only); -_z_transport_message_t _z_t_msg_make_sync(_z_zint_t sn, _Bool is_reliable, _z_zint_t count); -_z_transport_message_t _z_t_msg_make_ack_nack(_z_zint_t sn, _z_zint_t mask); -_z_transport_message_t _z_t_msg_make_keep_alive(_z_bytes_t zid); -_z_transport_message_t _z_t_msg_make_ping(_z_zint_t hash); -_z_transport_message_t _z_t_msg_make_pong(_z_zint_t hash); -_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_frame_payload_t payload, _Bool is_reliable, - _Bool is_fragment, _Bool is_final); -_z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, _Bool is_reliable, _Bool is_fragment, _Bool is_final); - -/*------------------ Copy ------------------*/ -// @TODO: implement the remaining copyers -void _z_t_msg_copy(_z_transport_message_t *clone, _z_transport_message_t *msg); -void _z_t_msg_copy_scout(_z_t_msg_scout_t *clone, _z_t_msg_scout_t *msg); -void _z_t_msg_copy_hello(_z_t_msg_hello_t *clone, _z_t_msg_hello_t *msg); -void _z_t_msg_copy_join(_z_t_msg_join_t *clone, _z_t_msg_join_t *msg); -void _z_t_msg_copy_init(_z_t_msg_init_t *clone, _z_t_msg_init_t *msg); -void _z_t_msg_copy_open(_z_t_msg_open_t *clone, _z_t_msg_open_t *msg); -void _z_t_msg_copy_close(_z_t_msg_close_t *clone, _z_t_msg_close_t *msg); -void _z_t_msg_copy_sync(_z_t_msg_sync_t *clone, _z_t_msg_sync_t *msg); -void _z_t_msg_copy_ack_nack(_z_t_msg_ack_nack_t *clone, _z_t_msg_ack_nack_t *msg); -void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_t *msg); -void _z_t_msg_copy_ping_pong(_z_t_msg_ping_pong_t *clone, _z_t_msg_ping_pong_t *msg); -void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg, uint8_t header); - -#endif /* ZENOH_PICO_PROTOCOL_MSG_H */ diff --git a/include/zenoh-pico/protocol/msgcodec.h b/include/zenoh-pico/protocol/msgcodec.h deleted file mode 100644 index ff896989a..000000000 --- a/include/zenoh-pico/protocol/msgcodec.h +++ /dev/null @@ -1,183 +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_MSGCODEC_H -#define ZENOH_PICO_MSGCODEC_H - -#define _ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE 32 - -#include "zenoh-pico/collections/element.h" -#include "zenoh-pico/link/endpoint.h" -#include "zenoh-pico/protocol/codec.h" -#include "zenoh-pico/protocol/msg.h" -#include "zenoh-pico/utils/result.h" - -/*------------------ Internal Zenoh-net Macros ------------------*/ -#define _Z_DECLARE_ENCODE(name) int8_t _z_##name##_encode(_z_wbuf_t *wbf, uint8_t header, const _z_##name##_t *m); -#define _Z_DECLARE_ENCODE_NOH(name) int8_t _z_##name##_encode(_z_wbuf_t *wbf, const _z_##name##_t *m); - -#define _Z_DECLARE_DECODE_NEW(name) \ - int8_t _z_##name##_decode(_z_##name##_t *t, _z_zbuf_t *zbf, uint8_t header); \ - int8_t _z_##name##_decode_na(_z_##name##_t *t, _z_zbuf_t *zbf, uint8_t header); - -#define _Z_DECLARE_DECODE_NOH_NEW(name) \ - int8_t _z_##name##_decode(_z_##name##_t *t, _z_zbuf_t *zbf); \ - int8_t _z_##name##_decode_na(_z_##name##_t *t, _z_zbuf_t *zbf); - -#define _Z_DECLARE_DECODE(name) \ - _z_##name##_result_t _z_##name##_decode(_z_zbuf_t *zbf, uint8_t header); \ - void _z_##name##_decode_na(_z_zbuf_t *zbf, uint8_t header, _z_##name##_result_t *r); - -#define _Z_DECLARE_DECODE_NOH(name) \ - _z_##name##_result_t _z_##name##_decode(_z_zbuf_t *zbf); \ - void _z_##name##_decode_na(_z_zbuf_t *zbf, _z_##name##_result_t *r); - -/*------------------ Zenoh Message ------------------*/ -int8_t _z_transport_message_encode(_z_wbuf_t *buf, const _z_transport_message_t *msg); -int8_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *buf); -int8_t _z_transport_message_decode_na(_z_transport_message_t *msg, _z_zbuf_t *buf); - -int8_t _z_zenoh_message_encode(_z_wbuf_t *buf, const _z_zenoh_message_t *msg); -int8_t _z_zenoh_message_decode(_z_zenoh_message_t *msg, _z_zbuf_t *buf); -int8_t _z_zenoh_message_decode_na(_z_zenoh_message_t *msg, _z_zbuf_t *buf); - -#endif /* ZENOH_PICO_MSGCODEC_H */ - -// NOTE: the following headers are for unit testing only -#ifdef ZENOH_PICO_TEST_H -// ------------------ Message Fields ------------------ -int8_t _z_payload_encode(_z_wbuf_t *buf, const _z_payload_t *pld); -int8_t _z_payload_decode(_z_payload_t *pld, _z_zbuf_t *buf); -int8_t _z_payload_decode_na(_z_payload_t *pld, _z_zbuf_t *buf); - -int8_t _z_timestamp_encode(_z_wbuf_t *buf, const _z_timestamp_t *ts); -int8_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *buf); -int8_t _z_timestamp_decode_na(_z_timestamp_t *ts, _z_zbuf_t *buf); - -int8_t _z_subinfo_encode(_z_wbuf_t *buf, const _z_subinfo_t *si); -int8_t _z_subinfo_decode(_z_subinfo_t *si, _z_zbuf_t *buf, uint8_t header); -int8_t _z_subinfo_decode_na(_z_subinfo_t *si, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_keyexpr_encode(_z_wbuf_t *buf, uint8_t header, const _z_keyexpr_t *ke); -int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *buf, uint8_t header); -int8_t _z_keyexpr_decode_na(_z_keyexpr_t *ke, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_data_info_encode(_z_wbuf_t *buf, const _z_data_info_t *di); -int8_t _z_data_info_decode(_z_data_info_t *di, _z_zbuf_t *buf); -int8_t _z_data_info_decode_na(_z_data_info_t *di, _z_zbuf_t *buf); - -// ------------------ Zenoh Message ------------------ -int8_t _z_res_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_res_decl_t *dcl); -int8_t _z_res_decl_decode(_z_res_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_res_decl_decode_na(_z_res_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_pub_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_pub_decl_t *dcl); -int8_t _z_pub_decl_decode(_z_pub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_pub_decl_decode_na(_z_pub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_sub_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_sub_decl_t *dcl); -int8_t _z_sub_decl_decode(_z_sub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_sub_decl_decode_na(_z_sub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_qle_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_qle_decl_t *dcl); -int8_t _z_qle_decl_decode(_z_qle_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_qle_decl_decode_na(_z_qle_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_forget_res_decl_encode(_z_wbuf_t *buf, const _z_forget_res_decl_t *dcl); -int8_t _z_forget_res_decl_decode(_z_forget_res_decl_t *dcl, _z_zbuf_t *buf); -int8_t _z_forget_res_decl_decode_na(_z_forget_res_decl_t *dcl, _z_zbuf_t *buf); - -int8_t _z_forget_pub_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_forget_pub_decl_t *dcl); -int8_t _z_forget_pub_decl_decode(_z_forget_pub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_forget_pub_decl_decode_na(_z_forget_pub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_forget_sub_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_forget_sub_decl_t *dcl); -int8_t _z_forget_sub_decl_decode(_z_forget_sub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_forget_sub_decl_decode_na(_z_forget_sub_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_forget_qle_decl_encode(_z_wbuf_t *buf, uint8_t header, const _z_forget_qle_decl_t *dcl); -int8_t _z_forget_qle_decl_decode(_z_forget_qle_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); -int8_t _z_forget_qle_decl_decode_na(_z_forget_qle_decl_t *dcl, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_attachment_encode(_z_wbuf_t *buf, const _z_attachment_t *atch); -int8_t _z_attachment_decode(_z_attachment_t **atch, _z_zbuf_t *buf, uint8_t header); -int8_t _z_attachment_decode_na(_z_attachment_t *atch, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_reply_context_encode(_z_wbuf_t *buf, const _z_reply_context_t *rc); -int8_t _z_reply_context_decode(_z_reply_context_t **rc, _z_zbuf_t *buf, uint8_t header); -int8_t _z_reply_context_decode_na(_z_reply_context_t *rc, _z_zbuf_t *buf, uint8_t header); - -int8_t _z_declare_encode(_z_wbuf_t *wbf, const _z_msg_declare_t *msg); -int8_t _z_declare_decode(_z_msg_declare_t *msg, _z_zbuf_t *zbf); -int8_t _z_declare_decode_na(_z_msg_declare_t *msg, _z_zbuf_t *zbf); - -int8_t _z_data_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_data_t *msg); -int8_t _z_data_decode_na(_z_msg_data_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_data_decode(_z_msg_data_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_pull_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_pull_t *msg); -int8_t _z_pull_decode_na(_z_msg_pull_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_pull_decode(_z_msg_pull_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_query_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_query_t *msg); -int8_t _z_query_decode_na(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_query_decode(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header); - -// ------------------ Transport Message ------------------ -int8_t _z_join_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_join_t *msg); -int8_t _z_join_decode_na(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t *msg); -int8_t _z_init_decode_na(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_open_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_open_t *msg); -int8_t _z_open_decode_na(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_close_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_close_t *msg); -int8_t _z_close_decode_na(_z_t_msg_close_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_close_decode(_z_t_msg_close_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_sync_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_sync_t *msg); -int8_t _z_sync_decode_na(_z_t_msg_sync_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_sync_decode(_z_t_msg_sync_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_ack_nack_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_ack_nack_t *msg); -int8_t _z_ack_nack_decode_na(_z_t_msg_ack_nack_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_ack_nack_decode(_z_t_msg_ack_nack_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_keep_alive_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_keep_alive_t *msg); -int8_t _z_keep_alive_decode_na(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_ping_pong_encode(_z_wbuf_t *wbf, const _z_t_msg_ping_pong_t *msg); -int8_t _z_ping_pong_decode_na(_z_t_msg_ping_pong_t *msg, _z_zbuf_t *zbf); -int8_t _z_ping_pong_decode(_z_t_msg_ping_pong_t *msg, _z_zbuf_t *zbf); - -int8_t _z_frame_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_frame_t *msg); -int8_t _z_frame_decode_na(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header); - -// ------------------ Discovery Message ------------------ -int8_t _z_scout_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_scout_t *msg); -int8_t _z_scout_decode_na(_z_t_msg_scout_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_scout_decode(_z_t_msg_scout_t *msg, _z_zbuf_t *zbf, uint8_t header); - -int8_t _z_hello_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_hello_t *msg); -int8_t _z_hello_decode_na(_z_t_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header); -int8_t _z_hello_decode(_z_t_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header); - -#endif /* ZENOH_PICO_TEST_H */ diff --git a/include/zenoh-pico/session/query.h b/include/zenoh-pico/session/query.h index ab8fb42b2..c5597c3c8 100644 --- a/include/zenoh-pico/session/query.h +++ b/include/zenoh-pico/session/query.h @@ -16,6 +16,7 @@ #define ZENOH_PICO_SESSION_QUERY_H #include "zenoh-pico/net/session.h" +#include "zenoh-pico/protocol/core.h" /*------------------ Query ------------------*/ _z_zint_t _z_get_query_id(_z_session_t *zn); @@ -23,10 +24,10 @@ _z_zint_t _z_get_query_id(_z_session_t *zn); _z_pending_query_t *_z_get_pending_query_by_id(_z_session_t *zn, const _z_zint_t id); 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, const _z_reply_context_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); -int8_t _z_trigger_query_reply_final(_z_session_t *zn, const _z_reply_context_t *reply_context); +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); +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 a86c3248a..d6218b262 100644 --- a/include/zenoh-pico/session/queryable.h +++ b/include/zenoh-pico/session/queryable.h @@ -27,7 +27,7 @@ _z_questionable_sptr_t *_z_get_questionable_by_id(_z_session_t *zn, const _z_zin _z_questionable_sptr_list_t *_z_get_questionable_by_key(_z_session_t *zn, const _z_keyexpr_t key); _z_questionable_sptr_t *_z_register_questionable(_z_session_t *zn, _z_questionable_t *q); -int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *query); +int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *query, const _z_keyexpr_t q_key, uint32_t qid); void _z_unregister_questionable(_z_session_t *zn, _z_questionable_sptr_t *q); void _z_flush_questionables(_z_session_t *zn); diff --git a/include/zenoh-pico/session/resource.h b/include/zenoh-pico/session/resource.h index 6a64eb057..7c6ef0cc1 100644 --- a/include/zenoh-pico/session/resource.h +++ b/include/zenoh-pico/session/resource.h @@ -12,25 +12,28 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_SESSION_RESOURCE_H -#define ZENOH_PICO_SESSION_RESOURCE_H +#ifndef INCLUDE_ZENOH_PICO_SESSION_RESOURCE_H +#define INCLUDE_ZENOH_PICO_SESSION_RESOURCE_H + +#include #include "zenoh-pico/net/session.h" /*------------------ Entity ------------------*/ -_z_zint_t _z_get_entity_id(_z_session_t *zn); +uint32_t _z_get_entity_id(_z_session_t *zn); /*------------------ Resource ------------------*/ -_z_zint_t _z_get_resource_id(_z_session_t *zn); -_z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint8_t is_local, _z_zint_t rid); -_z_resource_t *_z_get_resource_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); -_z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); -int8_t _z_register_resource(_z_session_t *zn, uint8_t is_local, _z_resource_t *res); -void _z_unregister_resource(_z_session_t *zn, uint8_t is_local, _z_resource_t *res); +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); +void _z_unregister_resource(_z_session_t *zn, uint16_t id, uint16_t mapping); +void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping); void _z_flush_resources(_z_session_t *zn); -_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); -_z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint8_t is_local, _z_zint_t id); -_z_resource_t *__unsafe_z_get_resource_matching_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr); +_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); +_z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t id); +_z_resource_t *__unsafe_z_get_resource_matching_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr); -#endif /* ZENOH_PICO_SESSION_RESOURCE_H */ +#endif /* INCLUDE_ZENOH_PICO_SESSION_RESOURCE_H */ diff --git a/include/zenoh-pico/session/session.h b/include/zenoh-pico/session/session.h index 88ab2e631..8b394e844 100644 --- a/include/zenoh-pico/session/session.h +++ b/include/zenoh-pico/session/session.h @@ -12,16 +12,18 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_SESSION_TYPES_H -#define ZENOH_PICO_SESSION_TYPES_H +#ifndef INCLUDE_ZENOH_PICO_SESSION_SESSION_H +#define INCLUDE_ZENOH_PICO_SESSION_SESSION_H #include +#include #include "zenoh-pico/collections/element.h" #include "zenoh-pico/collections/list.h" #include "zenoh-pico/collections/pointer.h" #include "zenoh-pico/collections/string.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/net/query.h" #include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/manager.h" @@ -43,7 +45,7 @@ typedef void (*_z_drop_handler_t)(void *arg); */ typedef struct { _z_sample_t sample; - _z_bytes_t replier_id; + _z_id_t replier_id; } _z_reply_data_t; void _z_reply_data_clear(_z_reply_data_t *rd); @@ -70,7 +72,8 @@ void _z_reply_free(_z_reply_t **hello); typedef struct { _z_keyexpr_t _key; - _z_zint_t _id; + uint16_t _id; + uint16_t _refcount; } _z_resource_t; _Bool _z_resource_eq(const _z_resource_t *one, const _z_resource_t *two); @@ -87,7 +90,7 @@ typedef void (*_z_data_handler_t)(const _z_sample_t *sample, void *arg); typedef struct { _z_keyexpr_t _key; - _z_zint_t _id; + uint32_t _id; _z_data_handler_t _callback; _z_drop_handler_t _dropper; void *_arg; @@ -97,14 +100,14 @@ typedef struct { _Bool _z_subscription_eq(const _z_subscription_t *one, const _z_subscription_t *two); void _z_subscription_clear(_z_subscription_t *sub); -_Z_POINTER_DEFINE(_z_subscription, _z_subscription); +_Z_POINTER_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_sptr, _z_subscription_sptr_t, _z_noop_size, _z_subscription_sptr_drop, _z_noop_copy) _Z_LIST_DEFINE(_z_subscription_sptr, _z_subscription_sptr_t) typedef struct { _z_keyexpr_t _key; - _z_zint_t _id; + uint32_t _id; } _z_publication_t; /** @@ -114,7 +117,7 @@ typedef void (*_z_questionable_handler_t)(const z_query_t *query, void *arg); typedef struct { _z_keyexpr_t _key; - _z_zint_t _id; + uint32_t _id; _z_questionable_handler_t _callback; _z_drop_handler_t _dropper; void *_arg; @@ -124,7 +127,7 @@ typedef struct { _Bool _z_questionable_eq(const _z_questionable_t *one, const _z_questionable_t *two); void _z_questionable_clear(_z_questionable_t *res); -_Z_POINTER_DEFINE(_z_questionable, _z_questionable); +_Z_POINTER_DEFINE(_z_questionable, _z_questionable) _Z_ELEM_DEFINE(_z_questionable, _z_questionable_t, _z_noop_size, _z_questionable_clear, _z_noop_copy) _Z_ELEM_DEFINE(_z_questionable_sptr, _z_questionable_sptr_t, _z_noop_size, _z_questionable_sptr_drop, _z_noop_copy) _Z_LIST_DEFINE(_z_questionable_sptr, _z_questionable_sptr_t) @@ -180,6 +183,6 @@ struct __z_hello_handler_wrapper_t; // Forward declaration to be used in _z_hel */ typedef void (*_z_hello_handler_t)(_z_hello_t *hello, struct __z_hello_handler_wrapper_t *arg); -int8_t _z_session_generate_zid(_z_bytes_t *bs, uint8_t size); +int8_t _z_session_generate_zid(_z_id_t *bs, uint8_t size); -#endif /* ZENOH_PICO_SESSION_TYPES_H */ +#endif /* INCLUDE_ZENOH_PICO_SESSION_SESSION_H */ diff --git a/include/zenoh-pico/session/utils.h b/include/zenoh-pico/session/utils.h index 02a693945..39cae73d3 100644 --- a/include/zenoh-pico/session/utils.h +++ b/include/zenoh-pico/session/utils.h @@ -12,24 +12,27 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_SESSION_UTILS_H -#define ZENOH_PICO_SESSION_UTILS_H +#ifndef INCLUDE_ZENOH_PICO_SESSION_UTILS_H +#define INCLUDE_ZENOH_PICO_SESSION_UTILS_H #include +#include +#include "zenoh-pico/api/constants.h" #include "zenoh-pico/net/session.h" +#include "zenoh-pico/protocol/core.h" /*------------------ Session ------------------*/ -_z_hello_list_t *_z_scout_inner(const uint8_t what, const char *locator, const uint32_t timeout, +_z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t id, const char *locator, const uint32_t timeout, const _Bool exit_on_first); -int8_t _z_session_init(_z_session_t *zn, _z_bytes_t *zid); +int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid); int8_t _z_session_close(_z_session_t *zn, uint8_t reason); void _z_session_clear(_z_session_t *zn); void _z_session_free(_z_session_t **zn); -int8_t _z_handle_zenoh_message(_z_session_t *zn, _z_zenoh_message_t *z_msg); -int8_t _z_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reliability_t reliability, +int8_t _z_handle_network_message(_z_session_t *zn, _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); -#endif /* ZENOH_PICO_SESSION_UTILS_H */ +#endif /* INCLUDE_ZENOH_PICO_SESSION_UTILS_H */ diff --git a/include/zenoh-pico/system/platform/arduino/opencr.h b/include/zenoh-pico/system/platform/arduino/opencr.h index 85f4b5752..23c43f222 100644 --- a/include/zenoh-pico/system/platform/arduino/opencr.h +++ b/include/zenoh-pico/system/platform/arduino/opencr.h @@ -42,7 +42,7 @@ typedef struct { #if Z_LINK_UDP_MULTICAST == 1 || Z_LINK_UDP_UNICAST == 1 WiFiUDP *_udp; // As pointer to cross the boundary between C and C++ #endif - _Bool _err; + _Bool _err; }; } _z_sys_net_socket_t; diff --git a/include/zenoh-pico/transport/link/rx.h b/include/zenoh-pico/transport/link/rx.h index b1c5f7c6a..f4c428a64 100644 --- a/include/zenoh-pico/transport/link/rx.h +++ b/include/zenoh-pico/transport/link/rx.h @@ -16,7 +16,6 @@ #define ZENOH_PICO_TRANSPORT_LINK_RX_H #include "zenoh-pico/link/link.h" -#include "zenoh-pico/protocol/msgcodec.h" #include "zenoh-pico/transport/transport.h" /*------------------ Transmission and Reception helpers ------------------*/ diff --git a/include/zenoh-pico/transport/link/tx.h b/include/zenoh-pico/transport/link/tx.h index 8c5c073eb..51aa3412d 100644 --- a/include/zenoh-pico/transport/link/tx.h +++ b/include/zenoh-pico/transport/link/tx.h @@ -21,8 +21,9 @@ void __unsafe_z_prepare_wbuf(_z_wbuf_t *buf, _Bool is_streamed); void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, _Bool is_streamed); +/*This function is unsafe because it operates in potentially concurrent + data.*Make sure that the following mutexes are locked before calling this function : *-ztu->mutex_tx */ int8_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn); -_z_transport_message_t _z_frame_header(z_reliability_t reliability, _Bool is_fragment, _Bool is_final, _z_zint_t sn); /*------------------ Transmission and Reception helpers ------------------*/ int8_t _z_unicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reliability_t reliability, @@ -30,6 +31,11 @@ int8_t _z_unicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reli int8_t _z_multicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl); +int8_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, + z_congestion_control_t cong_ctrl); +int8_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, + z_congestion_control_t cong_ctrl); + int8_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg); int8_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_message_t *t_msg); int8_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport_message_t *t_msg); diff --git a/include/zenoh-pico/transport/manager.h b/include/zenoh-pico/transport/manager.h index 2d378f782..faac8c25e 100644 --- a/include/zenoh-pico/transport/manager.h +++ b/include/zenoh-pico/transport/manager.h @@ -12,14 +12,14 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_TRANSPORT_MANAGER_H -#define ZENOH_PICO_TRANSPORT_MANAGER_H +#ifndef INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H +#define INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H #include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/link/manager.h" #include "zenoh-pico/transport/transport.h" -int8_t _z_new_transport(_z_transport_t *zt, _z_bytes_t *bs, char *locator, z_whatami_t mode); +int8_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, char *locator, z_whatami_t mode); void _z_free_transport(_z_transport_t **zt); -#endif /* ZENOH_PICO_TRANSPORT_MANAGER_H */ +#endif /* INCLUDE_ZENOH_PICO_TRANSPORT_MANAGER_H */ diff --git a/include/zenoh-pico/transport/transport.h b/include/zenoh-pico/transport/transport.h index b764657bb..1982b1b92 100644 --- a/include/zenoh-pico/transport/transport.h +++ b/include/zenoh-pico/transport/transport.h @@ -12,32 +12,34 @@ // ZettaScale Zenoh Team, // -#ifndef ZENOH_PICO_TRANSPORT_TYPES_H -#define ZENOH_PICO_TRANSPORT_TYPES_H +#ifndef INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H +#define INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H + +#include +#include #include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/collections/element.h" #include "zenoh-pico/config.h" #include "zenoh-pico/link/link.h" #include "zenoh-pico/protocol/core.h" -#include "zenoh-pico/protocol/msg.h" +#include "zenoh-pico/protocol/definitions/transport.h" typedef struct { // Defragmentation buffers _z_wbuf_t _dbuf_reliable; _z_wbuf_t _dbuf_best_effort; - _z_bytes_t _remote_zid; + _z_id_t _remote_zid; _z_bytes_t _remote_addr; + _z_conduit_sn_list_t _sn_rx_sns; // SN numbers - _z_zint_t _sn_resolution; - _z_zint_t _sn_resolution_half; + _z_zint_t _sn_res; volatile _z_zint_t _lease; volatile _z_zint_t _next_lease; - _z_conduit_sn_list_t _sn_rx_sns; - + uint16_t _peer_id; volatile _Bool _received; } _z_transport_peer_entry_t; @@ -48,6 +50,8 @@ _Bool _z_transport_peer_entry_eq(const _z_transport_peer_entry_t *left, const _z _Z_ELEM_DEFINE(_z_transport_peer_entry, _z_transport_peer_entry_t, _z_transport_peer_entry_size, _z_transport_peer_entry_clear, _z_transport_peer_entry_copy) _Z_LIST_DEFINE(_z_transport_peer_entry, _z_transport_peer_entry_t) +_z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport_peer_entry_list_t *root, + _z_transport_peer_entry_t *entry); typedef struct { // Session associated to the transport @@ -66,11 +70,10 @@ typedef struct { _z_wbuf_t _wbuf; _z_zbuf_t _zbuf; - _z_bytes_t _remote_zid; + _z_id_t _remote_zid; // SN numbers - _z_zint_t _sn_resolution; - _z_zint_t _sn_resolution_half; + _z_zint_t _sn_res; _z_zint_t _sn_tx_reliable; _z_zint_t _sn_tx_best_effort; _z_zint_t _sn_rx_reliable; @@ -110,8 +113,7 @@ typedef struct { _z_zbuf_t _zbuf; // SN initial numbers - _z_zint_t _sn_resolution; - _z_zint_t _sn_resolution_half; + _z_zint_t _sn_res; _z_zint_t _sn_tx_reliable; _z_zint_t _sn_tx_best_effort; volatile _z_zint_t _lease; @@ -145,32 +147,34 @@ _Z_ELEM_DEFINE(_z_transport, _z_transport_t, _z_noop_size, _z_noop_clear, _z_noo _Z_LIST_DEFINE(_z_transport, _z_transport_t) typedef struct { - _z_bytes_t _remote_zid; - _z_zint_t _sn_resolution; + _z_id_t _remote_zid; + uint16_t _batch_size; _z_zint_t _initial_sn_rx; _z_zint_t _initial_sn_tx; _z_zint_t _lease; z_whatami_t _whatami; + uint8_t _key_id_res; + uint8_t _req_id_res; + uint8_t _seq_num_res; _Bool _is_qos; } _z_transport_unicast_establish_param_t; typedef struct { - _z_zint_t _sn_resolution; - _z_zint_t _initial_sn_tx; - _Bool _is_qos; + _z_conduit_sn_list_t _initial_sn_tx; + uint8_t _seq_num_res; } _z_transport_multicast_establish_param_t; int8_t _z_transport_unicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_unicast_establish_param_t *param); int8_t _z_transport_multicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_multicast_establish_param_t *param); int8_t _z_transport_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid); + const _z_id_t *local_zid); int8_t _z_transport_multicast_open_client(_z_transport_multicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid); + const _z_id_t *local_zid); int8_t _z_transport_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid); + const _z_id_t *local_zid); int8_t _z_transport_multicast_open_peer(_z_transport_multicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid); + const _z_id_t *local_zid); int8_t _z_transport_close(_z_transport_t *zt, uint8_t reason); int8_t _z_transport_unicast_close(_z_transport_unicast_t *ztu, uint8_t reason); @@ -184,4 +188,4 @@ void _z_transport_free(_z_transport_t **zt); void _z_transport_unicast_free(_z_transport_unicast_t **ztu); void _z_transport_multicast_free(_z_transport_multicast_t **ztm); -#endif /* ZENOH_PICO_TRANSPORT_TYPES_H */ +#endif /* INCLUDE_ZENOH_PICO_TRANSPORT_TRANSPORT_H */ diff --git a/include/zenoh-pico/transport/utils.h b/include/zenoh-pico/transport/utils.h index 98b201f6c..a53267680 100644 --- a/include/zenoh-pico/transport/utils.h +++ b/include/zenoh-pico/transport/utils.h @@ -18,12 +18,16 @@ #include #include "zenoh-pico/protocol/core.h" -#include "zenoh-pico/protocol/msg.h" +#include "zenoh-pico/protocol/definitions/transport.h" /*------------------ SN helpers ------------------*/ -_Bool _z_sn_precedes(const _z_zint_t sn_resolution_half, const _z_zint_t sn_left, const _z_zint_t sn_right); +_z_zint_t _z_sn_max(uint8_t bits); +_z_zint_t _z_sn_half(_z_zint_t sn); +_z_zint_t _z_sn_modulo_mask(uint8_t bits); +_Bool _z_sn_precedes(const _z_zint_t sn_resolution, const _z_zint_t sn_left, const _z_zint_t sn_right); _z_zint_t _z_sn_increment(const _z_zint_t sn_resolution, const _z_zint_t sn); _z_zint_t _z_sn_decrement(const _z_zint_t sn_resolution, const _z_zint_t sn); + void _z_conduit_sn_list_copy(_z_conduit_sn_list_t *dst, const _z_conduit_sn_list_t *src); void _z_conduit_sn_list_decrement(const _z_zint_t sn_resolution, _z_conduit_sn_list_t *sns); diff --git a/include/zenoh-pico/utils/logging.h b/include/zenoh-pico/utils/logging.h index 359f70806..3066fcc91 100644 --- a/include/zenoh-pico/utils/logging.h +++ b/include/zenoh-pico/utils/logging.h @@ -22,38 +22,45 @@ static inline void __z_print_timestamp(void) { printf("[%s ", z_time_now_as_str(ret, sizeof(ret))); } +#define _Z_LOG_PREFIX(prefix) \ + __z_print_timestamp(); \ + printf(#prefix " ::%s] ", __func__); + #if (ZENOH_DEBUG == 3) -#define _Z_DEBUG(x, ...) \ - __z_print_timestamp(); \ - printf("DEBUG ::%s] ", __func__); \ +#define _Z_DEBUG(x, ...) \ + _Z_LOG_PREFIX(DEBUG); \ printf(x, ##__VA_ARGS__); -#define _Z_INFO(x, ...) \ - __z_print_timestamp(); \ - printf("INFO ::%s] ", __func__); \ +#define _Z_DEBUG_CONTINUE(x, ...) printf(x, ##__VA_ARGS__); +#define _Z_INFO(x, ...) \ + _Z_LOG_PREFIX(INFO); \ printf(x, ##__VA_ARGS__); -#define _Z_ERROR(x, ...) \ - __z_print_timestamp(); \ - printf("ERROR ::%s] ", __func__); \ +#define _Z_INFO_CONTINUE(x, ...) printf(x, ##__VA_ARGS__); +#define _Z_ERROR(x, ...) \ + _Z_LOG_PREFIX(ERROR); \ printf(x, ##__VA_ARGS__); +#define _Z_ERROR_CONTINUE(x, ...) printf(x, ##__VA_ARGS__); #elif (ZENOH_DEBUG == 2) #define _Z_DEBUG(x, ...) (void)(0) -#define _Z_INFO(x, ...) \ - __z_print_timestamp(); \ - printf("INFO ::%s] ", __func__); \ +#define _Z_DEBUG_CONTINUE(x, ...) (void)(0); +#define _Z_INFO(x, ...) \ + _Z_LOG_PREFIX(INFO); \ printf(x, ##__VA_ARGS__); -#define _Z_ERROR(x, ...) \ - __z_print_timestamp(); \ - printf("ERROR ::%s] ", __func__); \ +#define _Z_INFO_CONTINUE(x, ...) printf(x, ##__VA_ARGS__); +#define _Z_ERROR(x, ...) \ + _Z_LOG_PREFIX(ERROR); \ printf(x, ##__VA_ARGS__); +#define _Z_ERROR_CONTINUE(x, ...) printf(x, ##__VA_ARGS__); #elif (ZENOH_DEBUG == 1) #define _Z_DEBUG(x, ...) (void)(0) -#define _Z_INFO(x, ...) (void)(0) -#define _Z_ERROR(x, ...) \ - __z_print_timestamp(); \ - printf("ERROR ::%s] ", __func__); \ +#define _Z_DEBUG_CONTINUE(x, ...) (void)(0); +#define _Z_INFO(x, ...) (void)(0); +#define _Z_INFO_CONTINUE(x, ...) (void)(0); +#define _Z_ERROR(x, ...) \ + _Z_LOG_PREFIX(ERROR); \ printf(x, ##__VA_ARGS__); +#define _Z_ERROR_CONTINUE(x, ...) printf(x, ##__VA_ARGS__); #elif (ZENOH_DEBUG == 0) #define _Z_DEBUG(x, ...) (void)(0) diff --git a/include/zenoh-pico/utils/result.h b/include/zenoh-pico/utils/result.h index 4e6ed2838..7b4afe42e 100644 --- a/include/zenoh-pico/utils/result.h +++ b/include/zenoh-pico/utils/result.h @@ -34,6 +34,7 @@ typedef enum { _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN = -115, _Z_ERR_MESSAGE_ZENOH_UNKNOWN = -114, _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN = -113, + _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN = -112, _Z_ERR_ENTITY_DECLARATION_FAILED = -111, _Z_ERR_ENTITY_UNKNOWN = -110, diff --git a/include/zenoh-pico/utils/string.h b/include/zenoh-pico/utils/string.h index 96de0f729..89f8e7cf7 100644 --- a/include/zenoh-pico/utils/string.h +++ b/include/zenoh-pico/utils/string.h @@ -1,3 +1,17 @@ +// +// 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 diff --git a/include/zenoh-pico/utils/uuid.h b/include/zenoh-pico/utils/uuid.h new file mode 100644 index 000000000..b0e487235 --- /dev/null +++ b/include/zenoh-pico/utils/uuid.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, +// + +#include + +/** + * Converts an UUID in string format to a byte array. + * + * Parameters: + * bytes: Pointer to an already allocated byte array of size (at least) 16 bytes. + * 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/src/api/api.c b/src/api/api.c index f156f60eb..08996bf76 100644 --- a/src/api/api.c +++ b/src/api/api.c @@ -13,23 +13,28 @@ #include #include +#include #include #include #include "zenoh-pico/api/primitives.h" #include "zenoh-pico/api/types.h" +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/config.h" #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/resource.h" #include "zenoh-pico/net/session.h" +#include "zenoh-pico/protocol/core.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/system/platform.h" +#include "zenoh-pico/utils/logging.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; } @@ -72,7 +77,7 @@ z_bytes_t z_keyexpr_as_bytes(z_keyexpr_t keyexpr) { z_owned_str_t zp_keyexpr_resolve(z_session_t zs, z_keyexpr_t keyexpr) { z_owned_str_t ret = {._value = NULL}; - _z_keyexpr_t ekey = _z_get_expanded_key_from_key(zs._val, _Z_RESOURCE_IS_LOCAL, &keyexpr); + _z_keyexpr_t ekey = _z_get_expanded_key_from_key(zs._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 @@ -492,12 +497,31 @@ int8_t z_scout(z_owned_scouting_config_t *config, z_owned_closure_hello_t *callb wrapped_ctx->user_call = callback->call; wrapped_ctx->ctx = ctx; - char *what_str = _z_config_get(config->_value, Z_CONFIG_SCOUTING_WHAT_KEY); - z_whatami_t what = strtol(what_str, NULL, 10); - char *locator = _z_config_get(config->_value, Z_CONFIG_MULTICAST_LOCATOR_KEY); - char *tout_str = _z_config_get(config->_value, Z_CONFIG_SCOUTING_TIMEOUT_KEY); - uint32_t tout = strtoul(tout_str, NULL, 10); - _z_scout(what, locator, tout, __z_hello_handler, wrapped_ctx, callback->drop, ctx); + char *opt_as_str = _z_config_get(config->_value, Z_CONFIG_SCOUTING_WHAT_KEY); + if (opt_as_str == NULL) { + opt_as_str = Z_CONFIG_SCOUTING_WHAT_DEFAULT; + } + z_what_t what = strtol(opt_as_str, NULL, 10); + + opt_as_str = _z_config_get(config->_value, Z_CONFIG_MULTICAST_LOCATOR_KEY); + if (opt_as_str == NULL) { + opt_as_str = Z_CONFIG_MULTICAST_LOCATOR_DEFAULT; + } + char *mcast_locator = opt_as_str; + + opt_as_str = _z_config_get(config->_value, Z_CONFIG_SCOUTING_TIMEOUT_KEY); + if (opt_as_str == NULL) { + opt_as_str = Z_CONFIG_SCOUTING_TIMEOUT_DEFAULT; + } + 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); + 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_free(wrapped_ctx); z_scouting_config_drop(config); @@ -541,18 +565,10 @@ int8_t z_info_peers_zid(const z_session_t zs, z_owned_closure_zid_t *callback) { if (zs._val->_tp._type == _Z_TRANSPORT_MULTICAST_TYPE) { _z_transport_peer_entry_list_t *l = zs._val->_tp._transport._multicast._peers; for (; l != NULL; l = _z_transport_peer_entry_list_tail(l)) { - z_id_t id; _z_transport_peer_entry_t *val = _z_transport_peer_entry_list_head(l); + z_id_t id = val->_remote_zid; - if (val->_remote_zid.len <= sizeof(id.id)) { - _z_bytes_t bs = val->_remote_zid; - for (size_t i = 0; i < bs.len; i++) { - id.id[i] = bs.start[bs.len - i - 1]; - } - (void)memset(&id.id[bs.len], 0, sizeof(id.id) - bs.len); - - callback->call(&id, ctx); - } + callback->call(&id, ctx); } } #else @@ -572,16 +588,8 @@ int8_t z_info_routers_zid(const z_session_t zs, z_owned_closure_zid_t *callback) #if Z_UNICAST_TRANSPORT == 1 if (zs._val->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { - z_id_t id; - if (zs._val->_tp._transport._unicast._remote_zid.len <= sizeof(id.id)) { - _z_bytes_t bs = zs._val->_tp._transport._unicast._remote_zid; - for (size_t i = 0; i < bs.len; i++) { - id.id[i] = bs.start[bs.len - i - 1]; - } - (void)memset(&id.id[bs.len], 0, sizeof(id.id) - bs.len); - - callback->call(&id, ctx); - } + z_id_t id = zs._val->_tp._transport._unicast._remote_zid; + callback->call(&id, ctx); } #endif // Z_UNICAST_TRANSPORT == 1 @@ -592,20 +600,7 @@ int8_t z_info_routers_zid(const z_session_t zs, z_owned_closure_zid_t *callback) return 0; } -z_id_t z_info_zid(const z_session_t zs) { - z_id_t id; - if (zs._val->_local_zid.len <= sizeof(id.id)) { - _z_bytes_t bs = zs._val->_local_zid; - for (size_t i = 0; i < bs.len; i++) { - id.id[i] = bs.start[bs.len - i - 1]; - } - (void)memset(&id.id[bs.len], 0, sizeof(id.id) - bs.len); - } else { - (void)memset(&id.id[0], 0, sizeof(id.id)); - } - - return id; -} +z_id_t z_info_zid(const z_session_t zs) { return zs._val->_local_zid; } z_put_options_t z_put_options_default(void) { return (z_put_options_t){.encoding = z_encoding_default(), @@ -628,7 +623,7 @@ int8_t z_put(z_session_t zs, z_keyexpr_t keyexpr, const uint8_t *payload, z_zint opt.priority = options->priority; } ret = _z_write(zs._val, keyexpr, (const uint8_t *)payload, payload_len, opt.encoding, Z_SAMPLE_KIND_PUT, - opt.congestion_control); + opt.congestion_control, opt.priority); return ret; } @@ -641,7 +636,8 @@ int8_t z_delete(z_session_t zs, z_keyexpr_t keyexpr, const z_delete_options_t *o opt.congestion_control = options->congestion_control; opt.priority = options->priority; } - ret = _z_write(zs._val, keyexpr, NULL, 0, z_encoding_default(), Z_SAMPLE_KIND_DELETE, opt.congestion_control); + ret = _z_write(zs._val, keyexpr, NULL, 0, z_encoding_default(), Z_SAMPLE_KIND_DELETE, opt.congestion_control, + opt.priority); return ret; } @@ -661,7 +657,7 @@ void __z_reply_handler(_z_reply_t *reply, __z_reply_handler_wrapper_t *wrapped_c 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 + z_reply_drop(&oreply); // user_call is allowed to take ownership of the reply by setting oreply._value to NULL } int8_t z_get(z_session_t zs, z_keyexpr_t keyexpr, const char *parameters, z_owned_closure_reply_t *callback, @@ -717,7 +713,7 @@ z_owned_keyexpr_t z_declare_keyexpr(z_session_t zs, z_keyexpr_t keyexpr) { key._value = (z_keyexpr_t *)z_malloc(sizeof(z_keyexpr_t)); if (key._value != NULL) { - _z_zint_t id = _z_declare_resource(zs._val, keyexpr); + uint16_t id = _z_declare_resource(zs._val, keyexpr); *key._value = _z_rid_with_suffix(id, NULL); } @@ -746,9 +742,9 @@ z_owned_publisher_t z_declare_publisher(z_session_t zs, z_keyexpr_t keyexpr, con #if Z_MULTICAST_TRANSPORT == 1 if (zs._val->_tp._type != _Z_TRANSPORT_MULTICAST_TYPE) { #endif // Z_MULTICAST_TRANSPORT == 1 - _z_resource_t *r = _z_get_resource_by_key(zs._val, _Z_RESOURCE_IS_LOCAL, &keyexpr); + _z_resource_t *r = _z_get_resource_by_key(zs._val, &keyexpr); if (r == NULL) { - _z_zint_t id = _z_declare_resource(zs._val, keyexpr); + uint16_t id = _z_declare_resource(zs._val, keyexpr); key = _z_rid_with_suffix(id, NULL); } #if Z_MULTICAST_TRANSPORT == 1 @@ -791,7 +787,7 @@ int8_t z_publisher_put(const z_publisher_t pub, const uint8_t *payload, size_t l } ret = _z_write(pub._val->_zn, pub._val->_key, payload, len, opt.encoding, Z_SAMPLE_KIND_PUT, - pub._val->_congestion_control); + pub._val->_congestion_control, pub._val->_priority); return ret; } @@ -799,7 +795,7 @@ int8_t z_publisher_put(const z_publisher_t pub, const uint8_t *payload, size_t l 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, pub._val->_key, NULL, 0, z_encoding_default(), Z_SAMPLE_KIND_DELETE, - pub._val->_congestion_control); + pub._val->_congestion_control, pub._val->_priority); } z_subscriber_options_t z_subscriber_options_default(void) { @@ -822,10 +818,20 @@ z_owned_subscriber_t z_declare_subscriber(z_session_t zs, z_keyexpr_t keyexpr, z #if Z_MULTICAST_TRANSPORT == 1 if (zs._val->_tp._type != _Z_TRANSPORT_MULTICAST_TYPE) { #endif // Z_MULTICAST_TRANSPORT == 1 - _z_resource_t *r = _z_get_resource_by_key(zs._val, _Z_RESOURCE_IS_LOCAL, &keyexpr); + _z_resource_t *r = _z_get_resource_by_key(zs._val, &keyexpr); if (r == NULL) { - _z_zint_t id = _z_declare_resource(zs._val, keyexpr); - key = _z_rid_with_suffix(id, NULL); + char *wild = strpbrk(keyexpr._suffix, "*$"); + if (wild != NULL && wild != keyexpr._suffix) { + wild -= 1; + size_t len = wild - keyexpr._suffix; + char *suffix = z_malloc(len + 1); + memcpy(suffix, keyexpr._suffix, len); + suffix[len] = 0; + keyexpr._suffix = suffix; + _z_keyexpr_set_owns_suffix(&keyexpr, true); + } + uint16_t id = _z_declare_resource(zs._val, keyexpr); + key = _z_rid_with_suffix(id, wild); } #if Z_MULTICAST_TRANSPORT == 1 } @@ -849,9 +855,9 @@ z_owned_pull_subscriber_t z_declare_pull_subscriber(z_session_t zs, z_keyexpr_t callback->context = NULL; z_keyexpr_t key = keyexpr; - _z_resource_t *r = _z_get_resource_by_key(zs._val, _Z_RESOURCE_IS_LOCAL, &keyexpr); + _z_resource_t *r = _z_get_resource_by_key(zs._val, &keyexpr); if (r == NULL) { - _z_zint_t id = _z_declare_resource(zs._val, keyexpr); + uint16_t id = _z_declare_resource(zs._val, keyexpr); key = _z_rid_with_suffix(id, NULL); } @@ -901,9 +907,9 @@ z_owned_queryable_t z_declare_queryable(z_session_t zs, z_keyexpr_t keyexpr, z_o #if Z_MULTICAST_TRANSPORT == 1 if (zs._val->_tp._type != _Z_TRANSPORT_MULTICAST_TYPE) { #endif // Z_MULTICAST_TRANSPORT == 1 - _z_resource_t *r = _z_get_resource_by_key(zs._val, _Z_RESOURCE_IS_LOCAL, &keyexpr); + _z_resource_t *r = _z_get_resource_by_key(zs._val, &keyexpr); if (r == NULL) { - _z_zint_t id = _z_declare_resource(zs._val, keyexpr); + uint16_t id = _z_declare_resource(zs._val, keyexpr); key = _z_rid_with_suffix(id, NULL); } #if Z_MULTICAST_TRANSPORT == 1 @@ -934,8 +940,15 @@ z_query_reply_options_t z_query_reply_options_default(void) { 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) { - (void)(options); - return _z_send_reply(query, keyexpr, payload, payload_len); + 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, keyexpr, value); } _Bool z_reply_is_ok(const z_owned_reply_t *reply) { diff --git a/src/collections/bytes.c b/src/collections/bytes.c index 49643b827..d2a8939b0 100644 --- a/src/collections/bytes.c +++ b/src/collections/bytes.c @@ -78,7 +78,8 @@ void _z_bytes_free(_z_bytes_t **bs) { } 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 + 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); } @@ -99,3 +100,8 @@ _z_bytes_t _z_bytes_duplicate(const _z_bytes_t *src) { } _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; +} diff --git a/src/collections/vec.c b/src/collections/vec.c index d4e73b4bb..20afff6ca 100644 --- a/src/collections/vec.c +++ b/src/collections/vec.c @@ -20,14 +20,13 @@ /*-------- vec --------*/ _z_vec_t _z_vec_make(size_t capacity) { - _z_vec_t v; - v._val = (void **)z_malloc(sizeof(void *) * capacity); + _z_vec_t v = {._capacity = capacity, ._len = 0, ._val = NULL}; + if (capacity != 0) { + v._val = (void **)z_malloc(sizeof(void *) * capacity); + } if (v._val != NULL) { v._capacity = capacity; - } else { - v._capacity = 0; } - v._len = 0; return v; } diff --git a/src/link/link.c b/src/link/link.c index a70f2b9f5..5c409e353 100644 --- a/src/link/link.c +++ b/src/link/link.c @@ -148,8 +148,8 @@ size_t _z_link_recv_exact_zbuf(const _z_link_t *link, _z_zbuf_t *zbf, size_t len int8_t _z_link_send_wbuf(const _z_link_t *link, const _z_wbuf_t *wbf) { int8_t ret = _Z_RES_OK; - - for (size_t i = 0; (i < _z_wbuf_len_iosli(wbf)) || (ret == -1); i++) { + _Bool link_is_streamed = _Z_LINK_IS_STREAMED(link->_capabilities); + 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)); size_t n = bs.len; do { @@ -158,6 +158,10 @@ int8_t _z_link_send_wbuf(const _z_link_t *link, const _z_wbuf_t *wbf) { ret = _Z_ERR_TRANSPORT_TX_FAILED; break; } + if (link_is_streamed && wb != n) { + ret = _Z_ERR_TRANSPORT_TX_FAILED; + break; + } n = n - wb; bs.start = bs.start + (bs.len - n); } while (n > (size_t)0); diff --git a/src/net/memory.c b/src/net/memory.c index 23eb9b0cf..1b90e7f55 100644 --- a/src/net/memory.c +++ b/src/net/memory.c @@ -15,6 +15,8 @@ #include +#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 @@ -48,9 +50,6 @@ void _z_sample_free(_z_sample_t **sample) { } void _z_hello_clear(_z_hello_t *hello) { - if (hello->zid.len > 0) { - _z_bytes_clear(&hello->zid); - } if (hello->locators.len > 0) { _z_str_array_clear(&hello->locators); } @@ -69,7 +68,7 @@ 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); - _z_bytes_clear(&reply_data->replier_id); + reply_data->replier_id = _z_id_empty(); } void _z_reply_data_free(_z_reply_data_t **reply_data) { @@ -82,3 +81,19 @@ void _z_reply_data_free(_z_reply_data_t **reply_data) { *reply_data = NULL; } } + +void _z_value_clear(_z_value_t *value) { + _z_bytes_clear(&value->encoding.suffix); + _z_bytes_clear(&value->payload); +} + +void _z_value_free(_z_value_t **value) { + _z_value_t *ptr = *value; + + if (ptr != NULL) { + _z_value_clear(ptr); + + z_free(ptr); + *value = NULL; + } +} \ No newline at end of file diff --git a/src/net/primitives.c b/src/net/primitives.c index b28f82efa..374e52b0d 100644 --- a/src/net/primitives.c +++ b/src/net/primitives.c @@ -14,26 +14,35 @@ #include "zenoh-pico/net/primitives.h" #include +#include +#include +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/config.h" #include "zenoh-pico/net/logger.h" #include "zenoh-pico/net/memory.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/query.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" #include "zenoh-pico/session/subscription.h" #include "zenoh-pico/session/utils.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" /*------------------ Scouting ------------------*/ -void _z_scout(const z_whatami_t what, const char *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, locator, timeout, false); +void _z_scout(const z_what_t what, const _z_id_t zid, const char *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); // callback takes ownership of hello } if (dropper != NULL) { @@ -42,51 +51,44 @@ void _z_scout(const z_whatami_t what, const char *locator, const uint32_t timeou } /*------------------ Resource Declaration ------------------*/ -_z_zint_t _z_declare_resource(_z_session_t *zn, _z_keyexpr_t keyexpr) { - _z_zint_t ret = Z_RESOURCE_ID_NONE; +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 - - _z_resource_t *r = (_z_resource_t *)z_malloc(sizeof(_z_resource_t)); - if (r != NULL) { - r->_id = _z_get_resource_id(zn); - r->_key = _z_keyexpr_duplicate(&keyexpr); - if (_z_register_resource(zn, _Z_RESOURCE_IS_LOCAL, r) == _Z_RES_OK) { - // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_resource(r->_id, _z_keyexpr_duplicate(&keyexpr)); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { - ret = r->_id; - } else { - _z_unregister_resource(zn, _Z_RESOURCE_IS_LOCAL, r); - } - _z_msg_clear(&z_msg); + 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); + if (_z_send_n_msg(zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { + ret = id; } else { - _z_resource_free(&r); + _z_unregister_resource(zn, id, _Z_KEYEXPR_MAPPING_LOCAL); } + _z_n_msg_clear(&n_msg); } } return ret; } -int8_t _z_undeclare_resource(_z_session_t *zn, const _z_zint_t rid) { +int8_t _z_undeclare_resource(_z_session_t *zn, uint16_t rid) { int8_t ret = _Z_RES_OK; - - _z_resource_t *r = _z_get_resource_by_id(zn, _Z_RESOURCE_IS_LOCAL, rid); + _Z_DEBUG("Undeclaring local keyexpr %d\n", rid); + _z_resource_t *r = _z_get_resource_by_id(zn, _Z_KEYEXPR_MAPPING_LOCAL, rid); if (r != NULL) { // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_forget_resource(rid); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { - _z_unregister_resource(zn, _Z_RESOURCE_IS_LOCAL, r); // Only if message is send, local resource is removed + _z_declaration_t declaration = _z_make_undecl_keyexpr(rid); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); + 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 } else { ret = _Z_ERR_TRANSPORT_TX_FAILED; } - _z_msg_clear(&z_msg); + _z_n_msg_clear(&n_msg); } else { ret = _Z_ERR_KEYEXPR_UNKNOWN; } @@ -100,39 +102,26 @@ _z_publisher_t *_z_declare_publisher(_z_session_t *zn, _z_keyexpr_t keyexpr, z_c _z_publisher_t *ret = (_z_publisher_t *)z_malloc(sizeof(_z_publisher_t)); if (ret != NULL) { ret->_zn = zn; - ret->_key = _z_keyexpr_duplicate(&keyexpr); + ret->_key = _z_keyexpr_duplicate(keyexpr); ret->_id = _z_get_entity_id(zn); ret->_congestion_control = congestion_control; ret->_priority = priority; // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_publisher(_z_keyexpr_duplicate(&keyexpr)); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - // ret = _Z_ERR_TRANSPORT_TX_FAILED; - _z_publisher_free(&ret); - } - _z_msg_clear(&z_msg); + _z_declare_resource(zn, keyexpr); } return ret; } int8_t _z_undeclare_publisher(_z_publisher_t *pub) { - int8_t ret = _Z_ERR_GENERIC; + int8_t ret = _Z_RES_OK; if (pub != NULL) { - ret = _Z_RES_OK; - // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_forget_publisher(_z_keyexpr_duplicate(&pub->_key)); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(pub->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { - ret = _Z_ERR_TRANSPORT_TX_FAILED; - } - _z_msg_clear(&z_msg); + _z_undeclare_resource(pub->_zn, pub->_key._id); + } else { + ret = _Z_ERR_ENTITY_UNKNOWN; } return ret; @@ -143,7 +132,7 @@ _z_subscriber_t *_z_declare_subscriber(_z_session_t *zn, _z_keyexpr_t keyexpr, _ _z_data_handler_t callback, _z_drop_handler_t dropper, void *arg) { _z_subscription_t s; s._id = _z_get_entity_id(zn); - s._key = _z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_LOCAL, &keyexpr); + s._key = _z_get_expanded_key_from_key(zn, &keyexpr); s._info = sub_info; s._callback = callback; s._dropper = dropper; @@ -152,22 +141,22 @@ _z_subscriber_t *_z_declare_subscriber(_z_session_t *zn, _z_keyexpr_t keyexpr, _ _z_subscriber_t *ret = (_z_subscriber_t *)z_malloc(sizeof(_z_subscriber_t)); if (ret != NULL) { ret->_zn = zn; - ret->_id = s._id; + ret->_entity_id = s._id; _z_subscription_sptr_t *sp_s = _z_register_subscription( zn, _Z_RESOURCE_IS_LOCAL, &s); // This a pointer to the entry stored at session-level. // Do not drop it by the end of this function. if (sp_s != NULL) { // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_subscriber(_z_keyexpr_duplicate(&keyexpr), sub_info); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _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, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { // ret = _Z_ERR_TRANSPORT_TX_FAILED; _z_unregister_subscription(zn, _Z_RESOURCE_IS_LOCAL, sp_s); _z_subscriber_free(&ret); } - _z_msg_clear(&z_msg); + _z_n_msg_clear(&n_msg); } else { _z_subscriber_free(&ret); } @@ -182,25 +171,25 @@ int8_t _z_undeclare_subscriber(_z_subscriber_t *sub) { int8_t ret = _Z_ERR_GENERIC; if (sub != NULL) { - ret = _Z_RES_OK; - - _z_subscription_sptr_t *s = _z_get_subscription_by_id(sub->_zn, _Z_RESOURCE_IS_LOCAL, sub->_id); + _z_subscription_sptr_t *s = _z_get_subscription_by_id(sub->_zn, _Z_RESOURCE_IS_LOCAL, sub->_entity_id); if (s != NULL) { // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_forget_subscriber(_z_keyexpr_duplicate(&s->ptr->_key)); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(sub->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { + _z_declaration_t declaration = _z_make_undecl_subscriber(sub->_entity_id, &s->ptr->_key); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); + if (_z_send_n_msg(sub->_zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { // Only if message is successfully send, local subscription state can be removed _z_unregister_subscription(sub->_zn, _Z_RESOURCE_IS_LOCAL, s); } else { - ret = _Z_ERR_TRANSPORT_TX_FAILED; + ret = _Z_ERR_ENTITY_UNKNOWN; } - _z_msg_clear(&z_msg); + _z_n_msg_clear(&n_msg); } else { ret = _Z_ERR_ENTITY_UNKNOWN; } + } else { + ret = _Z_ERR_ENTITY_UNKNOWN; } + return ret; } @@ -209,7 +198,7 @@ _z_queryable_t *_z_declare_queryable(_z_session_t *zn, _z_keyexpr_t keyexpr, _Bo _z_questionable_handler_t callback, _z_drop_handler_t dropper, void *arg) { _z_questionable_t q; q._id = _z_get_entity_id(zn); - q._key = _z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_LOCAL, &keyexpr); + q._key = _z_get_expanded_key_from_key(zn, &keyexpr); q._complete = complete; q._callback = callback; q._dropper = dropper; @@ -218,23 +207,22 @@ _z_queryable_t *_z_declare_queryable(_z_session_t *zn, _z_keyexpr_t keyexpr, _Bo _z_queryable_t *ret = (_z_queryable_t *)z_malloc(sizeof(_z_queryable_t)); if (ret != NULL) { ret->_zn = zn; - ret->_id = q._id; + ret->_entity_id = q._id; _z_questionable_sptr_t *sp_q = _z_register_questionable(zn, &q); // This a pointer to the entry stored at session-level. // Do not drop it by the end of this function. if (sp_q != NULL) { // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_queryable(_z_keyexpr_duplicate(&keyexpr), q._complete, - _Z_QUERYABLE_DISTANCE_DEFAULT); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _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, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { // ret = _Z_ERR_TRANSPORT_TX_FAILED; _z_unregister_questionable(zn, sp_q); _z_queryable_free(&ret); } - _z_msg_clear(&z_msg); + _z_n_msg_clear(&n_msg); } else { _z_queryable_free(&ret); } @@ -246,39 +234,40 @@ _z_queryable_t *_z_declare_queryable(_z_session_t *zn, _z_keyexpr_t keyexpr, _Bo } int8_t _z_undeclare_queryable(_z_queryable_t *qle) { - int8_t ret = _Z_ERR_GENERIC; + int8_t ret = _Z_RES_OK; if (qle != NULL) { - _z_questionable_sptr_t *q = _z_get_questionable_by_id(qle->_zn, qle->_id); + _z_questionable_sptr_t *q = _z_get_questionable_by_id(qle->_zn, qle->_entity_id); if (q != NULL) { - ret = _Z_RES_OK; // Build the declare message to send on the wire - _z_declaration_array_t declarations = _z_declaration_array_make(1); - declarations._val[0] = _z_msg_make_declaration_forget_queryable(_z_keyexpr_duplicate(&q->ptr->_key)); - _z_zenoh_message_t z_msg = _z_msg_make_declare(declarations); - if (_z_send_z_msg(qle->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { + _z_declaration_t declaration = _z_make_undecl_queryable(qle->_entity_id, &q->ptr->_key); + _z_network_message_t n_msg = _z_n_msg_make_declare(declaration); + if (_z_send_n_msg(qle->_zn, &n_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) == _Z_RES_OK) { // Only if message is successfully send, local queryable state can be removed _z_unregister_questionable(qle->_zn, q); } else { ret = _Z_ERR_TRANSPORT_TX_FAILED; } - _z_msg_clear(&z_msg); + _z_n_msg_clear(&n_msg); + } else { ret = _Z_ERR_ENTITY_UNKNOWN; } + } else { + ret = _Z_ERR_ENTITY_UNKNOWN; } return ret; } -int8_t _z_send_reply(const z_query_t *query, _z_keyexpr_t keyexpr, const uint8_t *payload, const size_t len) { +int8_t _z_send_reply(const z_query_t *query, _z_keyexpr_t keyexpr, const _z_value_t payload) { int8_t ret = _Z_RES_OK; _z_keyexpr_t q_ke; _z_keyexpr_t r_ke; if (query->_anyke == false) { - q_ke = _z_get_expanded_key_from_key(query->_zn, _Z_RESOURCE_IS_LOCAL, &query->_key); - r_ke = _z_get_expanded_key_from_key(query->_zn, _Z_RESOURCE_IS_LOCAL, &keyexpr); + 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) { ret = _Z_ERR_KEYEXPR_NOT_MATCH; } @@ -288,20 +277,30 @@ int8_t _z_send_reply(const z_query_t *query, _z_keyexpr_t keyexpr, const uint8_t if (ret == _Z_RES_OK) { // Build the reply context decorator. This is NOT the final reply. - _z_bytes_t zid = - _z_bytes_wrap(((_z_session_t *)query->_zn)->_local_zid.start, ((_z_session_t *)query->_zn)->_local_zid.len); - _z_reply_context_t *rctx = _z_msg_make_reply_context(query->_qid, zid, false); - - _z_data_info_t di = {._flags = 0}; // Empty data info - _z_payload_t pld = {.len = len, .start = payload}; // Payload - _Bool can_be_dropped = false; // Congestion control - _z_zenoh_message_t z_msg = _z_msg_make_reply(keyexpr, di, pld, can_be_dropped, rctx); - - if (_z_send_z_msg(query->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_id_t zid = ((_z_session_t *)query->_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) { ret = _Z_ERR_TRANSPORT_TX_FAILED; } - z_free(rctx); + // Freeing z_msg is unnecessary, as all of its components are aliased } return ret; @@ -309,24 +308,51 @@ int8_t _z_send_reply(const z_query_t *query, _z_keyexpr_t keyexpr, const uint8_t /*------------------ 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) { + const _z_encoding_t encoding, const z_sample_kind_t kind, const z_congestion_control_t cong_ctrl, + z_priority_t priority) { int8_t ret = _Z_RES_OK; + _z_network_message_t msg; + switch (kind) { + case Z_SAMPLE_KIND_PUT: + msg = (_z_network_message_t){ + ._tag = _Z_N_PUSH, + ._body._push = + { + ._key = keyexpr, + ._qos = _z_n_qos_make(0, 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, + }, + }, + }; + break; + case Z_SAMPLE_KIND_DELETE: + msg = (_z_network_message_t){ + ._tag = _Z_N_PUSH, + ._body._push = + { + ._key = keyexpr, + ._qos = _z_n_qos_make(0, cong_ctrl == Z_CONGESTION_CONTROL_BLOCK, priority), + ._timestamp = _z_timestamp_null(), + ._body._is_put = false, + ._body._body._del = {._commons = {._timestamp = _z_timestamp_null(), + ._source_info = _z_source_info_null()}}, + }, + }; + break; + } - // @TODO: accept `const z_priority_t priority` as additional parameter - - // Data info - _z_data_info_t info = {._flags = 0, ._encoding = encoding, ._kind = kind}; - _Z_SET_FLAG(info._flags, _Z_DATA_INFO_ENC); - _Z_SET_FLAG(info._flags, _Z_DATA_INFO_KIND); - - _z_payload_t pld = {.len = len, .start = payload}; // Payload - _Bool can_be_dropped = cong_ctrl == Z_CONGESTION_CONTROL_DROP; // Congestion control - _z_zenoh_message_t z_msg = _z_msg_make_data(keyexpr, info, pld, can_be_dropped); - - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, cong_ctrl) != _Z_RES_OK) { + if (_z_send_n_msg(zn, &msg, Z_RELIABILITY_RELIABLE, cong_ctrl) != _Z_RES_OK) { ret = _Z_ERR_TRANSPORT_TX_FAILED; } + // Freeing z_msg is unnecessary, as all of its components are aliased + return ret; } @@ -340,7 +366,7 @@ int8_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, _z_pending_query_t *pq = (_z_pending_query_t *)z_malloc(sizeof(_z_pending_query_t)); if (pq != NULL) { pq->_id = _z_get_query_id(zn); - pq->_key = _z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_LOCAL, &keyexpr); + pq->_key = _z_get_expanded_key_from_key(zn, &keyexpr); pq->_parameters = _z_str_clone(parameters); pq->_target = target; pq->_consolidation = consolidation; @@ -353,10 +379,10 @@ int8_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, ret = _z_register_pending_query(zn, pq); // Add the pending query to the current session if (ret == _Z_RES_OK) { - _z_zenoh_message_t z_msg = - _z_msg_make_query(keyexpr, pq->_parameters, pq->_id, pq->_target, pq->_consolidation, value); + _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); - if (_z_send_z_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, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { _z_unregister_pending_query(zn, pq); ret = _Z_ERR_TRANSPORT_TX_FAILED; } @@ -372,14 +398,11 @@ int8_t _z_query(_z_session_t *zn, _z_keyexpr_t keyexpr, const char *parameters, int8_t _z_subscriber_pull(const _z_subscriber_t *sub) { int8_t ret = _Z_RES_OK; - _z_subscription_sptr_t *s = _z_get_subscription_by_id(sub->_zn, _Z_RESOURCE_IS_LOCAL, sub->_id); + _z_subscription_sptr_t *s = _z_get_subscription_by_id(sub->_zn, _Z_RESOURCE_IS_LOCAL, sub->_entity_id); if (s != NULL) { _z_zint_t pull_id = _z_get_pull_id(sub->_zn); - _z_zint_t max_samples = 0; // @TODO: get the correct value for max_sample - _Bool is_final = true; - _z_zenoh_message_t z_msg = _z_msg_make_pull(s->ptr->_key, pull_id, max_samples, is_final); - - if (_z_send_z_msg(sub->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_zenoh_message_t z_msg = _z_msg_make_pull(_z_keyexpr_alias(s->ptr->_key), pull_id); + if (_z_send_n_msg(sub->_zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { ret = _Z_ERR_TRANSPORT_TX_FAILED; } } else { diff --git a/src/net/publish.c b/src/net/publish.c index 97f33ba13..7ef50abd2 100644 --- a/src/net/publish.c +++ b/src/net/publish.c @@ -16,8 +16,6 @@ #include -#include "zenoh-pico/protocol/msg.h" - void _z_publisher_clear(_z_publisher_t *pub) { _z_keyexpr_clear(&pub->_key); } void _z_publisher_free(_z_publisher_t **pub) { diff --git a/src/net/resource.c b/src/net/resource.c deleted file mode 100644 index 8ce48333f..000000000 --- a/src/net/resource.c +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/net/resource.h" - -#include - -_z_keyexpr_t _z_rname(const char *rname) { - _z_keyexpr_t rk; - rk._id = Z_RESOURCE_ID_NONE; - rk._suffix = NULL; - if (rname != NULL) { - rk._suffix = rname; - } - - return rk; -} - -_z_keyexpr_t _z_rid_with_suffix(_z_zint_t rid, const char *suffix) { - _z_keyexpr_t rk; - rk._id = rid; - rk._suffix = NULL; - if (suffix != NULL) { - rk._suffix = _z_str_clone(suffix); - } - - return rk; -} diff --git a/src/net/session.c b/src/net/session.c index 76f0e9656..cf1f73407 100644 --- a/src/net/session.c +++ b/src/net/session.c @@ -16,32 +16,33 @@ #include #include +#include "zenoh-pico/collections/bytes.h" #include "zenoh-pico/net/memory.h" +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/link/task/join.h" #include "zenoh-pico/transport/link/task/lease.h" #include "zenoh-pico/transport/link/task/read.h" #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 ret = _Z_RES_OK; - _z_bytes_t local_zid = _z_bytes_empty(); - + _z_id_t local_zid = _z_id_empty(); #if Z_UNICAST_TRANSPORT == 1 || Z_MULTICAST_TRANSPORT == 1 ret = _z_session_generate_zid(&local_zid, Z_ZID_LENGTH); if (ret == _Z_RES_OK) { ret = _z_new_transport(&zn->_tp, &local_zid, locator, mode); if (ret != _Z_RES_OK) { - _z_bytes_clear(&local_zid); + local_zid = _z_id_empty(); } } else { - _z_bytes_clear(&local_zid); + local_zid = _z_id_empty(); } #else ret = _Z_ERR_TRANSPORT_NOT_AVAILABLE; #endif - if (ret == _Z_RES_OK) { ret = _z_session_init(zn, &local_zid); } @@ -52,14 +53,20 @@ int8_t __z_open_inner(_z_session_t *zn, char *locator, z_whatami_t mode) { int8_t _z_open(_z_session_t *zn, _z_config_t *config) { int8_t ret = _Z_RES_OK; + _z_id_t zid = _z_id_empty(); + char *opt_as_str = _z_config_get(config, Z_CONFIG_SESSION_ZID_KEY); + if (opt_as_str != NULL) { + _z_uuid_to_bytes(zid.id, opt_as_str); + } + if (config != NULL) { _z_str_array_t locators = _z_str_array_empty(); if (_z_config_get(config, Z_CONFIG_PEER_KEY) == NULL) { // Scout if peer is not configured - char *opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_WHAT_KEY); + opt_as_str = _z_config_get(config, Z_CONFIG_SCOUTING_WHAT_KEY); if (opt_as_str == NULL) { opt_as_str = Z_CONFIG_SCOUTING_WHAT_DEFAULT; } - z_whatami_t what = strtol(opt_as_str, NULL, 10); + z_what_t what = strtol(opt_as_str, NULL, 10); opt_as_str = _z_config_get(config, Z_CONFIG_MULTICAST_LOCATOR_KEY); if (opt_as_str == NULL) { @@ -74,7 +81,7 @@ int8_t _z_open(_z_session_t *zn, _z_config_t *config) { uint32_t timeout = strtoul(opt_as_str, NULL, 10); // Scout and return upon the first result - _z_hello_list_t *hellos = _z_scout_inner(what, 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); @@ -118,6 +125,7 @@ int8_t _z_open(_z_session_t *zn, _z_config_t *config) { _z_str_array_clear(&locators); } else { _Z_ERROR("A valid config is missing.\n"); + ret = _Z_ERR_GENERIC; } return ret; @@ -129,12 +137,14 @@ _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); - _zp_config_insert(ps, Z_INFO_PID_KEY, _z_string_from_bytes(&zn->_local_zid)); + _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)); #if Z_UNICAST_TRANSPORT == 1 if (zn->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { - _zp_config_insert(ps, Z_INFO_ROUTER_PID_KEY, - _z_string_from_bytes(&zn->_tp._transport._unicast._remote_zid)); + _z_id_t remote_zid = zn->_tp._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)); } else #endif // Z_UNICAST_TRANSPORT == 1 #if Z_MULTICAST_TRANSPORT == 1 @@ -142,7 +152,8 @@ _z_config_t *_z_info(const _z_session_t *zn) { _z_transport_peer_entry_list_t *xs = zn->_tp._transport._multicast._peers; while (xs != NULL) { _z_transport_peer_entry_t *peer = _z_transport_peer_entry_list_head(xs); - _zp_config_insert(ps, Z_INFO_PEER_PID_KEY, _z_string_from_bytes(&peer->_remote_zid)); + _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)); xs = _z_transport_peer_entry_list_tail(xs); } diff --git a/src/protocol/codec.c b/src/protocol/codec.c index d1c5c9ec1..e05d7ba28 100644 --- a/src/protocol/codec.c +++ b/src/protocol/codec.c @@ -14,12 +14,16 @@ #include "zenoh-pico/protocol/codec.h" +#include + +#include "zenoh-pico/protocol/core.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_EC(_z_uint_encode(buf, tp->origin)) - _Z_EC(_z_uint_encode(buf, tp->period)) + _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); } @@ -102,7 +106,7 @@ int8_t _z_uint_encode(_z_wbuf_t *wbf, unsigned int uint) { while (lv > (unsigned int)0x7f) { uint8_t c = (uint8_t)(lv & (unsigned int)0x7f) | (uint8_t)0x80; - _Z_EC(_z_wbuf_write(wbf, c)) + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) lv = lv >> (unsigned int)7; } @@ -144,12 +148,34 @@ int8_t _z_uint8_decode(uint8_t *u8, _z_zbuf_t *zbf) { return ret; } +int8_t _z_uint16_encode(_z_wbuf_t *wbf, uint16_t u16) { + int8_t ret = _Z_RES_OK; + + ret |= _z_wbuf_write(wbf, ((u16 >> 8) & 0xFF)); + ret |= _z_wbuf_write(wbf, (u16 & 0xFF)); + + return ret; +} + +int8_t _z_uint16_decode(uint16_t *u16, _z_zbuf_t *zbf) { + int8_t ret = _Z_RES_OK; + *u16 = 0; + + uint8_t u8; + ret |= _z_uint8_decode(&u8, zbf); + *u16 |= u8 << 8; + ret |= _z_uint8_decode(&u8, zbf); + *u16 |= u8; + + 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_EC(_z_wbuf_write(wbf, c)) + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) lv = lv >> (_z_zint_t)7; } @@ -176,19 +202,60 @@ int8_t _z_uint64_decode(uint64_t *u64, _z_zbuf_t *zbf) { } /*------------------ z_zint ------------------*/ +uint8_t _z_zint_len(_z_zint_t v) { + uint8_t len = 1; + while (v > 0x7f) { + v >>= 7; + len++; + } + return len; +} 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_EC(_z_wbuf_write(wbf, c)) + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, c)) lv = lv >> (_z_zint_t)7; } uint8_t c = lv & 0xff; return _z_wbuf_write(wbf, c); } +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; + } + uint8_t c = lv & 0xff; + return _z_wbuf_write(wbf, c); +} +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)); + if (buf <= UINT16_MAX) { + *zint = (uint16_t)buf; + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + 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)); + if (buf <= UINT32_MAX) { + *zint = (uint32_t)buf; + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + return ret; +} int8_t _z_zint_decode(_z_zint_t *zint, _z_zbuf_t *zbf) { int8_t ret = _Z_RES_OK; *zint = 0; @@ -206,14 +273,31 @@ int8_t _z_zint_decode(_z_zint_t *zint, _z_zbuf_t *zbf) { 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; +} /*------------------ uint8_array ------------------*/ -int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { +int8_t _z_bytes_val_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { int8_t ret = _Z_RES_OK; - _Z_EC(_z_zint_encode(wbf, bs->len)) - if ((wbf->_is_expandable == true) && (bs->len > Z_TSID_LENGTH)) { - ret |= _z_wbuf_wrap_bytes(wbf, bs->start, 0, bs->len); + if ((wbf->_expansion_step != 0) && (bs->len > Z_TSID_LENGTH)) { + // ret |= _z_wbuf_wrap_bytes(wbf, bs->start, 0, bs->len); + ret |= _z_wbuf_write_bytes(wbf, bs->start, 0, bs->len); } else { ret |= _z_wbuf_write_bytes(wbf, bs->start, 0, bs->len); } @@ -221,10 +305,19 @@ int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_t *bs) { return ret; } -int8_t _z_bytes_decode_na(_z_bytes_t *bs, _z_zbuf_t *zbf) { +int8_t _z_bytes_encode(_z_wbuf_t *wbf, const _z_bytes_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)) + + 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 ret = _Z_RES_OK; - ret |= _z_zint_decode(&bs->len, zbf); if (ret == _Z_RES_OK) { if (_z_zbuf_len(zbf) >= bs->len) { // Check if we have enought bytes to read *bs = _z_bytes_wrap(_z_zbuf_get_rptr(zbf), bs->len); // Decode without allocating @@ -243,12 +336,23 @@ int8_t _z_bytes_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; + + ret |= _z_zint_decode(&bs->len, zbf); + ret |= _z_bytes_val_decode_na(bs, zbf); + + return ret; +} + +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_decode(_z_bytes_t *bs, _z_zbuf_t *zbf) { return _z_bytes_decode_na(bs, zbf); } /*------------------ string with null terminator ------------------*/ int8_t _z_str_encode(_z_wbuf_t *wbf, const char *s) { size_t len = strlen(s); - _Z_EC(_z_zint_encode(wbf, len)) + _Z_RETURN_IF_ERR(_z_zint_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); } diff --git a/src/protocol/codec/core.c b/src/protocol/codec/core.c new file mode 100644 index 000000000..403c28d8c --- /dev/null +++ b/src/protocol/codec/core.c @@ -0,0 +1,10 @@ +#include "zenoh-pico/protocol/codec/core.h" + +#include "zenoh-pico/protocol/iobuf.h" +int8_t _z_zbuf_read_exact(_z_zbuf_t *zbf, uint8_t *dest, size_t length) { + if (length > _z_zbuf_len(zbf)) { + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + _z_zbuf_read_bytes(zbf, dest, 0, length); + return _Z_RES_OK; +} \ No newline at end of file diff --git a/src/protocol/codec/declarations.c b/src/protocol/codec/declarations.c new file mode 100644 index 000000000..7e474fb6a --- /dev/null +++ b/src/protocol/codec/declarations.c @@ -0,0 +1,415 @@ +// +// 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/protocol/codec/declarations.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/declarations.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" + +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 = _z_keyexpr_has_suffix(ke) ? strlen(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_uint8_encode(wbf, header)); + _Z_RETURN_IF_ERR(_z_zint_encode(wbf, ke._id)); + if (kelen) { + _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, (const uint8_t *)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); + 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_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); + if (has_extensions) { + header |= _Z_FLAG_Z_Z; + } + if (has_kesuffix) { + header |= _Z_DECL_SUBSCRIBER_FLAG_N; + } + if (_z_keyexpr_is_local(&keyexpr)) { + header |= _Z_DECL_SUBSCRIBER_FLAG_M; + } + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); + _Z_RETURN_IF_ERR(_z_zint_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; + _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))); + } + + 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); +} +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); + 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)); + if (has_keyexpr_ext) { + _Z_RETURN_IF_ERR(_z_decl_ext_keyexpr_encode(wbf, ke, false)); + } + return _Z_RES_OK; +} +int8_t _z_undecl_subscriber_encode(_z_wbuf_t *wbf, const _z_undecl_subscriber_t *decl) { + return _z_undecl_encode(wbf, _Z_UNDECL_SUBSCRIBER_MID, decl->_id, decl->_ext_keyexpr); +} +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); + _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)); + } + return _Z_RES_OK; +} +int8_t _z_undecl_queryable_encode(_z_wbuf_t *wbf, const _z_undecl_queryable_t *decl) { + return _z_undecl_encode(wbf, _Z_UNDECL_QUERYABLE_MID, decl->_id, decl->_ext_keyexpr); +} +int8_t _z_decl_token_encode(_z_wbuf_t *wbf, const _z_decl_token_t *decl) { + uint8_t header = _Z_DECL_TOKEN_MID; + _Z_RETURN_IF_ERR(_z_decl_commons_encode(wbf, header, false, decl->_id, decl->_keyexpr)); + return _Z_RES_OK; +} +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; + _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) { + case _Z_DECL_KEXPR: { + ret = _z_decl_kexpr_encode(wbf, &decl->_body._decl_kexpr); + } break; + case _Z_UNDECL_KEXPR: { + ret = _z_undecl_kexpr_encode(wbf, &decl->_body._undecl_kexpr); + } break; + case _Z_DECL_SUBSCRIBER: { + ret = _z_decl_subscriber_encode(wbf, &decl->_body._decl_subscriber); + } break; + case _Z_UNDECL_SUBSCRIBER: { + ret = _z_undecl_subscriber_encode(wbf, &decl->_body._undecl_subscriber); + } break; + case _Z_DECL_QUERYABLE: { + ret = _z_decl_queryable_encode(wbf, &decl->_body._decl_queryable); + } break; + case _Z_UNDECL_QUERYABLE: { + ret = _z_undecl_queryable_encode(wbf, &decl->_body._undecl_queryable); + } break; + case _Z_DECL_TOKEN: { + ret = _z_decl_token_encode(wbf, &decl->_body._decl_token); + } break; + 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); + } break; + } + return ret; +} +int8_t _z_decl_kexpr_decode(_z_decl_kexpr_t *decl, _z_zbuf_t *zbf, uint8_t header) { + *decl = _z_decl_kexpr_null(); + _Z_RETURN_IF_ERR(_z_zint16_decode(&decl->_id, zbf)); + _Z_RETURN_IF_ERR(_z_keyexpr_decode(&decl->_keyexpr, zbf, _Z_HAS_FLAG(header, _Z_DECL_KEXPR_FLAG_N))); + _z_keyexpr_set_mapping(&decl->_keyexpr, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x15)); + } + return _Z_RES_OK; +} +int8_t _z_undecl_kexpr_decode(_z_undecl_kexpr_t *decl, _z_zbuf_t *zbf, uint8_t header) { + *decl = _z_undecl_kexpr_null(); + _Z_RETURN_IF_ERR(_z_zint16_decode(&decl->_id, zbf)); + + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x10)); + } + return _Z_RES_OK; +} + +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 = &_zbf; + uint8_t header; + _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); + uint16_t mapping = _Z_HAS_FLAG(header, 2) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE : _Z_KEYEXPR_MAPPING_LOCAL; + _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) { + 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; + } else { + ke->_mapping = _z_keyexpr_mapping(mapping, false); + } + } break; + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + return _z_msg_ext_unknown_error(extension, 0x0e); + } + } + return _Z_RES_OK; +} +int8_t _z_undecl_trivial_decode(_z_zbuf_t *zbf, _z_keyexpr_t *_ext_keyexpr, uint32_t *decl_id, uint8_t header) { + _Z_RETURN_IF_ERR(_z_zint32_decode(decl_id, zbf)); + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_undecl_decode_extensions, _ext_keyexpr)); + } + return _Z_RES_OK; +} +int8_t _z_decl_commons_decode(_z_zbuf_t *zbf, uint8_t header, _Bool *has_extensions, uint32_t *id, _z_keyexpr_t *ke) { + *has_extensions = _Z_HAS_FLAG(header, _Z_FLAG_Z_Z); + uint16_t mapping = + _Z_HAS_FLAG(header, _Z_DECL_SUBSCRIBER_FLAG_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE : _Z_KEYEXPR_MAPPING_LOCAL; + _Z_RETURN_IF_ERR(_z_zint32_decode(id, zbf)); + _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)); + if (_z_zbuf_len(zbf) < len) { + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + ke->_suffix = z_malloc(len + 1); + if (ke->_suffix == NULL) { + 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; + } else { + ke->_suffix = NULL; + ke->_mapping = _z_keyexpr_mapping(mapping, false); + } + return _Z_RES_OK; +} +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: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + return _z_msg_ext_unknown_error(extension, 0x14); + } + } + return _Z_RES_OK; +} + +int8_t _z_decl_subscriber_decode(_z_decl_subscriber_t *decl, _z_zbuf_t *zbf, uint8_t header) { + _Bool has_ext; + *decl = _z_decl_subscriber_null(); + _Z_RETURN_IF_ERR(_z_decl_commons_decode(zbf, header, &has_ext, &decl->_id, &decl->_keyexpr)); + if (has_ext) { + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_decl_subscriber_decode_extensions, decl)); + } + return _Z_RES_OK; +} +int8_t _z_undecl_subscriber_decode(_z_undecl_subscriber_t *decl, _z_zbuf_t *zbf, uint8_t header) { + *decl = _z_undecl_subscriber_null(); + return _z_undecl_trivial_decode(zbf, &decl->_ext_keyexpr, &decl->_id, header); +} +int8_t _z_decl_queryable_decode_extensions(_z_msg_ext_t *extension, void *ctx) { + _z_decl_queryable_t *decl = (_z_decl_queryable_t *)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); + } break; + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + return _z_msg_ext_unknown_error(extension, 0x11); + } + } + return _Z_RES_OK; +} +int8_t _z_decl_queryable_decode(_z_decl_queryable_t *decl, _z_zbuf_t *zbf, uint8_t header) { + _Bool has_ext; + *decl = _z_decl_queryable_null(); + _Z_RETURN_IF_ERR(_z_decl_commons_decode(zbf, header, &has_ext, &decl->_id, &decl->_keyexpr)); + if (has_ext) { + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_decl_queryable_decode_extensions, decl)); + } + return _Z_RES_OK; +} +int8_t _z_undecl_queryable_decode(_z_undecl_queryable_t *decl, _z_zbuf_t *zbf, uint8_t header) { + *decl = _z_undecl_queryable_null(); + return _z_undecl_trivial_decode(zbf, &decl->_ext_keyexpr, &decl->_id, header); +} +int8_t _z_decl_token_decode(_z_decl_token_t *decl, _z_zbuf_t *zbf, uint8_t header) { + _Bool has_ext; + *decl = _z_decl_token_null(); + _Z_RETURN_IF_ERR(_z_decl_commons_decode(zbf, header, &has_ext, &decl->_id, &decl->_keyexpr)); + if (has_ext) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x12)); + } + return _Z_RES_OK; +} +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)); + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_skip_non_mandatories(zbf, 0x10)); + } + 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)); + switch (_Z_MID(header)) { + case _Z_DECL_KEXPR_MID: { + decl->_tag = _Z_DECL_KEXPR; + ret = _z_decl_kexpr_decode(&decl->_body._decl_kexpr, zbf, header); + } break; + case _Z_UNDECL_KEXPR_MID: { + decl->_tag = _Z_UNDECL_KEXPR; + ret = _z_undecl_kexpr_decode(&decl->_body._undecl_kexpr, zbf, header); + } break; + case _Z_DECL_SUBSCRIBER_MID: { + decl->_tag = _Z_DECL_SUBSCRIBER; + ret = _z_decl_subscriber_decode(&decl->_body._decl_subscriber, zbf, header); + } break; + case _Z_UNDECL_SUBSCRIBER_MID: { + decl->_tag = _Z_UNDECL_SUBSCRIBER; + ret = _z_undecl_subscriber_decode(&decl->_body._undecl_subscriber, zbf, header); + } break; + case _Z_DECL_QUERYABLE_MID: { + decl->_tag = _Z_DECL_QUERYABLE; + ret = _z_decl_queryable_decode(&decl->_body._decl_queryable, zbf, header); + } break; + case _Z_UNDECL_QUERYABLE_MID: { + decl->_tag = _Z_UNDECL_QUERYABLE; + ret = _z_undecl_queryable_decode(&decl->_body._undecl_queryable, zbf, header); + } break; + case _Z_DECL_TOKEN_MID: { + decl->_tag = _Z_DECL_TOKEN; + ret = _z_decl_token_decode(&decl->_body._decl_token, zbf, header); + } break; + case _Z_UNDECL_TOKEN_MID: { + 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); + } break; + default: { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + return ret; +} \ No newline at end of file diff --git a/src/protocol/codec/ext.c b/src/protocol/codec/ext.c new file mode 100644 index 000000000..fd4f478f2 --- /dev/null +++ b/src/protocol/codec/ext.c @@ -0,0 +1,228 @@ +// +// 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/protocol/ext.h" + +#include +#include +#include + +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/protocol/codec.h" +#include "zenoh-pico/protocol/codec/ext.h" +#include "zenoh-pico/system/platform.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" + +int8_t _z_msg_ext_encode_unit(_z_wbuf_t *wbf, const _z_msg_ext_unit_t *ext) { + int8_t ret = _Z_RES_OK; + (void)(wbf); + (void)(ext); + return ret; +} + +int8_t _z_msg_ext_decode_unit(_z_msg_ext_unit_t *ext, _z_zbuf_t *zbf) { + int8_t ret = _Z_RES_OK; + (void)(zbf); + (void)(ext); + return ret; +} + +int8_t _z_msg_ext_decode_unit_na(_z_msg_ext_unit_t *ext, _z_zbuf_t *zbf) { return _z_msg_ext_decode_unit(ext, zbf); } + +int8_t _z_msg_ext_encode_zint(_z_wbuf_t *wbf, const _z_msg_ext_zint_t *ext) { + int8_t ret = _Z_RES_OK; + _Z_RETURN_IF_ERR(_z_zint64_encode(wbf, ext->_val)) + return ret; +} + +int8_t _z_msg_ext_decode_zint(_z_msg_ext_zint_t *ext, _z_zbuf_t *zbf) { + int8_t ret = _Z_RES_OK; + ret |= _z_zint64_decode(&ext->_val, zbf); + return ret; +} + +int8_t _z_msg_ext_decode_zint_na(_z_msg_ext_zint_t *ext, _z_zbuf_t *zbf) { return _z_msg_ext_decode_zint(ext, zbf); } + +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)) + 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); + return ret; +} + +int8_t _z_msg_ext_decode_zbuf_na(_z_msg_ext_zbuf_t *ext, _z_zbuf_t *zbf) { return _z_msg_ext_decode_zbuf(ext, zbf); } + +/*------------------ Message Extension ------------------*/ +int8_t _z_msg_ext_encode(_z_wbuf_t *wbf, const _z_msg_ext_t *ext, _Bool has_next) { + int8_t ret = _Z_RES_OK; + + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, _Z_EXT_FULL_ID(ext->_header) | (has_next << 7))) + + uint8_t enc = _Z_EXT_ENC(ext->_header); + switch (enc) { + case _Z_MSG_EXT_ENC_UNIT: { + _z_msg_ext_encode_unit(wbf, &ext->_body._unit); + } break; + + case _Z_MSG_EXT_ENC_ZINT: { + _z_msg_ext_encode_zint(wbf, &ext->_body._zint); + } break; + + case _Z_MSG_EXT_ENC_ZBUF: { + _z_msg_ext_encode_zbuf(wbf, &ext->_body._zbuf); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to copy message extension with unknown encoding(%d)\n", enc); + } break; + } + + return ret; +} + +int8_t _z_msg_ext_unknown_body_decode(_z_msg_ext_body_t *body, uint8_t enc, _z_zbuf_t *zbf) { + int8_t ret = _Z_RES_OK; + + switch (enc) { + case _Z_MSG_EXT_ENC_UNIT: { + ret |= _z_msg_ext_decode_unit(&body->_unit, zbf); + } break; + + case _Z_MSG_EXT_ENC_ZINT: { + ret |= _z_msg_ext_decode_zint(&body->_zint, zbf); + } break; + + case _Z_MSG_EXT_ENC_ZBUF: { + ret |= _z_msg_ext_decode_zbuf(&body->_zbuf, zbf); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to copy message extension with unknown encoding(%d)\n", enc); + } break; + } + + return ret; +} + +int8_t _z_msg_ext_decode(_z_msg_ext_t *ext, _z_zbuf_t *zbf, _Bool *has_next) { + int8_t ret = _Z_RES_OK; + + ret |= _z_uint8_decode(&ext->_header, zbf); // Decode the header + if (ret == _Z_RES_OK) { + // TODO: define behaviour on decode failure, regarding zbuf allocation + ret |= _z_msg_ext_unknown_body_decode(&ext->_body, _Z_EXT_ENC(ext->_header), zbf); + } + *has_next = (ext->_header & _Z_MSG_EXT_FLAG_Z) != 0; + ext->_header &= _Z_EXT_FULL_ID_MASK; + + return ret; +} + +int8_t _z_msg_ext_decode_na(_z_msg_ext_t *ext, _z_zbuf_t *zbf, _Bool *has_next) { + return _z_msg_ext_decode(ext, zbf, has_next); +} + +int8_t _z_msg_ext_vec_encode(_z_wbuf_t *wbf, const _z_msg_ext_vec_t *extensions) { + int8_t ret = _Z_RES_OK; + size_t len = _z_msg_ext_vec_len(extensions); + if (len > 0) { + size_t i; + for (i = 0; ret == _Z_RES_OK && i < len - 1; i++) { + ret |= _z_msg_ext_encode(wbf, _z_msg_ext_vec_get(extensions, i), true); + } + if (ret == _Z_RES_OK) { + ret |= _z_msg_ext_encode(wbf, _z_msg_ext_vec_get(extensions, i), true); + } + } + return ret; +} +int8_t _z_msg_ext_vec_push_callback(_z_msg_ext_t *extension, _z_msg_ext_vec_t *extensions) { + _z_msg_ext_t *ext = (_z_msg_ext_t *)z_malloc(sizeof(_z_msg_ext_t)); + *ext = *extension; + *extension = _z_msg_ext_make_unit(0); + _z_msg_ext_vec_append(extensions, extension); + return 0; +} +int8_t _z_msg_ext_vec_decode(_z_msg_ext_vec_t *extensions, _z_zbuf_t *zbf) { + _z_msg_ext_vec_reset(extensions); + return _z_msg_ext_decode_iter(zbf, (int8_t(*)(_z_msg_ext_t *, void *))_z_msg_ext_vec_push_callback, + (void *)extensions); +} + +int8_t _z_msg_ext_unknown_error(_z_msg_ext_t *extension, uint8_t trace_id) { + uint8_t ext_id = _Z_EXT_ID(extension->_header); +#if (ZENOH_DEBUG >= 1) + switch (_Z_EXT_ENC(extension->_header)) { + case _Z_MSG_EXT_ENC_UNIT: { + _Z_ERROR("Unknown mandatory extension found (extension_id: %02x, trace_id: %02x), UNIT\n", ext_id, + trace_id); + break; + } + case _Z_MSG_EXT_ENC_ZINT: { + _Z_ERROR("Unknown mandatory extension found (extension_id: %02x, trace_id: %02x), ZINT(%02jx)\n", ext_id, + trace_id, (uintmax_t)extension->_body._zint._val); + break; + } + case _Z_MSG_EXT_ENC_ZBUF: { + _z_bytes_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]); + } + _Z_ERROR("Unknown mandatory extension found (extension_id: %02x, trace_id: %02x), ZBUF(%.*s)\n", ext_id, + trace_id, (int)buf.len * 2, hex); + z_free(hex); + break; + } + default: { + _Z_ERROR("Unknown mandatory extension found (extension_id: %02x, trace_id: %02x), UNKOWN_ENCODING\n", + ext_id, trace_id); + } + } +#endif + return _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN; +} + +int8_t _z_msg_ext_skip_non_mandatory(_z_msg_ext_t *extension, void *ctx) { + int8_t ret = _Z_RES_OK; + if ((extension->_header & _Z_MSG_EXT_FLAG_M) != 0) { + uint8_t trace_id = *(uint8_t *)ctx; + ret = _z_msg_ext_unknown_error(extension, trace_id); + } + + return ret; +} +int8_t _z_msg_ext_decode_iter(_z_zbuf_t *zbf, int8_t (*callback)(_z_msg_ext_t *, void *), void *context) { + int8_t ret = _Z_RES_OK; + _Bool has_next = true; + while (has_next && ret == _Z_RES_OK) { + _z_msg_ext_t ext = _z_msg_ext_make_unit(0); + ret |= _z_msg_ext_decode(&ext, zbf, &has_next); + if (ret == _Z_RES_OK) { + ret |= callback(&ext, context); + _z_msg_ext_clear(&ext); + } + } + return ret; +} + +int8_t _z_msg_ext_skip_non_mandatories(_z_zbuf_t *zbf, uint8_t trace_id) { + return _z_msg_ext_decode_iter(zbf, _z_msg_ext_skip_non_mandatory, &trace_id); +} \ No newline at end of file diff --git a/src/protocol/codec/message.c b/src/protocol/codec/message.c new file mode 100644 index 000000000..33de0a169 --- /dev/null +++ b/src/protocol/codec/message.c @@ -0,0 +1,891 @@ +// +// 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/protocol/definitions/message.h" + +#include +#include +#include +#include + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/link/endpoint.h" +#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/transport.h" +#include "zenoh-pico/protocol/ext.h" +#include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" + +/*=============================*/ +/* Fields */ +/*=============================*/ +/*------------------ Payload field ------------------*/ +int8_t _z_payload_encode(_z_wbuf_t *wbf, const _z_bytes_t *pld) { + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _PAYLOAD\n"); + ret |= _z_bytes_encode(wbf, pld); + + return ret; +} + +int8_t _z_payload_decode_na(_z_bytes_t *pld, _z_zbuf_t *zbf) { + _Z_DEBUG("Decoding _PAYLOAD\n"); + return _z_bytes_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_id_encode_as_zbytes(_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); + } else { + _Z_DEBUG("Attempted to encode invalid ID 0"); + ret = _Z_ERR_MESSAGE_ZENOH_UNKNOWN; + } + return ret; +} + +/// Decodes a `zid` from the zbf, returning a negative value in case of error. +/// +/// 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 ret = _Z_RES_OK; + uint8_t len = _z_zbuf_read(zbf); + _z_zbuf_read_bytes(zbf, id->id, 0, len); + memset(id->id + len, 0, 16 - len); + return ret; +} + +/*------------------ Timestamp Field ------------------*/ +int8_t _z_timestamp_encode(_z_wbuf_t *wbf, const _z_timestamp_t *ts) { + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _TIMESTAMP\n"); + + _Z_RETURN_IF_ERR(_z_uint64_encode(wbf, ts->time)) + ret |= _z_id_encode_as_zbytes(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))); + return _z_timestamp_encode(wbf, ts); +} + +int8_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *zbf) { + _Z_DEBUG("Decoding _TIMESTAMP\n"); + int8_t ret = _Z_RES_OK; + + ret |= _z_uint64_decode(&ts->time, zbf); + ret |= _z_id_decode_as_zbytes(&ts->id, zbf); + + return ret; +} + +/*------------------ ResKey Field ------------------*/ +int8_t _z_keyexpr_encode(_z_wbuf_t *wbf, _Bool has_suffix, const _z_keyexpr_t *fld) { + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _RESKEY\n"); + + _Z_RETURN_IF_ERR(_z_zint_encode(wbf, fld->_id)) + if (has_suffix == true) { + _Z_RETURN_IF_ERR(_z_str_encode(wbf, fld->_suffix)) + } + + return ret; +} + +int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *zbf, _Bool has_suffix) { + _Z_DEBUG("Decoding _RESKEY\n"); + int8_t ret = _Z_RES_OK; + + ret |= _z_zint16_decode(&ke->_id, zbf); + if (has_suffix == true) { + char *str = NULL; + ret |= _z_str_decode(&str, zbf); + if (ret == _Z_RES_OK) { + ke->_suffix = str; + ke->_mapping = _z_keyexpr_mapping(0, true); + } else { + ke->_suffix = NULL; + ke->_mapping = _z_keyexpr_mapping(0, false); + } + } else { + ke->_suffix = NULL; + } + + return ret; +} + +/*------------------ Locators Field ------------------*/ +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\n"); + _Z_RETURN_IF_ERR(_z_zint_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); + } + + return ret; +} + +int8_t _z_locators_decode_na(_z_locator_array_t *a_loc, _z_zbuf_t *zbf) { + _Z_DEBUG("Decoding _LOCATORS\n"); + int8_t ret = _Z_RES_OK; + + _z_zint_t len = 0; // Number of elements in the array + ret |= _z_zint_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); + 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); + } else { + a_loc->_len = i; + } + } + } else { + *a_loc = _z_locator_array_make(0); + } + + return ret; +} + +int8_t _z_locators_decode(_z_locator_array_t *a_loc, _z_zbuf_t *zbf) { return _z_locators_decode_na(a_loc, zbf); } + +/*=============================*/ +/* Zenoh Messages */ +/*=============================*/ + +int8_t _z_source_info_decode(_z_source_info_t *info, _z_zbuf_t *zbf) { + uint8_t zidlen = 0; + _z_zint_t intbuf; + int8_t ret = _z_uint8_decode(&zidlen, zbf); + if (ret == _Z_RES_OK) { + zidlen >>= 4; + if (_z_zbuf_len(zbf) >= zidlen) { + _z_zbuf_read_bytes(zbf, info->_id.id, 0, zidlen); + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + if (ret == _Z_RES_OK) { + ret = _z_zint_decode(&intbuf, zbf); + if (intbuf <= UINT32_MAX) { + info->_entity_id = (uint32_t)intbuf; + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + if (ret == _Z_RES_OK) { + ret = _z_zint_decode(&intbuf, zbf); + if (intbuf <= UINT32_MAX) { + info->_source_sn = (uint32_t)intbuf; + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + return ret; +} +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); + 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)); + _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)); + return ret; +} + +/*------------------ Push Body Field ------------------*/ +int8_t _z_push_body_encode(_z_wbuf_t *wbf, const _z_push_body_t *pshb) { + (void)(wbf); + (void)(pshb); + int8_t ret = _Z_RES_OK; + uint8_t header = pshb->_is_put ? _Z_MID_Z_PUT : _Z_MID_Z_DEL; + _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; + _Bool has_timestamp = _z_timestamp_check(&pshb->_body._put._commons._timestamp); + _Bool has_encoding = false; + if (has_source_info) { + header |= _Z_FLAG_Z_Z; + } + if (pshb->_is_put) { + 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); + if (has_encoding) { + header |= _Z_FLAG_Z_P_E; + } + } else { + if (has_timestamp) { + header |= _Z_FLAG_Z_D_T; + } + } + ret = _z_uint8_encode(wbf, header); + if ((ret == _Z_RES_OK) && has_timestamp) { + ret = _z_timestamp_encode(wbf, &pshb->_body._put._commons._timestamp); + } + + if ((ret == _Z_RES_OK) && has_encoding) { + ret = _z_encoding_prefix_encode(wbf, pshb->_body._put._encoding.prefix); + ret |= _z_bytes_encode(wbf, &pshb->_body._put._encoding.suffix); + } + + if ((ret == _Z_RES_OK) && has_source_info) { + ret = _z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x01); + ret |= _z_source_info_encode_ext(wbf, &pshb->_body._put._commons._source_info); + } + + if ((ret == _Z_RES_OK) && pshb->_is_put) { + ret = _z_bytes_encode(wbf, &pshb->_body._put._payload); + } + + return ret; +} +int8_t _z_push_body_decode_extensions(_z_msg_ext_t *extension, void *ctx) { + _z_push_body_t *pshb = (_z_push_body_t *)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); + ret = _z_source_info_decode(&pshb->_body._put._commons._source_info, &zbf); + break; + } + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + ret = _z_msg_ext_unknown_error(extension, 0x08); + } + } + return ret; +} + +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; + } + 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; +} + +int8_t _z_put_encode(_z_wbuf_t *wbf, const _z_msg_put_t *put) { + _z_push_body_t body = {._is_put = true, ._body = {._put = *put}}; + return _z_push_body_encode(wbf, &body); +} +int8_t _z_put_decode(_z_msg_put_t *put, _z_zbuf_t *zbf, uint8_t header) { + assert(_Z_MID(header) == _Z_MID_Z_PUT); + _z_push_body_t body = {._is_put = true, ._body = {._put = *put}}; + int8_t ret = _z_push_body_decode(&body, zbf, header); + *put = body._body._put; + return ret; +} + +int8_t _z_del_encode(_z_wbuf_t *wbf, const _z_msg_del_t *del) { + _z_push_body_t body = {._is_put = false, ._body = {._del = *del}}; + return _z_push_body_encode(wbf, &body); +} +int8_t _z_del_decode(_z_msg_del_t *del, _z_zbuf_t *zbf, uint8_t header) { + assert(_Z_MID(header) == _Z_MID_Z_DEL); + _z_push_body_t body = {._is_put = false, ._body = {._del = *del}}; + int8_t ret = _z_push_body_decode(&body, zbf, header); + *del = body._body._del; + return ret; +} + +/*------------------ Query Message ------------------*/ +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); + if (has_params) { + header |= _Z_FLAG_Z_P; + } + _z_msg_query_reqexts_t required_exts = _z_msg_query_required_extensions(msg); + if (required_exts.body || required_exts.consolidation || required_exts.info) { + header |= _Z_FLAG_Z_Z; + } + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); + + if (has_params) { + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_parameters)); + } + + if (required_exts.body) { + uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x03; + if (required_exts.consolidation || required_exts.info) { + 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) + + _z_bytes_encode_len(&msg->_ext_value.payload))); + _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_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) { + 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)); + } + if (required_exts.info) { + uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x01; + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); + _Z_RETURN_IF_ERR(_z_source_info_encode_ext(wbf, &msg->_ext_info)); + } + + return ret; +} + +int8_t _z_query_decode_extensions(_z_msg_ext_t *extension, void *ctx) { + _z_msg_query_t *msg = (_z_msg_query_t *)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); + 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); + ret |= _z_bytes_decode(&msg->_ext_value.payload, &zbf); + break; + } + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + ret = _z_msg_ext_unknown_error(extension, 0x09); + } + } + return ret; +} + +int8_t _z_query_decode(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header) { + _Z_DEBUG("Decoding _Z_MID_Z_QUERY\n"); + *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)); + } else { + _z_bytes_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; + } + _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; + if (reply->_ext_consolidation != Z_CONSOLIDATION_MODE_AUTO || has_sourceinfo) { + header |= _Z_FLAG_Z_Z; + } + _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)); + } + _Bool has_consolidation_ext = reply->_ext_consolidation != Z_CONSOLIDATION_MODE_AUTO; + if (has_sourceinfo) { + uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x01; + if (has_consolidation_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, &reply->_ext_source_info)); + } + if (has_consolidation_ext) { + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M | 0x02)); + _Z_RETURN_IF_ERR(_z_zint_encode(wbf, reply->_ext_consolidation)); + } + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &reply->_value.payload)); + return ret; +} +int8_t _z_reply_decode_extension(_z_msg_ext_t *extension, void *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; + } + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + ret = _z_msg_ext_unknown_error(extension, 0x0a); + } + } + 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_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; +} + +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; + } + _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; + } + _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)); + } + 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)); + } + return ret; +} +int8_t _z_err_decode_extension(_z_msg_ext_t *extension, void *ctx) { + int8_t ret = _Z_RES_OK; + _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); + 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); + } + } + return ret; +} +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_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)); + } + 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; +} + +/*=============================*/ +/* Scouting Messages */ +/*=============================*/ +/*------------------ Scout Message ------------------*/ +int8_t _z_scout_encode(_z_wbuf_t *wbf, uint8_t header, const _z_s_msg_scout_t *msg) { + int8_t ret = _Z_RES_OK; + (void)(header); + _Z_DEBUG("Encoding _Z_MID_SCOUT\n"); + + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, msg->_version)) + + uint8_t cbyte = 0; + cbyte |= (msg->_what & 0x07); + 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; + } + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, cbyte)) + + ret |= _z_wbuf_write_bytes(wbf, msg->_zid.id, 0, zid_len); + + return ret; +} + +int8_t _z_scout_decode(_z_s_msg_scout_t *msg, _z_zbuf_t *zbf, uint8_t header) { + int8_t ret = _Z_RES_OK; + (void)(header); + _Z_DEBUG("Decoding _Z_MID_SCOUT\n"); + *msg = (_z_s_msg_scout_t){0}; + + ret |= _z_uint8_decode(&msg->_version, zbf); + + uint8_t cbyte = 0; + ret |= _z_uint8_decode(&cbyte, zbf); + 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; + _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); + } + + return ret; +} + +/*------------------ Hello Message ------------------*/ +int8_t _z_hello_encode(_z_wbuf_t *wbf, uint8_t header, const _z_s_msg_hello_t *msg) { + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _Z_MID_HELLO\n"); + + _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; + _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})); + + if (_Z_HAS_FLAG(header, _Z_FLAG_T_HELLO_L) == true) { + _Z_RETURN_IF_ERR(_z_locators_encode(wbf, &msg->_locators)) + } + + return ret; +} + +int8_t _z_hello_decode_na(_z_s_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header) { + _Z_DEBUG("Decoding _Z_MID_HELLO\n"); + int8_t ret = _Z_RES_OK; + *msg = (_z_s_msg_hello_t){0}; + + ret |= _z_uint8_decode(&msg->_version, zbf); + + uint8_t cbyte = 0; + ret |= _z_uint8_decode(&cbyte, zbf); + msg->_whatami = cbyte & 0x03; + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + + if (ret == _Z_RES_OK) { + msg->_zid = _z_id_empty(); + _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); + } else { + msg->_zid = _z_id_empty(); + } + + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_HELLO_L) == true)) { + ret |= _z_locators_decode(&msg->_locators, zbf); + if (ret != _Z_RES_OK) { + msg->_locators = _z_locator_array_empty(); + } + } else { + msg->_locators = _z_locator_array_empty(); + } + + return ret; +} + +int8_t _z_hello_decode(_z_s_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header) { + return _z_hello_decode_na(msg, zbf, header); +} + +int8_t _z_scouting_message_encode(_z_wbuf_t *wbf, const _z_scouting_message_t *msg) { + int8_t ret = _Z_RES_OK; + + uint8_t header = msg->_header; + + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, header)) + switch (_Z_MID(msg->_header)) { + case _Z_MID_SCOUT: { + ret |= _z_scout_encode(wbf, msg->_header, &msg->_body._scout); + } break; + + case _Z_MID_HELLO: { + ret |= _z_hello_encode(wbf, msg->_header, &msg->_body._hello); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to encode session message with unknown ID(%d)\n", _Z_MID(msg->_header)); + ret |= _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN; + } break; + } + + return ret; +} +int8_t _z_scouting_message_decode_na(_z_scouting_message_t *msg, _z_zbuf_t *zbf) { + int8_t ret = _Z_RES_OK; + *msg = (_z_scouting_message_t){0}; + + _Bool is_last = false; + + do { + ret |= _z_uint8_decode(&msg->_header, zbf); // Decode the header + if (ret == _Z_RES_OK) { + uint8_t mid = _Z_MID(msg->_header); + switch (mid) { + case _Z_MID_SCOUT: { + ret |= _z_scout_decode(&msg->_body._scout, zbf, msg->_header); + is_last = true; + } break; + + case _Z_MID_HELLO: { + ret |= _z_hello_decode(&msg->_body._hello, zbf, msg->_header); + is_last = true; + } break; + + default: { + _Z_DEBUG("WARNING: Trying to decode scouting message with unknown ID(0x%x)\n", mid); + ret |= _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN; + is_last = true; + } break; + } + } else { + msg->_header = 0xFF; + } + } while ((ret == _Z_RES_OK) && (is_last == false)); + + if ((ret == _Z_RES_OK) && (msg->_header & _Z_MSG_EXT_FLAG_Z) != 0) { + ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x06); + } + + return ret; +} + +int8_t _z_scouting_message_decode(_z_scouting_message_t *s_msg, _z_zbuf_t *zbf) { + return _z_scouting_message_decode_na(s_msg, zbf); +} \ No newline at end of file diff --git a/src/protocol/codec/network.c b/src/protocol/codec/network.c new file mode 100644 index 000000000..857e391aa --- /dev/null +++ b/src/protocol/codec/network.c @@ -0,0 +1,518 @@ +// +// 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/protocol/definitions/network.h" + +#include +#include +#include + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/collections/bytes.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/network.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/core.h" +#include "zenoh-pico/protocol/definitions/message.h" +#include "zenoh-pico/protocol/ext.h" +#include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" + +/*------------------ Push Message ------------------*/ + +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_timestamp_ext = _z_timestamp_check(&msg->_timestamp); + if (has_suffix) { + header |= _Z_FLAG_N_REQUEST_N; + } + if (has_timestamp_ext) { + header |= _Z_FLAG_N_Z; + } + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); + _Z_RETURN_IF_ERR(_z_keyexpr_encode(wbf, has_suffix, &msg->_key)); + + if (msg->_qos._val != _Z_N_QOS_DEFAULT._val) { + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZINT | 0x01 | (has_timestamp_ext << 7))); + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, msg->_qos._val)); + } + + if (has_timestamp_ext) { + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, _Z_MSG_EXT_ENC_ZBUF | 0x02)); + _Z_RETURN_IF_ERR(_z_timestamp_encode_ext(wbf, &msg->_timestamp)); + } + + _Z_RETURN_IF_ERR(_z_push_body_encode(wbf, &msg->_body)); + + return _Z_RES_OK; +} + +int8_t _z_push_decode_ext_cb(_z_msg_ext_t *extension, void *ctx) { + int8_t ret = _Z_RES_OK; + _z_n_msg_push_t *msg = (_z_n_msg_push_t *)ctx; + switch (_Z_EXT_FULL_ID(extension->_header)) { + case _Z_MSG_EXT_ENC_ZINT | 0x01: { // QOS ext + 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}; + break; + } + case _Z_MSG_EXT_ENC_ZBUF | 0x02: { // Timestamp ext + _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + ret = _z_timestamp_decode(&msg->_timestamp, &zbf); + break; + } + default: + if ((extension->_header & _Z_MSG_EXT_FLAG_M) != 0) { + ret = _z_msg_ext_unknown_error(extension, 0x07); + } + } + return ret; +} + +int8_t _z_push_decode(_z_n_msg_push_t *msg, _z_zbuf_t *zbf, uint8_t header) { + int8_t ret = _Z_RES_OK; + *msg = (_z_n_msg_push_t){0}; + msg->_qos = _Z_N_QOS_DEFAULT; + ret |= _z_keyexpr_decode(&msg->_key, zbf, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_N)); + _z_keyexpr_set_mapping(&msg->_key, _Z_HAS_FLAG(header, _Z_FLAG_N_PUSH_M) ? _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE + : _Z_KEYEXPR_MAPPING_LOCAL); + if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(header, _Z_FLAG_N_Z)) { + ret = _z_msg_ext_decode_iter(zbf, _z_push_decode_ext_cb, msg); + } + if (ret == _Z_RES_OK) { + uint8_t msgheader; + _Z_RETURN_IF_ERR(_z_uint8_decode(&msgheader, zbf)); + _Z_RETURN_IF_ERR(_z_push_body_decode(&msg->_body, zbf, msgheader)); + } + + return ret; +} + +/*------------------ Request Message ------------------*/ +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); + 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_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)); + } + if (exts.ext_tstamp) { + exts.n -= 1; + uint8_t extheader = 0x02 | _Z_MSG_EXT_ENC_ZBUF | (exts.n ? _Z_FLAG_Z_Z : 0); + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); + _Z_RETURN_IF_ERR(_z_timestamp_encode_ext(wbf, &msg->_ext_timestamp)); + } + if (exts.ext_target) { + 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)); + } + 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)); + } + 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)); + } + + switch (msg->_tag) { + case _Z_REQUEST_QUERY: { + _Z_RETURN_IF_ERR(_z_query_encode(wbf, &msg->_body._query)); + } break; + case _Z_REQUEST_PUT: { + _Z_RETURN_IF_ERR(_z_put_encode(wbf, &msg->_body._put)); + } break; + 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; +} +int8_t _z_request_decode_extensions(_z_msg_ext_t *extension, void *ctx) { + _z_n_msg_request_t *msg = (_z_n_msg_request_t *)ctx; + switch (_Z_EXT_FULL_ID(extension->_header)) { + case 0x01 | _Z_MSG_EXT_ENC_ZINT: { // QOS ext + if (extension->_body._zint._val > UINT8_MAX) { + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + msg->_ext_qos = (_z_n_qos_t){._val = (uint8_t)extension->_body._zint._val}; + break; + } + case 0x02 | _Z_MSG_EXT_ENC_ZBUF: { // Timestamp ext + _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + _Z_RETURN_IF_ERR(_z_timestamp_decode(&msg->_ext_timestamp, &zbf)); + break; + } + case 0x04 | _Z_MSG_EXT_ENC_ZINT | _Z_MSG_EXT_FLAG_M: { + msg->_ext_target = (uint8_t)extension->_body._zint._val; + if (msg->_ext_target > 2) { + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } break; + case 0x05 | _Z_MSG_EXT_ENC_ZINT: { + if (extension->_body._zint._val > UINT32_MAX) { + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + msg->_ext_budget = (uint32_t)extension->_body._zint._val; + } break; + case 0x06 | _Z_MSG_EXT_ENC_ZINT: { + if (extension->_body._zint._val > UINT32_MAX) { + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + msg->_ext_timeout_ms = (uint32_t)extension->_body._zint._val; + } break; + default: + if ((extension->_header & _Z_MSG_EXT_FLAG_M) != 0) { + return _z_msg_ext_unknown_error(extension, 0x16); + } + } + return _Z_RES_OK; +} +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_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); + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_request_decode_extensions, msg)); + } + uint8_t zheader; + _Z_RETURN_IF_ERR(_z_uint8_decode(&zheader, zbf)); + switch (_Z_MID(zheader)) { + case _Z_MID_Z_QUERY: { + msg->_tag = _Z_REQUEST_QUERY; + _Z_RETURN_IF_ERR(_z_query_decode(&msg->_body._query, zbf, zheader)); + } break; + case _Z_MID_Z_PUT: { + msg->_tag = _Z_REQUEST_PUT; + _Z_RETURN_IF_ERR(_z_put_decode(&msg->_body._put, zbf, zheader)); + } break; + case _Z_MID_Z_DEL: { + 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; + } + return _Z_RES_OK; +} + +/*------------------ Response Message ------------------*/ +int8_t _z_response_encode(_z_wbuf_t *wbf, const _z_n_msg_response_t *msg) { + int8_t ret = _Z_RES_OK; + uint8_t header = _Z_MID_N_RESPONSE; + _Z_DEBUG("Encoding _Z_MID_N_RESPONSE\n"); + _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); + if (_z_keyexpr_is_local(&msg->_key)) { + _Z_SET_FLAG(header, _Z_FLAG_N_RESPONSE_M); + } + if (has_suffix) { + _Z_SET_FLAG(header, _Z_FLAG_N_RESPONSE_N); + } + if (n_ext != 0) { + _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, msg->_request_id)); + _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_key._id)); + if (has_suffix) { + _Z_RETURN_IF_ERR(_z_str_encode(wbf, msg->_key._suffix)) + } + if (has_qos_ext) { + n_ext -= 1; + uint8_t extheader = _Z_MSG_EXT_ENC_ZINT | 0x01; + if (n_ext != 0) { + 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)); + } + if (has_ts_ext) { + n_ext -= 1; + uint8_t extheader = _Z_MSG_EXT_ENC_ZBUF | 0x02 | (n_ext != 0 ? _Z_FLAG_Z_Z : 0); + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, extheader)); + _Z_RETURN_IF_ERR(_z_timestamp_encode_ext(wbf, &msg->_ext_timestamp)); + } + if (has_responder_ext) { + n_ext -= 1; + 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))); + _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)); + } + + switch (msg->_tag) { + case _Z_RESPONSE_BODY_REPLY: { + _Z_RETURN_IF_ERR(_z_reply_encode(wbf, &msg->_body._reply)); + break; + } + case _Z_RESPONSE_BODY_ERR: { + _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; + switch (_Z_EXT_FULL_ID(extension->_header)) { + case _Z_MSG_EXT_ENC_ZINT | 0x01: { + msg->_ext_qos._val = extension->_body._zint._val; + break; + } + case _Z_MSG_EXT_ENC_ZBUF | 0x02: { + _z_zbuf_t zbf = _z_zbytes_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 = &_zbf; + uint8_t header; + _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); + uint8_t zidlen = (header >> 4) + 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; + } + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + ret = _z_msg_ext_unknown_error(extension, 0x0d); + } + } + return ret; +} + +int8_t _z_response_decode(_z_n_msg_response_t *msg, _z_zbuf_t *zbf, uint8_t header) { + _Z_DEBUG("Decoding _Z_MID_N_RESPONSE\n"); + *msg = (_z_n_msg_response_t){0}; + msg->_ext_qos = _Z_N_QOS_DEFAULT; + 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_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)); + } + + uint8_t inner_header; + _Z_RETURN_IF_ERR(_z_uint8_decode(&inner_header, zbf)); + + switch (_Z_MID(inner_header)) { + case _Z_MID_Z_REPLY: { + msg->_tag = _Z_RESPONSE_BODY_REPLY; + ret = _z_reply_decode(&msg->_body._reply, zbf, inner_header); + break; + } + case _Z_MID_Z_ERR: { + msg->_tag = _Z_RESPONSE_BODY_ERR; + 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\n", _Z_MID(inner_header)); + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + return ret; +} + +/*------------------ 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\n"); + 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)); + + return ret; +} +int8_t _z_response_final_decode(_z_n_msg_response_final_t *msg, _z_zbuf_t *zbf, uint8_t header) { + (void)(header); + + *msg = (_z_n_msg_response_final_t){0}; + int8_t ret = _Z_RES_OK; + ret |= _z_zint_decode(&msg->_request_id, zbf); + return ret; +} + +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) { + header |= _Z_FLAG_N_Z; + } + _Z_RETURN_IF_ERR(_z_uint8_encode(wbf, header)); + 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)); + } + 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))); + _Z_RETURN_IF_ERR(_z_timestamp_encode_ext(wbf, &decl->_ext_timestamp)); + } + return _z_declaration_encode(wbf, &decl->_decl); +} +int8_t _z_declare_decode_extensions(_z_msg_ext_t *extension, void *ctx) { + _z_n_msg_declare_t *decl = (_z_n_msg_declare_t *)ctx; + switch (_Z_EXT_FULL_ID(extension->_header)) { + case _Z_MSG_EXT_ENC_ZINT | 0x01: { + decl->_ext_qos._val = extension->_body._zint._val; + break; + } + case _Z_MSG_EXT_ENC_ZBUF | 0x02: { + _z_zbuf_t zbf = _z_zbytes_as_zbuf(extension->_body._zbuf._val); + return _z_timestamp_decode(&decl->_ext_timestamp, &zbf); + } + default: + if (_Z_HAS_FLAG(extension->_header, _Z_MSG_EXT_FLAG_M)) { + return _z_msg_ext_unknown_error(extension, 0x19); + } + } + return _Z_RES_OK; +} +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; + if (_Z_HAS_FLAG(header, _Z_FLAG_N_Z)) { + _Z_RETURN_IF_ERR(_z_msg_ext_decode_iter(zbf, _z_declare_decode_extensions, decl)) + } + return _z_declaration_decode(&decl->_decl, zbf); +} + +int8_t _z_network_message_encode(_z_wbuf_t *wbf, const _z_network_message_t *msg) { + switch (msg->_tag) { + case _Z_N_DECLARE: { + return _z_declare_encode(wbf, &msg->_body._declare); + } break; + case _Z_N_PUSH: { + return _z_push_encode(wbf, &msg->_body._push); + } break; + case _Z_N_REQUEST: { + return _z_request_encode(wbf, &msg->_body._request); + } break; + case _Z_N_RESPONSE: { + return _z_response_encode(wbf, &msg->_body._response); + } break; + case _Z_N_RESPONSE_FINAL: { + return _z_response_final_encode(wbf, &msg->_body._response_final); + } break; + } + return _Z_ERR_GENERIC; +} +int8_t _z_network_message_decode(_z_network_message_t *msg, _z_zbuf_t *zbf) { + uint8_t header; + _Z_RETURN_IF_ERR(_z_uint8_decode(&header, zbf)); + switch (_Z_MID(header)) { + case _Z_MID_N_DECLARE: { + msg->_tag = _Z_N_DECLARE; + return _z_declare_decode(&msg->_body._declare, zbf, header); + } break; + case _Z_MID_N_PUSH: { + msg->_tag = _Z_N_PUSH; + return _z_push_decode(&msg->_body._push, zbf, header); + } break; + case _Z_MID_N_REQUEST: { + msg->_tag = _Z_N_REQUEST; + return _z_request_decode(&msg->_body._request, zbf, header); + } break; + case _Z_MID_N_RESPONSE: { + msg->_tag = _Z_N_RESPONSE; + return _z_response_decode(&msg->_body._response, zbf, header); + } break; + case _Z_MID_N_RESPONSE_FINAL: { + msg->_tag = _Z_N_RESPONSE_FINAL; + return _z_response_final_decode(&msg->_body._response_final, zbf, header); + } break; + default: + return _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } +} diff --git a/src/protocol/codec/transport.c b/src/protocol/codec/transport.c new file mode 100644 index 000000000..79fe71b4c --- /dev/null +++ b/src/protocol/codec/transport.c @@ -0,0 +1,513 @@ +// +// 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/protocol/definitions/transport.h" + +#include +#include + +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/codec/ext.h" +#include "zenoh-pico/protocol/codec/network.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/definitions/core.h" +#include "zenoh-pico/protocol/ext.h" +#include "zenoh-pico/protocol/iobuf.h" +#include "zenoh-pico/utils/logging.h" +#include "zenoh-pico/utils/result.h" +/*------------------ 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; + _Z_DEBUG("Encoding _Z_MID_T_JOIN\n"); + + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, msg->_version)); + + uint8_t cbyte = 0; + cbyte |= (msg->_whatami & 0x03); + uint8_t zidlen = _z_id_len(msg->_zid); + cbyte |= ((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 |= (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)); + } else { + _Z_RETURN_IF_ERR(_z_zint_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)); + 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)); + size_t len = 0; + for (uint8_t i = 0; (i < Z_PRIORITIES_NUM) && (ret == _Z_RES_OK); i++) { + 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)); + 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)); + } + } else { + _Z_DEBUG("Attempted to serialize QoS-SN extension, but the header extension flag was unset"); + ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED; + } + } + + return ret; +} + +int8_t _z_join_decode_ext(_z_msg_ext_t *extension, void *ctx) { + int8_t ret = _Z_RES_OK; + _z_t_msg_join_t *msg = (_z_t_msg_join_t *)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); + 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); + } + } else if (_Z_MSG_EXT_IS_MANDATORY(extension->_header)) { + ret = _Z_ERR_MESSAGE_EXTENSION_MANDATORY_AND_UNKNOWN; + } + return ret; +} + +int8_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) { + _Z_DEBUG("Decoding _Z_MID_T_JOIN\n"); + int8_t ret = _Z_RES_OK; + *msg = (_z_t_msg_join_t){0}; + + ret |= _z_uint8_decode(&msg->_version, zbf); + + uint8_t cbyte = 0; + ret |= _z_uint8_decode(&cbyte, zbf); + msg->_whatami = cbyte & 0x03; + + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + msg->_zid = _z_id_empty(); + if (ret == _Z_RES_OK) { + if (_z_zbuf_len(zbf) >= zidlen) { + _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + if (ret == _Z_RES_OK) { + if (_Z_HAS_FLAG(header, _Z_FLAG_T_JOIN_S) == true) { + cbyte = 0; + ret |= _z_uint8_decode(&cbyte, zbf); + msg->_seq_num_res = (cbyte & 0x03); + msg->_req_id_res = ((cbyte >> 2) & 0x03); + ret |= _z_uint16_decode(&msg->_batch_size, zbf); + } else { + msg->_seq_num_res = _Z_DEFAULT_RESOLUTION_SIZE; + msg->_req_id_res = _Z_DEFAULT_RESOLUTION_SIZE; + msg->_batch_size = _Z_DEFAULT_MULTICAST_BATCH_SIZE; + } + } + if (ret == _Z_RES_OK) { + ret |= _z_zint_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); + } + 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); + } + + return ret; +} + +/*------------------ Init Message ------------------*/ +int8_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t *msg) { + _Z_DEBUG("Encoding _Z_MID_T_INIT\n"); + int8_t ret = _Z_RES_OK; + + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, msg->_version)) + + uint8_t cbyte = 0; + cbyte |= (msg->_whatami & 0x03); + uint8_t zidlen = _z_id_len(msg->_zid); + cbyte |= ((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)) + + if (_Z_HAS_FLAG(header, _Z_FLAG_T_INIT_S) == true) { + 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_INIT_A) == true) { + _Z_RETURN_IF_ERR(_z_bytes_encode(wbf, &msg->_cookie)) + } + + return ret; +} + +int8_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) { + _Z_DEBUG("Decoding _Z_MID_T_INIT\n"); + *msg = (_z_t_msg_init_t){0}; + int8_t ret = _Z_RES_OK; + + ret |= _z_uint8_decode(&msg->_version, zbf); + + uint8_t cbyte = 0; + ret |= _z_uint8_decode(&cbyte, zbf); + msg->_zid = _z_id_empty(); + + if (ret == _Z_RES_OK) { + msg->_whatami = cbyte & 0x03; + uint8_t zidlen = ((cbyte & 0xF0) >> 4) + 1; + if (_z_zbuf_len(zbf) >= zidlen) { + _z_zbuf_read_bytes(zbf, msg->_zid.id, 0, zidlen); + } else { + ret = _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; + } + } + + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_INIT_S) == true)) { + cbyte = 0; + ret |= _z_uint8_decode(&cbyte, zbf); + msg->_seq_num_res = (cbyte & 0x03); + msg->_req_id_res = ((cbyte >> 2) & 0x03); + ret |= _z_uint16_decode(&msg->_batch_size, zbf); + } else { + msg->_seq_num_res = _Z_DEFAULT_RESOLUTION_SIZE; + msg->_req_id_res = _Z_DEFAULT_RESOLUTION_SIZE; + msg->_batch_size = _Z_DEFAULT_UNICAST_BATCH_SIZE; + } + + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_INIT_A) == true)) { + ret |= _z_bytes_decode(&msg->_cookie, zbf); + } else { + msg->_cookie = _z_bytes_empty(); + } + + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { + ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x01); + } + + return ret; +} + +/*------------------ Open Message ------------------*/ +int8_t _z_open_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_open_t *msg) { + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _Z_MID_T_OPEN\n"); + + if (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_T) == true) { + _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_lease / 1000)) + } else { + _Z_RETURN_IF_ERR(_z_zint_encode(wbf, msg->_lease)) + } + + _Z_RETURN_IF_ERR(_z_zint_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)) + } + + return ret; +} + +int8_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header) { + _Z_DEBUG("Decoding _Z_MID_T_OPEN\n"); + int8_t ret = _Z_RES_OK; + *msg = (_z_t_msg_open_t){0}; + + ret |= _z_zint_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); + + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_OPEN_A) == false)) { + ret |= _z_bytes_decode(&msg->_cookie, zbf); + if (ret != _Z_RES_OK) { + msg->_cookie = _z_bytes_empty(); + } + } else { + msg->_cookie = _z_bytes_empty(); + } + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { + ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x02); + } + + return ret; +} + +/*------------------ Close Message ------------------*/ +int8_t _z_close_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_close_t *msg) { + (void)(header); + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _Z_MID_T_CLOSE\n"); + + ret |= _z_wbuf_write(wbf, msg->_reason); + + return ret; +} + +int8_t _z_close_decode(_z_t_msg_close_t *msg, _z_zbuf_t *zbf, uint8_t header) { + (void)(header); + int8_t ret = _Z_RES_OK; + *msg = (_z_t_msg_close_t){0}; + _Z_DEBUG("Decoding _Z_MID_T_CLOSE\n"); + + ret |= _z_uint8_decode(&msg->_reason, zbf); + + return ret; +} + +/*------------------ Keep Alive Message ------------------*/ +int8_t _z_keep_alive_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_keep_alive_t *msg) { + (void)(wbf); + (void)(header); + (void)(msg); + + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Encoding _Z_MID_T_KEEP_ALIVE\n"); + + return ret; +} + +int8_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header) { + (void)(msg); + (void)(zbf); + (void)(header); + *msg = (_z_t_msg_keep_alive_t){0}; + + int8_t ret = _Z_RES_OK; + _Z_DEBUG("Decoding _Z_MID_T_KEEP_ALIVE\n"); + + if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Z)) { + ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x03); + } + + return ret; +} + +/*------------------ Frame Message ------------------*/ + +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)) + + if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z)) { + ret = _Z_ERR_MESSAGE_SERIALIZATION_FAILED; + } + if (ret == _Z_RES_OK) { + size_t len = _z_network_message_vec_len(&msg->_messages); + for (size_t i = 0; i < len; i++) { + _Z_RETURN_IF_ERR(_z_network_message_encode(wbf, _z_network_message_vec_get(&msg->_messages, i))) + } + } + + return ret; +} + +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); + if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true)) { + ret |= _z_msg_ext_skip_non_mandatories(zbf, 0x04); + } + if (ret == _Z_RES_OK) { + msg->_messages = _z_network_message_vec_make(_ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE); + while (_z_zbuf_len(zbf) > 0) { + // Mark the reading position of the iobfer + size_t r_pos = _z_zbuf_get_rpos(zbf); + _z_network_message_t *nm = (_z_network_message_t *)z_malloc(sizeof(_z_network_message_t)); + ret |= _z_network_message_decode(nm, zbf); + if (ret == _Z_RES_OK) { + _z_network_message_vec_append(&msg->_messages, nm); + } else { + _z_n_msg_free(&nm); + + _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer + + // FIXME: Check for the return error, since not all of them means a decoding error + // in this particular case. As of now, we roll-back the reading position + // and return to the Zenoh transport-level decoder. + // https://github.com/eclipse-zenoh/zenoh-pico/pull/132#discussion_r1045593602 + if ((ret & _Z_ERR_MESSAGE_ZENOH_UNKNOWN) == _Z_ERR_MESSAGE_ZENOH_UNKNOWN) { + ret = _Z_RES_OK; + } + break; + } + } + } + return ret; +} + +/*------------------ Fragment Message ------------------*/ +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\n"); + _Z_RETURN_IF_ERR(_z_zint_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)) { + _Z_RETURN_IF_ERR(_z_wbuf_write_bytes(wbf, msg->_payload.start, 0, msg->_payload.len)); + } + + return ret; +} + +int8_t _z_fragment_decode(_z_t_msg_fragment_t *msg, _z_zbuf_t *zbf, uint8_t header) { + int8_t ret = _Z_RES_OK; + *msg = (_z_t_msg_fragment_t){0}; + + _Z_DEBUG("Decoding _Z_TRANSPORT_FRAGMENT\n"); + ret |= _z_zint_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); + zbf->_ios._r_pos = zbf->_ios._w_pos; + + return ret; +} + +/*------------------ Transport Extensions Message ------------------*/ +int8_t _z_extensions_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_ext_vec_t *v_ext) { + (void)(header); + int8_t ret = _Z_RES_OK; + + _Z_DEBUG("Encoding _Z_TRANSPORT_EXTENSIONS\n"); + if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true) { + ret |= _z_msg_ext_vec_encode(wbf, v_ext); + } + + return ret; +} + +int8_t _z_extensions_decode(_z_msg_ext_vec_t *v_ext, _z_zbuf_t *zbf, uint8_t header) { + (void)(header); + int8_t ret = _Z_RES_OK; + + _Z_DEBUG("Decoding _Z_TRANSPORT_EXTENSIONS\n"); + if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == true) { + ret |= _z_msg_ext_vec_decode(v_ext, zbf); + } else { + _z_msg_ext_vec_reset(v_ext); + } + + return ret; +} + +/*------------------ Transport Message ------------------*/ +int8_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_message_t *msg) { + int8_t ret = _Z_RES_OK; + + uint8_t header = msg->_header; + + _Z_RETURN_IF_ERR(_z_wbuf_write(wbf, header)) + switch (_Z_MID(msg->_header)) { + case _Z_MID_T_FRAME: { + ret |= _z_frame_encode(wbf, msg->_header, &msg->_body._frame); + } break; + case _Z_MID_T_FRAGMENT: { + ret |= _z_fragment_encode(wbf, msg->_header, &msg->_body._fragment); + } break; + case _Z_MID_T_KEEP_ALIVE: { + ret |= _z_keep_alive_encode(wbf, msg->_header, &msg->_body._keep_alive); + } break; + case _Z_MID_T_JOIN: { + ret |= _z_join_encode(wbf, msg->_header, &msg->_body._join); + } break; + case _Z_MID_T_INIT: { + ret |= _z_init_encode(wbf, msg->_header, &msg->_body._init); + } break; + case _Z_MID_T_OPEN: { + ret |= _z_open_encode(wbf, msg->_header, &msg->_body._open); + } break; + case _Z_MID_T_CLOSE: { + ret |= _z_close_encode(wbf, msg->_header, &msg->_body._close); + } break; + default: { + _Z_DEBUG("WARNING: Trying to encode session message with unknown ID(%d)\n", _Z_MID(msg->_header)); + ret |= _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN; + } break; + } + + return ret; +} + +int8_t _z_transport_message_decode(_z_transport_message_t *msg, _z_zbuf_t *zbf) { + int8_t ret = _Z_RES_OK; + + ret |= _z_uint8_decode(&msg->_header, zbf); // Decode the header + if (ret == _Z_RES_OK) { + uint8_t mid = _Z_MID(msg->_header); + switch (mid) { + case _Z_MID_T_FRAME: { + ret |= _z_frame_decode(&msg->_body._frame, zbf, msg->_header); + } break; + case _Z_MID_T_FRAGMENT: { + ret |= _z_fragment_decode(&msg->_body._fragment, zbf, msg->_header); + } break; + case _Z_MID_T_KEEP_ALIVE: { + ret |= _z_keep_alive_decode(&msg->_body._keep_alive, zbf, msg->_header); + } break; + case _Z_MID_T_JOIN: { + ret |= _z_join_decode(&msg->_body._join, zbf, msg->_header); + } break; + case _Z_MID_T_INIT: { + ret |= _z_init_decode(&msg->_body._init, zbf, msg->_header); + } break; + case _Z_MID_T_OPEN: { + ret |= _z_open_decode(&msg->_body._open, zbf, msg->_header); + } break; + case _Z_MID_T_CLOSE: { + ret |= _z_close_decode(&msg->_body._close, zbf, msg->_header); + } break; + default: { + _Z_DEBUG("WARNING: Trying to decode session message with unknown ID(0x%x) (header=0x%x)\n", mid, + msg->_header); + ret |= _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN; + } break; + } + } else { + msg->_header = 0xFF; + } + + return ret; +} \ No newline at end of file diff --git a/src/protocol/core.c b/src/protocol/core.c new file mode 100644 index 000000000..c5cfc0c3f --- /dev/null +++ b/src/protocol/core.c @@ -0,0 +1,52 @@ +#include "zenoh-pico/protocol/core.h" + +#include "zenoh-pico/api/primitives.h" + +uint8_t _z_id_len(_z_id_t id) { + uint8_t len = 16; + while (len > 0) { + --len; + if (id.id[len] != 0) { + ++len; + break; + } + } + return len; +} +_Bool _z_id_check(_z_id_t id) { + _Bool ret = false; + for (int i = 0; !ret && i < 16; i++) { + ret |= id.id[i] != 0; + } + return ret; +} +_z_id_t _z_id_empty() { + return (_z_id_t){.id = { + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + }}; +} +_z_source_info_t _z_source_info_null() { + 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_value_t _z_value_steal(_z_value_t *value) { + _z_value_t ret = *value; + *value = _z_value_null(); + return ret; +} diff --git a/src/protocol/definitions/core.c b/src/protocol/definitions/core.c new file mode 100644 index 000000000..e69de29bb diff --git a/src/protocol/definitions/declarations.c b/src/protocol/definitions/declarations.c new file mode 100644 index 000000000..7572f5a24 --- /dev/null +++ b/src/protocol/definitions/declarations.c @@ -0,0 +1,162 @@ +// +// 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/protocol/definitions/declarations.h" + +#include "zenoh-pico/protocol/keyexpr.h" + +void _z_declaration_clear(_z_declaration_t* decl) { + switch (decl->_tag) { + case _Z_DECL_KEXPR: { + _z_keyexpr_clear(&decl->_body._decl_kexpr._keyexpr); + break; + } + case _Z_UNDECL_KEXPR: { + break; + } + case _Z_DECL_SUBSCRIBER: { + _z_keyexpr_clear(&decl->_body._decl_subscriber._keyexpr); + break; + } + case _Z_UNDECL_SUBSCRIBER: { + _z_keyexpr_clear(&decl->_body._undecl_subscriber._ext_keyexpr); + break; + } + case _Z_DECL_QUERYABLE: { + _z_keyexpr_clear(&decl->_body._decl_queryable._keyexpr); + break; + } + case _Z_UNDECL_QUERYABLE: { + _z_keyexpr_clear(&decl->_body._undecl_queryable._ext_keyexpr); + break; + } + case _Z_DECL_TOKEN: { + _z_keyexpr_clear(&decl->_body._decl_token._keyexpr); + break; + } + case _Z_UNDECL_TOKEN: { + _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); + break; + } + } +} +_z_declaration_t _z_make_decl_keyexpr(uint16_t id, _Z_MOVE(_z_keyexpr_t) key) { + return (_z_declaration_t){._tag = _Z_DECL_KEXPR, + ._body = {._decl_kexpr = {._id = id, ._keyexpr = _z_keyexpr_steal(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) { + 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}}}}; +} +_z_declaration_t _z_make_undecl_subscriber(uint32_t id, _Z_OPTIONAL _Z_MOVE(_z_keyexpr_t) key) { + return (_z_declaration_t){._tag = _Z_UNDECL_SUBSCRIBER, + ._body = {._undecl_subscriber = {._id = id, ._ext_keyexpr = _z_keyexpr_steal(key)}}}; +} +_z_declaration_t _z_make_decl_queryable(_Z_MOVE(_z_keyexpr_t) key, uint32_t id, uint32_t distance, uint8_t complete) { + return (_z_declaration_t){ + ._tag = _Z_DECL_QUERYABLE, + ._body = {._decl_queryable = {._id = id, + ._keyexpr = _z_keyexpr_steal(key), + ._ext_queryable_info = {._complete = complete, ._distance = distance}}}}; +} +_z_declaration_t _z_make_undecl_queryable(uint32_t id, _Z_OPTIONAL _Z_MOVE(_z_keyexpr_t) key) { + return (_z_declaration_t){._tag = _Z_UNDECL_QUERYABLE, + ._body = {._undecl_queryable = {._id = id, ._ext_keyexpr = _z_keyexpr_steal(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, + ._body = {._decl_token = { + ._id = id, + ._keyexpr = _z_keyexpr_steal(key), + }}}; +} +_z_declaration_t _z_make_undecl_token(uint32_t id, _Z_OPTIONAL _Z_MOVE(_z_keyexpr_t) key) { + return (_z_declaration_t){._tag = _Z_UNDECL_TOKEN, + ._body = {._undecl_token = {._id = id, ._ext_keyexpr = _z_keyexpr_steal(key)}}}; +} +_z_declaration_t _z_make_undecl_interest(uint32_t id, _Z_OPTIONAL _Z_MOVE(_z_keyexpr_t) key) { + return (_z_declaration_t){._tag = _Z_UNDECL_TOKEN, + ._body = {._undecl_token = {._id = id, ._ext_keyexpr = _z_keyexpr_steal(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), + }}}; +} +_z_declaration_t _z_make_final_decl(uint32_t id) { + return (_z_declaration_t){._tag = _Z_FINAL_INTEREST, ._body = {._final_interest = {._id = id}}}; +} +_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}; } +void _z_decl_fix_mapping(_z_declaration_t* msg, uint16_t mapping) { + switch (msg->_tag) { + case _Z_DECL_KEXPR: { + _z_keyexpr_fix_mapping(&msg->_body._decl_kexpr._keyexpr, mapping); + } break; + case _Z_DECL_SUBSCRIBER: { + _z_keyexpr_fix_mapping(&msg->_body._decl_subscriber._keyexpr, mapping); + } break; + case _Z_UNDECL_SUBSCRIBER: { + _z_keyexpr_fix_mapping(&msg->_body._undecl_subscriber._ext_keyexpr, mapping); + } break; + case _Z_DECL_QUERYABLE: { + _z_keyexpr_fix_mapping(&msg->_body._decl_queryable._keyexpr, mapping); + } break; + case _Z_UNDECL_QUERYABLE: { + _z_keyexpr_fix_mapping(&msg->_body._undecl_queryable._ext_keyexpr, mapping); + } break; + case _Z_DECL_TOKEN: { + _z_keyexpr_fix_mapping(&msg->_body._decl_token._keyexpr, mapping); + } break; + 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/message.c b/src/protocol/definitions/message.c new file mode 100644 index 000000000..fc6b14491 --- /dev/null +++ b/src/protocol/definitions/message.c @@ -0,0 +1,28 @@ +#include "zenoh-pico/protocol/definitions/message.h" + +#include "zenoh-pico/collections/bytes.h" + +void _z_msg_reply_clear(_z_msg_reply_t *msg) { _z_value_clear(&msg->_value); } + +void _z_msg_put_clear(_z_msg_put_t *msg) { + _z_bytes_clear(&msg->_encoding.suffix); + _z_bytes_clear(&msg->_payload); + _z_timestamp_clear(&msg->_commons._timestamp); +} + +_z_msg_query_reqexts_t _z_msg_query_required_extensions(const _z_msg_query_t *msg) { + 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), + .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}; +} + +void _z_msg_query_clear(_z_msg_query_t *msg) { + _z_bytes_clear(&msg->_parameters); + _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); +} diff --git a/src/protocol/definitions/network.c b/src/protocol/definitions/network.c new file mode 100644 index 000000000..af852e4e2 --- /dev/null +++ b/src/protocol/definitions/network.c @@ -0,0 +1,258 @@ +#include "zenoh-pico/protocol/definitions/network.h" + +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/definitions/message.h" +#include "zenoh-pico/utils/logging.h" + +_z_n_msg_request_exts_t _z_n_msg_request_needed_exts(const _z_n_msg_request_t *msg) { + _z_n_msg_request_exts_t ret = {.n = 0, + .ext_budget = msg->_ext_budget != 0, + .ext_target = msg->_ext_target != Z_QUERY_TARGET_BEST_MATCHING, + .ext_qos = msg->_ext_qos._val != _Z_N_QOS_DEFAULT._val, + .ext_timeout_ms = msg->_ext_timeout_ms != 0, + .ext_tstamp = _z_timestamp_check(&msg->_ext_timestamp)}; + if (ret.ext_budget) { + ret.n += 1; + } + if (ret.ext_target) { + ret.n += 1; + } + if (ret.ext_qos) { + ret.n += 1; + } + if (ret.ext_timeout_ms) { + ret.n += 1; + } + if (ret.ext_tstamp) { + ret.n += 1; + } + return ret; +} + +void _z_n_msg_request_clear(_z_n_msg_request_t *msg) { + _z_keyexpr_clear(&msg->_key); + switch (msg->_tag) { + case _Z_REQUEST_QUERY: { + _z_msg_query_clear(&msg->_body._query); + } break; + case _Z_REQUEST_PUT: { + _z_msg_put_clear(&msg->_body._put); + } break; + case _Z_REQUEST_DEL: { + _z_msg_del_clear(&msg->_body._del); + } break; + case _Z_REQUEST_PULL: { + _z_msg_pull_clear(&msg->_body._pull); + } break; + } +} + +/*=============================*/ +/* Network Messages */ +/*=============================*/ +void _z_push_body_clear(_z_push_body_t *msg) { + if (msg->_is_put) { + _z_msg_put_clear(&msg->_body._put); + } +} +_z_push_body_t _z_push_body_steal(_z_push_body_t *msg) { + _z_push_body_t ret = *msg; + *msg = _z_push_body_null(); + return ret; +} +_z_push_body_t _z_push_body_null() { + return (_z_push_body_t){ + ._is_put = false, + ._body._del._commons = {._timestamp = _z_timestamp_null(), ._source_info = _z_source_info_null()}}; +} + +void _z_n_msg_response_final_clear(_z_n_msg_response_final_t *msg) { (void)(msg); } + +void _z_n_msg_push_clear(_z_n_msg_push_t *msg) { + _z_keyexpr_clear(&msg->_key); + _z_push_body_clear(&msg->_body); +} + +void _z_n_msg_response_clear(_z_n_msg_response_t *msg) { + _z_timestamp_clear(&msg->_ext_timestamp); + _z_keyexpr_clear(&msg->_key); + switch (msg->_tag) { + case _Z_RESPONSE_BODY_REPLY: { + _z_msg_reply_clear(&msg->_body._reply); + break; + } + case _Z_RESPONSE_BODY_ERR: { + _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; + } + } +} + +void _z_n_msg_clear(_z_network_message_t *msg) { + switch (msg->_tag) { + case _Z_N_PUSH: + _z_n_msg_push_clear(&msg->_body._push); + break; + case _Z_N_REQUEST: + _z_n_msg_request_clear(&msg->_body._request); + break; + case _Z_N_RESPONSE: + _z_n_msg_response_clear(&msg->_body._response); + break; + case _Z_N_RESPONSE_FINAL: + _z_n_msg_response_final_clear(&msg->_body._response_final); + break; + case _Z_N_DECLARE: + _z_n_msg_declare_clear(&msg->_body._declare); + break; + } +} + +void _z_n_msg_free(_z_network_message_t **msg) { + _z_network_message_t *ptr = *msg; + + if (ptr != NULL) { + _z_n_msg_clear(ptr); + + z_free(ptr); + *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_consolidation_mode_t consolidation, _Z_MOVE(_z_value_t) value) { + return (_z_zenoh_message_t){ + ._tag = _Z_N_REQUEST, + ._body._request = + { + ._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(), + }, + ._ext_budget = 0, + ._ext_qos = _Z_N_QOS_DEFAULT, + ._ext_target = Z_QUERY_TARGET_BEST_MATCHING, + ._ext_timeout_ms = 0, + ._ext_timestamp = _z_timestamp_null(), + }, + }; +} +_z_network_message_t _z_n_msg_make_response_final(_z_zint_t rid) { + return (_z_zenoh_message_t){ + ._tag = _Z_N_RESPONSE_FINAL, + ._body = {._response_final = {._request_id = rid}}, + }; +} +_z_network_message_t _z_n_msg_make_declare(_z_declaration_t declaration) { + return (_z_network_message_t){ + ._tag = _Z_N_DECLARE, + ._body._declare = + { + ._decl = declaration, + ._ext_qos = _Z_N_QOS_DEFAULT, + ._ext_timestamp = _z_timestamp_null(), + }, + }; +} +_z_network_message_t _z_n_msg_make_push(_Z_MOVE(_z_keyexpr_t) key, _Z_MOVE(_z_push_body_t) body) { + return (_z_network_message_t){ + ._tag = _Z_N_PUSH, + ._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) { + return (_z_network_message_t){ + ._tag = _Z_N_RESPONSE, + ._body._response = + { + ._key = _z_keyexpr_steal(key), + ._tag = _Z_RESPONSE_BODY_REPLY, + ._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, + }, + ._ext_qos = _Z_N_QOS_DEFAULT, + ._ext_timestamp = _z_timestamp_null(), + ._ext_responder = + { + ._eid = 0, + ._zid = _z_id_empty(), + }, + }, + + }; +} +_z_network_message_t _z_n_msg_make_ack(_z_zint_t rid, _Z_MOVE(_z_keyexpr_t) key) { + return (_z_network_message_t){ + ._tag = _Z_N_RESPONSE, + ._body._response = + { + ._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()}, + }, + }; +} +void _z_msg_fix_mapping(_z_zenoh_message_t *msg, uint16_t mapping) { + switch (msg->_tag) { + case _Z_N_DECLARE: { + _z_decl_fix_mapping(&msg->_body._declare._decl, mapping); + } break; + case _Z_N_PUSH: { + _z_keyexpr_fix_mapping(&msg->_body._push._key, mapping); + } break; + case _Z_N_REQUEST: { + _z_keyexpr_fix_mapping(&msg->_body._request._key, mapping); + } break; + case _Z_N_RESPONSE: { + _z_keyexpr_fix_mapping(&msg->_body._response._key, mapping); + } break; + default: + break; + } +} diff --git a/src/protocol/definitions/transport.c b/src/protocol/definitions/transport.c new file mode 100644 index 000000000..3be09369f --- /dev/null +++ b/src/protocol/definitions/transport.c @@ -0,0 +1,403 @@ +#include "zenoh-pico/protocol/definitions/transport.h" + +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/utils/logging.h" + +void _z_s_msg_scout_clear(_z_s_msg_scout_t *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_init_clear(_z_t_msg_init_t *msg) { _z_bytes_clear(&msg->_cookie); } + +void _z_t_msg_open_clear(_z_t_msg_open_t *msg) { _z_bytes_clear(&msg->_cookie); } + +void _z_t_msg_close_clear(_z_t_msg_close_t *msg) { (void)(msg); } + +void _z_t_msg_keep_alive_clear(_z_t_msg_keep_alive_t *msg) { (void)(msg); } + +void _z_t_msg_frame_clear(_z_t_msg_frame_t *msg) { _z_network_message_vec_clear(&msg->_messages); } + +void _z_t_msg_fragment_clear(_z_t_msg_fragment_t *msg) { _z_bytes_clear(&msg->_payload); } + +void _z_t_msg_clear(_z_transport_message_t *msg) { + uint8_t mid = _Z_MID(msg->_header); + switch (mid) { + case _Z_MID_T_JOIN: { + _z_t_msg_join_clear(&msg->_body._join); + } break; + + case _Z_MID_T_INIT: { + _z_t_msg_init_clear(&msg->_body._init); + } break; + + case _Z_MID_T_OPEN: { + _z_t_msg_open_clear(&msg->_body._open); + } break; + + case _Z_MID_T_CLOSE: { + _z_t_msg_close_clear(&msg->_body._close); + } break; + + case _Z_MID_T_KEEP_ALIVE: { + _z_t_msg_keep_alive_clear(&msg->_body._keep_alive); + } break; + + case _Z_MID_T_FRAME: { + _z_t_msg_frame_clear(&msg->_body._frame); + } break; + + case _Z_MID_T_FRAGMENT: { + _z_t_msg_fragment_clear(&msg->_body._fragment); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to clear transport message with unknown ID(%d)\n", mid); + } break; + } +} + +/*------------------ Join Message ------------------*/ +_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 msg; + msg._header = _Z_MID_T_JOIN; + + msg._body._join._version = Z_PROTO_VERSION; + msg._body._join._whatami = whatami; + msg._body._join._lease = lease; + msg._body._join._seq_num_res = Z_SN_RESOLUTION; + msg._body._join._req_id_res = Z_REQ_RESOLUTION; + msg._body._join._batch_size = Z_BATCH_MULTICAST_SIZE; + msg._body._join._next_sn = next_sn; + msg._body._join._zid = zid; + + if ((lease % 1000) == 0) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_JOIN_T); + } + + if ((Z_BATCH_MULTICAST_SIZE != _Z_DEFAULT_MULTICAST_BATCH_SIZE) || + (Z_SN_RESOLUTION != _Z_DEFAULT_RESOLUTION_SIZE) || (Z_REQ_RESOLUTION != _Z_DEFAULT_RESOLUTION_SIZE)) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_JOIN_S); + } + + if (next_sn._is_qos) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_Z); + } + + return msg; +} + +/*------------------ Init Message ------------------*/ +_z_transport_message_t _z_t_msg_make_init_syn(z_whatami_t whatami, _z_id_t zid) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_INIT; + + msg._body._init._version = Z_PROTO_VERSION; + msg._body._init._whatami = whatami; + msg._body._init._zid = 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); + + if ((msg._body._init._batch_size != _Z_DEFAULT_UNICAST_BATCH_SIZE) || + (msg._body._init._seq_num_res != _Z_DEFAULT_RESOLUTION_SIZE) || + (msg._body._init._req_id_res != _Z_DEFAULT_RESOLUTION_SIZE)) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_INIT_S); + } + + 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 msg; + msg._header = _Z_MID_T_INIT; + _Z_SET_FLAG(msg._header, _Z_FLAG_T_INIT_A); + + msg._body._init._version = Z_PROTO_VERSION; + msg._body._init._whatami = whatami; + msg._body._init._zid = 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; + msg._body._init._cookie = cookie; + + if ((msg._body._init._batch_size != _Z_DEFAULT_UNICAST_BATCH_SIZE) || + (msg._body._init._seq_num_res != _Z_DEFAULT_RESOLUTION_SIZE) || + (msg._body._init._req_id_res != _Z_DEFAULT_RESOLUTION_SIZE)) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_INIT_S); + } + + return msg; +} + +/*------------------ 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 msg; + msg._header = _Z_MID_T_OPEN; + + msg._body._open._lease = lease; + msg._body._open._initial_sn = initial_sn; + msg._body._open._cookie = cookie; + + if ((lease % 1000) == 0) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_OPEN_T); + } + + return msg; +} + +_z_transport_message_t _z_t_msg_make_open_ack(_z_zint_t lease, _z_zint_t initial_sn) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_OPEN; + _Z_SET_FLAG(msg._header, _Z_FLAG_T_OPEN_A); + + msg._body._open._lease = lease; + msg._body._open._initial_sn = initial_sn; + _z_bytes_reset(&msg._body._open._cookie); + + if ((lease % 1000) == 0) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_OPEN_T); + } + + return msg; +} + +/*------------------ Close Message ------------------*/ +_z_transport_message_t _z_t_msg_make_close(uint8_t reason, _Bool link_only) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_CLOSE; + + msg._body._close._reason = reason; + if (link_only == false) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_CLOSE_S); + } + + return msg; +} + +/*------------------ Keep Alive Message ------------------*/ +_z_transport_message_t _z_t_msg_make_keep_alive(void) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_KEEP_ALIVE; + + return msg; +} + +_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_network_message_vec_t messages, _Bool is_reliable) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_FRAME; + + msg._body._frame._sn = sn; + if (is_reliable == true) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_FRAME_R); + } + + msg._body._frame._messages = messages; + + return msg; +} + +/*------------------ Frame Message ------------------*/ +_z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, _Bool is_reliable) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_FRAME; + + msg._body._frame._sn = sn; + if (is_reliable == true) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_FRAME_R); + } + + msg._body._frame._messages = _z_network_message_vec_make(0); + + return msg; +} + +/*------------------ Fragment Message ------------------*/ +_z_transport_message_t _z_t_msg_make_fragment_header(_z_zint_t sn, _Bool is_reliable, _Bool is_last) { + return _z_t_msg_make_fragment(sn, _z_bytes_empty(), is_reliable, is_last); +} +_z_transport_message_t _z_t_msg_make_fragment(_z_zint_t sn, _z_bytes_t payload, _Bool is_reliable, _Bool is_last) { + _z_transport_message_t msg; + msg._header = _Z_MID_T_FRAGMENT; + if (is_last == false) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_FRAGMENT_M); + } + if (is_reliable == true) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_FRAGMENT_R); + } + + msg._body._fragment._sn = sn; + msg._body._fragment._payload = payload; + + return msg; +} + +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); +} + +void _z_t_msg_copy_join(_z_t_msg_join_t *clone, _z_t_msg_join_t *msg) { + clone->_version = msg->_version; + clone->_whatami = msg->_whatami; + clone->_lease = msg->_lease; + clone->_seq_num_res = msg->_seq_num_res; + clone->_req_id_res = msg->_req_id_res; + clone->_batch_size = msg->_batch_size; + clone->_next_sn = msg->_next_sn; + memcpy(clone->_zid.id, msg->_zid.id, 16); +} + +void _z_t_msg_copy_init(_z_t_msg_init_t *clone, _z_t_msg_init_t *msg) { + clone->_version = msg->_version; + clone->_whatami = msg->_whatami; + clone->_seq_num_res = msg->_seq_num_res; + 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); +} + +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); +} + +void _z_t_msg_copy_close(_z_t_msg_close_t *clone, _z_t_msg_close_t *msg) { clone->_reason = msg->_reason; } + +void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_t *msg) { + (void)(clone); + (void)(msg); +} + +void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg) { + clone->_sn = msg->_sn; + _z_network_message_vec_copy(&clone->_messages, &msg->_messages); +} + +/*------------------ Transport Message ------------------*/ +void _z_t_msg_copy(_z_transport_message_t *clone, _z_transport_message_t *msg) { + clone->_header = msg->_header; + + uint8_t mid = _Z_MID(msg->_header); + switch (mid) { + case _Z_MID_T_JOIN: { + _z_t_msg_copy_join(&clone->_body._join, &msg->_body._join); + } break; + + case _Z_MID_T_INIT: { + _z_t_msg_copy_init(&clone->_body._init, &msg->_body._init); + } break; + + case _Z_MID_T_OPEN: { + _z_t_msg_copy_open(&clone->_body._open, &msg->_body._open); + } break; + + case _Z_MID_T_CLOSE: { + _z_t_msg_copy_close(&clone->_body._close, &msg->_body._close); + } break; + + case _Z_MID_T_KEEP_ALIVE: { + _z_t_msg_copy_keep_alive(&clone->_body._keep_alive, &msg->_body._keep_alive); + } break; + + case _Z_MID_T_FRAME: { + _z_t_msg_copy_frame(&clone->_body._frame, &msg->_body._frame); + } break; + + case _Z_MID_T_FRAGMENT: { + _z_t_msg_copy_fragment(&clone->_body._fragment, &msg->_body._fragment); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to copy transport message with unknown ID(%d)\n", mid); + } break; + } +} + +void _z_s_msg_clear(_z_scouting_message_t *msg) { + uint8_t mid = _Z_MID(msg->_header); + switch (mid) { + case _Z_MID_SCOUT: { + _z_s_msg_scout_clear(&msg->_body._scout); + } break; + + case _Z_MID_HELLO: { + _z_s_msg_hello_clear(&msg->_body._hello); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to clear session message with unknown ID(%d)\n", mid); + } break; + } +} + +/*=============================*/ +/* Transport Messages */ +/*=============================*/ +/*------------------ Scout Message ------------------*/ +_z_scouting_message_t _z_s_msg_make_scout(z_what_t what, _z_id_t zid) { + _z_scouting_message_t msg; + msg._header = _Z_MID_SCOUT; + + msg._body._scout._version = Z_PROTO_VERSION; + msg._body._scout._what = what; + msg._body._scout._zid = zid; + + return msg; +} + +/*------------------ Hello Message ------------------*/ +_z_scouting_message_t _z_s_msg_make_hello(z_whatami_t whatami, _z_id_t zid, _z_locator_array_t locators) { + _z_scouting_message_t msg; + msg._header = _Z_MID_HELLO; + + msg._body._hello._version = Z_PROTO_VERSION; + msg._body._hello._whatami = whatami; + msg._body._hello._zid = zid; + msg._body._hello._locators = locators; + + if (_z_locator_array_is_empty(&locators) == false) { + _Z_SET_FLAG(msg._header, _Z_FLAG_T_HELLO_L); + } + + return msg; +} + +void _z_s_msg_copy_scout(_z_s_msg_scout_t *clone, _z_s_msg_scout_t *msg) { + clone->_what = msg->_what; + clone->_version = msg->_version; + memcpy(clone->_zid.id, msg->_zid.id, 16); +} + +void _z_s_msg_copy_hello(_z_s_msg_hello_t *clone, _z_s_msg_hello_t *msg) { + _z_locator_array_copy(&clone->_locators, &msg->_locators); + memcpy(clone->_zid.id, msg->_zid.id, 16); + clone->_whatami = msg->_whatami; +} + +/*------------------ Scouting Message ------------------*/ +void _z_s_msg_copy(_z_scouting_message_t *clone, _z_scouting_message_t *msg) { + clone->_header = msg->_header; + + uint8_t mid = _Z_MID(msg->_header); + switch (mid) { + case _Z_MID_SCOUT: { + _z_s_msg_copy_scout(&clone->_body._scout, &msg->_body._scout); + } break; + + case _Z_MID_HELLO: { + _z_s_msg_copy_hello(&clone->_body._hello, &msg->_body._hello); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to copy session message with unknown ID(%d)\n", mid); + } break; + } +} \ No newline at end of file diff --git a/src/protocol/ext.c b/src/protocol/ext.c new file mode 100644 index 000000000..6202c11df --- /dev/null +++ b/src/protocol/ext.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/protocol/ext.h" + +#include + +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/utils/logging.h" + +_z_msg_ext_t _z_msg_ext_make_unit(uint8_t id) { + _z_msg_ext_t ext; + + ext._header = 0; + ext._header |= (id & _Z_EXT_ID_MASK); + ext._header |= _Z_MSG_EXT_ENC_UNIT; + + return ext; +} + +void _z_msg_ext_clear_unit(_z_msg_ext_unit_t *ext) { (void)(ext); } + +void _z_msg_ext_copy_unit(_z_msg_ext_unit_t *clone, const _z_msg_ext_unit_t *ext) { + (void)(clone); + (void)(ext); +} + +_z_msg_ext_t _z_msg_ext_make_zint(uint8_t id, _z_zint_t zid) { + _z_msg_ext_t ext; + + ext._header = 0; + ext._header |= (id & _Z_EXT_ID_MASK); + ext._header |= _Z_MSG_EXT_ENC_ZINT; + + ext._body._zint._val = zid; + + return ext; +} + +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 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); + + return ext; +} + +void _z_msg_ext_clear_zbuf(_z_msg_ext_zbuf_t *ext) { _z_bytes_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); +} + +void _z_msg_ext_copy(_z_msg_ext_t *clone, const _z_msg_ext_t *ext) { + clone->_header = ext->_header; + + uint8_t enc = _Z_EXT_ENC(clone->_header); + switch (enc) { + case _Z_MSG_EXT_ENC_UNIT: { + _z_msg_ext_copy_unit(&clone->_body._unit, &ext->_body._unit); + } break; + + case _Z_MSG_EXT_ENC_ZINT: { + _z_msg_ext_copy_zint(&clone->_body._zint, &ext->_body._zint); + } break; + + case _Z_MSG_EXT_ENC_ZBUF: { + _z_msg_ext_copy_zbuf(&clone->_body._zbuf, &ext->_body._zbuf); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to copy message extension with unknown encoding(%d)\n", enc); + } break; + } +} + +void _z_msg_ext_clear(_z_msg_ext_t *ext) { + uint8_t enc = _Z_EXT_ENC(ext->_header); + switch (enc) { + case _Z_MSG_EXT_ENC_UNIT: { + _z_msg_ext_clear_unit(&ext->_body._unit); + } break; + + case _Z_MSG_EXT_ENC_ZINT: { + _z_msg_ext_clear_zint(&ext->_body._zint); + } break; + + case _Z_MSG_EXT_ENC_ZBUF: { + _z_msg_ext_clear_zbuf(&ext->_body._zbuf); + } break; + + default: { + _Z_DEBUG("WARNING: Trying to free message extension with unknown encoding(%d)\n", enc); + } break; + } +} diff --git a/src/protocol/iobuf.c b/src/protocol/iobuf.c index eef65ad60..c5700886f 100644 --- a/src/protocol/iobuf.c +++ b/src/protocol/iobuf.c @@ -16,6 +16,7 @@ #include #include +#include #include #include "zenoh-pico/config.h" @@ -40,6 +41,10 @@ void __z_iosli_init(_z_iosli_t *ios, size_t capacity) { ios->_capacity = capacity; ios->_is_alloc = true; ios->_buf = (uint8_t *)z_malloc(capacity); + if (ios->_buf == NULL) { + ios->_capacity = 0; + ios->_is_alloc = false; + } } _z_iosli_t _z_iosli_make(size_t capacity) { @@ -80,14 +85,14 @@ size_t _z_iosli_writable(const _z_iosli_t *ios) { return ios->_capacity - ios->_ void _z_iosli_write(_z_iosli_t *ios, uint8_t b) { assert(_z_iosli_writable(ios) >= (size_t)1); ios->_buf[ios->_w_pos] = b; - ios->_w_pos = ios->_w_pos + 1; + ios->_w_pos += 1; } 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); - ios->_w_pos = ios->_w_pos + length; + ios->_w_pos += length; } void _z_iosli_put(_z_iosli_t *ios, uint8_t b, size_t pos) { @@ -166,11 +171,19 @@ _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) { + return (_z_zbuf_t){._ios = {._buf = (uint8_t *)slice.start, // Safety: `_z_zbuf_t` is an immutable buffer + ._is_alloc = false, + ._capacity = slice.len, + ._r_pos = 0, + ._w_pos = slice.len}}; +} 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); } 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; } @@ -249,14 +262,14 @@ _z_wbuf_t _z_wbuf_make(size_t capacity, _Bool is_expandable) { // Preallocate 4 slots, this is usually what we expect // when fragmenting a zenoh data message with attachment wbf._ioss = _z_iosli_vec_make(4); - _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(Z_IOSLICE_SIZE)); + _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); } else { wbf._ioss = _z_iosli_vec_make(1); _z_wbuf_add_iosli(&wbf, __z_wbuf_new_iosli(capacity)); } wbf._w_idx = 0; // This __must__ come after adding ioslices to reset w_idx wbf._r_idx = 0; - wbf._is_expandable = is_expandable; + wbf._expansion_step = is_expandable ? capacity : 0; wbf._capacity = capacity; return wbf; @@ -343,21 +356,22 @@ uint8_t _z_wbuf_get(const _z_wbuf_t *wbf, size_t pos) { } int8_t _z_wbuf_write(_z_wbuf_t *wbf, uint8_t b) { - int8_t ret = _Z_RES_OK; - _z_iosli_t *ios = _z_wbuf_get_iosli(wbf, wbf->_w_idx); size_t writable = _z_iosli_writable(ios); - if (writable >= (size_t)1) { - _z_iosli_write(ios, b); - } else if (wbf->_is_expandable == true) { - ios = __z_wbuf_new_iosli(Z_IOSLICE_SIZE); - _z_wbuf_add_iosli(wbf, ios); - _z_iosli_write(ios, b); - } else { - ret = _Z_ERR_TRANSPORT_NO_SPACE; + if (writable == (size_t)0) { + wbf->_w_idx += 1; + if (wbf->_ioss._len <= wbf->_w_idx) { + if (wbf->_expansion_step != 0) { + ios = __z_wbuf_new_iosli(wbf->_expansion_step); + _z_iosli_vec_append(&wbf->_ioss, ios); + } else { + return _Z_ERR_TRANSPORT_NO_SPACE; + } + } + ios = _z_wbuf_get_iosli(wbf, wbf->_w_idx); } - - return ret; + _z_iosli_write(ios, b); + return _Z_RES_OK; } int8_t _z_wbuf_write_bytes(_z_wbuf_t *wbf, const uint8_t *bs, size_t offset, size_t length) { @@ -370,12 +384,12 @@ int8_t _z_wbuf_write_bytes(_z_wbuf_t *wbf, const uint8_t *bs, size_t offset, siz size_t writable = _z_iosli_writable(ios); if (writable >= llength) { _z_iosli_write_bytes(ios, bs, loffset, llength); - } else if (wbf->_is_expandable == true) { + } else if (wbf->_expansion_step != 0) { _z_iosli_write_bytes(ios, bs, loffset, writable); llength = llength - writable; loffset = loffset + writable; while (llength > (size_t)0) { - ios = __z_wbuf_new_iosli(Z_IOSLICE_SIZE); + ios = __z_wbuf_new_iosli(wbf->_expansion_step); _z_wbuf_add_iosli(wbf, ios); writable = _z_iosli_writable(ios); @@ -518,7 +532,7 @@ void _z_wbuf_copy(_z_wbuf_t *dst, const _z_wbuf_t *src) { dst->_capacity = src->_capacity; dst->_r_idx = src->_r_idx; dst->_w_idx = src->_w_idx; - dst->_is_expandable = src->_is_expandable; + dst->_expansion_step = src->_expansion_step; _z_iosli_vec_copy(&dst->_ioss, &src->_ioss); } @@ -527,7 +541,7 @@ void _z_wbuf_reset(_z_wbuf_t *wbf) { wbf->_w_idx = 0; // Reset to default iosli allocation - for (size_t i = 0; i < _z_wbuf_len_iosli(wbf); i++) { + for (size_t i = 0; i < _z_iosli_vec_len(&wbf->_ioss); i++) { _z_iosli_t *ios = _z_wbuf_get_iosli(wbf, i); if (ios->_is_alloc == false) { _z_iosli_vec_remove(&wbf->_ioss, i); diff --git a/src/protocol/keyexpr.c b/src/protocol/keyexpr.c index e94b484dc..5d52a4377 100644 --- a/src/protocol/keyexpr.c +++ b/src/protocol/keyexpr.c @@ -18,9 +18,71 @@ #include #include +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/pointers.h" #include "zenoh-pico/utils/string.h" +_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, + }; +} + +void _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { + 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); +} + +_z_keyexpr_t _z_keyexpr_duplicate(_z_keyexpr_t src) { + _z_keyexpr_t dst; + _z_keyexpr_copy(&dst, &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_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); + } +} + +void _z_keyexpr_free(_z_keyexpr_t **rk) { + _z_keyexpr_t *ptr = *rk; + + if (ptr != NULL) { + _z_keyexpr_clear(ptr); + + z_free(ptr); + *rk = NULL; + } +} +_z_keyexpr_t _z_keyexpr_alias(_z_keyexpr_t src) { + _z_keyexpr_t alias = { + ._id = src._id, + ._mapping = src._mapping, + ._suffix = src._suffix, + }; + _z_keyexpr_set_owns_suffix(&alias, false); + return alias; +} + /*------------------ 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; @@ -745,4 +807,4 @@ 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); } +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 diff --git a/src/protocol/msg.c b/src/protocol/msg.c deleted file mode 100644 index 7d0c9ddba..000000000 --- a/src/protocol/msg.c +++ /dev/null @@ -1,985 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/protocol/msg.h" - -#include - -#include "zenoh-pico/protocol/core.h" -#include "zenoh-pico/session/queryable.h" -#include "zenoh-pico/utils/logging.h" - -/*=============================*/ -/* Message fields */ -/*=============================*/ -/*------------------ Payload field ------------------*/ -void _z_payload_clear(_z_payload_t *p) { _z_bytes_clear(p); } - -/*------------------ Timestamp Field ------------------*/ -void _z_timestamp_clear(_z_timestamp_t *ts) {} - -/*------------------ ResKey Field ------------------*/ -void _z_keyexpr_clear(_z_keyexpr_t *rk) { - rk->_id = 0; - if (rk->_suffix != NULL) { - _z_str_clear((char *)rk->_suffix); - } -} - -void _z_keyexpr_free(_z_keyexpr_t **rk) { - _z_keyexpr_t *ptr = *rk; - - if (ptr != NULL) { - _z_keyexpr_clear(ptr); - - z_free(ptr); - *rk = NULL; - } -} - -/*------------------ Locators Field ------------------*/ -void _z_locators_clear(_z_locator_array_t *ls) { _z_locator_array_clear(ls); } - -/*=============================*/ -/* Message decorators */ -/*=============================*/ -/*------------------ Attachment Decorator ------------------*/ -void _z_t_msg_clear_attachment(_z_attachment_t *a) { _z_payload_clear(&a->_payload); } - -/*------------------ ReplyContext Decorator ------------------*/ -_z_reply_context_t *_z_msg_make_reply_context(_z_zint_t qid, _z_bytes_t replier_id, _Bool is_final) { - _z_reply_context_t *rctx = (_z_reply_context_t *)z_malloc(sizeof(_z_reply_context_t)); - if (rctx != NULL) { - rctx->_qid = qid; - rctx->_replier_id = replier_id; - - rctx->_header = _Z_MID_REPLY_CONTEXT; - if (is_final == true) { - _Z_SET_FLAG(rctx->_header, _Z_FLAG_Z_F); - } - } - - return rctx; -} - -void _z_msg_clear_reply_context(_z_reply_context_t *rc) { - if (_Z_HAS_FLAG(rc->_header, _Z_FLAG_Z_F) == false) { - _z_bytes_clear(&rc->_replier_id); - } -} - -/*=============================*/ -/* Zenoh Messages */ -/*=============================*/ -/*------------------ Resource Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_resource(_z_zint_t id, _z_keyexpr_t key) { - _z_declaration_t decl; - - decl._body._res._id = id; - decl._body._res._key = key; - - decl._header = _Z_DECL_RESOURCE; - if (decl._body._res._key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - - return decl; -} - -void _z_msg_clear_declaration_resource(_z_res_decl_t *dcl) { _z_keyexpr_clear(&dcl->_key); } - -/*------------------ Forget Resource Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_forget_resource(_z_zint_t rid) { - _z_declaration_t decl; - - decl._body._forget_res._rid = rid; - - decl._header = _Z_DECL_FORGET_RESOURCE; - - return decl; -} - -void _z_msg_clear_declaration_forget_resource(_z_forget_res_decl_t *dcl) { (void)(dcl); } - -/*------------------ Publisher Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_publisher(_z_keyexpr_t key) { - _z_declaration_t decl; - - decl._body._pub._key = key; - - decl._header = _Z_DECL_PUBLISHER; - if (key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - - return decl; -} - -void _z_msg_clear_declaration_publisher(_z_pub_decl_t *dcl) { _z_keyexpr_clear(&dcl->_key); } - -/*------------------ Forget Publisher Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_forget_publisher(_z_keyexpr_t key) { - _z_declaration_t decl; - - decl._body._forget_pub._key = key; - - decl._header = _Z_DECL_FORGET_PUBLISHER; - if (key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - - return decl; -} - -void _z_msg_clear_declaration_forget_publisher(_z_forget_pub_decl_t *dcl) { _z_keyexpr_clear(&dcl->_key); } - -/*------------------ Subscriber Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_subscriber(_z_keyexpr_t key, _z_subinfo_t subinfo) { - _z_declaration_t decl; - - decl._body._sub._key = key; - decl._body._sub._subinfo = subinfo; - - decl._header = _Z_DECL_SUBSCRIBER; - if (key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - if (subinfo.mode != Z_SUBMODE_PUSH) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_S); - } - if (subinfo.reliability == Z_RELIABILITY_RELIABLE) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_R); - } - - return decl; -} - -void _z_subinfo_clear(_z_subinfo_t *si) { - (void)(si); - // Nothing to clear -} - -void _z_msg_clear_declaration_subscriber(_z_sub_decl_t *dcl) { - _z_keyexpr_clear(&dcl->_key); - _z_subinfo_clear(&dcl->_subinfo); -} - -/*------------------ Forget Subscriber Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_forget_subscriber(_z_keyexpr_t key) { - _z_declaration_t decl; - - decl._body._forget_sub._key = key; - - decl._header = _Z_DECL_FORGET_SUBSCRIBER; - if (key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - - return decl; -} - -void _z_msg_clear_declaration_forget_subscriber(_z_forget_sub_decl_t *dcl) { _z_keyexpr_clear(&dcl->_key); } - -/*------------------ Queryable Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_queryable(_z_keyexpr_t key, _z_zint_t complete, _z_zint_t distance) { - _z_declaration_t decl; - - decl._body._qle._key = key; - - decl._header = _Z_DECL_QUERYABLE; - if (key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - - decl._body._qle._complete = complete; - decl._body._qle._distance = distance; - if ((decl._body._qle._complete != _Z_QUERYABLE_COMPLETE_DEFAULT) || - (decl._body._qle._distance != _Z_QUERYABLE_DISTANCE_DEFAULT)) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_Q); - } - - return decl; -} - -void _z_msg_clear_declaration_queryable(_z_qle_decl_t *dcl) { _z_keyexpr_clear(&dcl->_key); } - -/*------------------ Forget Queryable Declaration ------------------*/ -_z_declaration_t _z_msg_make_declaration_forget_queryable(_z_keyexpr_t key) { - _z_declaration_t decl; - - decl._body._forget_qle._key = key; - - decl._header = _Z_DECL_FORGET_QUERYABLE; - if (key._suffix != NULL) { - _Z_SET_FLAG(decl._header, _Z_FLAG_Z_K); - } - - return decl; -} - -void _z_msg_clear_declaration_forget_queryable(_z_forget_qle_decl_t *dcl) { _z_keyexpr_clear(&dcl->_key); } - -/*------------------ Declare ------------------*/ -_z_zenoh_message_t _z_msg_make_declare(_z_declaration_array_t declarations) { - _z_zenoh_message_t msg; - - msg._body._declare._declarations = declarations; - - msg._header = _Z_MID_DECLARE; - - msg._attachment = NULL; - msg._reply_context = NULL; - - return msg; -} - -void _z_msg_clear_declaration(_z_declaration_t *dcl) { - uint8_t did = _Z_MID(dcl->_header); - switch (did) { - case _Z_DECL_RESOURCE: - _z_msg_clear_declaration_resource(&dcl->_body._res); - break; - case _Z_DECL_PUBLISHER: - _z_msg_clear_declaration_publisher(&dcl->_body._pub); - break; - case _Z_DECL_SUBSCRIBER: - _z_msg_clear_declaration_subscriber(&dcl->_body._sub); - break; - case _Z_DECL_QUERYABLE: - _z_msg_clear_declaration_queryable(&dcl->_body._qle); - break; - case _Z_DECL_FORGET_RESOURCE: - _z_msg_clear_declaration_forget_resource(&dcl->_body._forget_res); - break; - case _Z_DECL_FORGET_PUBLISHER: - _z_msg_clear_declaration_forget_publisher(&dcl->_body._forget_pub); - break; - case _Z_DECL_FORGET_SUBSCRIBER: - _z_msg_clear_declaration_forget_subscriber(&dcl->_body._forget_sub); - break; - case _Z_DECL_FORGET_QUERYABLE: - _z_msg_clear_declaration_forget_queryable(&dcl->_body._forget_qle); - break; - default: - _Z_DEBUG("WARNING: Trying to free declaration with unknown ID(%d)\n", did); - break; - } -} - -void _z_msg_clear_declare(_z_msg_declare_t *msg) { _z_declaration_array_clear(&msg->_declarations); } - -/*------------------ Data Info Field ------------------*/ -// @TODO: implement builder for _z_data_info_t - -void _z_data_info_clear(_z_data_info_t *di) { - _z_bytes_clear(&di->_encoding.suffix); - _z_bytes_clear(&di->_source_id); - _z_timestamp_clear(&di->_tstamp); -} - -/*------------------ Data Message ------------------*/ -_z_zenoh_message_t _z_msg_make_data(_z_keyexpr_t key, _z_data_info_t info, _z_payload_t payload, _Bool can_be_dropped) { - _z_zenoh_message_t msg; - - msg._body._data._key = key; - msg._body._data._info = info; - msg._body._data._payload = payload; - - msg._header = _Z_MID_DATA; - if (msg._body._data._info._flags != 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_I); - } - if (msg._body._data._key._suffix != NULL) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_K); - } - if (can_be_dropped == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_D); - } - - msg._attachment = NULL; - msg._reply_context = NULL; - - return msg; -} - -void _z_msg_clear_data(_z_msg_data_t *msg) { - _z_keyexpr_clear(&msg->_key); - _z_data_info_clear(&msg->_info); - _z_payload_clear(&msg->_payload); -} - -/*------------------ Unit Message ------------------*/ -_z_zenoh_message_t _z_msg_make_unit(_Bool can_be_dropped) { - _z_zenoh_message_t msg; - - msg._header = _Z_MID_UNIT; - if (can_be_dropped == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_D); - } - - msg._attachment = NULL; - msg._reply_context = NULL; - - return msg; -} - -void _z_msg_clear_unit(_z_msg_unit_t *unt) { (void)(unt); } - -/*------------------ Pull Message ------------------*/ -_z_zenoh_message_t _z_msg_make_pull(_z_keyexpr_t key, _z_zint_t pull_id, _z_zint_t max_samples, _Bool is_final) { - _z_zenoh_message_t msg; - - msg._body._pull._key = key; - msg._body._pull._pull_id = pull_id; - msg._body._pull._max_samples = max_samples; - - msg._header = _Z_MID_PULL; - if (is_final == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_F); - } - if (max_samples == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_N); - } - if (msg._body._pull._key._suffix != NULL) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_K); - } - - msg._attachment = NULL; - msg._reply_context = NULL; - - return msg; -} - -void _z_msg_clear_pull(_z_msg_pull_t *msg) { _z_keyexpr_clear(&msg->_key); } - -/*------------------ Query Message ------------------*/ -_z_zenoh_message_t _z_msg_make_query(_z_keyexpr_t key, char *parameters, _z_zint_t qid, z_query_target_t target, - z_consolidation_mode_t consolidation, _z_value_t value) { - _z_zenoh_message_t msg; - - msg._body._query._key = key; - msg._body._query._parameters = parameters; - msg._body._query._qid = qid; - msg._body._query._target = target; - msg._body._query._consolidation = consolidation; - (void)memset(&msg._body._query._info, 0, sizeof(msg._body._query._info)); - msg._body._query._info._encoding = value.encoding; - msg._body._query._payload = value.payload; - - msg._header = _Z_MID_QUERY; - if (msg._body._query._target != Z_QUERY_TARGET_BEST_MATCHING) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_T); - } - if (msg._body._query._key._suffix != NULL) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_K); - } - if (msg._body._query._payload.len > 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_Z_B); - } - - msg._attachment = NULL; - msg._reply_context = NULL; - - return msg; -} - -void _z_msg_clear_query(_z_msg_query_t *msg) { - _z_keyexpr_clear(&msg->_key); - _z_str_clear(msg->_parameters); -} - -/*------------------ Reply Message ------------------*/ -_z_zenoh_message_t _z_msg_make_reply(_z_keyexpr_t key, _z_data_info_t info, _z_payload_t payload, _Bool can_be_dropped, - _z_reply_context_t *rctx) { - _z_zenoh_message_t msg = _z_msg_make_data(key, info, payload, can_be_dropped); - msg._reply_context = rctx; - - return msg; -} - -/*------------------ Zenoh Message ------------------*/ -void _z_msg_clear(_z_zenoh_message_t *msg) { - if (msg->_attachment != NULL) { - _z_t_msg_clear_attachment(msg->_attachment); - z_free(msg->_attachment); - } - if (msg->_reply_context != NULL) { - _z_msg_clear_reply_context(msg->_reply_context); - z_free(msg->_reply_context); - } - - uint8_t mid = _Z_MID(msg->_header); - switch (mid) { - case _Z_MID_DECLARE: - _z_msg_clear_declare(&msg->_body._declare); - break; - case _Z_MID_DATA: - _z_msg_clear_data(&msg->_body._data); - break; - case _Z_MID_PULL: - _z_msg_clear_pull(&msg->_body._pull); - break; - case _Z_MID_QUERY: - _z_msg_clear_query(&msg->_body._query); - break; - case _Z_MID_UNIT: - _z_msg_clear_unit(&msg->_body._unit); - break; - default: - _Z_DEBUG("WARNING: Trying to clear message with unknown ID(%d)\n", mid); - break; - } -} - -/*=============================*/ -/* Transport Messages */ -/*=============================*/ -/*------------------ Scout Message ------------------*/ -_z_transport_message_t _z_t_msg_make_scout(z_whatami_t what, _Bool request_zid) { - _z_transport_message_t msg; - - msg._body._scout._what = what; - - msg._header = _Z_MID_SCOUT; - if (request_zid == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_I); - } - - if (what != Z_WHATAMI_ROUTER) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_W); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_scout(_z_t_msg_scout_t *clone, _z_t_msg_scout_t *msg) { clone->_what = msg->_what; } - -void _z_t_msg_clear_scout(_z_t_msg_scout_t *msg) { - // NOTE: scout does not involve any heap allocation - (void)(msg); -} - -/*------------------ Hello Message ------------------*/ -_z_transport_message_t _z_t_msg_make_hello(z_whatami_t whatami, _z_bytes_t zid, _z_locator_array_t locators) { - _z_transport_message_t msg; - - msg._body._hello._whatami = whatami; - msg._body._hello._zid = zid; - msg._body._hello._locators = locators; - - msg._header = _Z_MID_HELLO; - if (whatami != Z_WHATAMI_ROUTER) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_W); - } - if (_z_bytes_is_empty(&zid) == false) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_I); - } - if (_z_locator_array_is_empty(&locators) == false) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_L); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_hello(_z_t_msg_hello_t *clone, _z_t_msg_hello_t *msg) { - _z_locator_array_copy(&clone->_locators, &msg->_locators); - _z_bytes_copy(&clone->_zid, &msg->_zid); - clone->_whatami = msg->_whatami; -} - -void _z_t_msg_clear_hello(_z_t_msg_hello_t *msg) { - _z_bytes_clear(&msg->_zid); - _z_locators_clear(&msg->_locators); -} - -/*------------------ Join Message ------------------*/ -_z_transport_message_t _z_t_msg_make_join(uint8_t version, z_whatami_t whatami, _z_zint_t lease, - _z_zint_t sn_resolution, _z_bytes_t zid, _z_conduit_sn_list_t next_sns) { - _z_transport_message_t msg; - - msg._body._join._options = 0; - if (next_sns._is_qos == true) { - _Z_SET_FLAG(msg._body._join._options, _Z_OPT_JOIN_QOS); - } - msg._body._join._version = version; - msg._body._join._whatami = whatami; - msg._body._join._lease = lease; - msg._body._join._sn_resolution = sn_resolution; - msg._body._join._next_sns = next_sns; - msg._body._join._zid = zid; - - msg._header = _Z_MID_JOIN; - if ((lease % 1000) == 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_T1); - } - if (sn_resolution != Z_SN_RESOLUTION) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_S); - } - if (msg._body._join._options != 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_O); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_join(_z_t_msg_join_t *clone, _z_t_msg_join_t *msg) { - clone->_options = msg->_options; - clone->_version = msg->_version; - clone->_whatami = msg->_whatami; - clone->_lease = msg->_lease; - clone->_sn_resolution = msg->_sn_resolution; - clone->_next_sns = msg->_next_sns; - _z_bytes_copy(&clone->_zid, &msg->_zid); -} - -void _z_t_msg_clear_join(_z_t_msg_join_t *msg) { _z_bytes_clear(&msg->_zid); } - -/*------------------ Init Message ------------------*/ -_z_transport_message_t _z_t_msg_make_init_syn(uint8_t version, z_whatami_t whatami, _z_zint_t sn_resolution, - _z_bytes_t zid, _Bool is_qos) { - _z_transport_message_t msg; - - msg._body._init._options = 0; - if (is_qos == true) { - _Z_SET_FLAG(msg._body._init._options, _Z_OPT_INIT_QOS); - } - msg._body._init._version = version; - msg._body._init._whatami = whatami; - msg._body._init._sn_resolution = sn_resolution; - msg._body._init._zid = zid; - _z_bytes_reset(&msg._body._init._cookie); - - msg._header = _Z_MID_INIT; - if (sn_resolution != Z_SN_RESOLUTION) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_S); - } - if (msg._body._init._options != 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_O); - } - - msg._attachment = NULL; - - return msg; -} - -_z_transport_message_t _z_t_msg_make_init_ack(uint8_t version, z_whatami_t whatami, _z_zint_t sn_resolution, - _z_bytes_t zid, _z_bytes_t cookie, _Bool is_qos) { - _z_transport_message_t msg; - - msg._body._init._options = 0; - if (is_qos == true) { - _Z_SET_FLAG(msg._body._init._options, _Z_OPT_INIT_QOS); - } - msg._body._init._version = version; - msg._body._init._whatami = whatami; - msg._body._init._sn_resolution = sn_resolution; - msg._body._init._zid = zid; - msg._body._init._cookie = cookie; - - msg._header = _Z_MID_INIT; - _Z_SET_FLAG(msg._header, _Z_FLAG_T_A); - if (sn_resolution != Z_SN_RESOLUTION) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_S); - } - if (msg._body._init._options != 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_O); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_init(_z_t_msg_init_t *clone, _z_t_msg_init_t *msg) { - clone->_options = msg->_options; - clone->_version = msg->_version; - clone->_whatami = msg->_whatami; - clone->_sn_resolution = msg->_sn_resolution; - _z_bytes_copy(&clone->_zid, &msg->_zid); - _z_bytes_copy(&clone->_cookie, &msg->_cookie); -} - -void _z_t_msg_clear_init(_z_t_msg_init_t *msg) { - _z_bytes_clear(&msg->_zid); - _z_bytes_clear(&msg->_cookie); -} - -/*------------------ 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 msg; - - msg._body._open._lease = lease; - msg._body._open._initial_sn = initial_sn; - msg._body._open._cookie = cookie; - - msg._header = _Z_MID_OPEN; - if ((lease % 1000) == 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_T2); - } - - msg._attachment = NULL; - - return msg; -} - -_z_transport_message_t _z_t_msg_make_open_ack(_z_zint_t lease, _z_zint_t initial_sn) { - _z_transport_message_t msg; - - msg._body._open._lease = lease; - msg._body._open._initial_sn = initial_sn; - _z_bytes_reset(&msg._body._open._cookie); - - msg._header = _Z_MID_OPEN; - _Z_SET_FLAG(msg._header, _Z_FLAG_T_A); - if ((lease % 1000) == 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_T2); - } - - msg._attachment = NULL; - - return msg; -} - -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); -} - -void _z_t_msg_clear_open(_z_t_msg_open_t *msg) { _z_bytes_clear(&msg->_cookie); } - -/*------------------ Close Message ------------------*/ -_z_transport_message_t _z_t_msg_make_close(uint8_t reason, _z_bytes_t zid, _Bool link_only) { - _z_transport_message_t msg; - - msg._body._close._reason = reason; - msg._body._close._zid = zid; - - msg._header = _Z_MID_CLOSE; - if (_z_bytes_is_empty(&zid) == false) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_I); - } - if (link_only == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_K); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_close(_z_t_msg_close_t *clone, _z_t_msg_close_t *msg) { - _z_bytes_copy(&clone->_zid, &msg->_zid); - clone->_reason = msg->_reason; -} - -void _z_t_msg_clear_close(_z_t_msg_close_t *msg) { _z_bytes_clear(&msg->_zid); } - -/*------------------ Sync Message ------------------*/ -_z_transport_message_t _z_t_msg_make_sync(_z_zint_t sn, _Bool is_reliable, _z_zint_t count) { - _z_transport_message_t msg; - - msg._body._sync._sn = sn; - msg._body._sync._count = count; - - msg._header = _Z_MID_SYNC; - if (is_reliable == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_R); - if (count != 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_C); - } - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_sync(_z_t_msg_sync_t *clone, _z_t_msg_sync_t *msg) { - clone->_sn = msg->_sn; - clone->_count = msg->_count; -} - -void _z_t_msg_clear_sync(_z_t_msg_sync_t *msg) { - // NOTE: sync does not involve any heap allocation - (void)(msg); -} - -/*------------------ AckNack Message ------------------*/ -_z_transport_message_t _z_t_msg_make_ack_nack(_z_zint_t sn, _z_zint_t mask) { - _z_transport_message_t msg; - - msg._body._ack_nack._sn = sn; - msg._body._ack_nack._mask = mask; - - msg._header = _Z_MID_ACK_NACK; - if (mask != 0) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_M); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_ack_nack(_z_t_msg_ack_nack_t *clone, _z_t_msg_ack_nack_t *msg) { - clone->_sn = msg->_sn; - clone->_mask = msg->_mask; -} - -void _z_t_msg_clear_ack_nack(_z_t_msg_ack_nack_t *msg) { - // NOTE: ack_nack does not involve any heap allocation - (void)(msg); -} - -/*------------------ Keep Alive Message ------------------*/ -_z_transport_message_t _z_t_msg_make_keep_alive(_z_bytes_t zid) { - _z_transport_message_t msg; - - msg._body._keep_alive._zid = zid; - - msg._header = _Z_MID_KEEP_ALIVE; - if (_z_bytes_is_empty(&zid) == false) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_I); - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_keep_alive(_z_t_msg_keep_alive_t *clone, _z_t_msg_keep_alive_t *msg) { - _z_bytes_copy(&clone->_zid, &msg->_zid); -} - -void _z_t_msg_clear_keep_alive(_z_t_msg_keep_alive_t *msg) { _z_bytes_clear(&msg->_zid); } - -/*------------------ PingPong Messages ------------------*/ -_z_transport_message_t _z_t_msg_make_ping(_z_zint_t hash) { - _z_transport_message_t msg; - - msg._body._ping_pong._hash = hash; - - msg._header = _Z_MID_PING_PONG; - - msg._attachment = NULL; - - return msg; -} - -_z_transport_message_t _z_t_msg_make_pong(_z_zint_t hash) { - _z_transport_message_t msg; - - msg._body._ping_pong._hash = hash; - - msg._header = _Z_MID_PING_PONG; - _Z_SET_FLAG(msg._header, _Z_FLAG_T_P); - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_ping_pong(_z_t_msg_ping_pong_t *clone, _z_t_msg_ping_pong_t *msg) { clone->_hash = msg->_hash; } - -void _z_t_msg_clear_ping_pong(_z_t_msg_ping_pong_t *msg) { - // NOTE: ping_pong does not involve any heap allocation - (void)(msg); -} - -/*------------------ Frame Message ------------------*/ -_z_transport_message_t _z_t_msg_make_frame_header(_z_zint_t sn, _Bool is_reliable, _Bool is_fragment, _Bool is_final) { - _z_transport_message_t msg; - - msg._body._frame._sn = sn; - - // Reset payload content - (void)memset(&msg._body._frame._payload, 0, sizeof(_z_frame_payload_t)); - - msg._header = _Z_MID_FRAME; - if (is_reliable == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_R); - } - if (is_fragment == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_F); - if (is_final == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_E); - } - } - - msg._attachment = NULL; - - return msg; -} - -_z_transport_message_t _z_t_msg_make_frame(_z_zint_t sn, _z_frame_payload_t payload, _Bool is_reliable, - _Bool is_fragment, _Bool is_final) { - _z_transport_message_t msg; - - msg._body._frame._sn = sn; - msg._body._frame._payload = payload; - - msg._header = _Z_MID_FRAME; - if (is_reliable == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_R); - } - if (is_fragment == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_F); - if (is_final == true) { - _Z_SET_FLAG(msg._header, _Z_FLAG_T_E); - } - } - - msg._attachment = NULL; - - return msg; -} - -void _z_t_msg_copy_frame(_z_t_msg_frame_t *clone, _z_t_msg_frame_t *msg, uint8_t header) { - clone->_sn = msg->_sn; - if (_Z_HAS_FLAG(header, _Z_FLAG_T_F) == true) { - _z_bytes_copy(&clone->_payload._fragment, &msg->_payload._fragment); - } else { - _z_zenoh_message_vec_copy(&clone->_payload._messages, &msg->_payload._messages); - } -} - -void _z_t_msg_clear_frame(_z_t_msg_frame_t *msg, uint8_t header) { - if (_Z_HAS_FLAG(header, _Z_FLAG_T_F) == true) { - _z_payload_clear(&msg->_payload._fragment); - } else { - _z_zenoh_message_vec_clear(&msg->_payload._messages); - } -} - -/*------------------ Transport Message ------------------*/ -void _z_t_msg_copy(_z_transport_message_t *clone, _z_transport_message_t *msg) { - clone->_header = msg->_header; - clone->_attachment = msg->_attachment; - - uint8_t mid = _Z_MID(msg->_header); - switch (mid) { - case _Z_MID_SCOUT: { - _z_t_msg_copy_scout(&clone->_body._scout, &msg->_body._scout); - } break; - - case _Z_MID_HELLO: { - _z_t_msg_copy_hello(&clone->_body._hello, &msg->_body._hello); - } break; - - case _Z_MID_JOIN: { - _z_t_msg_copy_join(&clone->_body._join, &msg->_body._join); - } break; - - case _Z_MID_INIT: { - _z_t_msg_copy_init(&clone->_body._init, &msg->_body._init); - } break; - - case _Z_MID_OPEN: { - _z_t_msg_copy_open(&clone->_body._open, &msg->_body._open); - } break; - - case _Z_MID_CLOSE: { - _z_t_msg_copy_close(&clone->_body._close, &msg->_body._close); - } break; - - case _Z_MID_SYNC: { - _z_t_msg_copy_sync(&clone->_body._sync, &msg->_body._sync); - } break; - - case _Z_MID_ACK_NACK: { - _z_t_msg_copy_ack_nack(&clone->_body._ack_nack, &msg->_body._ack_nack); - } break; - - case _Z_MID_KEEP_ALIVE: { - _z_t_msg_copy_keep_alive(&clone->_body._keep_alive, &msg->_body._keep_alive); - } break; - - case _Z_MID_PING_PONG: { - _z_t_msg_copy_ping_pong(&clone->_body._ping_pong, &msg->_body._ping_pong); - } break; - - case _Z_MID_FRAME: { - _z_t_msg_copy_frame(&clone->_body._frame, &msg->_body._frame, clone->_header); - } break; - - default: { - _Z_DEBUG("WARNING: Trying to free session message with unknown ID(%d)\n", mid); - } break; - } -} - -void _z_t_msg_clear(_z_transport_message_t *msg) { - if (msg->_attachment != NULL) { - _z_t_msg_clear_attachment(msg->_attachment); - z_free(msg->_attachment); - } - - uint8_t mid = _Z_MID(msg->_header); - switch (mid) { - case _Z_MID_SCOUT: { - _z_t_msg_clear_scout(&msg->_body._scout); - } break; - - case _Z_MID_HELLO: { - _z_t_msg_clear_hello(&msg->_body._hello); - } break; - - case _Z_MID_JOIN: { - _z_t_msg_clear_join(&msg->_body._join); - } break; - - case _Z_MID_INIT: { - _z_t_msg_clear_init(&msg->_body._init); - } break; - - case _Z_MID_OPEN: { - _z_t_msg_clear_open(&msg->_body._open); - } break; - - case _Z_MID_CLOSE: { - _z_t_msg_clear_close(&msg->_body._close); - } break; - - case _Z_MID_SYNC: { - _z_t_msg_clear_sync(&msg->_body._sync); - } break; - - case _Z_MID_ACK_NACK: { - _z_t_msg_clear_ack_nack(&msg->_body._ack_nack); - } break; - - case _Z_MID_KEEP_ALIVE: { - _z_t_msg_clear_keep_alive(&msg->_body._keep_alive); - } break; - - case _Z_MID_PING_PONG: { - _z_t_msg_clear_ping_pong(&msg->_body._ping_pong); - } break; - - case _Z_MID_FRAME: { - _z_t_msg_clear_frame(&msg->_body._frame, msg->_header); - } break; - - default: { - _Z_DEBUG("WARNING: Trying to free session message with unknown ID(%d)\n", mid); - } break; - } -} diff --git a/src/protocol/msgcodec.c b/src/protocol/msgcodec.c deleted file mode 100644 index e2793d810..000000000 --- a/src/protocol/msgcodec.c +++ /dev/null @@ -1,1615 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// - -#include "zenoh-pico/protocol/msgcodec.h" - -#include -#include -#include - -#include "zenoh-pico/protocol/core.h" -#include "zenoh-pico/protocol/iobuf.h" -#include "zenoh-pico/protocol/keyexpr.h" -#include "zenoh-pico/utils/logging.h" - -/*=============================*/ -/* Fields */ -/*=============================*/ -/*------------------ Payload field ------------------*/ -int8_t _z_payload_encode(_z_wbuf_t *wbf, const _z_payload_t *pld) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _PAYLOAD\n"); - ret |= _z_bytes_encode(wbf, pld); - - return ret; -} - -int8_t _z_payload_decode_na(_z_payload_t *pld, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _PAYLOAD\n"); - return _z_bytes_decode(pld, zbf); -} - -int8_t _z_payload_decode(_z_payload_t *pld, _z_zbuf_t *zbf) { return _z_payload_decode_na(pld, zbf); } - -int8_t _z_id_encode(_z_wbuf_t *wbf, const _z_id_t *id) { - int len; - int8_t ret = _Z_RES_OK; - for (len = 15; len > 0; len--) { - if (id->id[len]) { - break; - } - } - len++; // `len` is treated as an "end" until this point, and as a length from then on - if (id->id[len] != 0) { - ret |= _z_wbuf_write(wbf, len); - ret |= _z_wbuf_write_bytes(wbf, id->id, 0, len); - } else { - _Z_DEBUG("Attempted to encode invalid ID 0"); - ret = _Z_ERR_MESSAGE_ZENOH_UNKNOWN; - } - return ret; -} - -/// Decodes a `zid` from the zbf, returning a negative value in case of error. -/// -/// 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(_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); - memset(id->id + len, 0, 16 - len); - return ret; -} - -/*------------------ Timestamp Field ------------------*/ -int8_t _z_timestamp_encode(_z_wbuf_t *wbf, const _z_timestamp_t *ts) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _TIMESTAMP\n"); - - _Z_EC(_z_uint64_encode(wbf, ts->time)) - ret |= _z_id_encode(wbf, &ts->id); - - return ret; -} - -int8_t _z_timestamp_decode_na(_z_timestamp_t *ts, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _TIMESTAMP\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_uint64_decode(&ts->time, zbf); - ret |= _z_id_decode(&ts->id, zbf); - - return ret; -} - -int8_t _z_timestamp_decode(_z_timestamp_t *ts, _z_zbuf_t *zbf) { return _z_timestamp_decode_na(ts, zbf); } - -/*------------------ SubMode Field ------------------*/ -int8_t _z_subinfo_encode(_z_wbuf_t *wbf, const _z_subinfo_t *fld) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _SUB_MODE\n"); - - uint8_t header = fld->mode; - if ((fld->period.origin != 0) || (fld->period.period != 0) || (fld->period.duration != 0)) { - _Z_SET_FLAG(header, _Z_FLAG_Z_P); - _Z_EC(_z_wbuf_write(wbf, header)) - ret |= _z_period_encode(wbf, &fld->period); - } else { - _Z_EC(_z_wbuf_write(wbf, header)) - } - - return ret; -} - -int8_t _z_subinfo_decode_na(_z_subinfo_t *si, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _SUB_MODE\n"); - int8_t ret = _Z_RES_OK; - - // Decode the header - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R) == true) { - si->reliability = Z_RELIABILITY_RELIABLE; - } else { - si->reliability = Z_RELIABILITY_BEST_EFFORT; - } - - uint8_t h_subifo; - ret |= _z_uint8_decode(&h_subifo, zbf); - si->mode = _Z_MID(h_subifo); - if (_Z_HAS_FLAG(h_subifo, _Z_FLAG_Z_P) == true) { - ret |= _z_period_decode(&si->period, zbf); - } else { - si->period = (_z_period_t){.origin = 0, .period = 0, .duration = 0}; - } - - return ret; -} - -int8_t _z_subinfo_decode(_z_subinfo_t *si, _z_zbuf_t *zbf, uint8_t header) { - return _z_subinfo_decode_na(si, zbf, header); -} - -/*------------------ ResKey Field ------------------*/ -int8_t _z_keyexpr_encode(_z_wbuf_t *wbf, uint8_t header, const _z_keyexpr_t *fld) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _RESKEY\n"); - - _Z_EC(_z_zint_encode(wbf, fld->_id)) - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_K) == true) { - _Z_EC(_z_str_encode(wbf, fld->_suffix)) - } - - return ret; -} - -int8_t _z_keyexpr_decode_na(_z_keyexpr_t *ke, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _RESKEY\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&ke->_id, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_K) == true) { - char *str = NULL; - ret |= _z_str_decode(&str, zbf); - if (ret == _Z_RES_OK) { - ke->_suffix = str; - } else { - ke->_suffix = NULL; - } - } else { - ke->_suffix = NULL; - } - - return ret; -} - -int8_t _z_keyexpr_decode(_z_keyexpr_t *ke, _z_zbuf_t *zbf, uint8_t header) { - return _z_keyexpr_decode_na(ke, zbf, header); -} - -/*------------------ Locators Field ------------------*/ -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\n"); - _Z_EC(_z_zint_encode(wbf, la->_len)) - for (size_t i = 0; i < la->_len; i++) { - char *s = _z_locator_to_str(&la->_val[i]); - _Z_EC(_z_str_encode(wbf, s)) - z_free(s); - } - - return ret; -} - -int8_t _z_locators_decode_na(_z_locator_array_t *a_loc, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _LOCATORS\n"); - int8_t ret = _Z_RES_OK; - - _z_zint_t len = 0; // Number of elements in the array - ret |= _z_zint_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); - 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); - } else { - a_loc->_len = i; - } - } - } else { - *a_loc = _z_locator_array_make(0); - } - - return ret; -} - -int8_t _z_locators_decode(_z_locator_array_t *a_loc, _z_zbuf_t *zbf) { return _z_locators_decode_na(a_loc, zbf); } - -/*=============================*/ -/* Message decorators */ -/*=============================*/ -/*------------------ Attachment Decorator ------------------*/ -int8_t _z_attachment_encode(_z_wbuf_t *wbf, const _z_attachment_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_ATTACHMENT\n"); - - // WARNING: we do not support sliced content in zenoh-pico. - // Disable the SLICED flag to be on the safe side. - _Z_EC(_z_wbuf_write(wbf, msg->_header & ~_Z_FLAG_T_Z)) - - ret |= _z_payload_encode(wbf, &msg->_payload); - - return ret; -} - -int8_t _z_attachment_decode_na(_z_attachment_t *atch, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_ATTACHMENT\n"); - int8_t ret = _Z_RES_OK; - - atch->_header = header; - - // WARNING: we do not support sliced content in zenoh-pico. - // Return error in case the payload is sliced. - if (_Z_HAS_FLAG(header, _Z_FLAG_T_Z) == false) { - ret |= _z_payload_decode(&atch->_payload, zbf); - } - - return ret; -} - -int8_t _z_attachment_decode(_z_attachment_t **atch, _z_zbuf_t *zbf, uint8_t header) { - int8_t ret = _Z_RES_OK; - - *atch = (_z_attachment_t *)z_malloc(sizeof(_z_attachment_t)); - if (atch != NULL) { - _z_attachment_t *ptr = *atch; - ret |= _z_attachment_decode_na(ptr, zbf, header); - if (ret != _Z_RES_OK) { - z_free(ptr); - *atch = NULL; - } - } else { - ret |= _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - - return ret; -} - -/*------------------ ReplyContext Decorator ------------------*/ -int8_t _z_reply_context_encode(_z_wbuf_t *wbf, const _z_reply_context_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_REPLY_CONTEXT\n"); - - _Z_EC(_z_wbuf_write(wbf, msg->_header)) - - _Z_EC(_z_zint_encode(wbf, msg->_qid)) - if (_Z_HAS_FLAG(msg->_header, _Z_FLAG_Z_F) == false) { - _Z_EC(_z_bytes_encode(wbf, &msg->_replier_id)) - } - - return ret; -} - -int8_t _z_reply_context_decode_na(_z_reply_context_t *rc, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_REPLY_CONTEXT\n"); - int8_t ret = _Z_RES_OK; - - rc->_header = header; - - ret |= _z_zint_decode(&rc->_qid, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_F) == false) { - _z_bytes_t rid; - ret |= _z_bytes_decode(&rid, zbf); - _z_bytes_copy(&rc->_replier_id, &rid); - } else { - rc->_replier_id = _z_bytes_empty(); - } - - return ret; -} - -int8_t _z_reply_context_decode(_z_reply_context_t **rc, _z_zbuf_t *zbf, uint8_t header) { - int8_t ret = _Z_RES_OK; - - *rc = (_z_reply_context_t *)z_malloc(sizeof(_z_reply_context_t)); - if (rc != NULL) { - _z_reply_context_t *ptr = *rc; - ret |= _z_reply_context_decode_na(ptr, zbf, header); - if (ret != _Z_RES_OK) { - z_free(ptr); - *rc = NULL; - } - } else { - ret |= _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - - return ret; -} - -/*=============================*/ -/* Zenoh Messages */ -/*=============================*/ -/*------------------ Resource Declaration ------------------*/ -int8_t _z_res_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_res_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_RESOURCE\n"); - - _Z_EC(_z_zint_encode(wbf, dcl->_id)) - ret |= _z_keyexpr_encode(wbf, header, &dcl->_key); - - return ret; -} - -int8_t _z_res_decl_decode_na(_z_res_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_RESOURCE\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&dcl->_id, zbf); - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - - return ret; -} - -int8_t _z_res_decl_decode(_z_res_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_res_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Publisher Declaration ------------------*/ -int8_t _z_pub_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_pub_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_PUBLISHER\n"); - - ret |= _z_keyexpr_encode(wbf, header, &dcl->_key); - - return ret; -} - -int8_t _z_pub_decl_decode_na(_z_pub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_PUBLISHER\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - - return ret; -} - -int8_t _z_pub_decl_decode(_z_pub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_pub_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Subscriber Declaration ------------------*/ -int8_t _z_sub_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_sub_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_SUBSCRIBER\n"); - - _Z_EC(_z_keyexpr_encode(wbf, header, &dcl->_key)) - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_S) == true) { - ret |= _z_subinfo_encode(wbf, &dcl->_subinfo); - } - - return ret; -} - -int8_t _z_sub_decl_decode_na(_z_sub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_SUBSCRIBER\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_S) == true) { - ret |= _z_subinfo_decode(&dcl->_subinfo, zbf, header); - } else { - dcl->_subinfo.mode = Z_SUBMODE_PUSH; // Default subscription mode is non-periodic PUSH - dcl->_subinfo.period = (_z_period_t){.origin = 0, .period = 0, .duration = 0}; - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_R) == true) { - dcl->_subinfo.reliability = Z_RELIABILITY_RELIABLE; - } else { - dcl->_subinfo.reliability = Z_RELIABILITY_BEST_EFFORT; - } - } - - return ret; -} - -int8_t _z_sub_decl_decode(_z_sub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_sub_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Queryable Declaration ------------------*/ -int8_t _z_qle_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_qle_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_QUERYABLE\n"); - - _Z_EC(_z_keyexpr_encode(wbf, header, &dcl->_key)); - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Q) == true) { - _Z_EC(_z_zint_encode(wbf, dcl->_complete)); - _Z_EC(_z_zint_encode(wbf, dcl->_distance)); - } - - return ret; -} - -int8_t _z_qle_decl_decode_na(_z_qle_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_QUERYABLE\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_Q) == true) { - ret |= _z_zint_decode(&dcl->_complete, zbf); - ret |= _z_zint_decode(&dcl->_distance, zbf); - } else { - dcl->_complete = 0; - dcl->_distance = 0; - } - - return ret; -} - -int8_t _z_qle_decl_decode(_z_qle_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_qle_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Forget Resource Declaration ------------------*/ -int8_t _z_forget_res_decl_encode(_z_wbuf_t *wbf, const _z_forget_res_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_FORGET_RESOURCE\n"); - - ret |= _z_zint_encode(wbf, dcl->_rid); - - return ret; -} - -int8_t _z_forget_res_decl_decode_na(_z_forget_res_decl_t *dcl, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _Z_DECL_FORGET_RESOURCE\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&dcl->_rid, zbf); - - return ret; -} - -int8_t _z_forget_res_decl_decode(_z_forget_res_decl_t *dcl, _z_zbuf_t *zbf) { - return _z_forget_res_decl_decode_na(dcl, zbf); -} - -/*------------------ Forget Publisher Declaration ------------------*/ -int8_t _z_forget_pub_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_forget_pub_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_FORGET_PUBLISHER\n"); - - ret |= _z_keyexpr_encode(wbf, header, &dcl->_key); - - return ret; -} - -int8_t _z_forget_pub_decl_decode_na(_z_forget_pub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_FORGET_PUBLISHER\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - - return ret; -} - -int8_t _z_forget_pub_decl_decode(_z_forget_pub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_forget_pub_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Forget Subscriber Declaration ------------------*/ -int8_t _z_forget_sub_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_forget_sub_decl_t *dcl) { - _Z_DEBUG("Encoding _Z_DECL_FORGET_PUBLISHER\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_encode(wbf, header, &dcl->_key); - - return ret; -} - -int8_t _z_forget_sub_decl_decode_na(_z_forget_sub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_FORGET_PUBLISHER\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - - return ret; -} - -int8_t _z_forget_sub_decl_decode(_z_forget_sub_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_forget_sub_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Forget Queryable Declaration ------------------*/ -int8_t _z_forget_qle_decl_encode(_z_wbuf_t *wbf, uint8_t header, const _z_forget_qle_decl_t *dcl) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DECL_FORGET_QUERYABLE\n"); - - ret |= _z_keyexpr_encode(wbf, header, &dcl->_key); - - return ret; -} - -int8_t _z_forget_qle_decl_decode_na(_z_forget_qle_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_DECL_FORGET_QUERYABLE\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&dcl->_key, zbf, header); - - return ret; -} - -int8_t _z_forget_qle_decl_decode(_z_forget_qle_decl_t *dcl, _z_zbuf_t *zbf, uint8_t header) { - return _z_forget_qle_decl_decode_na(dcl, zbf, header); -} - -/*------------------ Declaration Field ------------------*/ -int8_t _z_declaration_encode(_z_wbuf_t *wbf, _z_declaration_t *dcl) { - int8_t ret = _Z_RES_OK; - - _Z_EC(_z_wbuf_write(wbf, dcl->_header)) - uint8_t did = _Z_MID(dcl->_header); - switch (did) { - case _Z_DECL_RESOURCE: { - ret |= _z_res_decl_encode(wbf, dcl->_header, &dcl->_body._res); - } break; - - case _Z_DECL_PUBLISHER: { - ret |= _z_pub_decl_encode(wbf, dcl->_header, &dcl->_body._pub); - } break; - - case _Z_DECL_SUBSCRIBER: { - ret |= _z_sub_decl_encode(wbf, dcl->_header, &dcl->_body._sub); - } break; - - case _Z_DECL_QUERYABLE: { - ret |= _z_qle_decl_encode(wbf, dcl->_header, &dcl->_body._qle); - } break; - - case _Z_DECL_FORGET_RESOURCE: { - ret |= _z_forget_res_decl_encode(wbf, &dcl->_body._forget_res); - } break; - - case _Z_DECL_FORGET_PUBLISHER: { - ret |= _z_forget_pub_decl_encode(wbf, dcl->_header, &dcl->_body._forget_pub); - } break; - - case _Z_DECL_FORGET_SUBSCRIBER: { - ret |= _z_forget_sub_decl_encode(wbf, dcl->_header, &dcl->_body._forget_sub); - } break; - - case _Z_DECL_FORGET_QUERYABLE: { - ret |= _z_forget_qle_decl_encode(wbf, dcl->_header, &dcl->_body._forget_qle); - } break; - - default: { - _Z_DEBUG("WARNING: Trying to encode declaration with unknown ID(%d)\n", did); - ret |= _Z_ERR_MESSAGE_SERIALIZATION_FAILED; - } break; - } - - return ret; -} - -int8_t _z_declaration_decode_na(_z_declaration_t *decl, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - - ret |= _z_uint8_decode(&decl->_header, zbf); - if (ret == _Z_RES_OK) { - uint8_t mid = _Z_MID(decl->_header); - - switch (mid) { - case _Z_DECL_RESOURCE: { - ret |= _z_res_decl_decode(&decl->_body._res, zbf, decl->_header); - } break; - - case _Z_DECL_PUBLISHER: { - ret |= _z_pub_decl_decode(&decl->_body._pub, zbf, decl->_header); - } break; - - case _Z_DECL_SUBSCRIBER: { - ret |= _z_sub_decl_decode(&decl->_body._sub, zbf, decl->_header); - } break; - - case _Z_DECL_QUERYABLE: { - ret |= _z_qle_decl_decode(&decl->_body._qle, zbf, decl->_header); - } break; - - case _Z_DECL_FORGET_RESOURCE: { - ret |= _z_forget_res_decl_decode(&decl->_body._forget_res, zbf); - } break; - - case _Z_DECL_FORGET_PUBLISHER: { - ret |= _z_forget_pub_decl_decode(&decl->_body._forget_pub, zbf, decl->_header); - } break; - - case _Z_DECL_FORGET_SUBSCRIBER: { - ret |= _z_forget_sub_decl_decode(&decl->_body._forget_sub, zbf, decl->_header); - } break; - - case _Z_DECL_FORGET_QUERYABLE: { - ret |= _z_forget_qle_decl_decode(&decl->_body._forget_qle, zbf, decl->_header); - } break; - - default: { - _Z_DEBUG("WARNING: Trying to decode declaration with unknown ID(%d)\n", mid); - ret |= _Z_ERR_MESSAGE_DESERIALIZATION_FAILED; - } break; - } - } - - return ret; -} - -int8_t _z_declaration_decode(_z_declaration_t *decl, _z_zbuf_t *zbf) { return _z_declaration_decode_na(decl, zbf); } - -/*------------------ Declaration Message ------------------*/ -int8_t _z_declare_encode(_z_wbuf_t *wbf, const _z_msg_declare_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_DECLARE\n"); - - _Z_EC(_z_zint_encode(wbf, msg->_declarations._len)) - for (_z_zint_t i = 0; i < msg->_declarations._len; i++) { - _Z_EC(_z_declaration_encode(wbf, &msg->_declarations._val[i])); - } - - return ret; -} - -int8_t _z_declare_decode_na(_z_msg_declare_t *msg, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _Z_MID_DECLARE\n"); - int8_t ret = _Z_RES_OK; - - _z_zint_t len = 0; - ret |= _z_zint_decode(&len, zbf); - if (ret == _Z_RES_OK) { - msg->_declarations = _z_declaration_array_make(len); - for (size_t i = 0; (ret == _Z_RES_OK) && (i < len); i++) { - ret |= _z_declaration_decode_na(&msg->_declarations._val[i], zbf); - if (ret != _Z_RES_OK) { - msg->_declarations._len = i; - } - } - } else { - msg->_declarations = _z_declaration_array_make(0); - } - - return ret; -} - -int8_t _z_declare_decode(_z_msg_declare_t *msg, _z_zbuf_t *zbf) { return _z_declare_decode_na(msg, zbf); } - -/*------------------ Data Info Field ------------------*/ -int8_t _z_data_info_encode(_z_wbuf_t *wbf, const _z_data_info_t *fld) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_DATA_INFO\n"); - - // Encode the flags - // WARNING: we do not support sliced content in zenoh-pico. - // Disable the SLICED flag to be on the safe side. - _Z_EC(_z_zint_encode(wbf, fld->_flags & ~_Z_DATA_INFO_SLICED)) - - if (_Z_HAS_FLAG(fld->_flags, _Z_DATA_INFO_KIND) == true) { - _Z_EC(_z_uint8_encode(wbf, fld->_kind)) - } - if (_Z_HAS_FLAG(fld->_flags, _Z_DATA_INFO_ENC) == true) { - _Z_EC(_z_encoding_prefix_encode(wbf, fld->_encoding.prefix)) - _Z_EC(_z_bytes_encode(wbf, &fld->_encoding.suffix)) - } - if (_Z_HAS_FLAG(fld->_flags, _Z_DATA_INFO_TSTAMP) == true) { - _Z_EC(_z_timestamp_encode(wbf, &fld->_tstamp)) - } - if (_Z_HAS_FLAG(fld->_flags, _Z_DATA_INFO_SRC_ID) == true) { - _Z_EC(_z_bytes_encode(wbf, &fld->_source_id)) - } - if (_Z_HAS_FLAG(fld->_flags, _Z_DATA_INFO_SRC_SN) == true) { - _Z_EC(_z_zint_encode(wbf, fld->_source_sn)) - } - - return ret; -} - -int8_t _z_data_info_decode_na(_z_data_info_t *di, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _Z_DATA_INFO\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&di->_flags, zbf); - // WARNING: we do not support sliced content in zenoh-pico. - // Return error in case the payload is sliced. - if ((ret == _Z_RES_OK) && _Z_HAS_FLAG(di->_flags, _Z_DATA_INFO_SLICED) == false) { - if (_Z_HAS_FLAG(di->_flags, _Z_DATA_INFO_KIND) == true) { - ret |= _z_uint8_decode(&di->_kind, zbf); - } else { - di->_kind = Z_SAMPLE_KIND_PUT; - } - - if (_Z_HAS_FLAG(di->_flags, _Z_DATA_INFO_ENC) == true) { - ret |= _z_encoding_prefix_decode(&di->_encoding.prefix, zbf); - ret |= _z_bytes_decode(&di->_encoding.suffix, zbf); - } else { - di->_encoding.prefix = Z_ENCODING_PREFIX_EMPTY; - di->_encoding.suffix = _z_bytes_empty(); - } - - if (_Z_HAS_FLAG(di->_flags, _Z_DATA_INFO_TSTAMP) == true) { - ret |= _z_timestamp_decode(&di->_tstamp, zbf); - } else { - _z_timestamp_reset(&di->_tstamp); - } - - if (_Z_HAS_FLAG(di->_flags, _Z_DATA_INFO_SRC_ID) == true) { - ret |= _z_bytes_decode(&di->_source_id, zbf); - } else { - di->_source_id = _z_bytes_empty(); - } - - if (_Z_HAS_FLAG(di->_flags, _Z_DATA_INFO_SRC_SN) == true) { - ret |= _z_zint_decode(&di->_source_sn, zbf); - } else { - di->_source_sn = 0; - } - } - - return ret; -} - -int8_t _z_data_info_decode(_z_data_info_t *di, _z_zbuf_t *zbf) { return _z_data_info_decode_na(di, zbf); } - -/*------------------ Data Message ------------------*/ -int8_t _z_data_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_data_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_DATA\n"); - - _Z_EC(_z_keyexpr_encode(wbf, header, &msg->_key)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_I) == true) { - _Z_EC(_z_data_info_encode(wbf, &msg->_info)) - } - _Z_EC(_z_payload_encode(wbf, &msg->_payload)) - - return ret; -} - -int8_t _z_data_decode_na(_z_msg_data_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_DATA\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&msg->_key, zbf, header); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_I) == true) { - ret |= _z_data_info_decode(&msg->_info, zbf); - } else { - msg->_info._flags = 0; - msg->_info._kind = Z_SAMPLE_KIND_PUT; - msg->_info._encoding.prefix = Z_ENCODING_PREFIX_EMPTY; - msg->_info._encoding.suffix = _z_bytes_empty(); - msg->_info._source_id = _z_bytes_empty(); - msg->_info._source_sn = 0; - _z_timestamp_reset(&msg->_info._tstamp); - } - ret |= _z_payload_decode(&msg->_payload, zbf); - - return ret; -} - -int8_t _z_data_decode(_z_msg_data_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_data_decode_na(msg, zbf, header); -} - -/*------------------ Pull Message ------------------*/ -int8_t _z_pull_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_pull_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_PULL\n"); - - _Z_EC(_z_keyexpr_encode(wbf, header, &msg->_key)) - - _Z_EC(_z_zint_encode(wbf, msg->_pull_id)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_N) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_max_samples)) - } - - return ret; -} - -int8_t _z_pull_decode_na(_z_msg_pull_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_PULL\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&msg->_key, zbf, header); - ret |= _z_zint_decode(&msg->_pull_id, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_N) == true) { - ret |= _z_zint_decode(&msg->_max_samples, zbf); - } else { - msg->_max_samples = 1; // FIXME: confirm default value - } - - return ret; -} - -int8_t _z_pull_decode(_z_msg_pull_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_pull_decode_na(msg, zbf, header); -} - -/*------------------ Query Message ------------------*/ -int8_t _z_query_encode(_z_wbuf_t *wbf, uint8_t header, const _z_msg_query_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_QUERY\n"); - - _Z_EC(_z_keyexpr_encode(wbf, header, &msg->_key)) - - _Z_EC(_z_str_encode(wbf, msg->_parameters)) - - _Z_EC(_z_zint_encode(wbf, msg->_qid)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_T) == true) { - _Z_EC(_z_query_target_encode(wbf, msg->_target)) - } - ret |= _z_consolidation_mode_encode(wbf, msg->_consolidation); - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_B) == true) { - _Z_EC(_z_data_info_encode(wbf, &msg->_info)) - _Z_EC(_z_payload_encode(wbf, &msg->_payload)) - } - - return ret; -} - -int8_t _z_query_decode_na(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_QUERY\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_keyexpr_decode(&msg->_key, zbf, header); - ret |= _z_str_decode(&msg->_parameters, zbf); - ret |= _z_zint_decode(&msg->_qid, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_T) == true) { - ret |= _z_query_target_decode(&msg->_target, zbf); - } else { - msg->_target = Z_QUERY_TARGET_BEST_MATCHING; - } - ret |= _z_consolidation_mode_decode(&msg->_consolidation, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_I) == true) { - ret |= _z_data_info_decode(&msg->_info, zbf); - ret |= _z_payload_decode(&msg->_payload, zbf); - } else { - msg->_info._flags = 0; - msg->_info._kind = Z_SAMPLE_KIND_PUT; - msg->_info._encoding.prefix = Z_ENCODING_PREFIX_EMPTY; - msg->_info._encoding.suffix = _z_bytes_empty(); - msg->_info._source_id = _z_bytes_empty(); - msg->_info._source_sn = 0; - _z_timestamp_reset(&msg->_info._tstamp); - msg->_payload = _z_bytes_empty(); - } - - return ret; -} - -int8_t _z_query_decode(_z_msg_query_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_query_decode_na(msg, zbf, header); -} - -/*------------------ Zenoh Message ------------------*/ -int8_t _z_zenoh_message_encode(_z_wbuf_t *wbf, const _z_zenoh_message_t *msg) { - int8_t ret = _Z_RES_OK; - - // Encode the decorators if present - if (msg->_attachment != NULL) { - _Z_EC(_z_attachment_encode(wbf, msg->_attachment)) - } - if (msg->_reply_context != NULL) { - _Z_EC(_z_reply_context_encode(wbf, msg->_reply_context)) - } - - _Z_EC(_z_wbuf_write(wbf, msg->_header)) - - uint8_t mid = _Z_MID(msg->_header); - switch (mid) { - case _Z_MID_DATA: { - ret |= _z_data_encode(wbf, msg->_header, &msg->_body._data); - } break; - - case _Z_MID_QUERY: { - ret |= _z_query_encode(wbf, msg->_header, &msg->_body._query); - } break; - - case _Z_MID_DECLARE: { - ret |= _z_declare_encode(wbf, &msg->_body._declare); - } break; - - case _Z_MID_PULL: { - ret |= _z_pull_encode(wbf, msg->_header, &msg->_body._pull); - } break; - - case _Z_MID_UNIT: { - // Do nothing. Unit messages have no body - } break; - - default: { - _Z_DEBUG("WARNING: Trying to encode message with unknown ID(%d)\n", mid); - ret |= _Z_ERR_MESSAGE_ZENOH_UNKNOWN; - } break; - } - - return ret; -} - -int8_t _z_zenoh_message_decode_na(_z_zenoh_message_t *msg, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - - msg->_attachment = NULL; - msg->_reply_context = NULL; - _Bool is_last = false; - do { - ret |= _z_uint8_decode(&msg->_header, zbf); - if (ret == _Z_RES_OK) { - uint8_t mid = _Z_MID(msg->_header); - switch (mid) { - case _Z_MID_DATA: { - ret |= _z_data_decode(&msg->_body._data, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_ATTACHMENT: { - ret |= _z_attachment_decode(&msg->_attachment, zbf, msg->_header); - } break; - - case _Z_MID_REPLY_CONTEXT: { - ret |= _z_reply_context_decode(&msg->_reply_context, zbf, msg->_header); - } break; - - case _Z_MID_QUERY: { - ret |= _z_query_decode(&msg->_body._query, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_DECLARE: { - ret |= _z_declare_decode(&msg->_body._declare, zbf); - is_last = true; - } break; - - case _Z_MID_PULL: { - ret |= _z_pull_decode(&msg->_body._pull, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_UNIT: { - // Do nothing. Unit messages have no body. - is_last = true; - } break; - - case _Z_MID_PRIORITY: { - // Ignore the priority decorator for the time being since zenoh-pico does not - // perform any routing. Hence, priority information does not need to be propagated. - } break; - - case _Z_MID_LINK_STATE_LIST: { - _Z_DEBUG("WARNING: Link state not supported in zenoh-pico\n"); - is_last = true; - } break; - - default: { - _Z_DEBUG("WARNING: Trying to decode zenoh message with unknown ID(%d)\n", mid); - ret |= _Z_ERR_MESSAGE_ZENOH_UNKNOWN; - } break; - } - } else { - msg->_header = 0xFF; - } - } while ((ret == _Z_RES_OK) && (is_last == false)); - - return ret; -} - -int8_t _z_zenoh_message_decode(_z_zenoh_message_t *msg, _z_zbuf_t *zbf) { return _z_zenoh_message_decode_na(msg, zbf); } - -/*=============================*/ -/* Transport Messages */ -/*=============================*/ -/*------------------ Scout Message ------------------*/ -int8_t _z_scout_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_scout_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_SCOUT\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_W) == true) { - _Z_EC(_z_whatami_encode(wbf, msg->_what)) - } - - return ret; -} - -int8_t _z_scout_decode_na(_z_t_msg_scout_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_SCOUT\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_W) == true) { - ret |= _z_whatami_decode(&msg->_what, zbf); - } else { - msg->_what = Z_WHATAMI_ROUTER; - } - - return ret; -} - -int8_t _z_scout_decode(_z_t_msg_scout_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_scout_decode_na(msg, zbf, header); -} - -/*------------------ Hello Message ------------------*/ -int8_t _z_hello_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_hello_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_HELLO\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - _Z_EC(_z_bytes_encode(wbf, &msg->_zid)) - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_W) == true) { - _Z_EC(_z_whatami_encode(wbf, msg->_whatami)) - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_L) == true) { - _Z_EC(_z_locators_encode(wbf, &msg->_locators)) - } - - return ret; -} - -int8_t _z_hello_decode_na(_z_t_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_HELLO\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - ret |= _z_bytes_decode(&msg->_zid, zbf); - } else { - msg->_zid = _z_bytes_empty(); - } - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_W) == true) { - ret |= _z_whatami_decode(&msg->_whatami, zbf); - } else { - msg->_whatami = Z_WHATAMI_ROUTER; - } - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_L) == true) { - ret |= _z_locators_decode(&msg->_locators, zbf); - } else { - msg->_locators = _z_locator_array_make(0); - } - - return ret; -} - -int8_t _z_hello_decode(_z_t_msg_hello_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_hello_decode_na(msg, zbf, header); -} - -/*------------------ 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; - _Z_DEBUG("Encoding _Z_MID_JOIN\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_O) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_options)) - } - _Z_EC(_z_uint8_encode(wbf, msg->_version)) - _Z_EC(_z_whatami_encode(wbf, msg->_whatami)) - _Z_EC(_z_bytes_encode(wbf, &msg->_zid)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_T1) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_lease / 1000)) - } else { - _Z_EC(_z_zint_encode(wbf, msg->_lease)) - } - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_S) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_sn_resolution)) - } - if (_Z_HAS_FLAG(msg->_options, _Z_OPT_JOIN_QOS) == true) { - for (uint8_t i = 0; i < Z_PRIORITIES_NUM; i++) { - _Z_EC(_z_zint_encode(wbf, msg->_next_sns._val._qos[i]._reliable)) - _Z_EC(_z_zint_encode(wbf, msg->_next_sns._val._qos[i]._best_effort)) - } - } else { - _Z_EC(_z_zint_encode(wbf, msg->_next_sns._val._plain._reliable)) - _Z_EC(_z_zint_encode(wbf, msg->_next_sns._val._plain._best_effort)) - } - - return ret; -} - -int8_t _z_join_decode_na(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_JOIN\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_O) == true) { - ret |= _z_zint_decode(&msg->_options, zbf); - } else { - msg->_options = 0; - } - ret |= _z_uint8_decode(&msg->_version, zbf); - ret |= _z_whatami_decode(&msg->_whatami, zbf); - ret |= _z_bytes_decode(&msg->_zid, zbf); - ret |= _z_zint_decode(&msg->_lease, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_T_T1) == true) { - msg->_lease = msg->_lease * 1000; - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_S) == true) { - ret |= _z_zint_decode(&msg->_sn_resolution, zbf); - } else { - msg->_sn_resolution = Z_SN_RESOLUTION; - } - if (_Z_HAS_FLAG(msg->_options, _Z_OPT_JOIN_QOS) == true) { - msg->_next_sns._is_qos = true; - for (uint8_t i = 0; (ret == _Z_RES_OK) && (i < Z_PRIORITIES_NUM); i++) { - ret |= _z_zint_decode(&msg->_next_sns._val._qos[i]._reliable, zbf); - ret |= _z_zint_decode(&msg->_next_sns._val._qos[i]._best_effort, zbf); - } - } else { - msg->_next_sns._is_qos = false; - ret |= _z_zint_decode(&msg->_next_sns._val._plain._reliable, zbf); - ret |= _z_zint_decode(&msg->_next_sns._val._plain._best_effort, zbf); - } - - return ret; -} - -int8_t _z_join_decode(_z_t_msg_join_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_join_decode_na(msg, zbf, header); -} - -/*------------------ Init Message ------------------*/ -int8_t _z_init_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_init_t *msg) { - _Z_DEBUG("Encoding _Z_MID_INIT\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_O) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_options)) - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == false) { - _Z_EC(_z_wbuf_write(wbf, msg->_version)) - } - _Z_EC(_z_whatami_encode(wbf, msg->_whatami)) - _Z_EC(_z_bytes_encode(wbf, &msg->_zid)) - if (_Z_HAS_FLAG(header, _Z_FLAG_T_S) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_sn_resolution)) - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == true) { - _Z_EC(_z_bytes_encode(wbf, &msg->_cookie)) - } - - return ret; -} - -int8_t _z_init_decode_na(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_INIT\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_O) == true) { - ret |= _z_zint_decode(&msg->_options, zbf); - } else { - msg->_options = 0; - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == false) { - ret |= _z_uint8_decode(&msg->_version, zbf); - } else { - msg->_version = Z_PROTO_VERSION; - } - ret |= _z_whatami_decode(&msg->_whatami, zbf); - ret |= _z_bytes_decode(&msg->_zid, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_T_S) == true) { - ret |= _z_zint_decode(&msg->_sn_resolution, zbf); - } else { - msg->_sn_resolution = Z_SN_RESOLUTION; - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == true) { - ret |= _z_bytes_decode(&msg->_cookie, zbf); - } else { - msg->_cookie = _z_bytes_empty(); - } - - return ret; -} - -int8_t _z_init_decode(_z_t_msg_init_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_init_decode_na(msg, zbf, header); -} - -/*------------------ Open Message ------------------*/ -int8_t _z_open_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_open_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_OPEN\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_T2) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_lease / 1000)) - } else { - _Z_EC(_z_zint_encode(wbf, msg->_lease)) - } - - _Z_EC(_z_zint_encode(wbf, msg->_initial_sn)) - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == false) { - _Z_EC(_z_bytes_encode(wbf, &msg->_cookie)) - } - - return ret; -} - -int8_t _z_open_decode_na(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_OPEN\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&msg->_lease, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_T_T2) == true) { - msg->_lease = msg->_lease * 1000; - } - ret |= _z_zint_decode(&msg->_initial_sn, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == false) { - ret |= _z_bytes_decode(&msg->_cookie, zbf); - } else { - msg->_cookie = _z_bytes_empty(); - } - - return ret; -} - -int8_t _z_open_decode(_z_t_msg_open_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_open_decode_na(msg, zbf, header); -} - -/*------------------ Close Message ------------------*/ -int8_t _z_close_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_close_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_CLOSE\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - _Z_EC(_z_bytes_encode(wbf, &msg->_zid)) - } - ret |= _z_wbuf_write(wbf, msg->_reason); - - return ret; -} - -int8_t _z_close_decode_na(_z_t_msg_close_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_CLOSE\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - ret |= _z_bytes_decode(&msg->_zid, zbf); - } else { - msg->_zid = _z_bytes_empty(); - } - ret |= _z_uint8_decode(&msg->_reason, zbf); - - return ret; -} - -int8_t _z_close_decode(_z_t_msg_close_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_close_decode_na(msg, zbf, header); -} - -/*------------------ Sync Message ------------------*/ -int8_t _z_sync_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_sync_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_SYNC\n"); - - _Z_EC(_z_zint_encode(wbf, msg->_sn)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_C) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_count)) - } - - return ret; -} - -int8_t _z_sync_decode_na(_z_t_msg_sync_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_SYNC\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&msg->_sn, zbf); - if ((_Z_HAS_FLAG(header, _Z_FLAG_T_R) == true) && (_Z_HAS_FLAG(header, _Z_FLAG_T_C) == true)) { - ret |= _z_zint_decode(&msg->_count, zbf); - } else { - msg->_count = 0; - } - - return ret; -} - -int8_t _z_sync_decode(_z_t_msg_sync_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_sync_decode_na(msg, zbf, header); -} - -/*------------------ AckNack Message ------------------*/ -int8_t _z_ack_nack_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_ack_nack_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_ACK_NACK\n"); - - _Z_EC(_z_zint_encode(wbf, msg->_sn)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_M) == true) { - _Z_EC(_z_zint_encode(wbf, msg->_mask)) - } - - return ret; -} - -int8_t _z_ack_nack_decode_na(_z_t_msg_ack_nack_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_ACK_NACK\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&msg->_sn, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_T_M) == true) { - ret |= _z_zint_decode(&msg->_mask, zbf); - } else { - msg->_mask = 0; - } - - return ret; -} - -int8_t _z_ack_nack_decode(_z_t_msg_ack_nack_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_ack_nack_decode_na(msg, zbf, header); -} - -/*------------------ Keep Alive Message ------------------*/ -int8_t _z_keep_alive_encode(_z_wbuf_t *wbf, uint8_t header, const _z_t_msg_keep_alive_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_KEEP_ALIVE\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - _Z_EC(_z_bytes_encode(wbf, &msg->_zid)) - } - - return ret; -} - -int8_t _z_keep_alive_decode_na(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_KEEP_ALIVE\n"); - int8_t ret = _Z_RES_OK; - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - ret |= _z_bytes_decode(&msg->_zid, zbf); - } else { - msg->_zid = _z_bytes_empty(); - } - - return ret; -} - -int8_t _z_keep_alive_decode(_z_t_msg_keep_alive_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_keep_alive_decode_na(msg, zbf, header); -} - -/*------------------ PingPong Messages ------------------*/ -int8_t _z_ping_pong_encode(_z_wbuf_t *wbf, const _z_t_msg_ping_pong_t *msg) { - int8_t ret = _Z_RES_OK; - _Z_DEBUG("Encoding _Z_MID_PING_PONG\n"); - - ret |= _z_zint_encode(wbf, msg->_hash); - - return ret; -} - -int8_t _z_ping_pong_decode_na(_z_t_msg_ping_pong_t *msg, _z_zbuf_t *zbf) { - _Z_DEBUG("Decoding _Z_MID_PING_PONG\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&msg->_hash, zbf); - - return ret; -} - -int8_t _z_ping_pong_decode(_z_t_msg_ping_pong_t *msg, _z_zbuf_t *zbf) { return _z_ping_pong_decode_na(msg, zbf); } - -/*------------------ Frame Message ------------------*/ -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_DEBUG("Encoding _Z_MID_FRAME\n"); - - _Z_EC(_z_zint_encode(wbf, msg->_sn)) - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_F) == true) { - // Do not write the fragment as _z_bytes_t since the total frame length - // is eventually prepended to the frame. There is no need to encode the fragment length. - ret |= _z_wbuf_write_bytes(wbf, msg->_payload._fragment.start, 0, msg->_payload._fragment.len); - } else { - size_t len = _z_zenoh_message_vec_len(&msg->_payload._messages); - for (size_t i = 0; i < len; i++) { - _Z_EC(_z_zenoh_message_encode(wbf, _z_zenoh_message_vec_get(&msg->_payload._messages, i))) - } - } - - return ret; -} - -int8_t _z_frame_decode_na(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header) { - _Z_DEBUG("Decoding _Z_MID_FRAME\n"); - int8_t ret = _Z_RES_OK; - - ret |= _z_zint_decode(&msg->_sn, zbf); - if (_Z_HAS_FLAG(header, _Z_FLAG_T_F) == true) { - msg->_payload._fragment = _z_bytes_wrap(_z_zbuf_get_rptr(zbf), _z_zbuf_len(zbf)); // All remaining bytes - _z_zbuf_set_rpos(zbf, _z_zbuf_get_wpos(zbf)); // Manually move the r_pos to w_pos, we have read it all - } else { - if (ret == _Z_RES_OK) { - msg->_payload._messages = _z_zenoh_message_vec_make(_ZENOH_PICO_FRAME_MESSAGES_VEC_SIZE); - while (_z_zbuf_len(zbf) > 0) { - // Mark the reading position of the iobfer - size_t r_pos = _z_zbuf_get_rpos(zbf); - _z_zenoh_message_t *zm = (_z_zenoh_message_t *)z_malloc(sizeof(_z_zenoh_message_t)); - ret |= _z_zenoh_message_decode(zm, zbf); - if (ret == _Z_RES_OK) { - _z_zenoh_message_vec_append(&msg->_payload._messages, zm); - } else { - _z_zbuf_set_rpos(zbf, r_pos); // Restore the reading position of the iobfer - - // FIXME: Check for the return error, since not all of them means a decoding error - // in this particular case. As of now, we roll-back the reading position - // and return to the Zenoh transport-level decoder. - // https://github.com/eclipse-zenoh/zenoh-pico/pull/132#discussion_r1045593602 - if ((ret & _Z_ERR_MESSAGE_ZENOH_UNKNOWN) == _Z_ERR_MESSAGE_ZENOH_UNKNOWN) { - ret = _Z_RES_OK; - } - break; - } - } - } else { - msg->_payload._messages = _z_zenoh_message_vec_make(0); - } - } - - return ret; -} - -int8_t _z_frame_decode(_z_t_msg_frame_t *msg, _z_zbuf_t *zbf, uint8_t header) { - return _z_frame_decode_na(msg, zbf, header); -} - -/*------------------ Transport Message ------------------*/ -int8_t _z_transport_message_encode(_z_wbuf_t *wbf, const _z_transport_message_t *msg) { - int8_t ret = _Z_RES_OK; - - // Encode the decorators if present - if (msg->_attachment != NULL) { - _Z_EC(_z_attachment_encode(wbf, msg->_attachment)) - } - - _Z_EC(_z_wbuf_write(wbf, msg->_header)) - - switch (_Z_MID(msg->_header)) { - case _Z_MID_FRAME: { - ret |= _z_frame_encode(wbf, msg->_header, &msg->_body._frame); - } break; - - case _Z_MID_KEEP_ALIVE: { - ret |= _z_keep_alive_encode(wbf, msg->_header, &msg->_body._keep_alive); - } break; - - case _Z_MID_JOIN: { - ret |= _z_join_encode(wbf, msg->_header, &msg->_body._join); - } break; - - case _Z_MID_SCOUT: { - ret |= _z_scout_encode(wbf, msg->_header, &msg->_body._scout); - } break; - - case _Z_MID_HELLO: { - ret |= _z_hello_encode(wbf, msg->_header, &msg->_body._hello); - } break; - - case _Z_MID_INIT: { - ret |= _z_init_encode(wbf, msg->_header, &msg->_body._init); - } break; - - case _Z_MID_OPEN: { - ret |= _z_open_encode(wbf, msg->_header, &msg->_body._open); - } break; - - case _Z_MID_CLOSE: { - ret |= _z_close_encode(wbf, msg->_header, &msg->_body._close); - } break; - - case _Z_MID_SYNC: { - ret |= _z_sync_encode(wbf, msg->_header, &msg->_body._sync); - } break; - - case _Z_MID_ACK_NACK: { - ret |= _z_ack_nack_encode(wbf, msg->_header, &msg->_body._ack_nack); - } break; - - case _Z_MID_PING_PONG: { - ret |= _z_ping_pong_encode(wbf, &msg->_body._ping_pong); - } break; - - default: { - _Z_DEBUG("WARNING: Trying to encode session message with unknown ID(%d)\n", _Z_MID(msg->_header)); - ret |= _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN; - } break; - } - - return ret; -} - -int8_t _z_transport_message_decode_na(_z_transport_message_t *msg, _z_zbuf_t *zbf) { - int8_t ret = _Z_RES_OK; - - msg->_attachment = NULL; - _Bool is_last = false; - - do { - ret |= _z_uint8_decode(&msg->_header, zbf); // Decode the header - if (ret == _Z_RES_OK) { - uint8_t mid = _Z_MID(msg->_header); - switch (mid) { - case _Z_MID_FRAME: { - ret |= _z_frame_decode(&msg->_body._frame, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_ATTACHMENT: { - ret |= _z_attachment_decode(&msg->_attachment, zbf, msg->_header); - } break; - - case _Z_MID_KEEP_ALIVE: { - ret |= _z_keep_alive_decode(&msg->_body._keep_alive, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_JOIN: { - ret |= _z_join_decode(&msg->_body._join, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_SCOUT: { - ret |= _z_scout_decode(&msg->_body._scout, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_HELLO: { - ret |= _z_hello_decode(&msg->_body._hello, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_INIT: { - ret |= _z_init_decode(&msg->_body._init, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_OPEN: { - ret |= _z_open_decode(&msg->_body._open, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_CLOSE: { - ret |= _z_close_decode(&msg->_body._close, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_SYNC: { - ret |= _z_sync_decode(&msg->_body._sync, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_ACK_NACK: { - ret |= _z_ack_nack_decode(&msg->_body._ack_nack, zbf, msg->_header); - is_last = true; - } break; - - case _Z_MID_PING_PONG: { - ret |= _z_ping_pong_decode(&msg->_body._ping_pong, zbf); - is_last = true; - } break; - - case _Z_MID_PRIORITY: { - // Ignore the priority decorator for the time being since zenoh-pico does not - // perform any routing. Hence, priority information does not need to be propagated. - } break; - - default: { - _Z_DEBUG("WARNING: Trying to decode session message with unknown ID(%d)\n", mid); - ret |= _Z_ERR_MESSAGE_TRANSPORT_UNKNOWN; - is_last = true; - } break; - } - } else { - msg->_header = 0xFF; - } - } while ((ret == _Z_RES_OK) && (is_last == false)); - - return ret; -} - -int8_t _z_transport_message_decode(_z_transport_message_t *t_msg, _z_zbuf_t *zbf) { - return _z_transport_message_decode_na(t_msg, zbf); -} diff --git a/src/session/query.c b/src/session/query.c index 6951dbede..17a8667db 100644 --- a/src/session/query.c +++ b/src/session/query.c @@ -117,7 +117,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 *pen_qry) { int8_t ret = _Z_RES_OK; - _Z_DEBUG(">>> Allocating query for (%zu:%s,%s)\n", pen_qry->_key._id, pen_qry->_key._suffix, pen_qry->_parameters); + _Z_DEBUG(">>> Allocating query for (%ju:%s,%s)\n", (uintmax_t)pen_qry->_key._id, pen_qry->_key._suffix, + pen_qry->_parameters); #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); @@ -137,26 +138,21 @@ int8_t _z_register_pending_query(_z_session_t *zn, _z_pending_query_t *pen_qry) return ret; } -int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_reply_context_t *reply_context, - const _z_keyexpr_t keyexpr, const _z_bytes_t payload, - const _z_encoding_t encoding, const _z_zint_t kind, +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) { int8_t ret = _Z_RES_OK; - if (_Z_HAS_FLAG(reply_context->_header, _Z_FLAG_Z_F) == true) { - ret = _Z_ERR_MESSAGE_FLAG_UNEXPECTED; - } - #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, reply_context->_qid); + _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; } - _z_keyexpr_t expanded_ke = __unsafe_z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_REMOTE, &keyexpr); + _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))) { @@ -166,7 +162,7 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_reply_context_t // Build the reply _z_reply_t reply; reply._tag = Z_REPLY_TAG_DATA; - _z_bytes_copy(&reply.data.replier_id, &reply_context->_replier_id); + 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; @@ -206,7 +202,7 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_reply_context_t _z_reply_t partial_reply; (void)memset(&partial_reply, 0, sizeof(_z_reply_t)); // Avoid warnings on uninitialised values on the reply - partial_reply.data.sample.keyexpr = _z_keyexpr_duplicate(&reply.data.sample.keyexpr); + partial_reply.data.sample.keyexpr = _z_keyexpr_duplicate(reply.data.sample.keyexpr); pen_rep->_reply = partial_reply; } else { pen_rep->_reply = reply; // Store the whole reply in the latest mode @@ -235,21 +231,15 @@ int8_t _z_trigger_query_reply_partial(_z_session_t *zn, const _z_reply_context_t return ret; } -int8_t _z_trigger_query_reply_final(_z_session_t *zn, const _z_reply_context_t *reply_context) { +int8_t _z_trigger_query_reply_final(_z_session_t *zn, _z_zint_t id) { int8_t ret = _Z_RES_OK; #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - if ((ret == _Z_RES_OK) && (_Z_HAS_FLAG(reply_context->_header, _Z_FLAG_Z_F) == - false)) { // FIXME: to be checked, but this might never - // happen with the current version of the protocol - ret = _Z_ERR_MESSAGE_FLAG_UNEXPECTED; - } - // Final reply received for unknown query id - _z_pending_query_t *pen_qry = __unsafe__z_get_pending_query_by_id(zn, reply_context->_qid); + _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; } diff --git a/src/session/queryable.c b/src/session/queryable.c index 466e2c54c..d18c5705e 100644 --- a/src/session/queryable.c +++ b/src/session/queryable.c @@ -13,9 +13,12 @@ // #include +#include +#include #include "zenoh-pico/config.h" -#include "zenoh-pico/net/resource.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/utils.h" @@ -104,7 +107,7 @@ _z_questionable_sptr_list_t *_z_get_questionable_by_key(_z_session_t *zn, const _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_LOCAL, keyexpr); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); _z_questionable_sptr_list_t *qles = __unsafe_z_get_questionable_by_key(zn, key); #if Z_MULTI_THREAD == 1 @@ -115,7 +118,7 @@ _z_questionable_sptr_list_t *_z_get_questionable_by_key(_z_session_t *zn, const } _z_questionable_sptr_t *_z_register_questionable(_z_session_t *zn, _z_questionable_t *q) { - _Z_DEBUG(">>> Allocating queryable for (%zu:%s)\n", q->_key._id, q->_key._suffix); + _Z_DEBUG(">>> Allocating queryable for (%ju:%s)\n", (uintmax_t)q->_key._id, q->_key._suffix); _z_questionable_sptr_t *ret = NULL; #if Z_MULTI_THREAD == 1 @@ -135,14 +138,14 @@ _z_questionable_sptr_t *_z_register_questionable(_z_session_t *zn, _z_questionab return ret; } -int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *query) { +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 ret = _Z_RES_OK; #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_REMOTE, &query->_key); + _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, &q_key); if (key._suffix != NULL) { _z_questionable_sptr_list_t *qles = __unsafe_z_get_questionable_by_key(zn, key); @@ -153,11 +156,18 @@ int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *query) { // Build the query z_query_t q; q._zn = zn; - q._qid = query->_qid; + q._request_id = qid; q._key = key; - q._parameters = query->_parameters; - q._value.encoding = query->_info._encoding; - q._value.payload = query->_payload; +#if defined(__STDC_NO_VLA__) || ((__STDC_VERSION__ < 201000L) && (defined(_WIN32) || defined(WIN32))) + char *params = z_malloc(query->_parameters.len + 1); +#else + char params[query->_parameters.len + 1]; +#endif + memcpy(params, query->_parameters.start, query->_parameters.len); + params[query->_parameters.len] = 0; + q._parameters = params; + q._value.encoding = query->_ext_value.encoding; + q._value.payload = query->_ext_value.payload; q._anyke = (strstr(q._parameters, Z_SELECTOR_QUERY_MATCH) == NULL) ? false : true; _z_questionable_sptr_list_t *xs = qles; while (xs != NULL) { @@ -168,22 +178,14 @@ int8_t _z_trigger_queryables(_z_session_t *zn, const _z_msg_query_t *query) { _z_keyexpr_clear(&key); _z_questionable_sptr_list_free(&qles); +#if defined(__STDC_NO_VLA__) || ((__STDC_VERSION__ < 201000L) && (defined(_WIN32) || defined(WIN32))) + z_free(params); +#endif // Send the final reply - // Final flagged reply context does not encode the ZID - _z_bytes_t zid; - _z_bytes_reset(&zid); - _Bool is_final = true; - _z_reply_context_t *rctx = _z_msg_make_reply_context(query->_qid, zid, is_final); - - // Congestion control - _Bool can_be_dropped = false; - // Create the final reply - _z_zenoh_message_t z_msg = _z_msg_make_unit(can_be_dropped); - z_msg._reply_context = rctx; - - if (_z_send_z_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { + _z_zenoh_message_t z_msg = _z_n_msg_make_response_final(q._request_id); + if (_z_send_n_msg(zn, &z_msg, Z_RELIABILITY_RELIABLE, Z_CONGESTION_CONTROL_BLOCK) != _Z_RES_OK) { ret = _Z_ERR_TRANSPORT_TX_FAILED; } _z_msg_clear(&z_msg); diff --git a/src/session/resource.c b/src/session/resource.c index efa3f3acc..d997b5b4b 100644 --- a/src/session/resource.c +++ b/src/session/resource.c @@ -15,8 +15,14 @@ #include "zenoh-pico/session/resource.h" #include +#include +#include "zenoh-pico/api/types.h" #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/keyexpr.h" +#include "zenoh-pico/session/session.h" +#include "zenoh-pico/system/platform.h" #include "zenoh-pico/utils/logging.h" _Bool _z_resource_eq(const _z_resource_t *other, const _z_resource_t *this) { return this->_id == other->_id; } @@ -35,18 +41,18 @@ void _z_resource_free(_z_resource_t **res) { } /*------------------ Entity ------------------*/ -_z_zint_t _z_get_entity_id(_z_session_t *zn) { return zn->_entity_id++; } +uint32_t _z_get_entity_id(_z_session_t *zn) { return zn->_entity_id++; } -_z_zint_t _z_get_resource_id(_z_session_t *zn) { return zn->_resource_id++; } +uint16_t _z_get_resource_id(_z_session_t *zn) { return zn->_resource_id++; } /*------------------ Resource ------------------*/ -_z_resource_t *__z_get_resource_by_id(_z_resource_list_t *rl, const _z_zint_t id) { +_z_resource_t *__z_get_resource_by_id(_z_resource_list_t *rl, uint16_t mapping, const _z_zint_t id) { _z_resource_t *ret = NULL; _z_resource_list_t *xs = rl; while (xs != NULL) { _z_resource_t *r = _z_resource_list_head(xs); - if (r->_id == id) { + if (r->_id == id && _z_keyexpr_mapping_id(&r->_key) == mapping) { ret = r; break; } @@ -59,11 +65,13 @@ _z_resource_t *__z_get_resource_by_id(_z_resource_list_t *rl, const _z_zint_t id _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_str_eq(r->_key._suffix, keyexpr->_suffix) == true)) { + if ((r->_key._id == keyexpr->_id) && _z_keyexpr_mapping_id(&r->_key) == mapping && + (_z_str_eq(r->_key._suffix, keyexpr->_suffix) == true)) { ret = r; break; } @@ -75,7 +83,7 @@ _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}; + _z_keyexpr_t ret = {._id = Z_RESOURCE_ID_NONE, ._suffix = NULL, ._mapping = _z_keyexpr_mapping(0, true)}; // Need to build the complete resource name, by recursively look at RIDs // Resource names are looked up from right to left @@ -92,8 +100,9 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye // Recursevely go through all the RIDs _z_zint_t id = keyexpr->_id; + uint16_t mapping = _z_keyexpr_mapping_id(keyexpr); while (id != Z_RESOURCE_ID_NONE) { - _z_resource_t *res = __z_get_resource_by_id(xs, id); + _z_resource_t *res = __z_get_resource_by_id(xs, mapping, id); if (res == NULL) { len = 0; break; @@ -139,9 +148,9 @@ _z_keyexpr_t __z_get_expanded_key_from_key(_z_resource_list_t *xs, const _z_keye * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint8_t is_local, _z_zint_t id) { - _z_resource_list_t *decls = (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_resources : zn->_remote_resources; - return __z_get_resource_by_id(decls, id); +_z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t id) { + _z_resource_list_t *decls = (mapping == _Z_KEYEXPR_MAPPING_LOCAL) ? zn->_local_resources : zn->_remote_resources; + return __z_get_resource_by_id(decls, mapping, id); } /** @@ -149,8 +158,8 @@ _z_resource_t *__unsafe_z_get_resource_by_id(_z_session_t *zn, uint8_t is_local, * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_resource_t *__unsafe_z_get_resource_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr) { - _z_resource_list_t *decls = (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_resources : zn->_remote_resources; +_z_resource_t *__unsafe_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { + _z_resource_list_t *decls = _z_keyexpr_is_local(keyexpr) ? zn->_local_resources : zn->_remote_resources; return __z_get_resource_by_key(decls, keyexpr); } @@ -159,17 +168,17 @@ _z_resource_t *__unsafe_z_get_resource_by_key(_z_session_t *zn, uint8_t is_local * Make sure that the following mutexes are locked before calling this function: * - zn->_mutex_inner */ -_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr) { - _z_resource_list_t *decls = (is_local == _Z_RESOURCE_IS_LOCAL) ? zn->_local_resources : zn->_remote_resources; +_z_keyexpr_t __unsafe_z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { + _z_resource_list_t *decls = _z_keyexpr_is_local(keyexpr) ? zn->_local_resources : zn->_remote_resources; return __z_get_expanded_key_from_key(decls, keyexpr); } -_z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint8_t is_local, _z_zint_t rid) { +_z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint16_t mapping, _z_zint_t rid) { #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - _z_resource_t *res = __unsafe_z_get_resource_by_id(zn, is_local, rid); + _z_resource_t *res = __unsafe_z_get_resource_by_id(zn, mapping, rid); #if Z_MULTI_THREAD == 1 _z_mutex_unlock(&zn->_mutex_inner); @@ -178,12 +187,15 @@ _z_resource_t *_z_get_resource_by_id(_z_session_t *zn, uint8_t is_local, _z_zint return res; } -_z_resource_t *_z_get_resource_by_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr) { +_z_resource_t *_z_get_resource_by_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { + if (keyexpr->_suffix == NULL) { + return _z_get_resource_by_id(zn, _z_keyexpr_mapping_id(keyexpr), keyexpr->_id); + } #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - _z_resource_t *res = __unsafe_z_get_resource_by_key(zn, is_local, keyexpr); + _z_resource_t *res = __unsafe_z_get_resource_by_key(zn, keyexpr); #if Z_MULTI_THREAD == 1 _z_mutex_unlock(&zn->_mutex_inner); @@ -192,12 +204,11 @@ _z_resource_t *_z_get_resource_by_key(_z_session_t *zn, uint8_t is_local, const return res; } -_z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, uint8_t is_local, const _z_keyexpr_t *keyexpr) { +_z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, const _z_keyexpr_t *keyexpr) { #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - - _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, is_local, keyexpr); + _z_keyexpr_t res = __unsafe_z_get_expanded_key_from_key(zn, keyexpr); #if Z_MULTI_THREAD == 1 _z_mutex_unlock(&zn->_mutex_inner); @@ -206,26 +217,42 @@ _z_keyexpr_t _z_get_expanded_key_from_key(_z_session_t *zn, uint8_t is_local, co return res; } -int8_t _z_register_resource(_z_session_t *zn, uint8_t is_local, _z_resource_t *res) { - int8_t ret = _Z_RES_OK; - - _Z_DEBUG(">>> Allocating res decl for (%zu,%zu:%s)\n", res->_id, res->_key._id, res->_key._suffix); +/// 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; + key = _z_keyexpr_alias(key); + uint16_t mapping = register_to_mapping; + uint16_t parent_mapping = _z_keyexpr_mapping_id(&key); #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - // FIXME: check by keyexpr instead - _z_resource_t *r = __unsafe_z_get_resource_by_id(zn, is_local, res->_id); - if (r == NULL) { - // Register the resource - if (is_local == _Z_RESOURCE_IS_LOCAL) { - zn->_local_resources = _z_resource_list_push(zn->_local_resources, res); + if (key._id != Z_RESOURCE_ID_NONE) { + if (parent_mapping == mapping) { + _z_resource_t *parent = __unsafe_z_get_resource_by_id(zn, parent_mapping, key._id); + parent->_refcount++; } else { - zn->_remote_resources = _z_resource_list_push(zn->_remote_resources, res); + key = __unsafe_z_get_expanded_key_from_key(zn, &key); + } + } + ret = key._id; + if ((key._suffix != NULL)) { + _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); + ret = id == Z_RESOURCE_ID_NONE ? _z_get_resource_id(zn) : id; + res->_id = ret; + // Register the resource + if (mapping == _Z_KEYEXPR_MAPPING_LOCAL) { + zn->_local_resources = _z_resource_list_push(zn->_local_resources, res); + } else { + zn->_remote_resources = _z_resource_list_push(zn->_remote_resources, res); + } } - } else { - ret = _Z_ERR_ENTITY_DECLARATION_FAILED; } #if Z_MULTI_THREAD == 1 @@ -235,16 +262,49 @@ int8_t _z_register_resource(_z_session_t *zn, uint8_t is_local, _z_resource_t *r return ret; } -void _z_unregister_resource(_z_session_t *zn, uint8_t is_local, _z_resource_t *res) { +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\n", id, mapping); #if Z_MULTI_THREAD == 1 _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - - if (is_local == _Z_RESOURCE_IS_LOCAL) { - zn->_local_resources = _z_resource_list_drop_filter(zn->_local_resources, _z_resource_eq, res); - } else { - zn->_remote_resources = _z_resource_list_drop_filter(zn->_remote_resources, _z_resource_eq, res); + _z_resource_list_t **parent_mut = is_local ? &zn->_local_resources : &zn->_remote_resources; + while (id != 0) { + _z_resource_list_t *parent = *parent_mut; + while (parent != NULL) { + _z_resource_t *head = _z_resource_list_head(parent); + if (head && head->_id == id && _z_keyexpr_mapping_id(&head->_key) == mapping) { + head->_refcount--; + if (head->_refcount == 0) { + *parent_mut = _z_resource_list_pop(parent, &head); + id = head->_key._id; + mapping = _z_keyexpr_mapping_id(&head->_key); + _z_resource_free(&head); + } else { + id = 0; + } + break; + } + parent_mut = &parent->_tail; + parent = *parent_mut; + } } +#if Z_MULTI_THREAD == 1 + _z_mutex_unlock(&zn->_mutex_inner); +#endif // Z_MULTI_THREAD == 1 +} + +_Bool _z_unregister_resource_for_peer_filter(const _z_resource_t *candidate, const _z_resource_t *ctx) { + uint16_t mapping = ctx->_id; + return _z_keyexpr_mapping_id(&candidate->_key) == mapping; +} +void _z_unregister_resources_for_peer(_z_session_t *zn, uint16_t mapping) { +#if Z_MULTI_THREAD == 1 + _z_mutex_lock(&zn->_mutex_inner); +#endif // Z_MULTI_THREAD == 1 + _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_MULTI_THREAD == 1 _z_mutex_unlock(&zn->_mutex_inner); diff --git a/src/session/rx.c b/src/session/rx.c index 3b9f15e80..082fe21ee 100644 --- a/src/session/rx.c +++ b/src/session/rx.c @@ -13,166 +13,152 @@ // #include - +#include + +#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/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/protocol/msgcodec.h" #include "zenoh-pico/session/query.h" #include "zenoh-pico/session/queryable.h" #include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/session.h" #include "zenoh-pico/session/subscription.h" +#include "zenoh-pico/session/utils.h" #include "zenoh-pico/utils/logging.h" /*------------------ Handle message ------------------*/ -int8_t _z_handle_zenoh_message(_z_session_t *zn, _z_zenoh_message_t *msg) { +int8_t _z_handle_network_message(_z_session_t *zn, _z_zenoh_message_t *msg, uint16_t local_peer_id) { int8_t ret = _Z_RES_OK; - switch (_Z_MID(msg->_header)) { - case _Z_MID_DATA: { - _Z_INFO("Received _Z_MID_DATA message %d\n", msg->_header); - if (msg->_reply_context != NULL) { // This is some data from a query - ret = _z_trigger_query_reply_partial(zn, msg->_reply_context, msg->_body._data._key, - msg->_body._data._payload, msg->_body._data._info._encoding, - msg->_body._data._info._kind, msg->_body._data._info._tstamp); - } else { // This is pure data - ret = _z_trigger_subscriptions(zn, msg->_body._data._key, msg->_body._data._payload, - msg->_body._data._info._encoding, msg->_body._data._info._kind, - msg->_body._data._info._tstamp); + switch (msg->_tag) { + case _Z_N_DECLARE: { + _Z_DEBUG("Handling _Z_N_DECLARE\n"); + _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) { + ret = _Z_ERR_ENTITY_DECLARATION_FAILED; + } + } break; + case _Z_UNDECL_KEXPR: { + _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 + } break; + case _Z_DECL_QUERYABLE: { + // TODO: add support or explicitly discard + } break; + case _Z_UNDECL_QUERYABLE: { + // TODO: add support or explicitly discard + } break; + case _Z_DECL_TOKEN: { + // TODO: add support or explicitly discard + } break; + 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 + } break; } } break; - - case _Z_MID_DECLARE: { - _Z_INFO("Received _Z_DECLARE message\n"); - for (size_t i = 0; i < msg->_body._declare._declarations._len; i++) { - _z_declaration_t decl = msg->_body._declare._declarations._val[i]; - switch (_Z_MID(decl._header)) { - case _Z_DECL_RESOURCE: { - _Z_INFO("Received declare-resource message\n"); - - // Register remote resource declaration - _z_resource_t *r = (_z_resource_t *)z_malloc(sizeof(_z_resource_t)); - if (r != NULL) { - r->_id = decl._body._res._id; - r->_key = _z_keyexpr_duplicate(&decl._body._res._key); - - ret = _z_register_resource(zn, _Z_RESOURCE_IS_REMOTE, r); - if (ret != _Z_RES_OK) { - _z_resource_free(&r); - } - } else { - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - } break; - - case _Z_DECL_PUBLISHER: { - _Z_INFO("Received declare-publisher message\n"); - // TODO: not supported yet - } break; - - case _Z_DECL_SUBSCRIBER: { - _Z_INFO("Received declare-subscriber message\n"); - _z_keyexpr_t key = - _z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_REMOTE, &decl._body._sub._key); - _z_subscription_sptr_list_t *subs = - _z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_REMOTE, &key); - if (subs != NULL) { - _z_keyexpr_clear(&key); - _z_subscription_sptr_list_free(&subs); - break; - } - - _z_subscription_t s; - s._id = _z_get_entity_id(zn); - s._key = key; - s._info = decl._body._sub._subinfo; - s._callback = NULL; - s._dropper = NULL; - s._arg = NULL; - - _z_subscription_sptr_t *sp_s = _z_register_subscription( - zn, _Z_RESOURCE_IS_REMOTE, &s); // This a pointer to the entry stored at session-level. - // Do not drop it by the end of this function. - if (sp_s == NULL) { - _z_unregister_subscription(zn, _Z_RESOURCE_IS_REMOTE, sp_s); - break; - } - - _z_subscription_sptr_list_free(&subs); - } break; - - case _Z_DECL_QUERYABLE: { - _Z_INFO("Received declare-queryable message\n"); - // TODO: not supported yet - } break; - - case _Z_DECL_FORGET_RESOURCE: { - _Z_INFO("Received forget-resource message\n"); - _z_resource_t *rd = - _z_get_resource_by_id(zn, _Z_RESOURCE_IS_REMOTE, decl._body._forget_res._rid); - if (rd != NULL) { - _z_unregister_resource(zn, _Z_RESOURCE_IS_REMOTE, rd); - } - } break; - - case _Z_DECL_FORGET_PUBLISHER: { - _Z_INFO("Received forget-publisher message\n"); - // TODO: not supported yet - - } break; - - case _Z_DECL_FORGET_SUBSCRIBER: { - _Z_INFO("Received forget-subscriber message\n"); - _z_keyexpr_t key = - _z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_REMOTE, &decl._body._forget_sub._key); - _z_subscription_sptr_list_t *subs = - _z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_REMOTE, &key); - - _z_subscription_sptr_list_t *xs = subs; - while (xs != NULL) { - _z_subscription_sptr_t *sub = _z_subscription_sptr_list_head(xs); - _z_unregister_subscription(zn, _Z_RESOURCE_IS_REMOTE, sub); - xs = _z_subscription_sptr_list_tail(xs); - } - - _z_subscription_sptr_list_free(&subs); - _z_keyexpr_clear(&key); - } break; - - case _Z_DECL_FORGET_QUERYABLE: { - _Z_INFO("Received forget-queryable message\n"); - // TODO: not supported yet - } break; - - default: { - _Z_INFO("Unknown declaration message ID"); - ret = _Z_ERR_MESSAGE_ZENOH_DECLARATION_UNKNOWN; - } break; - } - } - } break; - - case _Z_MID_PULL: { - _Z_INFO("Received _Z_PULL message\n"); - // TODO: not supported yet + case _Z_N_PUSH: { + _Z_DEBUG("Handling _Z_N_PUSH\n"); + _z_n_msg_push_t push = msg->_body._push; + _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; + ret = _z_trigger_subscriptions(zn, push._key, payload, encoding, kind, push._timestamp); } break; - - case _Z_MID_QUERY: { - _Z_INFO("Received _Z_QUERY message\n"); - _z_trigger_queryables(zn, &msg->_body._query); + case _Z_N_REQUEST: { + _Z_DEBUG("Handling _Z_N_REQUEST\n"); + _z_n_msg_request_t req = msg->_body._request; + switch (req._tag) { + case _Z_REQUEST_QUERY: { + _z_msg_query_t *query = &req._body._query; + ret = _z_trigger_queryables(zn, query, req._key, req._rid); + } break; + case _Z_REQUEST_PUT: { + _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); + 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); + 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; + ret = _z_trigger_subscriptions(zn, req._key, _z_bytes_empty(), z_encoding_default(), + Z_SAMPLE_KIND_DELETE, del._commons._timestamp); + 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); + 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_MID_UNIT: { - _Z_INFO("Received _Z_UNIT message\n"); - // This might be the final reply - if (msg->_reply_context != NULL) { - _z_trigger_query_reply_final(zn, msg->_reply_context); + case _Z_N_RESPONSE: { + _Z_DEBUG("Handling _Z_N_RESPONSE\n"); + _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_query_reply_partial(zn, response._request_id, response._key, reply._value.payload, + reply._value.encoding, Z_SAMPLE_KIND_PUT, reply._timestamp); + } 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; + _Z_ERROR("Received Err for query %zu: code=%d, message=%.*s\n", 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; + ret = _z_trigger_subscriptions(zn, response._key, put._payload, put._encoding, Z_SAMPLE_KIND_PUT, + put._commons._timestamp); + } break; + case _Z_RESPONSE_BODY_DEL: { + _z_msg_del_t del = response._body._del; + ret = _z_trigger_subscriptions(zn, response._key, _z_bytes_empty(), z_encoding_default(), + Z_SAMPLE_KIND_DELETE, del._commons._timestamp); + } break; } } break; - - default: { - _Z_ERROR("Unknown zenoh message ID\n"); - ret = _Z_ERR_MESSAGE_ZENOH_UNKNOWN; - } + case _Z_N_RESPONSE_FINAL: { + _Z_DEBUG("Handling _Z_N_RESPONSE_FINAL\n"); + _z_zint_t id = msg->_body._response_final._request_id; + _z_trigger_query_reply_final(zn, id); + } break; } - + _z_msg_clear(msg); return ret; } diff --git a/src/session/scout.c b/src/session/scout.c index c2c501297..7a45a3ecc 100644 --- a/src/session/scout.c +++ b/src/session/scout.c @@ -13,9 +13,11 @@ // #include +#include #include "zenoh-pico/link/manager.h" -#include "zenoh-pico/protocol/msgcodec.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/utils/logging.h" #if Z_SCOUTING_UDP == 1 && Z_LINK_UDP_UNICAST == 0 @@ -50,7 +52,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, const char *locator, unsig err = _z_link_send_wbuf(&zl, wbf); if (err == _Z_RES_OK) { // The receiving buffer - _z_zbuf_t zbf = _z_zbuf_make(Z_BATCH_SIZE_RX); + _z_zbuf_t zbf = _z_zbuf_make(Z_BATCH_UNICAST_SIZE); z_time_t start = z_time_now(); while (z_time_elapsed_ms(&start) < period) { @@ -63,35 +65,28 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, const char *locator, unsig continue; } - _z_transport_message_t t_msg; - err = _z_transport_message_decode(&t_msg, &zbf); + _z_scouting_message_t s_msg; + err = _z_scouting_message_decode(&s_msg, &zbf); if (err != _Z_RES_OK) { _Z_ERROR("Scouting loop received malformed message\n"); continue; } - switch (_Z_MID(t_msg._header)) { + switch (_Z_MID(s_msg._header)) { case _Z_MID_HELLO: { _Z_INFO("Received _Z_HELLO message\n"); _z_hello_t *hello = (_z_hello_t *)z_malloc(sizeof(_z_hello_t)); if (hello != NULL) { - if (_Z_HAS_FLAG(t_msg._header, _Z_FLAG_T_I) == true) { - _z_bytes_copy(&hello->zid, &t_msg._body._hello._zid); - } else { - _z_bytes_reset(&hello->zid); - } - - if (_Z_HAS_FLAG(t_msg._header, _Z_FLAG_T_W) == true) { - hello->whatami = t_msg._body._hello._whatami; - } else { - hello->whatami = Z_WHATAMI_ROUTER; // Default value is from a router - } - - if (_Z_HAS_FLAG(t_msg._header, _Z_FLAG_T_L) == true) { - hello->locators = _z_str_array_make(t_msg._body._hello._locators._len); - for (size_t i = 0; i < hello->locators.len; i++) { + 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); + for (size_t i = 0; i < n_loc; i++) { hello->locators.val[i] = - _z_locator_to_str(&t_msg._body._hello._locators._val[i]); + _z_locator_to_str(&s_msg._body._hello._locators._val[i]); } } else { // @TODO: construct the locator departing from the sock address @@ -110,7 +105,7 @@ _z_hello_list_t *__z_scout_loop(const _z_wbuf_t *wbf, const char *locator, unsig break; } } - _z_t_msg_clear(&t_msg); + _z_s_msg_clear(&s_msg); if ((_z_hello_list_len(ret) > 0) && (exit_on_first == true)) { break; @@ -132,18 +127,17 @@ _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_whatami_t what, const char *locator, const uint32_t timeout, +_z_hello_list_t *_z_scout_inner(const z_what_t what, _z_id_t zid, const char *locator, const uint32_t timeout, const _Bool exit_on_first) { _z_hello_list_t *ret = NULL; // Create the buffer to serialize the scout message on - _z_wbuf_t wbf = _z_wbuf_make(Z_BATCH_SIZE_TX, false); + _z_wbuf_t wbf = _z_wbuf_make(Z_BATCH_UNICAST_SIZE, false); // Create and encode the scout message - _Bool request_zid = true; - _z_transport_message_t scout = _z_t_msg_make_scout(what, request_zid); + _z_scouting_message_t scout = _z_s_msg_make_scout(what, zid); - _z_transport_message_encode(&wbf, &scout); + _z_scouting_message_encode(&wbf, &scout); // Scout on multicast #if Z_MULTICAST_TRANSPORT == 1 diff --git a/src/session/subscription.c b/src/session/subscription.c index f7e002b33..fd057aac3 100644 --- a/src/session/subscription.c +++ b/src/session/subscription.c @@ -15,11 +15,13 @@ #include "zenoh-pico/session/subscription.h" #include +#include #include "zenoh-pico/config.h" -#include "zenoh-pico/net/resource.h" +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/protocol/keyexpr.h" #include "zenoh-pico/session/resource.h" +#include "zenoh-pico/session/session.h" #include "zenoh-pico/utils/logging.h" _Bool _z_subscription_eq(const _z_subscription_t *other, const _z_subscription_t *this) { @@ -122,7 +124,7 @@ _z_subscription_sptr_list_t *_z_get_subscriptions_by_key(_z_session_t *zn, uint8 } _z_subscription_sptr_t *_z_register_subscription(_z_session_t *zn, uint8_t is_local, _z_subscription_t *s) { - _Z_DEBUG(">>> Allocating sub decl for (%zu:%s)\n", s->_key._id, s->_key._suffix); + _Z_DEBUG(">>> Allocating sub decl for (%ju:%s)\n", (uintmax_t)s->_key._id, s->_key._suffix); _z_subscription_sptr_t *ret = NULL; #if Z_MULTI_THREAD == 1 @@ -157,7 +159,9 @@ int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, co _z_mutex_lock(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 - _z_keyexpr_t key = __unsafe_z_get_expanded_key_from_key(zn, _Z_RESOURCE_IS_REMOTE, &keyexpr); + _Z_DEBUG("Resolving %d - %s on mapping 0x%x\n", keyexpr._id, 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\n", key._id, key._suffix); if (key._suffix != NULL) { _z_subscription_sptr_list_t *subs = __unsafe_z_get_subscriptions_by_key(zn, _Z_RESOURCE_IS_LOCAL, key); @@ -173,6 +177,7 @@ int8_t _z_trigger_subscriptions(_z_session_t *zn, const _z_keyexpr_t keyexpr, co s.kind = kind; s.timestamp = timestamp; _z_subscription_sptr_list_t *xs = subs; + _Z_DEBUG("Triggering %ju subs\n", (uintmax_t)_z_subscription_sptr_list_len(xs)); while (xs != NULL) { _z_subscription_sptr_t *sub = _z_subscription_sptr_list_head(xs); sub->ptr->_callback(&s, sub->ptr->_arg); diff --git a/src/session/tx.c b/src/session/tx.c index 092bb29fb..ae3697b42 100644 --- a/src/session/tx.c +++ b/src/session/tx.c @@ -16,19 +16,19 @@ #include "zenoh-pico/utils/logging.h" -int8_t _z_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reliability_t reliability, +int8_t _z_send_n_msg(_z_session_t *zn, const _z_network_message_t *z_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { int8_t ret = _Z_RES_OK; - _Z_DEBUG(">> send zenoh message\n"); + _Z_DEBUG(">> send network message\n"); #if Z_UNICAST_TRANSPORT == 1 if (zn->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { - ret = _z_unicast_send_z_msg(zn, z_msg, reliability, cong_ctrl); + ret = _z_unicast_send_n_msg(zn, z_msg, reliability, cong_ctrl); } else #endif // Z_UNICAST_TRANSPORT == 1 #if Z_MULTICAST_TRANSPORT == 1 if (zn->_tp._type == _Z_TRANSPORT_MULTICAST_TYPE) { - ret = _z_multicast_send_z_msg(zn, z_msg, reliability, cong_ctrl); + ret = _z_multicast_send_n_msg(zn, z_msg, reliability, cong_ctrl); } else #endif // Z_MULTICAST_TRANSPORT == 1 { diff --git a/src/session/utils.c b/src/session/utils.c index bba256942..215c2717f 100644 --- a/src/session/utils.c +++ b/src/session/utils.c @@ -17,23 +17,13 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/core.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" /*------------------ clone helpers ------------------*/ -void _z_keyexpr_copy(_z_keyexpr_t *dst, const _z_keyexpr_t *src) { - dst->_id = src->_id; - dst->_suffix = src->_suffix ? _z_str_clone(src->_suffix) : NULL; -} - -_z_keyexpr_t _z_keyexpr_duplicate(const _z_keyexpr_t *src) { - _z_keyexpr_t dst; - _z_keyexpr_copy(&dst, src); - return dst; -} - _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { _z_timestamp_t ts; ts.id = tstamp->id; @@ -41,7 +31,7 @@ _z_timestamp_t _z_timestamp_duplicate(const _z_timestamp_t *tstamp) { return ts; } -void _z_timestamp_reset(_z_timestamp_t *tstamp) { +void _z_timestamp_clear(_z_timestamp_t *tstamp) { memset(&tstamp->id, 0, sizeof(_z_id_t)); tstamp->time = 0; } @@ -52,21 +42,14 @@ _Bool _z_timestamp_check(const _z_timestamp_t *stamp) { return false; } -int8_t _z_session_generate_zid(_z_bytes_t *bs, uint8_t size) { +int8_t _z_session_generate_zid(_z_id_t *bs, uint8_t size) { int8_t ret = _Z_RES_OK; - - *bs = _z_bytes_make(size); - if (bs->_is_alloc == true) { - z_random_fill((uint8_t *)bs->start, bs->len); - } else { - ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; - } - + z_random_fill((uint8_t *)bs->id, size); return ret; } /*------------------ Init/Free/Close session ------------------*/ -int8_t _z_session_init(_z_session_t *zn, _z_bytes_t *zid) { +int8_t _z_session_init(_z_session_t *zn, _z_id_t *zid) { int8_t ret = _Z_RES_OK; // Initialize the counters to 1 @@ -87,8 +70,7 @@ int8_t _z_session_init(_z_session_t *zn, _z_bytes_t *zid) { ret = _z_mutex_init(&zn->_mutex_inner); #endif // Z_MULTI_THREAD == 1 if (ret == _Z_RES_OK) { - zn->_local_zid = _z_bytes_empty(); - _z_bytes_move(&zn->_local_zid, zid); + zn->_local_zid = *zid; #if Z_UNICAST_TRANSPORT == 1 if (zn->_tp._type == _Z_TRANSPORT_UNICAST_TYPE) { zn->_tp._transport._unicast._session = zn; @@ -104,7 +86,6 @@ int8_t _z_session_init(_z_session_t *zn, _z_bytes_t *zid) { } } else { _z_transport_clear(&zn->_tp); - _z_bytes_clear(&zn->_local_zid); } return ret; @@ -112,7 +93,6 @@ int8_t _z_session_init(_z_session_t *zn, _z_bytes_t *zid) { void _z_session_clear(_z_session_t *zn) { // Clear Zenoh PID - _z_bytes_clear(&zn->_local_zid); // Clean up transports _z_transport_clear(&zn->_tp); diff --git a/src/system/unix/network.c b/src/system/unix/network.c index cde8766e6..cc00f6d3e 100644 --- a/src/system/unix/network.c +++ b/src/system/unix/network.c @@ -352,9 +352,9 @@ int8_t _z_open_udp_multicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoin // implementations: // https://lists.debian.org/debian-glibc/2016/03/msg00241.html // To avoid a fix to break zenoh-pico, we are let it leak for the moment. - //#if defined(ZENOH_LINUX) + // #if defined(ZENOH_LINUX) // z_free(lsockaddr); - //#endif + // #endif } else { ret = _Z_ERR_GENERIC; } diff --git a/src/system/windows/network.c b/src/system/windows/network.c index 8895b68ea..3268a0890 100644 --- a/src/system/windows/network.c +++ b/src/system/windows/network.c @@ -390,9 +390,9 @@ int8_t _z_open_udp_multicast(_z_sys_net_socket_t *sock, const _z_sys_net_endpoin // implementations: // https://lists.debian.org/debian-glibc/2016/03/msg00241.html // To avoid a fix to break zenoh-pico, we are let it leak for the moment. - //#if defined(ZENOH_LINUX) + // #if defined(ZENOH_LINUX) // z_free(lsockaddr); - //#endif + // #endif } else { ret = _Z_ERR_GENERIC; } diff --git a/src/system/windows/system.c b/src/system/windows/system.c index 80643d9f3..b813d6627 100644 --- a/src/system/windows/system.c +++ b/src/system/windows/system.c @@ -12,10 +12,11 @@ // ZettaScale Zenoh Team, // +#include #include // The following includes must come after winsock2 -#include #include +#include #include "zenoh-pico/config.h" #include "zenoh-pico/system/platform.h" @@ -46,7 +47,7 @@ uint64_t z_random_u64(void) { return ret; } -void z_random_fill(void *buf, size_t len) { RtlGenRandom(buf, len); } +void z_random_fill(void *buf, size_t len) { RtlGenRandom(buf, (unsigned long)len); } /*------------------ Memory ------------------*/ // #define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) diff --git a/src/transport/common/rx.c b/src/transport/common/rx.c index c617efe86..5a7d2e45a 100644 --- a/src/transport/common/rx.c +++ b/src/transport/common/rx.c @@ -16,6 +16,7 @@ #include +#include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/utils/logging.h" /*------------------ Reception helper ------------------*/ @@ -23,7 +24,7 @@ int8_t _z_link_recv_t_msg(_z_transport_message_t *t_msg, const _z_link_t *zl) { int8_t ret = _Z_RES_OK; // Create and prepare the buffer - _z_zbuf_t zbf = _z_zbuf_make(Z_BATCH_SIZE_RX); + _z_zbuf_t zbf = _z_zbuf_make(Z_BATCH_UNICAST_SIZE); _z_zbuf_reset(&zbf); if (_Z_LINK_IS_STREAMED(zl->_capabilities) == true) { diff --git a/src/transport/common/tx.c b/src/transport/common/tx.c index 1116fad15..a1144be24 100644 --- a/src/transport/common/tx.c +++ b/src/transport/common/tx.c @@ -14,7 +14,10 @@ #include "zenoh-pico/transport/link/tx.h" -#include "zenoh-pico/protocol/msgcodec.h" +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/protocol/codec/core.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/definitions/transport.h" #include "zenoh-pico/utils/logging.h" /*------------------ Transmission helper ------------------*/ @@ -48,49 +51,6 @@ void __unsafe_z_finalize_wbuf(_z_wbuf_t *buf, _Bool is_streamed) { } } -_z_transport_message_t _z_frame_header(z_reliability_t reliability, _Bool is_fragment, _Bool is_final, _z_zint_t sn) { - // Create the frame session message that carries the zenoh message - _Bool is_reliable = reliability == Z_RELIABILITY_RELIABLE; - - _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, is_reliable, is_fragment, is_final); - - return t_msg; -} - -/** - * This function is unsafe because it operates in potentially concurrent data. - * Make sure that the following mutexes are locked before calling this function: - * - ztu->mutex_tx - */ -int8_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn) { - int8_t ret = _Z_RES_OK; - - // Assume first that this is not the final fragment - _Bool is_final = false; - do { - size_t w_pos = _z_wbuf_get_wpos(dst); // Mark the buffer for the writing operation - - _z_transport_message_t f_hdr = _z_frame_header(reliability, true, is_final, sn); - ret = _z_transport_message_encode(dst, &f_hdr); // Encode the frame header - if (ret == _Z_RES_OK) { - size_t space_left = _z_wbuf_space_left(dst); - size_t bytes_left = _z_wbuf_len(src); - - if ((is_final == false) && (bytes_left <= space_left)) { // Check if it is really the final fragment - _z_wbuf_set_wpos(dst, w_pos); // Revert the buffer - is_final = true; // It is really the finally fragment, reserialize the header - continue; - } - - size_t to_copy = (bytes_left <= space_left) ? bytes_left : space_left; // Compute bytes to write - ret = _z_wbuf_siphon(dst, src, to_copy); // Write the fragment - } - break; - } while (1); - - return ret; -} - int8_t _z_send_t_msg(_z_transport_t *zt, const _z_transport_message_t *t_msg) { int8_t ret = _Z_RES_OK; @@ -116,7 +76,7 @@ int8_t _z_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_m int8_t ret = _Z_RES_OK; // Create and prepare the buffer to serialize the message on - uint16_t mtu = (zl->_mtu < Z_BATCH_SIZE_TX) ? zl->_mtu : Z_BATCH_SIZE_TX; + uint16_t mtu = (zl->_mtu < Z_BATCH_UNICAST_SIZE) ? zl->_mtu : Z_BATCH_UNICAST_SIZE; _z_wbuf_t wbf = _z_wbuf_make(mtu, false); if (_Z_LINK_IS_STREAMED(zl->_capabilities) == true) { for (uint8_t i = 0; i < _Z_MSG_LEN_ENC_SIZE; i++) { @@ -144,3 +104,32 @@ int8_t _z_link_send_t_msg(const _z_link_t *zl, const _z_transport_message_t *t_m return ret; } #endif // Z_UNICAST_TRANSPORT == 1 || Z_MULTICAST_TRANSPORT == 1 +int8_t __unsafe_z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, z_reliability_t reliability, size_t sn) { + int8_t ret = _Z_RES_OK; + + // Assume first that this is not the final fragment + _Bool is_final = false; + do { + size_t w_pos = _z_wbuf_get_wpos(dst); // Mark the buffer for the writing operation + + _z_transport_message_t f_hdr = + _z_t_msg_make_fragment_header(sn, reliability == Z_RELIABILITY_RELIABLE, is_final); + ret = _z_transport_message_encode(dst, &f_hdr); // Encode the frame header + if (ret == _Z_RES_OK) { + size_t space_left = _z_wbuf_space_left(dst); + size_t bytes_left = _z_wbuf_len(src); + + if ((is_final == false) && (bytes_left <= space_left)) { // Check if it is really the final fragment + _z_wbuf_set_wpos(dst, w_pos); // Revert the buffer + is_final = true; // It is really the finally fragment, reserialize the header + continue; + } + + size_t to_copy = (bytes_left <= space_left) ? bytes_left : space_left; // Compute bytes to write + ret = _z_wbuf_siphon(dst, src, to_copy); // Write the fragment + } + break; + } while (1); + + return ret; +} diff --git a/src/transport/manager.c b/src/transport/manager.c index 49c0cbab2..f365a399e 100644 --- a/src/transport/manager.c +++ b/src/transport/manager.c @@ -17,7 +17,7 @@ #include #include -int8_t _z_new_transport_client(_z_transport_t *zt, char *locator, _z_bytes_t *local_zid) { +int8_t _z_new_transport_client(_z_transport_t *zt, char *locator, _z_id_t *local_zid) { int8_t ret = _Z_RES_OK; _z_link_t zl; @@ -56,7 +56,7 @@ int8_t _z_new_transport_client(_z_transport_t *zt, char *locator, _z_bytes_t *lo return ret; } -int8_t _z_new_transport_peer(_z_transport_t *zt, char *locator, _z_bytes_t *local_zid) { +int8_t _z_new_transport_peer(_z_transport_t *zt, char *locator, _z_id_t *local_zid) { int8_t ret = _Z_RES_OK; _z_link_t zl; @@ -95,7 +95,7 @@ int8_t _z_new_transport_peer(_z_transport_t *zt, char *locator, _z_bytes_t *loca return ret; } -int8_t _z_new_transport(_z_transport_t *zt, _z_bytes_t *bs, char *locator, z_whatami_t mode) { +int8_t _z_new_transport(_z_transport_t *zt, _z_id_t *bs, char *locator, z_whatami_t mode) { int8_t ret; if (mode == Z_WHATAMI_CLIENT) { diff --git a/src/transport/multicast/link/rx.c b/src/transport/multicast/link/rx.c index 52e9d788f..b5d50e030 100644 --- a/src/transport/multicast/link/rx.c +++ b/src/transport/multicast/link/rx.c @@ -15,8 +15,14 @@ #include "zenoh-pico/transport/link/rx.h" #include +#include #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/codec/network.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/definitions/network.h" +#include "zenoh-pico/protocol/definitions/transport.h" +#include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -59,7 +65,7 @@ int8_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_me if (_z_zbuf_len(&ztm->_zbuf) < _Z_MSG_LEN_ENC_SIZE) { _z_zbuf_compact(&ztm->_zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; - continue; + break; } } @@ -73,7 +79,7 @@ int8_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_me _z_zbuf_set_rpos(&ztm->_zbuf, _z_zbuf_get_rpos(&ztm->_zbuf) - _Z_MSG_LEN_ENC_SIZE); _z_zbuf_compact(&ztm->_zbuf); ret = _Z_ERR_TRANSPORT_NOT_ENOUGH_BYTES; - continue; + break; } } } else { @@ -85,12 +91,9 @@ int8_t _z_multicast_recv_t_msg_na(_z_transport_multicast_t *ztm, _z_transport_me } } while (false); // The 1-iteration loop to use continue to break the entire loop on error - // Wrap the main buffer for to_read bytes - _z_zbuf_t zbuf = _z_zbuf_view(&ztm->_zbuf, to_read); - if (ret == _Z_RES_OK) { - _Z_DEBUG(">> \t transport_message_decode\n"); - ret = _z_transport_message_decode_na(t_msg, &ztm->_zbuf); + _Z_DEBUG(">> \t transport_message_decode: %ju\n", (uintmax_t)_z_zbuf_len(&ztm->_zbuf)); + ret = _z_transport_message_decode(t_msg, &ztm->_zbuf); } #if Z_MULTI_THREAD == 1 @@ -115,81 +118,177 @@ int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_t // Mark the session that we have received data from this peer _z_transport_peer_entry_t *entry = _z_find_peer_entry(ztm->_peers, addr); switch (_Z_MID(t_msg->_header)) { - case _Z_MID_SCOUT: { - // Do nothing, multicast transports are not expected to handle SCOUT messages on established sessions + case _Z_MID_T_FRAME: { + _Z_INFO("Received _Z_FRAME message\n"); + if (entry == NULL) { + break; + } + entry->_received = true; + + // Check if the SN is correct + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { + // @TODO: amend once reliability is in place. For the time being only + // monotonic SNs are ensured + if (_z_sn_precedes(entry->_sn_res, entry->_sn_rx_sns._val._plain._reliable, t_msg->_body._frame._sn) == + true) { + entry->_sn_rx_sns._val._plain._reliable = t_msg->_body._frame._sn; + } else { + _z_wbuf_clear(&entry->_dbuf_reliable); + _Z_INFO("Reliable message dropped because it is out of order\n"); + break; + } + } else { + if (_z_sn_precedes(entry->_sn_res, entry->_sn_rx_sns._val._plain._best_effort, + t_msg->_body._frame._sn) == true) { + entry->_sn_rx_sns._val._plain._best_effort = t_msg->_body._frame._sn; + } else { + _z_wbuf_clear(&entry->_dbuf_best_effort); + _Z_INFO("Best effort message dropped because it is out of order\n"); + break; + } + } + + // Handle all the zenoh message, one by one + uint16_t mapping = entry->_peer_id; + size_t len = _z_vec_len(&t_msg->_body._frame._messages); + for (size_t i = 0; i < len; i++) { + _z_network_message_t *zm = _z_network_message_vec_get(&t_msg->_body._frame._messages, i); + _z_msg_fix_mapping(zm, mapping); + _z_handle_network_message(ztm->_session, zm, mapping); + } + break; } - case _Z_MID_HELLO: { - // Do nothing, multicast transports are not expected to handle HELLO messages on established sessions + case _Z_MID_T_FRAGMENT: { + _Z_INFO("Received Z_FRAGMENT message\n"); + if (entry == NULL) { + break; + } + entry->_received = true; + + _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) + ? &entry->_dbuf_reliable + : &entry->_dbuf_best_effort; // Select the right defragmentation buffer + + _Bool drop = false; + if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { + // Filling the wbuf capacity as a way to signaling the last fragment to reset the dbuf + // Otherwise, last (smaller) fragments can be understood as a complete message + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, _z_wbuf_space_left(dbuf)); + drop = true; + } else { + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, + t_msg->_body._fragment._payload.len); + } + + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_M) == false) { + if (drop == true) { // Drop message if it exceeds the fragmentation size + _z_wbuf_reset(dbuf); + break; + } + + _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); // Convert the defragmentation buffer into a decoding buffer + + _z_zenoh_message_t zm; + ret = _z_network_message_decode(&zm, &zbf); + if (ret == _Z_RES_OK) { + uint16_t mapping = entry->_peer_id; + _z_msg_fix_mapping(&zm, mapping); + _z_handle_network_message(ztm->_session, &zm, mapping); + _z_msg_clear(&zm); // Clear must be explicitly called for fragmented zenoh messages. Non-fragmented + // zenoh messages are released when their transport message is released. + } + + // Free the decoding buffer + _z_zbuf_clear(&zbf); + // Reset the defragmentation buffer + _z_wbuf_reset(dbuf); + } break; } - case _Z_MID_INIT: { - // Do nothing, multicas transports are not expected to handle INIT messages + case _Z_MID_T_KEEP_ALIVE: { + _Z_INFO("Received _Z_KEEP_ALIVE message\n"); + if (entry == NULL) { + break; + } + entry->_received = true; + + break; + } + + case _Z_MID_T_INIT: { + // Do nothing, multicast transports are not expected to handle INIT messages break; } - case _Z_MID_OPEN: { - // Do nothing, multicas transports are not expected to handle OPEN messages + case _Z_MID_T_OPEN: { + // Do nothing, multicast transports are not expected to handle OPEN messages break; } - case _Z_MID_JOIN: { + case _Z_MID_T_JOIN: { _Z_INFO("Received _Z_JOIN message\n"); - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_A) == true) { - if (t_msg->_body._join._version != Z_PROTO_VERSION) { - break; - } + if (t_msg->_body._join._version != Z_PROTO_VERSION) { + break; } if (entry == NULL) // New peer { entry = (_z_transport_peer_entry_t *)z_malloc(sizeof(_z_transport_peer_entry_t)); if (entry != NULL) { - entry->_remote_addr = _z_bytes_duplicate(addr); - entry->_remote_zid = _z_bytes_duplicate(&t_msg->_body._join._zid); - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_S) == true) { - entry->_sn_resolution = t_msg->_body._join._sn_resolution; - } else { - entry->_sn_resolution = Z_SN_RESOLUTION; + entry->_sn_res = _z_sn_max(t_msg->_body._join._seq_num_res); + + // If the new node has less representing capabilities then it is incompatible to communication + if ((t_msg->_body._join._seq_num_res != Z_SN_RESOLUTION) || + (t_msg->_body._join._req_id_res != Z_REQ_RESOLUTION) || + (t_msg->_body._join._batch_size != Z_BATCH_MULTICAST_SIZE)) { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; } - entry->_sn_resolution_half = entry->_sn_resolution / 2; - _z_conduit_sn_list_copy(&entry->_sn_rx_sns, &t_msg->_body._join._next_sns); - _z_conduit_sn_list_decrement(entry->_sn_resolution, &entry->_sn_rx_sns); + if (ret == _Z_RES_OK) { + entry->_remote_addr = _z_bytes_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); + _z_conduit_sn_list_decrement(entry->_sn_res, &entry->_sn_rx_sns); #if Z_DYNAMIC_MEMORY_ALLOCATION == 1 - entry->_dbuf_reliable = _z_wbuf_make(0, true); - entry->_dbuf_best_effort = _z_wbuf_make(0, true); + entry->_dbuf_reliable = _z_wbuf_make(0, true); + entry->_dbuf_best_effort = _z_wbuf_make(0, true); #else - entry->_dbuf_reliable = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); - entry->_dbuf_best_effort = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); + entry->_dbuf_reliable = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); + entry->_dbuf_best_effort = _z_wbuf_make(Z_FRAG_MAX_SIZE, false); #endif - // Update lease time (set as ms during) - entry->_lease = t_msg->_body._join._lease; - entry->_next_lease = entry->_lease; - entry->_received = true; + // Update lease time (set as ms during) + entry->_lease = t_msg->_body._join._lease; + entry->_next_lease = entry->_lease; + entry->_received = true; - ztm->_peers = _z_transport_peer_entry_list_push(ztm->_peers, entry); + ztm->_peers = _z_transport_peer_entry_list_insert(ztm->_peers, entry); + } else { + z_free(entry); + } } else { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; } - } else // Existing peer - { + } else { // Existing peer entry->_received = true; - // Check if the sn resolution remains the same - if ((_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_S) == true) && - (entry->_sn_resolution != t_msg->_body._join._sn_resolution)) { + // Check if the representing capabilities are still the same + if ((t_msg->_body._join._seq_num_res != Z_SN_RESOLUTION) || + (t_msg->_body._join._req_id_res != Z_REQ_RESOLUTION) || + (t_msg->_body._join._batch_size != Z_BATCH_MULTICAST_SIZE)) { _z_transport_peer_entry_list_drop_filter(ztm->_peers, _z_transport_peer_entry_eq, entry); + // TODO: cleanup here should also be done on mappings/subs/etc... break; } // Update SNs - _z_conduit_sn_list_copy(&entry->_sn_rx_sns, &t_msg->_body._join._next_sns); - _z_conduit_sn_list_decrement(entry->_sn_resolution, &entry->_sn_rx_sns); + _z_conduit_sn_list_copy(&entry->_sn_rx_sns, &t_msg->_body._join._next_sn); + _z_conduit_sn_list_decrement(entry->_sn_res, &entry->_sn_rx_sns); // Update lease time (set as ms during) entry->_lease = t_msg->_body._join._lease; @@ -197,136 +296,17 @@ int8_t _z_multicast_handle_transport_message(_z_transport_multicast_t *ztm, _z_t break; } - case _Z_MID_CLOSE: { + case _Z_MID_T_CLOSE: { _Z_INFO("Closing session as requested by the remote peer\n"); if (entry == NULL) { break; } - - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_I) == true) { - // Check if the Peer ID matches the remote address in the knonw peer list - if ((entry->_remote_zid.len != t_msg->_body._close._zid.len) || - (memcmp(entry->_remote_zid.start, t_msg->_body._close._zid.start, entry->_remote_zid.len) != 0)) { - break; - } - } ztm->_peers = _z_transport_peer_entry_list_drop_filter(ztm->_peers, _z_transport_peer_entry_eq, entry); break; } - case _Z_MID_SYNC: { - _Z_INFO("Handling of Sync messages not implemented\n"); - break; - } - - case _Z_MID_ACK_NACK: { - _Z_INFO("Handling of AckNack messages not implemented\n"); - break; - } - - case _Z_MID_KEEP_ALIVE: { - _Z_INFO("Received _Z_KEEP_ALIVE message\n"); - if (entry == NULL) { - break; - } - entry->_received = true; - - break; - } - - case _Z_MID_PING_PONG: { - _Z_DEBUG("Handling of PingPong messages not implemented"); - break; - } - - case _Z_MID_FRAME: { - _Z_INFO("Received _Z_FRAME message\n"); - if (entry == NULL) { - break; - } - entry->_received = true; - - // Check if the SN is correct - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_R) == true) { - // @TODO: amend once reliability is in place. For the time being only - // monothonic SNs are ensured - if (_z_sn_precedes(entry->_sn_resolution_half, entry->_sn_rx_sns._val._plain._reliable, - t_msg->_body._frame._sn) == true) { - entry->_sn_rx_sns._val._plain._reliable = t_msg->_body._frame._sn; - } else { - _z_wbuf_clear(&entry->_dbuf_reliable); - _Z_INFO("Reliable message dropped because it is out of order"); - break; - } - } else { - if (_z_sn_precedes(entry->_sn_resolution_half, entry->_sn_rx_sns._val._plain._best_effort, - t_msg->_body._frame._sn) == true) { - entry->_sn_rx_sns._val._plain._best_effort = t_msg->_body._frame._sn; - } else { - _z_wbuf_clear(&entry->_dbuf_best_effort); - _Z_INFO("Best effort message dropped because it is out of order"); - break; - } - } - - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_F) == true) { - // Select the right defragmentation buffer - _z_wbuf_t *dbuf = (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_R) == true) ? &entry->_dbuf_reliable - : &entry->_dbuf_best_effort; - - _Bool drop = false; - if ((_z_wbuf_len(dbuf) + t_msg->_body._frame._payload._fragment.len) > Z_FRAG_MAX_SIZE) { - // Filling the wbuf capacity as a way to signling the last fragment to reset the dbuf - // Otherwise, last (smaller) fragments can be understood as a complete message - _z_wbuf_write_bytes(dbuf, t_msg->_body._frame._payload._fragment.start, 0, - _z_wbuf_space_left(dbuf)); - drop = true; - } else { - // Add the fragment to the defragmentation buffer - _z_wbuf_write_bytes(dbuf, t_msg->_body._frame._payload._fragment.start, 0, - t_msg->_body._frame._payload._fragment.len); - } - - // Check if this is the last fragment - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_E) == true) { - // Drop message if it is bigger the max buffer size - if (drop == true) { - _z_wbuf_reset(dbuf); - break; - } - - // Convert the defragmentation buffer into a decoding buffer - _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); - - // Decode the zenoh message - _z_zenoh_message_t zm; - ret = _z_zenoh_message_decode(&zm, &zbf); - if (ret == _Z_RES_OK) { - _z_handle_zenoh_message(ztm->_session, &zm); - - // Clear must be explicitly called for fragmented zenoh messages. - // Non-fragmented zenoh messages are released when their transport message is released. - _z_msg_clear(&zm); - } - - // Free the decoding buffer - _z_zbuf_clear(&zbf); - // Reset the defragmentation buffer - _z_wbuf_reset(dbuf); - } - } else { - // Handle all the zenoh message, one by one - size_t len = _z_vec_len(&t_msg->_body._frame._payload._messages); - for (size_t i = 0; i < len; i++) { - _z_handle_zenoh_message( - ztm->_session, (_z_zenoh_message_t *)_z_vec_get(&t_msg->_body._frame._payload._messages, i)); - } - } - break; - } - default: { _Z_ERROR("Unknown session message ID\n"); break; diff --git a/src/transport/multicast/link/task/join.c b/src/transport/multicast/link/task/join.c index 0dbc9b337..345ab689c 100644 --- a/src/transport/multicast/link/task/join.c +++ b/src/transport/multicast/link/task/join.c @@ -20,15 +20,13 @@ #if Z_MULTICAST_TRANSPORT == 1 int8_t _zp_multicast_send_join(_z_transport_multicast_t *ztm) { - _z_conduit_sn_list_t next_sns; - next_sns._is_qos = false; // FIXME: make transport aware of qos configuration - next_sns._val._plain._best_effort = ztm->_sn_tx_best_effort; - next_sns._val._plain._reliable = ztm->_sn_tx_reliable; + _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_bytes_t zid = _z_bytes_wrap(((_z_session_t *)ztm->_session)->_local_zid.start, - ((_z_session_t *)ztm->_session)->_local_zid.len); - _z_transport_message_t jsm = - _z_t_msg_make_join(Z_PROTO_VERSION, Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, Z_SN_RESOLUTION, zid, next_sns); + _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 _z_multicast_send_t_msg(ztm, &jsm); } diff --git a/src/transport/multicast/link/task/lease.c b/src/transport/multicast/link/task/lease.c index 6edac4c22..c653d2dea 100644 --- a/src/transport/multicast/link/task/lease.c +++ b/src/transport/multicast/link/task/lease.c @@ -61,10 +61,7 @@ _z_zint_t _z_get_next_lease(_z_transport_peer_entry_list_t *peers) { int8_t _zp_multicast_send_keep_alive(_z_transport_multicast_t *ztm) { int8_t ret = _Z_RES_OK; - _z_bytes_t zid = _z_bytes_wrap(((_z_session_t *)ztm->_session)->_local_zid.start, - ((_z_session_t *)ztm->_session)->_local_zid.len); - _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(zid); - + _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(); ret = _z_multicast_send_t_msg(ztm, &t_msg); return ret; diff --git a/src/transport/multicast/link/task/read.c b/src/transport/multicast/link/task/read.c index 3100b5f86..2c4278426 100644 --- a/src/transport/multicast/link/task/read.c +++ b/src/transport/multicast/link/task/read.c @@ -17,6 +17,8 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/transport/link/rx.h" #include "zenoh-pico/utils/logging.h" @@ -88,7 +90,7 @@ void *_zp_multicast_read_task(void *ztm_arg) { // Decode one session message _z_transport_message_t t_msg; - ret = _z_transport_message_decode_na(&t_msg, &zbuf); + ret = _z_transport_message_decode(&t_msg, &zbuf); if (ret == _Z_RES_OK) { ret = _z_multicast_handle_transport_message(ztm, &t_msg, &addr); diff --git a/src/transport/multicast/link/tx.c b/src/transport/multicast/link/tx.c index a84ab8a10..67e4e35bd 100644 --- a/src/transport/multicast/link/tx.c +++ b/src/transport/multicast/link/tx.c @@ -15,7 +15,8 @@ #include "zenoh-pico/transport/link/tx.h" #include "zenoh-pico/config.h" -#include "zenoh-pico/protocol/msgcodec.h" +#include "zenoh-pico/protocol/codec/network.h" +#include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -30,10 +31,10 @@ _z_zint_t __unsafe_z_multicast_get_sn(_z_transport_multicast_t *ztm, z_reliabili _z_zint_t sn; if (reliability == Z_RELIABILITY_RELIABLE) { sn = ztm->_sn_tx_reliable; - ztm->_sn_tx_reliable = _z_sn_increment(ztm->_sn_resolution, ztm->_sn_tx_reliable); + ztm->_sn_tx_reliable = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_reliable); } else { sn = ztm->_sn_tx_best_effort; - ztm->_sn_tx_best_effort = _z_sn_increment(ztm->_sn_resolution, ztm->_sn_tx_best_effort); + ztm->_sn_tx_best_effort = _z_sn_increment(ztm->_sn_res, ztm->_sn_tx_best_effort); } return sn; } @@ -69,10 +70,10 @@ int8_t _z_multicast_send_t_msg(_z_transport_multicast_t *ztm, const _z_transport return ret; } -int8_t _z_multicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reliability_t reliability, +int8_t _z_multicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { int8_t ret = _Z_RES_OK; - _Z_DEBUG(">> send zenoh message\n"); + _Z_DEBUG(">> send network message\n"); _z_transport_multicast_t *ztm = &zn->_tp._transport._multicast; @@ -99,10 +100,10 @@ int8_t _z_multicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_re _z_zint_t sn = __unsafe_z_multicast_get_sn(ztm, reliability); // Get the next sequence number - _z_transport_message_t t_msg = _z_frame_header(reliability, 0, 0, sn); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); ret = _z_transport_message_encode(&ztm->_wbuf, &t_msg); // Encode the frame header if (ret == _Z_RES_OK) { - ret = _z_zenoh_message_encode(&ztm->_wbuf, z_msg); // Encode the zenoh message + ret = _z_network_message_encode(&ztm->_wbuf, n_msg); // Encode the network message if (ret == _Z_RES_OK) { // Write the message legnth in the reserved space if needed __unsafe_z_finalize_wbuf(&ztm->_wbuf, _Z_LINK_IS_STREAMED(ztm->_link._capabilities)); @@ -114,9 +115,9 @@ int8_t _z_multicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_re } else { // The message does not fit in the current batch, let's fragment it // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(Z_IOSLICE_SIZE, true); + _z_wbuf_t fbf = _z_wbuf_make(ztm->_wbuf._capacity - 12, true); - ret = _z_zenoh_message_encode(&fbf, z_msg); // Encode the message on the expandable wbuf + ret = _z_network_message_encode(&fbf, n_msg); // Encode the message on the expandable wbuf if (ret == _Z_RES_OK) { _Bool is_first = true; // Fragment and send the message while (_z_wbuf_len(&fbf) > 0) { @@ -141,8 +142,6 @@ int8_t _z_multicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_re } } } - - _z_wbuf_clear(&fbf); // Free the fragmentation buffer memory } } diff --git a/src/transport/peer_entry.c b/src/transport/peer_entry.c index 7d5c2f84a..eebb7508f 100644 --- a/src/transport/peer_entry.c +++ b/src/transport/peer_entry.c @@ -12,6 +12,7 @@ // ZettaScale Zenoh Team, // +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/transport.h" #include "zenoh-pico/transport/utils.h" @@ -19,7 +20,7 @@ void _z_transport_peer_entry_clear(_z_transport_peer_entry_t *src) { _z_wbuf_clear(&src->_dbuf_reliable); _z_wbuf_clear(&src->_dbuf_best_effort); - _z_bytes_clear(&src->_remote_zid); + src->_remote_zid = _z_id_empty(); _z_bytes_clear(&src->_remote_addr); } @@ -27,15 +28,14 @@ void _z_transport_peer_entry_copy(_z_transport_peer_entry_t *dst, const _z_trans _z_wbuf_copy(&dst->_dbuf_reliable, &src->_dbuf_reliable); _z_wbuf_copy(&dst->_dbuf_best_effort, &src->_dbuf_best_effort); - dst->_sn_resolution = src->_sn_resolution; - dst->_sn_resolution_half = src->_sn_resolution_half; + dst->_sn_res = src->_sn_res; _z_conduit_sn_list_copy(&dst->_sn_rx_sns, &src->_sn_rx_sns); dst->_lease = src->_lease; dst->_next_lease = src->_next_lease; dst->_received = src->_received; - _z_bytes_copy(&dst->_remote_zid, &src->_remote_zid); + dst->_remote_zid = src->_remote_zid; _z_bytes_copy(&dst->_remote_addr, &src->_remote_addr); } @@ -46,11 +46,7 @@ size_t _z_transport_peer_entry_size(const _z_transport_peer_entry_t *src) { _Bool _z_transport_peer_entry_eq(const _z_transport_peer_entry_t *left, const _z_transport_peer_entry_t *right) { _Bool ret = true; - if (left->_remote_zid.len == right->_remote_zid.len) { - if (memcmp(left->_remote_zid.start, right->_remote_zid.start, left->_remote_zid.len) != 0) { - ret = false; - } - } else { + if (memcmp(left->_remote_zid.id, right->_remote_zid.id, 16) != 0) { ret = false; } diff --git a/src/transport/transport.c b/src/transport/transport.c index 576a5e65d..af71c2016 100644 --- a/src/transport/transport.c +++ b/src/transport/transport.c @@ -15,9 +15,12 @@ #include "zenoh-pico/transport/transport.h" #include +#include #include #include "zenoh-pico/config.h" +#include "zenoh-pico/link/link.h" +#include "zenoh-pico/protocol/core.h" #include "zenoh-pico/transport/link/rx.h" #include "zenoh-pico/transport/link/tx.h" #include "zenoh-pico/transport/utils.h" @@ -27,9 +30,7 @@ int8_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, _Bool link_only) { int8_t ret = _Z_RES_OK; - _z_bytes_t zid = _z_bytes_wrap(((_z_session_t *)ztu->_session)->_local_zid.start, - ((_z_session_t *)ztu->_session)->_local_zid.len); - _z_transport_message_t cm = _z_t_msg_make_close(reason, zid, link_only); + _z_transport_message_t cm = _z_t_msg_make_close(reason, link_only); ret = _z_unicast_send_t_msg(ztu, &cm); _z_t_msg_clear(&cm); @@ -42,9 +43,7 @@ int8_t _z_unicast_send_close(_z_transport_unicast_t *ztu, uint8_t reason, _Bool int8_t _z_multicast_send_close(_z_transport_multicast_t *ztm, uint8_t reason, _Bool link_only) { int8_t ret = _Z_RES_OK; - _z_bytes_t zid = _z_bytes_wrap(((_z_session_t *)ztm->_session)->_local_zid.start, - ((_z_session_t *)ztm->_session)->_local_zid.len); - _z_transport_message_t cm = _z_t_msg_make_close(reason, zid, link_only); + _z_transport_message_t cm = _z_t_msg_make_close(reason, link_only); ret = _z_multicast_send_t_msg(ztm, &cm); _z_t_msg_clear(&cm); @@ -92,23 +91,24 @@ int8_t _z_transport_unicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_unic // Initialize the read and write buffers if (ret == _Z_RES_OK) { - uint16_t mtu = (zl->_mtu < Z_BATCH_SIZE_TX) ? zl->_mtu : Z_BATCH_SIZE_TX; - zt->_transport._unicast._wbuf = _z_wbuf_make(mtu, false); - zt->_transport._unicast._zbuf = _z_zbuf_make(Z_BATCH_SIZE_RX); - - // Initialize the defragmentation buffers + uint16_t mtu = (zl->_mtu < Z_BATCH_UNICAST_SIZE) ? zl->_mtu : Z_BATCH_UNICAST_SIZE; + _Bool expandable = _Z_LINK_IS_STREAMED(zl->_capabilities); size_t dbuf_size = 0; - _Bool dbuf_expandable = true; + #if Z_DYNAMIC_MEMORY_ALLOCATION == 0 + expandable = false; dbuf_size = Z_FRAG_MAX_SIZE; - dbuf_expandable = false; #endif - zt->_transport._unicast._dbuf_reliable = _z_wbuf_make(dbuf_size, dbuf_expandable); - zt->_transport._unicast._dbuf_best_effort = _z_wbuf_make(dbuf_size, dbuf_expandable); + zt->_transport._unicast._wbuf = _z_wbuf_make(mtu, false); + zt->_transport._unicast._zbuf = _z_zbuf_make(Z_BATCH_UNICAST_SIZE); + + // Initialize the defragmentation buffers + zt->_transport._unicast._dbuf_reliable = _z_wbuf_make(dbuf_size, expandable); + zt->_transport._unicast._dbuf_best_effort = _z_wbuf_make(dbuf_size, expandable); // Clean up the buffers if one of them failed to be allocated if ((_z_wbuf_capacity(&zt->_transport._unicast._wbuf) != mtu) || - (_z_zbuf_capacity(&zt->_transport._unicast._zbuf) != Z_BATCH_SIZE_RX) || + (_z_zbuf_capacity(&zt->_transport._unicast._zbuf) != Z_BATCH_UNICAST_SIZE) || #if Z_DYNAMIC_MEMORY_ALLOCATION == 0 (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_reliable) != dbuf_size) || (_z_wbuf_capacity(&zt->_transport._unicast._dbuf_best_effort) != dbuf_size)) { @@ -132,16 +132,16 @@ int8_t _z_transport_unicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_unic if (ret == _Z_RES_OK) { // Set default SN resolution - zt->_transport._unicast._sn_resolution = param->_sn_resolution; - zt->_transport._unicast._sn_resolution_half = param->_sn_resolution / 2; + zt->_transport._unicast._sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side zt->_transport._unicast._sn_tx_reliable = param->_initial_sn_tx; zt->_transport._unicast._sn_tx_best_effort = param->_initial_sn_tx; // The initial SN at RX side - zt->_transport._unicast._sn_rx_reliable = param->_initial_sn_rx; - zt->_transport._unicast._sn_rx_best_effort = param->_initial_sn_rx; + _z_zint_t initial_sn_rx = _z_sn_decrement(zt->_transport._unicast._sn_res, param->_initial_sn_rx); + zt->_transport._unicast._sn_rx_reliable = initial_sn_rx; + zt->_transport._unicast._sn_rx_best_effort = initial_sn_rx; #if Z_MULTI_THREAD == 1 // Tasks @@ -162,9 +162,9 @@ int8_t _z_transport_unicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_unic zt->_transport._unicast._link = *zl; // Remote peer PID - _z_bytes_move(&zt->_transport._unicast._remote_zid, ¶m->_remote_zid); + zt->_transport._unicast._remote_zid = param->_remote_zid; } else { - _z_bytes_clear(¶m->_remote_zid); + param->_remote_zid = _z_id_empty(); } return ret; @@ -196,13 +196,13 @@ int8_t _z_transport_multicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_mu // Initialize the read and write buffers if (ret == _Z_RES_OK) { - uint16_t mtu = (zl->_mtu < Z_BATCH_SIZE_TX) ? zl->_mtu : Z_BATCH_SIZE_TX; + uint16_t mtu = (zl->_mtu < Z_BATCH_MULTICAST_SIZE) ? zl->_mtu : Z_BATCH_MULTICAST_SIZE; zt->_transport._multicast._wbuf = _z_wbuf_make(mtu, false); - zt->_transport._multicast._zbuf = _z_zbuf_make(Z_BATCH_SIZE_RX); + zt->_transport._multicast._zbuf = _z_zbuf_make(Z_BATCH_MULTICAST_SIZE); // Clean up the buffers if one of them failed to be allocated if ((_z_wbuf_capacity(&zt->_transport._multicast._wbuf) != mtu) || - (_z_zbuf_capacity(&zt->_transport._multicast._zbuf) != Z_BATCH_SIZE_RX)) { + (_z_zbuf_capacity(&zt->_transport._multicast._zbuf) != Z_BATCH_MULTICAST_SIZE)) { ret = _Z_ERR_SYSTEM_OUT_OF_MEMORY; #if Z_MULTI_THREAD == 1 @@ -218,12 +218,11 @@ int8_t _z_transport_multicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_mu if (ret == _Z_RES_OK) { // Set default SN resolution - zt->_transport._multicast._sn_resolution = param->_sn_resolution; - zt->_transport._multicast._sn_resolution_half = param->_sn_resolution / 2; + zt->_transport._multicast._sn_res = _z_sn_max(param->_seq_num_res); // The initial SN at TX side - zt->_transport._multicast._sn_tx_reliable = param->_initial_sn_tx; - zt->_transport._multicast._sn_tx_best_effort = param->_initial_sn_tx; + zt->_transport._multicast._sn_tx_reliable = param->_initial_sn_tx._val._plain._reliable; + zt->_transport._multicast._sn_tx_best_effort = param->_initial_sn_tx._val._plain._best_effort; // Initialize peer list zt->_transport._multicast._peers = _z_transport_peer_entry_list_new(); @@ -251,18 +250,14 @@ int8_t _z_transport_multicast(_z_transport_t *zt, _z_link_t *zl, _z_transport_mu #if Z_UNICAST_TRANSPORT == 1 int8_t _z_transport_unicast_open_client(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid) { + const _z_id_t *local_zid) { int8_t ret = _Z_RES_OK; - // Build the open message - uint8_t version = Z_PROTO_VERSION; - z_whatami_t whatami = Z_WHATAMI_CLIENT; - _z_zint_t sn_resolution = Z_SN_RESOLUTION; - _Bool is_qos = false; - - _z_bytes_t zid = _z_bytes_wrap(local_zid->start, local_zid->len); - _z_transport_message_t ism = _z_t_msg_make_init_syn(version, whatami, sn_resolution, zid, is_qos); - param->_sn_resolution = ism._body._init._sn_resolution; // The announced sn resolution + _z_id_t zid = *local_zid; + _z_transport_message_t ism = _z_t_msg_make_init_syn(Z_WHATAMI_CLIENT, zid); + param->_seq_num_res = ism._body._init._seq_num_res; // The announced sn resolution + param->_req_id_res = ism._body._init._req_id_res; // The announced req id resolution + param->_batch_size = ism._body._init._batch_size; // The announced batch size // Encode and send the message _Z_INFO("Sending Z_INIT(Syn)\n"); @@ -272,28 +267,40 @@ int8_t _z_transport_unicast_open_client(_z_transport_unicast_establish_param_t * _z_transport_message_t iam; ret = _z_link_recv_t_msg(&iam, zl); if (ret == _Z_RES_OK) { - if ((_Z_MID(iam._header) == _Z_MID_INIT) && (_Z_HAS_FLAG(iam._header, _Z_FLAG_T_A) == true)) { + if ((_Z_MID(iam._header) == _Z_MID_T_INIT) && (_Z_HAS_FLAG(iam._header, _Z_FLAG_T_INIT_A) == true)) { _Z_INFO("Received Z_INIT(Ack)\n"); - // Handle SN resolution option if present - if (_Z_HAS_FLAG(iam._header, _Z_FLAG_T_S) == true) { - // The resolution in the InitAck must be less or equal than the resolution in the InitSyn, - // otherwise the InitAck message is considered invalid and it should be treated as a - // CLOSE message with L==0 by the Initiating Peer -- the recipient of the InitAck message. - if (iam._body._init._sn_resolution <= param->_sn_resolution) { - param->_sn_resolution = iam._body._init._sn_resolution; - } else { - ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; - } + // Any of the size parameters in the InitAck must be less or equal than the one in the InitSyn, + // otherwise the InitAck message is considered invalid and it should be treated as a + // CLOSE message with L==0 by the Initiating Peer -- the recipient of the InitAck message. + if (iam._body._init._seq_num_res <= param->_seq_num_res) { + param->_seq_num_res = iam._body._init._seq_num_res; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; + } + + if (iam._body._init._req_id_res <= param->_req_id_res) { + param->_req_id_res = iam._body._init._req_id_res; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; + } + + if (iam._body._init._batch_size <= param->_batch_size) { + param->_batch_size = iam._body._init._batch_size; + } else { + ret = _Z_ERR_TRANSPORT_OPEN_SN_RESOLUTION; } if (ret == _Z_RES_OK) { + param->_key_id_res = 0x08 << param->_key_id_res; + param->_req_id_res = 0x08 << param->_req_id_res; + // The initial SN at TX side z_random_fill(¶m->_initial_sn_tx, sizeof(param->_initial_sn_tx)); - param->_initial_sn_tx = param->_initial_sn_tx % param->_sn_resolution; + param->_initial_sn_tx = param->_initial_sn_tx & !_z_sn_modulo_mask(param->_seq_num_res); // Initialize the Local and Remote Peer IDs - _z_bytes_copy(¶m->_remote_zid, &iam._body._init._zid); + param->_remote_zid = iam._body._init._zid; // Create the OpenSyn message _z_zint_t lease = Z_TRANSPORT_LEASE; @@ -310,15 +317,14 @@ int8_t _z_transport_unicast_open_client(_z_transport_unicast_establish_param_t * _z_transport_message_t oam; ret = _z_link_recv_t_msg(&oam, zl); if (ret == _Z_RES_OK) { - if ((_Z_MID(oam._header) == _Z_MID_OPEN) && - (_Z_HAS_FLAG(oam._header, _Z_FLAG_T_A) == true)) { + if ((_Z_MID(oam._header) == _Z_MID_T_OPEN) && + (_Z_HAS_FLAG(oam._header, _Z_FLAG_T_OPEN_A) == true)) { _Z_INFO("Received Z_OPEN(Ack)\n"); param->_lease = oam._body._open._lease; // The session lease // The initial SN at RX side. Initialize the session as we had already received // a message with a SN equal to initial_sn - 1. - param->_initial_sn_rx = - _z_sn_decrement(param->_sn_resolution, oam._body._open._initial_sn); + param->_initial_sn_rx = oam._body._open._initial_sn; } else { ret = _Z_ERR_MESSAGE_UNEXPECTED; } @@ -341,7 +347,7 @@ int8_t _z_transport_unicast_open_client(_z_transport_unicast_establish_param_t * #if Z_MULTICAST_TRANSPORT == 1 int8_t _z_transport_multicast_open_client(_z_transport_multicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid) { + const _z_id_t *local_zid) { (void)(param); (void)(zl); (void)(local_zid); @@ -355,7 +361,7 @@ int8_t _z_transport_multicast_open_client(_z_transport_multicast_establish_param #if Z_UNICAST_TRANSPORT == 1 int8_t _z_transport_unicast_open_peer(_z_transport_unicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid) { + const _z_id_t *local_zid) { (void)(param); (void)(zl); (void)(local_zid); @@ -369,29 +375,31 @@ int8_t _z_transport_unicast_open_peer(_z_transport_unicast_establish_param_t *pa #if Z_MULTICAST_TRANSPORT == 1 int8_t _z_transport_multicast_open_peer(_z_transport_multicast_establish_param_t *param, const _z_link_t *zl, - const _z_bytes_t *local_zid) { + const _z_id_t *local_zid) { int8_t ret = _Z_RES_OK; - param->_is_qos = false; // FIXME: make transport aware of qos configuration - param->_initial_sn_tx = 0; - param->_sn_resolution = Z_SN_RESOLUTION; + _z_zint_t initial_sn_tx = 0; + z_random_fill(&initial_sn_tx, sizeof(initial_sn_tx)); + initial_sn_tx = initial_sn_tx & !_z_sn_modulo_mask(Z_SN_RESOLUTION); - // Explicitly send a JOIN message upon startup - // FIXME: make transport aware of qos configuration - _z_conduit_sn_list_t next_sns; - next_sns._is_qos = false; - next_sns._val._plain._best_effort = param->_initial_sn_tx; - next_sns._val._plain._reliable = param->_initial_sn_tx; + _z_conduit_sn_list_t next_sn; + next_sn._is_qos = false; + next_sn._val._plain._best_effort = initial_sn_tx; + next_sn._val._plain._reliable = initial_sn_tx; - _z_bytes_t zid = _z_bytes_wrap(local_zid->start, local_zid->len); - _z_transport_message_t jsm = - _z_t_msg_make_join(Z_PROTO_VERSION, Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, param->_sn_resolution, zid, next_sns); + _z_id_t zid = *local_zid; + _z_transport_message_t jsm = _z_t_msg_make_join(Z_WHATAMI_PEER, Z_TRANSPORT_LEASE, zid, next_sn); // Encode and send the message _Z_INFO("Sending Z_JOIN message\n"); ret = _z_link_send_t_msg(zl, &jsm); _z_t_msg_clear(&jsm); + if (ret == _Z_RES_OK) { + param->_seq_num_res = jsm._body._join._seq_num_res; + param->_initial_sn_tx = next_sn; + } + return ret; } #endif // Z_MULTICAST_TRANSPORT == 1 @@ -435,7 +443,7 @@ void _z_transport_unicast_clear(_z_transport_unicast_t *ztu) { _z_wbuf_clear(&ztu->_dbuf_best_effort); // Clean up PIDs - _z_bytes_clear(&ztu->_remote_zid); + ztu->_remote_zid = _z_id_empty(); _z_link_clear(&ztu->_link); } #endif // Z_UNICAST_TRANSPORT == 1 @@ -495,3 +503,43 @@ void _z_transport_free(_z_transport_t **zt) { *zt = NULL; } } + +/** + * @brief Inserts an entry into `root`, allocating it a `_peer_id` + * + * @param root the insertion root. + * @param entry the entry to be inserted. + * @return _z_transport_peer_entry_list_t* the new root, after inserting the entry. + */ +_z_transport_peer_entry_list_t *_z_transport_peer_entry_list_insert(_z_transport_peer_entry_list_t *root, + _z_transport_peer_entry_t *entry) { + if (root == NULL) { + entry->_peer_id = 1; + root = _z_transport_peer_entry_list_push(root, entry); + } else { + _z_transport_peer_entry_t *head = _z_transport_peer_entry_list_head(root); + if (head->_peer_id + 1 < _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE) { + entry->_peer_id = head->_peer_id + 1; + root = _z_transport_peer_entry_list_push(root, entry); + } else { + _z_transport_peer_entry_list_t *parent = root; + uint16_t target = head->_peer_id - 1; + while (parent->_tail != NULL) { + _z_transport_peer_entry_list_t *list = _z_transport_peer_entry_list_tail(parent); + head = _z_transport_peer_entry_list_head(list); + if (head->_peer_id < target) { + entry->_peer_id = head->_peer_id + 1; + parent->_tail = _z_transport_peer_entry_list_push(list, entry); + return root; + } + parent = list; + target = head->_peer_id - 1; + } + assert(target > 0); + entry->_peer_id = 1; + parent->_tail = _z_transport_peer_entry_list_push(NULL, entry); + parent->_tail->_val = entry; + } + } + return root; +} diff --git a/src/transport/unicast/link/rx.c b/src/transport/unicast/link/rx.c index f5a0025d4..bac48d82e 100644 --- a/src/transport/unicast/link/rx.c +++ b/src/transport/unicast/link/rx.c @@ -17,6 +17,10 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/codec/network.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/session/utils.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -65,12 +69,9 @@ int8_t _z_unicast_recv_t_msg_na(_z_transport_unicast_t *ztu, _z_transport_messag } } while (false); // The 1-iteration loop to use continue to break the entire loop on error - // Wrap the main buffer for to_read bytes - _z_zbuf_t zbuf = _z_zbuf_view(&ztu->_zbuf, to_read); - if (ret == _Z_RES_OK) { _Z_DEBUG(">> \t transport_message_decode\n"); - ret = _z_transport_message_decode_na(t_msg, &ztu->_zbuf); + ret = _z_transport_message_decode(t_msg, &ztu->_zbuf); // Mark the session that we have received data if (ret == _Z_RES_OK) { @@ -91,58 +92,13 @@ int8_t _z_unicast_recv_t_msg(_z_transport_unicast_t *ztu, _z_transport_message_t int8_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_transport_message_t *t_msg) { switch (_Z_MID(t_msg->_header)) { - case _Z_MID_SCOUT: { - _Z_INFO("Handling of Scout messages not implemented\n"); - break; - } - - case _Z_MID_HELLO: { - // Do nothing, zenoh-pico clients are not expected to handle hello messages - break; - } - - case _Z_MID_INIT: { - // Do nothing, zenoh clients are not expected to handle accept messages on established sessions - break; - } - - case _Z_MID_OPEN: { - // Do nothing, zenoh clients are not expected to handle accept messages on established sessions - break; - } - - case _Z_MID_CLOSE: { - _Z_INFO("Closing session as requested by the remote peer\n"); - break; - } - - case _Z_MID_SYNC: { - _Z_INFO("Handling of Sync messages not implemented\n"); - break; - } - - case _Z_MID_ACK_NACK: { - _Z_INFO("Handling of AckNack messages not implemented\n"); - break; - } - - case _Z_MID_KEEP_ALIVE: { - _Z_INFO("Received Z_KEEP_ALIVE message\n"); - break; - } - - case _Z_MID_PING_PONG: { - _Z_INFO("Handling of PingPong messages not implemented\n"); - break; - } - - case _Z_MID_FRAME: { + case _Z_MID_T_FRAME: { _Z_INFO("Received Z_FRAME message\n"); // Check if the SN is correct - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_R) == true) { + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAME_R) == true) { // @TODO: amend once reliability is in place. For the time being only // monothonic SNs are ensured - if (_z_sn_precedes(ztu->_sn_resolution_half, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { + if (_z_sn_precedes(ztu->_sn_res, ztu->_sn_rx_reliable, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_reliable = t_msg->_body._frame._sn; } else { _z_wbuf_clear(&ztu->_dbuf_reliable); @@ -150,8 +106,7 @@ int8_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_trans break; } } else { - if (_z_sn_precedes(ztu->_sn_resolution_half, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == - true) { + if (_z_sn_precedes(ztu->_sn_res, ztu->_sn_rx_best_effort, t_msg->_body._frame._sn) == true) { ztu->_sn_rx_best_effort = t_msg->_body._frame._sn; } else { _z_wbuf_clear(&ztu->_dbuf_best_effort); @@ -160,64 +115,79 @@ int8_t _z_unicast_handle_transport_message(_z_transport_unicast_t *ztu, _z_trans } } - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_F) == true) { - // Select the right defragmentation buffer - _z_wbuf_t *dbuf = - _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_R) ? &ztu->_dbuf_reliable : &ztu->_dbuf_best_effort; - - _Bool drop = false; - if ((_z_wbuf_len(dbuf) + t_msg->_body._frame._payload._fragment.len) > Z_FRAG_MAX_SIZE) { - // Filling the wbuf capacity as a way to signling the last fragment to reset the dbuf - // Otherwise, last (smaller) fragments can be understood as a complete message - _z_wbuf_write_bytes(dbuf, t_msg->_body._frame._payload._fragment.start, 0, - _z_wbuf_space_left(dbuf)); - drop = true; - } else { - // Add the fragment to the defragmentation buffer - _z_wbuf_write_bytes(dbuf, t_msg->_body._frame._payload._fragment.start, 0, - t_msg->_body._frame._payload._fragment.len); - } + // Handle all the zenoh message, one by one + size_t len = _z_vec_len(&t_msg->_body._frame._messages); + for (size_t i = 0; i < len; i++) { + _z_handle_network_message(ztu->_session, + (_z_zenoh_message_t *)_z_vec_get(&t_msg->_body._frame._messages, i), + _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + } + + break; + } + + case _Z_MID_T_FRAGMENT: { + _z_wbuf_t *dbuf = _Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_R) + ? &ztu->_dbuf_reliable + : &ztu->_dbuf_best_effort; // Select the right defragmentation buffer + + _Bool drop = false; + if ((_z_wbuf_len(dbuf) + t_msg->_body._fragment._payload.len) > Z_FRAG_MAX_SIZE) { + // Filling the wbuf capacity as a way to signling the last fragment to reset the dbuf + // Otherwise, last (smaller) fragments can be understood as a complete message + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, _z_wbuf_space_left(dbuf)); + drop = true; + } else { + _z_wbuf_write_bytes(dbuf, t_msg->_body._fragment._payload.start, 0, + t_msg->_body._fragment._payload.len); + } - // Check if this is the last fragment - if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_E) == true) { - // Drop message if it is bigger the max buffer size - if (drop == true) { - _z_wbuf_reset(dbuf); - break; - } - - // Convert the defragmentation buffer into a decoding buffer - _z_zbuf_t zbf = _z_wbuf_to_zbuf(dbuf); - - // Decode the zenoh message - _z_zenoh_message_t zm; - int8_t ret = _z_zenoh_message_decode(&zm, &zbf); - if (ret == _Z_RES_OK) { - _z_handle_zenoh_message(ztu->_session, &zm); - - // Clear must be explicitly called for fragmented zenoh messages. - // Non-fragmented zenoh messages are released when their transport message is released. - _z_msg_clear(&zm); - } - - // Free the decoding buffer - _z_zbuf_clear(&zbf); - // Reset the defragmentation buffer + if (_Z_HAS_FLAG(t_msg->_header, _Z_FLAG_T_FRAGMENT_M) == false) { + if (drop == true) { // Drop message if it exceeds the fragmentation size _z_wbuf_reset(dbuf); + break; } - break; - } else { - // Handle all the zenoh message, one by one - size_t len = _z_vec_len(&t_msg->_body._frame._payload._messages); - for (size_t i = 0; i < len; i++) { - _z_handle_zenoh_message( - ztu->_session, (_z_zenoh_message_t *)_z_vec_get(&t_msg->_body._frame._payload._messages, i)); + _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); + if (ret == _Z_RES_OK) { + _z_handle_network_message(ztu->_session, &zm, _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE); + _z_msg_clear(&zm); // Clear must be explicitly called for fragmented zenoh messages. Non-fragmented + // zenoh messages are released when their transport message is released. + } else { + _Z_DEBUG("Failed to decode defragmented message\n"); } + + // Free the decoding buffer + _z_zbuf_clear(&zbf); + // Reset the defragmentation buffer + _z_wbuf_reset(dbuf); } break; } + case _Z_MID_T_KEEP_ALIVE: { + _Z_INFO("Received Z_KEEP_ALIVE message\n"); + break; + } + + case _Z_MID_T_INIT: { + // Do nothing, zenoh clients are not expected to handle accept messages on established sessions + break; + } + + case _Z_MID_T_OPEN: { + // Do nothing, zenoh clients are not expected to handle accept messages on established sessions + break; + } + + case _Z_MID_T_CLOSE: { + _Z_INFO("Closing session as requested by the remote peer\n"); + break; + } + default: { _Z_ERROR("Unknown session message ID\n"); break; diff --git a/src/transport/unicast/link/task/lease.c b/src/transport/unicast/link/task/lease.c index 57aabadfa..5d9e0a2f2 100644 --- a/src/transport/unicast/link/task/lease.c +++ b/src/transport/unicast/link/task/lease.c @@ -22,12 +22,8 @@ int8_t _zp_unicast_send_keep_alive(_z_transport_unicast_t *ztu) { int8_t ret = _Z_RES_OK; - _z_bytes_t zid; - _z_bytes_reset(&zid); // Do not send the PID on unicast links - - _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(zid); + _z_transport_message_t t_msg = _z_t_msg_make_keep_alive(); ret = _z_unicast_send_t_msg(ztu, &t_msg); - // FIXME: double check why we dont clear t_msg return ret; } diff --git a/src/transport/unicast/link/task/read.c b/src/transport/unicast/link/task/read.c index af45dc5c9..31bc35609 100644 --- a/src/transport/unicast/link/task/read.c +++ b/src/transport/unicast/link/task/read.c @@ -17,6 +17,7 @@ #include #include "zenoh-pico/config.h" +#include "zenoh-pico/protocol/codec/transport.h" #include "zenoh-pico/transport/link/rx.h" #include "zenoh-pico/utils/logging.h" @@ -85,7 +86,7 @@ void *_zp_unicast_read_task(void *ztu_arg) { // Decode one session message _z_transport_message_t t_msg; - int8_t ret = _z_transport_message_decode_na(&t_msg, &zbuf); + int8_t ret = _z_transport_message_decode(&t_msg, &zbuf); if (ret == _Z_RES_OK) { ret = _z_unicast_handle_transport_message(ztu, &t_msg); diff --git a/src/transport/unicast/link/tx.c b/src/transport/unicast/link/tx.c index 394be48cb..3375d08e9 100644 --- a/src/transport/unicast/link/tx.c +++ b/src/transport/unicast/link/tx.c @@ -14,8 +14,12 @@ #include "zenoh-pico/transport/link/tx.h" +#include + #include "zenoh-pico/config.h" -#include "zenoh-pico/protocol/msgcodec.h" +#include "zenoh-pico/protocol/codec/network.h" +#include "zenoh-pico/protocol/codec/transport.h" +#include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/transport/utils.h" #include "zenoh-pico/utils/logging.h" @@ -30,10 +34,10 @@ _z_zint_t __unsafe_z_unicast_get_sn(_z_transport_unicast_t *ztu, z_reliability_t _z_zint_t sn; if (reliability == Z_RELIABILITY_RELIABLE) { sn = ztu->_sn_tx_reliable; - ztu->_sn_tx_reliable = _z_sn_increment(ztu->_sn_resolution, ztu->_sn_tx_reliable); + ztu->_sn_tx_reliable = _z_sn_increment(ztu->_sn_res, ztu->_sn_tx_reliable); } else { sn = ztu->_sn_tx_best_effort; - ztu->_sn_tx_best_effort = _z_sn_increment(ztu->_sn_resolution, ztu->_sn_tx_best_effort); + ztu->_sn_tx_best_effort = _z_sn_increment(ztu->_sn_res, ztu->_sn_tx_best_effort); } return sn; } @@ -69,10 +73,10 @@ int8_t _z_unicast_send_t_msg(_z_transport_unicast_t *ztu, const _z_transport_mes return ret; } -int8_t _z_unicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reliability_t reliability, +int8_t _z_unicast_send_n_msg(_z_session_t *zn, const _z_network_message_t *n_msg, z_reliability_t reliability, z_congestion_control_t cong_ctrl) { int8_t ret = _Z_RES_OK; - _Z_DEBUG(">> send zenoh message\n"); + _Z_DEBUG(">> send network message\n"); _z_transport_unicast_t *ztu = &zn->_tp._transport._unicast; @@ -99,24 +103,30 @@ int8_t _z_unicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reli _z_zint_t sn = __unsafe_z_unicast_get_sn(ztu, reliability); // Get the next sequence number - _z_transport_message_t t_msg = _z_frame_header(reliability, 0, 0, sn); + _z_transport_message_t t_msg = _z_t_msg_make_frame_header(sn, reliability); ret = _z_transport_message_encode(&ztu->_wbuf, &t_msg); // Encode the frame header if (ret == _Z_RES_OK) { - ret = _z_zenoh_message_encode(&ztu->_wbuf, z_msg); // Encode the zenoh message + ret = _z_network_message_encode(&ztu->_wbuf, n_msg); // Encode the network message if (ret == _Z_RES_OK) { // Write the message legnth in the reserved space if needed __unsafe_z_finalize_wbuf(&ztu->_wbuf, _Z_LINK_IS_STREAMED(ztu->_link._capabilities)); - ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); // Send the wbuf on the socket + if (ztu->_wbuf._ioss._len == 1) { + ret = _z_link_send_wbuf(&ztu->_link, &ztu->_wbuf); // Send the wbuf on the socket + } else { + // Change the MID + + // for () + } if (ret == _Z_RES_OK) { ztu->_transmitted = true; // Mark the session that we have transmitted data } } else { // The message does not fit in the current batch, let's fragment it // Create an expandable wbuf for fragmentation - _z_wbuf_t fbf = _z_wbuf_make(Z_IOSLICE_SIZE, true); + _z_wbuf_t fbf = _z_wbuf_make(ztu->_wbuf._capacity - 12, true); - ret = _z_zenoh_message_encode(&fbf, z_msg); // Encode the message on the expandable wbuf + ret = _z_network_message_encode(&fbf, n_msg); // Encode the message on the expandable wbuf if (ret == _Z_RES_OK) { _Bool is_first = true; // Fragment and send the message while (_z_wbuf_len(&fbf) > 0) { @@ -141,8 +151,6 @@ int8_t _z_unicast_send_z_msg(_z_session_t *zn, _z_zenoh_message_t *z_msg, z_reli } } } - - _z_wbuf_clear(&fbf); // Free the fragmentation buffer memory } } diff --git a/src/transport/utils.c b/src/transport/utils.c index b5d4b0bcd..9e3ad968c 100644 --- a/src/transport/utils.c +++ b/src/transport/utils.c @@ -14,32 +14,84 @@ #include "zenoh-pico/transport/utils.h" -_Bool _z_sn_precedes(const _z_zint_t sn_resolution_half, const _z_zint_t sn_left, const _z_zint_t sn_right) { - _Bool ret = false; +#include "zenoh-pico/protocol/core.h" - if (sn_right > sn_left) { - ret = ((sn_right - sn_left) <= sn_resolution_half); - } else { - ret = ((sn_left - sn_right) > sn_resolution_half); +#define U8_MAX 0xFF +#define U16_MAX 0xFFFF +#define U32_MAX 0xFFFFFFFF +#define U64_MAX 0xFFFFFFFFFFFFFFFF + +_z_zint_t _z_sn_max(uint8_t bits) { + _z_zint_t ret = 0; + switch (bits) { + case 0x00: { + ret = U8_MAX >> 1; + } break; + + case 0x01: { + ret = U16_MAX >> 2; + } break; + + case 0x02: { + ret = U32_MAX >> 4; + } break; + + case 0x03: { + ret = (_z_zint_t)(U64_MAX >> 1); + } break; + + default: { + // Do nothing + } break; } return ret; } -_z_zint_t _z_sn_increment(const _z_zint_t sn_resolution, const _z_zint_t sn) { return (sn + 1) % sn_resolution; } +_z_zint_t _z_sn_half(_z_zint_t sn) { return sn >> 1; } -_z_zint_t _z_sn_decrement(const _z_zint_t sn_resolution, const _z_zint_t sn) { +_z_zint_t _z_sn_modulo_mask(uint8_t bits) { _z_zint_t ret = 0; + switch (bits) { + case 0x00: { + ret = U8_MAX >> 1; + } break; - if (sn == 0) { - ret = sn_resolution - 1; - } else { - ret = sn - 1; + case 0x01: { + ret = U16_MAX >> 2; + } break; + + case 0x02: { + ret = U32_MAX >> 4; + } break; + + case 0x03: { + ret = (_z_zint_t)(U64_MAX >> 1); + } break; + + default: { + // Do nothing + } break; } return ret; } +_Bool _z_sn_precedes(const _z_zint_t sn_resolution, const _z_zint_t sn_left, const _z_zint_t sn_right) { + _z_zint_t distance = (sn_right - sn_left) & sn_resolution; + return ((distance <= _z_sn_half(sn_resolution)) && (distance != 0)); +} + +_z_zint_t _z_sn_increment(const _z_zint_t sn_resolution, const _z_zint_t sn) { + _z_zint_t ret = sn + 1; + return (ret &= sn_resolution); +} + +_z_zint_t _z_sn_decrement(const _z_zint_t sn_resolution, const _z_zint_t sn) { + _z_zint_t ret = sn - 1; + return (ret &= sn_resolution); +} + void _z_conduit_sn_list_copy(_z_conduit_sn_list_t *dst, const _z_conduit_sn_list_t *src) { dst->_is_qos = src->_is_qos; if (dst->_is_qos == false) { diff --git a/src/utils/string.c b/src/utils/string.c index 21436681a..651eff436 100644 --- a/src/utils/string.c +++ b/src/utils/string.c @@ -1,3 +1,17 @@ +// +// 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/utils/string.h" #include diff --git a/src/utils/uuid.c b/src/utils/uuid.c new file mode 100644 index 000000000..7b9984871 --- /dev/null +++ b/src/utils/uuid.c @@ -0,0 +1,34 @@ +// +// 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/utils/uuid.h" + +#include +#include + +#include "zenoh-pico/utils/pointers.h" + +#define UUID_SIZE 16 + +void _z_uuid_to_bytes(uint8_t *bytes, const char *uuid_str) { + uint8_t n_dash = 0; + for (uint8_t i = 0; i < 32; i += 2) { + if (i == 8 || i == 12 || i == 16 || i == 18) { + n_dash += 1; + } + char val[5] = {'0', 'x', uuid_str[i + n_dash], uuid_str[i + 1 + n_dash], '\0'}; + *bytes = (uint8_t)strtoul(val, NULL, 0); + bytes = _z_ptr_u8_offset(bytes, 1); + } +} diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 1e04dbe38..a11d3095c 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -29,6 +29,16 @@ #define SLEEP 2 #define SCOUTING_TIMEOUT "1000" +#define assert_eq(x, y) \ + { \ + int l = (int)x; \ + int r = (int)y; \ + if (l != r) { \ + printf("assert_eq failed: l=%d, r=%d\n", l, r); \ + assert(false); \ + } \ + } + const char *value = "Test value"; volatile unsigned int zids = 0; @@ -109,7 +119,7 @@ void data_handler(const z_sample_t *sample, void *arg) { } int main(int argc, char **argv) { - assert(argc == 2); + assert_eq(argc, 2); (void)(argc); setvbuf(stdout, NULL, _IOLBF, 1024); @@ -120,25 +130,25 @@ int main(int argc, char **argv) { printf("Testing Keyexpr..."); z_keyexpr_t key = z_keyexpr("demo/example"); _Bool _ret_bool = z_keyexpr_is_initialized(&key); - assert(_ret_bool == true); + assert_eq(_ret_bool, true); int8_t _ret_int8 = z_keyexpr_includes(z_keyexpr("demo/example/**"), z_keyexpr("demo/example/a")); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); #ifdef ZENOH_PICO _ret_int8 = zp_keyexpr_includes_null_terminated("demo/example/**", "demo/example/a"); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); #endif _ret_int8 = z_keyexpr_intersects(z_keyexpr("demo/example/**"), z_keyexpr("demo/example/a")); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); #ifdef ZENOH_PICO _ret_int8 = zp_keyexpr_intersect_null_terminated("demo/example/**", "demo/example/a"); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); #endif _ret_int8 = z_keyexpr_equals(z_keyexpr("demo/example/**"), z_keyexpr("demo/example")); - assert(_ret_int8 == -1); + assert_eq(_ret_int8, -1); #ifdef ZENOH_PICO _ret_int8 = zp_keyexpr_equals_null_terminated("demo/example/**", "demo/example"); - assert(_ret_int8 == -1); + assert_eq(_ret_int8, -1); #endif sleep(SLEEP); @@ -155,12 +165,12 @@ int main(int argc, char **argv) { assert(_ret_int8 < 0); #endif _ret_int8 = z_keyexpr_canonize(keyexpr_str, &keyexpr_len); - assert(_ret_int8 == 0); - assert(strlen("demo/example/**/*") == 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(_ret_int8 == 0); - assert(strlen("demo/example/**/*") == keyexpr_len); + assert_eq(_ret_int8, 0); + assert_eq(strlen("demo/example/**/*"), keyexpr_len); #endif printf("Ok\n"); @@ -174,10 +184,10 @@ int main(int argc, char **argv) { assert(z_check(_ret_config)); #ifdef ZENOH_PICO _ret_int8 = zp_config_insert(z_loan(_ret_config), Z_CONFIG_PEER_KEY, z_string_make(argv[1])); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); const char *_ret_cstr = zp_config_get(z_loan(_ret_config), Z_CONFIG_PEER_KEY); - assert(strlen(_ret_cstr) == strlen(argv[1])); - assert(strncmp(_ret_cstr, argv[1], strlen(_ret_cstr)) == 0); + 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(); @@ -185,10 +195,10 @@ int main(int argc, char **argv) { #ifdef ZENOH_PICO _ret_int8 = zp_scouting_config_insert(z_loan(_ret_sconfig), Z_CONFIG_SCOUTING_TIMEOUT_KEY, z_string_make(SCOUTING_TIMEOUT)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); _ret_cstr = zp_scouting_config_get(z_loan(_ret_sconfig), Z_CONFIG_SCOUTING_TIMEOUT_KEY); - assert(strlen(_ret_cstr) == strlen(SCOUTING_TIMEOUT)); - assert(strncmp(_ret_cstr, SCOUTING_TIMEOUT, strlen(_ret_cstr)) == 0); + 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)); @@ -199,7 +209,7 @@ int main(int argc, char **argv) { _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)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); assert(hellos >= 1); uint32_t _scouting_timeout = strtoul(SCOUTING_TIMEOUT, NULL, 10); @@ -218,15 +228,15 @@ int main(int argc, char **argv) { z_owned_closure_zid_t _ret_closure_zid = z_closure(zid_handler, NULL, NULL); _ret_int8 = z_info_peers_zid(z_loan(s1), z_move(_ret_closure_zid)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); sleep(SLEEP); - assert(zids == 0); + assert_eq(zids, 0); _ret_int8 = z_info_routers_zid(z_loan(s1), z_move(_ret_closure_zid)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); sleep(SLEEP); - assert(zids == 1); + assert_eq(zids, 1); #ifdef ZENOH_PICO zp_task_read_options_t _ret_read_opt = zp_task_read_options_default(); @@ -240,10 +250,10 @@ int main(int argc, char **argv) { _ret_config = z_config_default(); #ifdef ZENOH_PICO _ret_int8 = zp_config_insert(z_loan(_ret_config), Z_CONFIG_PEER_KEY, z_string_make(argv[1])); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); _ret_cstr = zp_config_get(z_loan(_ret_config), Z_CONFIG_PEER_KEY); - assert(strlen(_ret_cstr) == strlen(argv[1])); - assert(strncmp(_ret_cstr, argv[1], strlen(_ret_cstr)) == 0); + 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)); @@ -288,29 +298,30 @@ int main(int argc, char **argv) { _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); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP); - assert(datas == 1); + assert_eq(datas, 1); printf("Session delete..."); z_delete_options_t _ret_delete_opt = z_delete_options_default(); _ret_int8 = z_delete(z_loan(s1), z_loan(_ret_expr), &_ret_delete_opt); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP); - assert(datas == 2); + assert_eq(datas, 2); printf("Undeclaring Keyexpr..."); _ret_int8 = z_undeclare_keyexpr(z_loan(s1), z_move(_ret_expr)); - assert(_ret_int8 == 0); + 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(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Declaring Pull Subscriber..."); z_owned_closure_sample_t _ret_closure_sample2 = z_closure(data_handler, NULL, &ls1); @@ -332,44 +343,44 @@ int main(int argc, char **argv) { 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(_ret_int8 == 0); + 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(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP); - assert(datas == 3); + assert_eq(datas, 3); printf("Publisher Delete..."); z_publisher_delete_options_t _ret_pdelete_opt = z_publisher_delete_options_default(); _ret_int8 = z_publisher_delete(z_loan(_ret_pub), &_ret_pdelete_opt); - assert(_ret_int8 == 0); + 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(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP); - assert(datas == 4); + assert_eq(datas, 4); printf("Undeclaring Publisher..."); _ret_int8 = z_undeclare_publisher(z_move(_ret_pub)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); assert(!z_check(_ret_pub)); printf("Ok\n"); printf("Undeclaring Pull Subscriber..."); _ret_int8 = z_undeclare_pull_subscriber(z_move(_ret_psub)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP); @@ -403,16 +414,16 @@ int main(int argc, char **argv) { printf("Testing Get..."); _ret_int8 = z_get(z_loan(s2), z_keyexpr(s1_res), "", z_move(_ret_closure_reply), &_ret_get_opt); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP); - assert(queries == 1); - assert(replies == 1); + assert_eq(queries, 1); + assert_eq(replies, 1); printf("Undeclaring Queryable..."); _ret_int8 = z_undeclare_queryable(z_move(qle)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); #ifdef ZENOH_PICO @@ -422,14 +433,14 @@ int main(int argc, char **argv) { printf("Close sessions..."); _ret_int8 = z_close(z_move(s1)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); #ifdef ZENOH_PICO zp_stop_read_task(z_loan(s2)); zp_stop_lease_task(z_loan(s2)); #endif _ret_int8 = z_close(z_move(s2)); - assert(_ret_int8 == 0); + assert_eq(_ret_int8, 0); printf("Ok\n"); sleep(SLEEP * 5); diff --git a/tests/z_client_test.c b/tests/z_client_test.c index f226c1962..5c4b1fd1d 100644 --- a/tests/z_client_test.c +++ b/tests/z_client_test.c @@ -13,10 +13,13 @@ #include #include +#include #include #include #include "zenoh-pico.h" +#include "zenoh-pico/api/types.h" +#include "zenoh-pico/collections/string.h" #define MSG 1000 #define MSG_LEN 1024 @@ -95,6 +98,11 @@ void data_handler(const z_sample_t *sample, void *arg) { 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); +} + int main(int argc, char **argv) { setvbuf(stdout, NULL, _IOLBF, 1024); @@ -110,7 +118,7 @@ int main(int argc, char **argv) { z_owned_session_t s1 = z_open(z_move(config)); assert(z_check(s1)); - z_string_t zid1 = _z_string_from_bytes(&z_loan(s1)._val->_local_zid); + z_string_t zid1 = format_id(&z_loan(s1)._val->_local_zid); printf("Session 1 with PID: %s\n", zid1.val); _z_string_clear(&zid1); @@ -125,7 +133,7 @@ int main(int argc, char **argv) { z_owned_session_t s2 = z_open(z_move(config)); assert(z_check(s2)); - z_string_t zid2 = _z_string_from_bytes(&z_loan(s2)._val->_local_zid); + z_string_t zid2 = format_id(&z_loan(s2)._val->_local_zid); printf("Session 2 with PID: %s\n", zid2.val); _z_string_clear(&zid2); @@ -140,7 +148,7 @@ 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(s1), z_keyexpr(s1_res)); - printf("Declared resource on session 1: %zu %s\n", z_loan(expr)._id, z_loan(expr)._suffix); + printf("Declared resource on session 1: %u %s\n", z_loan(expr)._id, z_loan(expr)._suffix); rids1[i] = expr; } @@ -149,7 +157,7 @@ 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: %zu %s\n", z_loan(expr)._id, z_loan(expr)._suffix); + printf("Declared resource on session 2: %u %s\n", z_loan(expr)._id, z_loan(expr)._suffix); rids2[i] = expr; } @@ -161,7 +169,7 @@ int main(int argc, char **argv) { 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: %zu %zu %s\n", z_subscriber_loan(sub)._val->_id, + printf("Declared subscription on session 2: %ju %u %s\n", (uintmax_t)z_subscriber_loan(sub)._val->_entity_id, z_loan(rids2[i])._id, ""); subs2 = _z_list_push(subs2, sub); } @@ -174,7 +182,8 @@ int main(int argc, char **argv) { 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: %zu %zu %s\n", qle->_value->_id, (z_zint_t)0, s1_res); + printf("Declared queryable on session 2: %ju %zu %s\n", (uintmax_t)qle->_value->_entity_id, (z_zint_t)0, + s1_res); qles2 = _z_list_push(qles2, qle); } @@ -201,7 +210,7 @@ int main(int argc, char **argv) { z_put_options_t opt = z_put_options_default(); 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: %zu %zu b\t(%u/%u)\n", z_loan(rids1[i])._id, len, n * SET + (i + 1), + printf("Wrote data from session 1: %u %zu b\t(%u/%u)\n", z_loan(rids1[i])._id, len, n * SET + (i + 1), total); } } @@ -275,7 +284,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: %zu\n", sub->_value->_id); + printf("Undeclared subscriber on session 2: %ju\n", (uintmax_t)sub->_value->_entity_id); z_undeclare_subscriber(z_move(*sub)); subs2 = _z_list_pop(subs2, _z_noop_elem_free, NULL); } @@ -284,7 +293,7 @@ int main(int argc, char **argv) { while (qles2) { z_owned_queryable_t *qle = _z_list_head(qles2); - printf("Undeclared queryable on session 2: %zu\n", qle->_value->_id); + printf("Undeclared queryable on session 2: %ju\n", (uintmax_t)qle->_value->_entity_id); z_undeclare_queryable(z_move(*qle)); qles2 = _z_list_pop(qles2, _z_noop_elem_free, NULL); } @@ -293,14 +302,14 @@ 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: %zu\n", z_loan(rids1[i])._id); + printf("Undeclared resource on session 1: %u\n", z_loan(rids1[i])._id); z_undeclare_keyexpr(z_loan(s1), z_move(rids1[i])); } z_sleep_s(SLEEP); for (unsigned int i = 0; i < SET; i++) { - printf("Undeclared resource on session 2: %zu\n", z_loan(rids2[i])._id); + printf("Undeclared resource on session 2: %u\n", z_loan(rids2[i])._id); z_undeclare_keyexpr(z_loan(s2), z_move(rids2[i])); } diff --git a/tests/z_data_struct_test.c b/tests/z_data_struct_test.c index cc88e4a39..8990ef678 100644 --- a/tests/z_data_struct_test.c +++ b/tests/z_data_struct_test.c @@ -18,13 +18,41 @@ #include #include "zenoh-pico/collections/string.h" +#include "zenoh-pico/protocol/core.h" +#include "zenoh-pico/system/platform.h" +#include "zenoh-pico/transport/transport.h" + +void entry_list_test(void) { + _z_transport_peer_entry_list_t *root = _z_transport_peer_entry_list_new(); + for (int i = 0; i < 10; i++) { + _z_transport_peer_entry_t *entry = (_z_transport_peer_entry_t *)z_malloc(sizeof(_z_transport_peer_entry_t)); + root = _z_transport_peer_entry_list_insert(root, entry); + } + _z_transport_peer_entry_list_t *list = root; + for (int i = 10; list != NULL; i--, list = _z_transport_peer_entry_list_tail(list)) { + assert(_z_transport_peer_entry_list_head(list)->_peer_id == i); + } + _z_transport_peer_entry_list_head(root)->_peer_id = _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE - 1; + + for (int i = 0; i < 11; i++) { + _z_transport_peer_entry_t *entry = (_z_transport_peer_entry_t *)z_malloc(sizeof(_z_transport_peer_entry_t)); + root = _z_transport_peer_entry_list_insert(root, entry); + } + assert(_z_transport_peer_entry_list_head(root)->_peer_id == _Z_KEYEXPR_MAPPING_UNKNOWN_REMOTE - 1); + list = _z_transport_peer_entry_list_tail(root); + for (int i = 20; list != NULL; i--, list = _z_transport_peer_entry_list_tail(list)) { + assert(_z_transport_peer_entry_list_head(list)->_peer_id == i); + } + _z_transport_peer_entry_list_free(&root); +} int main(void) { + entry_list_test(); char *s = (char *)malloc(64); size_t len = 128; // str-vec - printf(">>> str-vec\n"); + printf(">>> str-vec\r\n"); _z_str_vec_t vec = _z_str_vec_make(1); assert(_z_str_vec_is_empty(&vec) == true); @@ -34,12 +62,12 @@ int main(void) { _z_str_vec_append(&vec, _z_str_clone(s)); char *e = _z_str_vec_get(&vec, i); - printf("append(%zu) = %s\n", i, e); + printf("append(%zu) = %s\r\n", i, e); assert(_z_str_eq(s, e) == true); _z_str_vec_set(&vec, i, _z_str_clone(s)); e = _z_str_vec_get(&vec, i); - printf("set(%zu) = %s\n", i, e); + printf("set(%zu) = %s\r\n", i, e); assert(_z_str_eq(s, e) == true); assert(_z_str_vec_len(&vec) == i + 1); @@ -50,7 +78,7 @@ int main(void) { assert(_z_str_vec_is_empty(&vec) == true); // str-list - printf(">>> str-list\n"); + printf(">>> str-list\r\n"); _z_str_list_t *list = _z_str_list_new(); assert(_z_str_list_is_empty(list) == true); @@ -60,7 +88,7 @@ int main(void) { list = _z_str_list_push(list, _z_str_clone(s)); char *e = _z_str_list_head(list); - printf("push(%zu) = %s\n", i, e); + printf("push(%zu) = %s\r\n", i, e); assert(_z_str_eq(s, e) == true); assert(_z_str_list_len(list) == i + 1); @@ -84,7 +112,7 @@ int main(void) { assert(_z_str_list_is_empty(list) == true); // str-intmap - printf(">>> str-intmap\n"); + printf(">>> str-intmap\r\n"); _z_str_intmap_t map = _z_str_intmap_make(); assert(_z_str_intmap_is_empty(&map) == true); @@ -94,7 +122,7 @@ int main(void) { _z_str_intmap_insert(&map, i, _z_str_clone(s)); char *e = _z_str_intmap_get(&map, i); - printf("get(%zu) = %s\n", i, e); + printf("get(%zu) = %s\r\n", i, e); assert(_z_str_eq(s, e) == true); assert(_z_str_intmap_len(&map) == i + 1); diff --git a/tests/z_iobuf_test.c b/tests/z_iobuf_test.c index f7512e5db..4b7d41462 100644 --- a/tests/z_iobuf_test.c +++ b/tests/z_iobuf_test.c @@ -12,6 +12,7 @@ // ZettaScale Zenoh Team, // #include +#include #include #include #include @@ -27,7 +28,7 @@ void print_zbuf_overview(_z_zbuf_t *zbf) { printf(" ZBuf => Capacity: %zu\n", zbf->_ios._capacity); } void print_wbuf_overview(_z_wbuf_t *wbf) { - printf(" WBuf => Expandable: %u, Capacity: %zu\n", wbf->_is_expandable, wbf->_capacity); + printf(" WBuf => Expandable: %zu, Capacity: %zu\n", wbf->_expansion_step, wbf->_capacity); } void print_iosli(_z_iosli_t *ios) { @@ -437,13 +438,15 @@ void wbuf_put_zbuf_get(void) { void wbuf_reusable_write_zbuf_read(void) { _z_wbuf_t wbf = gen_wbuf(128); - for (int i = 0; i < 10; i++) { + for (int i = 1; i <= 10; i++) { size_t len = z_random_u8() % 128; - printf("\n>>> WBuf => Write and Read\n"); + printf("\n>>> WBuf => Write and Read round %d\n", i); print_wbuf_overview(&wbf); printf(" Writing %zu bytes\n", len); for (size_t z = 0; z < len; z++) { - _z_wbuf_write(&wbf, z % (uint8_t)255); + size_t prev_len = _z_wbuf_len(&wbf); + assert(_z_wbuf_write(&wbf, z % (uint8_t)255) == 0); + assert(_z_wbuf_len(&wbf) == prev_len + 1); } printf(" IOSlices: %zu, RIdx: %zu, WIdx: %zu\n", _z_wbuf_len_iosli(&wbf), wbf._r_idx, wbf._w_idx); diff --git a/tests/z_msgcodec_test.c b/tests/z_msgcodec_test.c index 32d1b3af7..dcf051d41 100644 --- a/tests/z_msgcodec_test.c +++ b/tests/z_msgcodec_test.c @@ -12,25 +12,47 @@ // ZettaScale Zenoh Team, // -#include +#include "zenoh-pico/api/constants.h" +#include "zenoh-pico/protocol/codec/message.h" +#include "zenoh-pico/protocol/codec/network.h" +#include "zenoh-pico/protocol/definitions/message.h" +#include "zenoh-pico/protocol/definitions/transport.h" #define ZENOH_PICO_TEST_H #include +#include #include #include #include #include +#include #include "zenoh-pico/collections/bytes.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/transport.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/ext.h" #include "zenoh-pico/protocol/iobuf.h" #include "zenoh-pico/protocol/keyexpr.h" -#include "zenoh-pico/protocol/msg.h" -#include "zenoh-pico/protocol/msgcodec.h" #include "zenoh-pico/system/platform.h" #define RUNS 1000 +#define _Z_MOCK_EXTENSION_UNIT 0x01 +#define _Z_MOCK_EXTENSION_ZINT 0x02 +#define _Z_MOCK_EXTENSION_ZBUF 0x03 + +#if defined(_WIN32) || defined(WIN32) +#pragma warning(push) +#pragma warning(disable : 4244 4267) // Disable truncation warnings in MSVC, + // as it is used voluntarily in this file when working with RNG +#endif + /*=============================*/ /* Helper functions */ /*=============================*/ @@ -65,37 +87,25 @@ void print_uint8_array(_z_bytes_t *arr) { void print_transport_message_type(uint8_t header) { switch (_Z_MID(header)) { - case _Z_MID_SCOUT: - printf("Scout message"); - break; - case _Z_MID_HELLO: - printf("Hello message"); - break; - case _Z_MID_JOIN: + case _Z_MID_T_JOIN: printf("Join message"); break; - case _Z_MID_INIT: + case _Z_MID_T_INIT: printf("Init message"); break; - case _Z_MID_OPEN: + case _Z_MID_T_OPEN: printf("Open message"); break; - case _Z_MID_CLOSE: + case _Z_MID_T_CLOSE: printf("Close message"); break; - case _Z_MID_SYNC: - printf("Sync message"); - break; - case _Z_MID_ACK_NACK: - printf("AckNack message"); - break; - case _Z_MID_KEEP_ALIVE: + case _Z_MID_T_KEEP_ALIVE: printf("KeepAlive message"); break; - case _Z_MID_PING_PONG: - printf("PingPong message"); + case _Z_MID_T_FRAME: + printf("Frame message"); break; - case _Z_MID_FRAME: + case _Z_MID_T_FRAGMENT: printf("Frame message"); break; default: @@ -104,12 +114,28 @@ void print_transport_message_type(uint8_t header) { } } +void print_scouting_message_type(uint8_t header) { + switch (_Z_MID(header)) { + case _Z_MID_SCOUT: + printf("Scout message"); + break; + case _Z_MID_HELLO: + printf("Hello message"); + break; + default: + assert(0); + break; + } +} + /*=============================*/ /* Generating functions */ /*=============================*/ _Bool gen_bool(void) { return z_random_u8() % 2; } -uint8_t gen_uint8(void) { return z_random_u8() % 255; } +uint8_t gen_uint8(void) { return z_random_u8(); } + +uint8_t gen_uint16(void) { return z_random_u16(); } uint64_t gen_uint64(void) { uint64_t ret = 0; @@ -140,8 +166,8 @@ _z_wbuf_t gen_wbuf(size_t len) { return _z_wbuf_make(len, is_expandable); } -_z_payload_t gen_payload(size_t len) { - _z_payload_t pld; +_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); @@ -163,6 +189,19 @@ _z_bytes_t gen_bytes(size_t len) { return arr; } +_z_id_t gen_zid(void) { + _z_id_t id = _z_id_empty(); + uint8_t hash = 55; + uint8_t len = gen_uint8() % 16; + for (uint8_t i = 0; i < len; i++) { + uint8_t byte = gen_uint8(); + id.id[i] = byte; + hash ^= i * byte; + } + id.id[0] = hash; + return id; +} + char *gen_str(size_t size) { char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; char *str = (char *)z_malloc(size + 1); @@ -205,7 +244,7 @@ _z_value_t gen_value(void) { if (gen_bool()) { val.payload = _z_bytes_empty(); } else { - val.payload = _z_bytes_make(16); + val.payload = gen_bytes(16); } return val; @@ -233,7 +272,7 @@ void assert_eq_iosli(_z_iosli_t *left, _z_iosli_t *right) { printf(")"); } -void assert_eq_uint8_array(_z_bytes_t *left, _z_bytes_t *right) { +void assert_eq_uint8_array(const _z_bytes_t *left, const _z_bytes_t *right) { printf("Array -> "); printf("Length (%zu:%zu), ", left->len, right->len); @@ -269,7 +308,7 @@ void assert_eq_str_array(_z_str_array_t *left, _z_str_array_t *right) { printf(")"); } -void assert_eq_locator_array(_z_locator_array_t *left, _z_locator_array_t *right) { +void assert_eq_locator_array(const _z_locator_array_t *left, const _z_locator_array_t *right) { printf("Locators -> "); printf("Length (%zu:%zu), ", left->_len, right->_len); @@ -293,41 +332,183 @@ void assert_eq_locator_array(_z_locator_array_t *left, _z_locator_array_t *right printf(")"); } +/*=============================*/ +/* Zenoh Messages Extensions */ +/*=============================*/ +/*------------------ UNIT extension ------------------*/ +_z_msg_ext_t gen_unit_extension(void) { return _z_msg_ext_make_unit(_Z_MOCK_EXTENSION_UNIT); } + +void assert_eq_unit_extension(_z_msg_ext_unit_t *left, _z_msg_ext_unit_t *right) { + (void)(left); + (void)(right); +} + +void unit_extension(void) { + printf("\n>> UNIT Extension\n"); + _z_wbuf_t wbf = gen_wbuf(65535); + + // Initialize + _z_msg_ext_t ext = gen_unit_extension(); + assert(_Z_EXT_ENC(ext._header) == _Z_MSG_EXT_ENC_UNIT); + + _z_msg_ext_unit_t e_u = ext._body._unit; + + // Encode + int8_t res = _z_msg_ext_encode_unit(&wbf, &e_u); + assert(res == _Z_RES_OK); + (void)(res); + + // Decode + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + _z_msg_ext_unit_t d_u; + res = _z_msg_ext_decode_unit(&d_u, &zbf); + assert(res == _Z_RES_OK); + + assert_eq_unit_extension(&e_u, &d_u); + + // Free + _z_msg_ext_clear_unit(&d_u); + _z_msg_ext_clear(&ext); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + +/*------------------ ZINT extension ------------------*/ +_z_msg_ext_t gen_zint_extension(void) { + _z_zint_t val = gen_zint(); + return _z_msg_ext_make_zint(_Z_MOCK_EXTENSION_ZINT, val); +} + +void assert_eq_zint_extension(_z_msg_ext_zint_t *left, _z_msg_ext_zint_t *right) { + printf(" ZINT (%ju:%ju), ", (uintmax_t)left->_val, (uintmax_t)right->_val); + assert(left->_val == right->_val); +} + +void zint_extension(void) { + printf("\n>> ZINT Extension\n"); + _z_wbuf_t wbf = gen_wbuf(65535); + + // Initialize + _z_msg_ext_t ext = gen_zint_extension(); + assert(_Z_EXT_ENC(ext._header) == _Z_MSG_EXT_ENC_ZINT); + + _z_msg_ext_zint_t e_u = ext._body._zint; + + // Encode + int8_t res = _z_msg_ext_encode_zint(&wbf, &e_u); + assert(res == _Z_RES_OK); + (void)(res); + + // Decode + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + _z_msg_ext_zint_t d_u; + res = _z_msg_ext_decode_zint(&d_u, &zbf); + assert(res == _Z_RES_OK); + + assert_eq_zint_extension(&e_u, &d_u); + + // Free + _z_msg_ext_clear_zint(&d_u); + _z_msg_ext_clear(&ext); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + +/*------------------ Unit extension ------------------*/ +_z_msg_ext_t gen_zbuf_extension(void) { + _z_bytes_t val = gen_bytes(gen_uint8()); + return _z_msg_ext_make_zbuf(_Z_MOCK_EXTENSION_ZBUF, val); +} + +void assert_eq_zbuf_extension(_z_msg_ext_zbuf_t *left, _z_msg_ext_zbuf_t *right) { + printf(" ZBUF ("); + assert_eq_uint8_array(&left->_val, &right->_val); + printf(")"); +} + +void zbuf_extension(void) { + printf("\n>> ZBUF Extension\n"); + _z_wbuf_t wbf = gen_wbuf(65535); + + // Initialize + _z_msg_ext_t ext = gen_zbuf_extension(); + assert(_Z_EXT_ENC(ext._header) == _Z_MSG_EXT_ENC_ZBUF); + + _z_msg_ext_zbuf_t e_u = ext._body._zbuf; + + // Encode + int8_t res = _z_msg_ext_encode_zbuf(&wbf, &e_u); + assert(res == _Z_RES_OK); + (void)(res); + + // Decode + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + _z_msg_ext_zbuf_t d_u; + res = _z_msg_ext_decode_zbuf(&d_u, &zbf); + assert(res == _Z_RES_OK); + + assert_eq_zbuf_extension(&e_u, &d_u); + + // Free + _z_msg_ext_clear_zbuf(&d_u); + _z_msg_ext_clear(&ext); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + /*=============================*/ /* Message Fields */ /*=============================*/ /*------------------ Payload field ------------------*/ -void assert_eq_payload(_z_payload_t *left, _z_payload_t *right) { assert_eq_uint8_array(left, right); } +void assert_eq_bytes(const _z_bytes_t *left, const _z_bytes_t *right) { assert_eq_uint8_array(left, right); } void payload_field(void) { printf("\n>> Payload field\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_payload_t e_pld = gen_payload(64); + _z_bytes_t e_pld = gen_payload(64); // Encode - int8_t res = _z_payload_encode(&wbf, &e_pld); + int8_t res = _z_bytes_encode(&wbf, &e_pld); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_payload_t d_pld; - res = _z_payload_decode(&d_pld, &zbf); + _z_bytes_t d_pld; + res = _z_bytes_decode(&d_pld, &zbf); assert(res == _Z_RES_OK); printf(" "); - assert_eq_payload(&e_pld, &d_pld); + assert_eq_bytes(&e_pld, &d_pld); printf("\n"); // Free - _z_payload_clear(&e_pld); - _z_payload_clear(&d_pld); + _z_bytes_clear(&e_pld); + _z_bytes_clear(&d_pld); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } +_z_source_info_t gen_source_info(void) { + return (_z_source_info_t){._id = gen_zid(), ._source_sn = gen_uint64(), ._entity_id = gen_uint64()}; +} + +void assert_eq_source_info(const _z_source_info_t *left, const _z_source_info_t *right) { + assert(left->_source_sn == right->_source_sn); + 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); +} +void assert_eq_value(const _z_value_t *left, const _z_value_t *right) { + assert_eq_encoding(&left->encoding, &right->encoding); + assert_eq_bytes(&left->payload, &right->payload); +} /*------------------ Timestamp field ------------------*/ _z_timestamp_t gen_timestamp(void) { _z_timestamp_t ts; @@ -337,15 +518,19 @@ _z_timestamp_t gen_timestamp(void) { return ts; } -void assert_eq_timestamp(_z_timestamp_t *left, _z_timestamp_t *right) { +void assert_eq_timestamp(const _z_timestamp_t *left, const _z_timestamp_t *right) { printf("Timestamp -> "); printf("Time (%llu:%llu), ", (unsigned long long)left->time, (unsigned long long)right->time); assert(left->time == right->time); printf("ID ("); + for (int i = 0; i < 16; i++) { + printf("%02x:%02x, ", left->id.id[i], right->id.id[i]); + } + printf(")\n"); assert(memcmp(left->id.id, right->id.id, 16) == 0); - printf(")"); } +/*------------------ Timestamp field ------------------*/ void timestamp_field(void) { printf("\n>> Timestamp field\n"); @@ -363,6 +548,7 @@ void timestamp_field(void) { _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); print_wbuf(&wbf); print_iosli(&zbf._ios); + printf("\n"); _z_timestamp_t d_ts; res = _z_timestamp_decode(&d_ts, &zbf); assert(res == _Z_RES_OK); @@ -414,54 +600,30 @@ void assert_eq_subinfo(_z_subinfo_t *left, _z_subinfo_t *right) { assert(left->period.duration == right->period.duration); } -void subinfo_field(void) { - printf("\n>> SubInfo field\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_subinfo_t e_sm = gen_subinfo(); - - // Encode - uint8_t header = e_sm.reliability == Z_RELIABILITY_RELIABLE ? _Z_FLAG_Z_R : 0; - int8_t res = _z_subinfo_encode(&wbf, &e_sm); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_subinfo_t d_sm; - res = _z_subinfo_decode(&d_sm, &zbf, header); - assert(res == _Z_RES_OK); - - printf(" "); - assert_eq_subinfo(&e_sm, &d_sm); - printf("\n"); - - // Free - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - /*------------------ ResKey field ------------------*/ -_z_keyexpr_t gen_res_key(void) { +_z_keyexpr_t gen_keyexpr(void) { _z_keyexpr_t key; key._id = gen_zint(); + key._mapping._val = gen_uint8(); _Bool is_numerical = gen_bool(); - if (is_numerical == true) + if (is_numerical == true) { key._suffix = NULL; - else + _z_keyexpr_set_owns_suffix(&key, false); + } else { key._suffix = gen_str(gen_zint() % 16); - + _z_keyexpr_set_owns_suffix(&key, true); + } return key; } -void assert_eq_res_key(_z_keyexpr_t *left, _z_keyexpr_t *right, uint8_t header) { +void assert_eq_keyexpr(const _z_keyexpr_t *left, const _z_keyexpr_t *right) { printf("ResKey -> "); - printf("ID (%zu:%zu), ", left->_id, right->_id); + printf("ID (%u:%u), ", left->_id, right->_id); assert(left->_id == right->_id); + assert(!(_z_keyexpr_has_suffix(*left) ^ _z_keyexpr_has_suffix(*right))); printf("Name ("); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_K) == true) { + if (_z_keyexpr_has_suffix(*left)) { printf("%s:%s", left->_suffix, right->_suffix); assert(_z_str_eq(left->_suffix, right->_suffix) == true); } else { @@ -470,27 +632,27 @@ void assert_eq_res_key(_z_keyexpr_t *left, _z_keyexpr_t *right, uint8_t header) printf(")"); } -void res_key_field(void) { +void keyexpr_field(void) { printf("\n>> ResKey field\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_keyexpr_t e_rk = gen_res_key(); + _z_keyexpr_t e_rk = gen_keyexpr(); // Encode uint8_t header = (e_rk._suffix) ? _Z_FLAG_Z_K : 0; - int8_t res = _z_keyexpr_encode(&wbf, header, &e_rk); + int8_t res = _z_keyexpr_encode(&wbf, _Z_HAS_FLAG(header, _Z_FLAG_Z_K), &e_rk); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); _z_keyexpr_t d_rk; - res = _z_keyexpr_decode(&d_rk, &zbf, header); + res = _z_keyexpr_decode(&d_rk, &zbf, _Z_HAS_FLAG(header, _Z_FLAG_Z_K)); assert(res == _Z_RES_OK); printf(" "); - assert_eq_res_key(&e_rk, &d_rk, header); + assert_eq_keyexpr(&e_rk, &d_rk); printf("\n"); // Free @@ -500,2135 +662,1164 @@ void res_key_field(void) { _z_wbuf_clear(&wbf); } -/*------------------ DataInfo field ------------------*/ -_z_data_info_t gen_data_info(void) { - _z_data_info_t di; - - di._flags = 0; - - if (gen_bool()) { - di._kind = gen_uint8(); - _Z_SET_FLAG(di._flags, _Z_DATA_INFO_KIND); - } else { - di._kind = 0; - } - - if (gen_bool()) { - di._encoding.prefix = gen_uint8(); - if (gen_bool()) { - di._encoding.suffix = gen_bytes(8); - } else { - di._encoding.suffix = _z_bytes_empty(); - } - _Z_SET_FLAG(di._flags, _Z_DATA_INFO_ENC); - } else { - di._encoding.prefix = 0; - di._encoding.suffix = _z_bytes_empty(); - } - - if (gen_bool()) { - di._tstamp = gen_timestamp(); - _Z_SET_FLAG(di._flags, _Z_DATA_INFO_TSTAMP); - } else { - _z_timestamp_reset(&di._tstamp); - } - - // WARNING: we do not support sliced content in zenoh-pico. - - if (gen_bool()) { - di._source_id = gen_bytes(16); - _Z_SET_FLAG(di._flags, _Z_DATA_INFO_SRC_ID); - } else { - di._source_id = _z_bytes_empty(); - } - if (gen_bool()) { - di._source_sn = gen_zint(); - _Z_SET_FLAG(di._flags, _Z_DATA_INFO_SRC_SN); - } else { - di._source_sn = 0; - } - - return di; +/*=============================*/ +/* Declaration Fields */ +/*=============================*/ +/*------------------ Resource declaration ------------------*/ +_z_decl_kexpr_t gen_resource_declaration(void) { + return (_z_decl_kexpr_t){._id = gen_zint(), ._keyexpr = gen_keyexpr()}; } -void assert_eq_data_info(_z_data_info_t *left, _z_data_info_t *right) { - printf("DataInfo -> "); - printf("Flags (%zu:%zu), ", left->_flags, right->_flags); - assert(left->_flags == right->_flags); - - if (_Z_HAS_FLAG(left->_flags, _Z_DATA_INFO_KIND) == true) { - printf("Kind (%d:%d), ", left->_kind, right->_kind); - assert(left->_kind == right->_kind); - } - if (_Z_HAS_FLAG(left->_flags, _Z_DATA_INFO_ENC) == true) { - printf("Encoding (%u %.*s:%u %.*s), ", left->_encoding.prefix, (int)left->_encoding.suffix.len, - left->_encoding.suffix.start, right->_encoding.prefix, (int)right->_encoding.suffix.len, - right->_encoding.suffix.start); - assert(left->_encoding.prefix == right->_encoding.prefix); - assert_eq_uint8_array(&left->_encoding.suffix, &right->_encoding.suffix); - } - if (_Z_HAS_FLAG(left->_flags, _Z_DATA_INFO_TSTAMP) == true) { - printf("Tstamp -> "); - assert_eq_timestamp(&left->_tstamp, &right->_tstamp); - printf(", "); - } - - if (_Z_HAS_FLAG(left->_flags, _Z_DATA_INFO_SRC_ID) == true) { - printf("Src ID -> "); - assert_eq_uint8_array(&left->_source_id, &right->_source_id); - printf(", "); - } - if (_Z_HAS_FLAG(left->_flags, _Z_DATA_INFO_SRC_SN) == true) { - printf("Src SN (%zu:%zu), ", left->_source_sn, right->_source_sn); - assert(left->_source_sn == right->_source_sn); - } +void assert_eq_resource_declaration(const _z_decl_kexpr_t *left, const _z_decl_kexpr_t *right) { + printf("RID (%u:%u), ", left->_id, right->_id); + assert(left->_id == right->_id); + assert_eq_keyexpr(&left->_keyexpr, &right->_keyexpr); } -void data_info_field(void) { - printf("\n>> DataInfo field\n"); +void resource_declaration(void) { + printf("\n>> Resource declaration\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_data_info_t e_di = gen_data_info(); + _z_decl_kexpr_t e_rd = gen_resource_declaration(); // Encode - int8_t res = _z_data_info_encode(&wbf, &e_di); + int8_t res = _z_decl_kexpr_encode(&wbf, &e_rd); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_data_info_t d_di; - res = _z_data_info_decode(&d_di, &zbf); + _z_decl_kexpr_t d_rd; + uint8_t e_hdr; + _z_uint8_decode(&e_hdr, &zbf); + res = _z_decl_kexpr_decode(&d_rd, &zbf, e_hdr); assert(res == _Z_RES_OK); printf(" "); - assert_eq_data_info(&e_di, &d_di); + assert_eq_resource_declaration(&e_rd, &d_rd); printf("\n"); // Free - _z_data_info_clear(&d_di); - _z_data_info_clear(&e_di); + _z_keyexpr_clear(&e_rd._keyexpr); + _z_keyexpr_clear(&d_rd._keyexpr); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*=============================*/ -/* Message decorators */ -/*=============================*/ -/*------------------ Attachment decorator ------------------*/ -void print_attachment(_z_attachment_t *att) { - printf(" Header: %x\n", att->_header); - printf(" Payload: "); - print_uint8_array(&att->_payload); - printf("\n"); -} - -_z_attachment_t *gen_attachment(void) { - _z_attachment_t *p_at = (_z_attachment_t *)z_malloc(sizeof(_z_attachment_t)); - - p_at->_header = _Z_MID_ATTACHMENT; - // _Z_SET_FLAG(p_at->_header, _Z_FLAGS(gen_uint8())); - p_at->_payload = gen_payload(64); - - return p_at; +/*------------------ Subscriber declaration ------------------*/ +_z_decl_subscriber_t gen_subscriber_declaration(void) { + _z_subinfo_t subinfo = gen_subinfo(); + _z_decl_subscriber_t e_sd = {._keyexpr = gen_keyexpr(), + ._id = gen_uint64(), + ._ext_subinfo = {._pull_mode = subinfo.mode == Z_SUBMODE_PULL, + ._reliable = subinfo.reliability == Z_RELIABILITY_RELIABLE}}; + return e_sd; } -void assert_eq_attachment(_z_attachment_t *left, _z_attachment_t *right) { - printf("Header (%x:%x), ", left->_header, right->_header); - assert(left->_header == right->_header); - assert_eq_payload(&left->_payload, &right->_payload); +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 attachment_decorator(void) { - printf("\n>> Attachment decorator\n"); +void subscriber_declaration(void) { + printf("\n>> Subscriber declaration\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_attachment_t *e_at = gen_attachment(); - + _z_decl_subscriber_t e_sd = gen_subscriber_declaration(); // Encode - int8_t res = _z_attachment_encode(&wbf, e_at); + int8_t res = _z_decl_subscriber_encode(&wbf, &e_sd); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - uint8_t header = _z_zbuf_read(&zbf); - _z_attachment_t *d_at = NULL; - res = _z_attachment_decode(&d_at, &zbf, header); + _z_decl_subscriber_t d_sd; + uint8_t e_hdr; + _z_uint8_decode(&e_hdr, &zbf); + res = _z_decl_subscriber_decode(&d_sd, &zbf, e_hdr); assert(res == _Z_RES_OK); printf(" "); - assert_eq_attachment(e_at, d_at); + assert_eq_subscriber_declaration(&e_sd, &d_sd); printf("\n"); // Free - _z_t_msg_clear_attachment(e_at); - _z_t_msg_clear_attachment(d_at); - z_free(e_at); - z_free(d_at); + _z_keyexpr_clear(&e_sd._keyexpr); + _z_keyexpr_clear(&d_sd._keyexpr); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ ReplyContext decorator ------------------*/ -void print_reply_context(_z_reply_context_t *rc) { - printf(" Header: %x\n", rc->_header); - printf(" QID: %zu\n", rc->_qid); - if (_Z_HAS_FLAG(rc->_header, _Z_FLAG_Z_F) == false) { - printf(" Replier ID: "); - print_uint8_array((_z_bytes_t *)&rc->_replier_id); - } - printf("\n"); -} - -_z_reply_context_t *gen_reply_context(void) { - _z_zint_t qid = gen_zint(); - _z_bytes_t replier_id = gen_bytes(16); - _Bool is_final = gen_bool(); - if (is_final == true) { - _z_bytes_clear(&replier_id); - } +/*------------------ Queryable declaration ------------------*/ +_z_decl_queryable_t gen_queryable_declaration(void) { + _z_decl_queryable_t e_qd = {._keyexpr = gen_keyexpr(), + ._id = gen_uint64(), + ._ext_queryable_info = {._complete = gen_zint(), ._distance = gen_zint()}}; - return _z_msg_make_reply_context(qid, replier_id, is_final); + return e_qd; } -void assert_eq_reply_context(_z_reply_context_t *left, _z_reply_context_t *right) { - printf("Header (%x:%x), ", left->_header, right->_header); - assert(left->_header == right->_header); - - printf("QID (%zu:%zu), ", left->_qid, right->_qid); - assert(left->_qid == right->_qid); +void assert_eq_queryable_declaration(const _z_decl_queryable_t *left, const _z_decl_queryable_t *right) { + assert_eq_keyexpr(&left->_keyexpr, &right->_keyexpr); - printf("Replier ID ("); - if (_Z_HAS_FLAG(left->_header, _Z_FLAG_Z_F) == false) - assert_eq_uint8_array(&left->_replier_id, &right->_replier_id); - else - printf("NULL:NULL"); - printf(")"); + printf("Complete (%u:%u), ", left->_ext_queryable_info._complete, right->_ext_queryable_info._complete); + assert(left->_ext_queryable_info._complete == right->_ext_queryable_info._complete); + printf("Distance (%u:%u), ", left->_ext_queryable_info._distance, right->_ext_queryable_info._distance); + assert(left->_ext_queryable_info._distance == right->_ext_queryable_info._distance); } -void reply_contex_decorator(void) { - printf("\n>> ReplyContext decorator\n"); +void queryable_declaration(void) { + printf("\n>> Queryable declaration\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_reply_context_t *e_rc = gen_reply_context(); + _z_decl_queryable_t e_qd = gen_queryable_declaration(); // Encode - int8_t res = _z_reply_context_encode(&wbf, e_rc); + int8_t res = _z_decl_queryable_encode(&wbf, &e_qd); assert(res == _Z_RES_OK); + (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - uint8_t header = _z_zbuf_read(&zbf); - _z_reply_context_t *d_rc = NULL; - res = _z_reply_context_decode(&d_rc, &zbf, header); + _z_decl_queryable_t d_qd; + uint8_t e_hdr = 0; + _z_uint8_decode(&e_hdr, &zbf); + res = _z_decl_queryable_decode(&d_qd, &zbf, e_hdr); assert(res == _Z_RES_OK); printf(" "); - assert_eq_reply_context(e_rc, d_rc); + assert_eq_queryable_declaration(&e_qd, &d_qd); printf("\n"); // Free - _z_msg_clear_reply_context(e_rc); - _z_msg_clear_reply_context(d_rc); - z_free(e_rc); - z_free(d_rc); + _z_keyexpr_clear(&e_qd._keyexpr); + _z_keyexpr_clear(&d_qd._keyexpr); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*=============================*/ -/* Declaration Fields */ -/*=============================*/ -/*------------------ Resource declaration ------------------*/ -_z_res_decl_t gen_resource_declaration(uint8_t *header) { - _z_res_decl_t e_rd; +/*------------------ Forget Resource declaration ------------------*/ +_z_undecl_kexpr_t gen_forget_resource_declaration(void) { + _z_undecl_kexpr_t e_frd; - e_rd._id = gen_zint(); - e_rd._key = gen_res_key(); - _Z_SET_FLAG(*header, (e_rd._key._suffix) ? _Z_FLAG_Z_K : 0); + e_frd._id = gen_zint(); - return e_rd; + return e_frd; } -void assert_eq_resource_declaration(_z_res_decl_t *left, _z_res_decl_t *right, uint8_t header) { - printf("RID (%zu:%zu), ", left->_id, right->_id); +void assert_eq_forget_resource_declaration(const _z_undecl_kexpr_t *left, const _z_undecl_kexpr_t *right) { + printf("RID (%u:%u)", left->_id, right->_id); assert(left->_id == right->_id); - assert_eq_res_key(&left->_key, &right->_key, header); } -void resource_declaration(void) { - printf("\n>> Resource declaration\n"); +void forget_resource_declaration(void) { + printf("\n>> Forget resource declaration\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - uint8_t e_hdr = 0; - _z_res_decl_t e_rd = gen_resource_declaration(&e_hdr); + _z_undecl_kexpr_t e_frd = gen_forget_resource_declaration(); // Encode - int8_t res = _z_res_decl_encode(&wbf, e_hdr, &e_rd); + int8_t res = _z_undecl_kexpr_encode(&wbf, &e_frd); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_res_decl_t d_rd; - res = _z_res_decl_decode(&d_rd, &zbf, e_hdr); + _z_undecl_kexpr_t d_frd; + uint8_t hdr; + _z_uint8_decode(&hdr, &zbf); + res = _z_undecl_kexpr_decode(&d_frd, &zbf, hdr); assert(res == _Z_RES_OK); printf(" "); - assert_eq_resource_declaration(&e_rd, &d_rd, e_hdr); + assert_eq_forget_resource_declaration(&e_frd, &d_frd); printf("\n"); // Free - _z_msg_clear_declaration_resource(&e_rd); - _z_msg_clear_declaration_resource(&d_rd); + // NOTE: forget_res_decl does not involve any heap allocation _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Publisher declaration ------------------*/ -_z_pub_decl_t gen_publisher_declaration(uint8_t *header) { - _z_pub_decl_t e_pd; - - e_pd._key = gen_res_key(); - _Z_SET_FLAG(*header, (e_pd._key._suffix) ? _Z_FLAG_Z_K : 0); - - return e_pd; +/*------------------ Forget Subscriber declaration ------------------*/ +_z_undecl_subscriber_t gen_forget_subscriber_declaration(void) { + _z_undecl_subscriber_t e_fsd = {._ext_keyexpr = gen_keyexpr(), ._id = gen_uint64()}; + return e_fsd; } -void assert_eq_publisher_declaration(_z_pub_decl_t *left, _z_pub_decl_t *right, uint8_t header) { - assert_eq_res_key(&left->_key, &right->_key, header); +void assert_eq_forget_subscriber_declaration(const _z_undecl_subscriber_t *left, const _z_undecl_subscriber_t *right) { + assert_eq_keyexpr(&left->_ext_keyexpr, &right->_ext_keyexpr); + assert(left->_id == right->_id); } -void publisher_declaration(void) { - printf("\n>> Publisher declaration\n"); +void forget_subscriber_declaration(void) { + printf("\n>> Forget subscriber declaration\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - uint8_t e_hdr = 0; - _z_pub_decl_t e_pd = gen_publisher_declaration(&e_hdr); + _z_undecl_subscriber_t e_fsd = gen_forget_subscriber_declaration(); // Encode - int8_t res = _z_pub_decl_encode(&wbf, e_hdr, &e_pd); + int8_t res = _z_undecl_subscriber_encode(&wbf, &e_fsd); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_pub_decl_t d_pd; - res = _z_pub_decl_decode(&d_pd, &zbf, e_hdr); + _z_undecl_subscriber_t d_fsd = {._id = 0, ._ext_keyexpr = {0}}; + uint8_t e_hdr = 0; + _z_uint8_decode(&e_hdr, &zbf); + res = _z_undecl_subscriber_decode(&d_fsd, &zbf, e_hdr); assert(res == _Z_RES_OK); printf(" "); - assert_eq_publisher_declaration(&e_pd, &d_pd, e_hdr); + assert_eq_forget_subscriber_declaration(&e_fsd, &d_fsd); printf("\n"); // Free - _z_msg_clear_declaration_publisher(&e_pd); - _z_msg_clear_declaration_publisher(&d_pd); + _z_keyexpr_clear(&e_fsd._ext_keyexpr); + _z_keyexpr_clear(&d_fsd._ext_keyexpr); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Subscriber declaration ------------------*/ -_z_sub_decl_t gen_subscriber_declaration(uint8_t *header) { - _z_sub_decl_t e_sd; - - e_sd._subinfo = gen_subinfo(); - if (e_sd._subinfo.mode != Z_SUBMODE_PUSH || e_sd._subinfo.period.period != 0) _Z_SET_FLAG(*header, _Z_FLAG_Z_S); - if (e_sd._subinfo.reliability == Z_RELIABILITY_RELIABLE) _Z_SET_FLAG(*header, _Z_FLAG_Z_R); - - e_sd._key = gen_res_key(); - if (e_sd._key._suffix) _Z_SET_FLAG(*header, _Z_FLAG_Z_K); - - return e_sd; +/*------------------ Forget Queryable declaration ------------------*/ +_z_undecl_queryable_t gen_forget_queryable_declaration(void) { + _z_undecl_queryable_t e_fqd = {._ext_keyexpr = gen_keyexpr(), ._id = gen_zint()}; + return e_fqd; } -void assert_eq_subscriber_declaration(_z_sub_decl_t *left, _z_sub_decl_t *right, uint8_t header) { - assert_eq_res_key(&left->_key, &right->_key, header); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_S) == true) { - printf(", "); - assert_eq_subinfo(&left->_subinfo, &right->_subinfo); - } +void assert_eq_forget_queryable_declaration(const _z_undecl_queryable_t *left, const _z_undecl_queryable_t *right) { + assert_eq_keyexpr(&left->_ext_keyexpr, &right->_ext_keyexpr); + assert(left->_id == right->_id); } -void subscriber_declaration(void) { - printf("\n>> Subscriber declaration\n"); +void forget_queryable_declaration(void) { + printf("\n>> Forget queryable declaration\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - uint8_t e_hdr = 0; - _z_sub_decl_t e_sd = gen_subscriber_declaration(&e_hdr); + _z_undecl_queryable_t e_fqd = gen_forget_queryable_declaration(); // Encode - int8_t res = _z_sub_decl_encode(&wbf, e_hdr, &e_sd); + int8_t res = _z_undecl_queryable_encode(&wbf, &e_fqd); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_sub_decl_t d_sd; - res = _z_sub_decl_decode(&d_sd, &zbf, e_hdr); + uint8_t e_hdr = 0; + _z_uint8_decode(&e_hdr, &zbf); + _z_undecl_queryable_t d_fqd = {._ext_keyexpr = _z_keyexpr_null()}; + res = _z_undecl_queryable_decode(&d_fqd, &zbf, e_hdr); assert(res == _Z_RES_OK); printf(" "); - assert_eq_subscriber_declaration(&e_sd, &d_sd, e_hdr); + assert_eq_forget_queryable_declaration(&e_fqd, &d_fqd); printf("\n"); // Free - _z_msg_clear_declaration_subscriber(&e_sd); - _z_msg_clear_declaration_subscriber(&d_sd); + _z_keyexpr_clear(&e_fqd._ext_keyexpr); + _z_keyexpr_clear(&d_fqd._ext_keyexpr); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Queryable declaration ------------------*/ -_z_qle_decl_t gen_queryable_declaration(uint8_t *header) { - _z_qle_decl_t e_qd; - - e_qd._key = gen_res_key(); - _Z_SET_FLAG(*header, (e_qd._key._suffix) ? _Z_FLAG_Z_K : 0); +/*------------------ Declaration ------------------*/ +_z_declaration_t gen_declaration(void) { + uint8_t decl[] = { + _Z_DECL_KEXPR, _Z_UNDECL_KEXPR, _Z_DECL_SUBSCRIBER, + _Z_UNDECL_SUBSCRIBER, _Z_DECL_QUERYABLE, _Z_UNDECL_QUERYABLE, + }; - if (gen_bool()) { - e_qd._complete = gen_zint(); - e_qd._distance = gen_zint(); - _Z_SET_FLAG(*header, _Z_FLAG_Z_Q); + _z_declaration_t d; + d._tag = decl[gen_uint8() % (sizeof(decl) / sizeof(uint8_t))]; + + switch (d._tag) { + case _Z_DECL_KEXPR: { + d._body._decl_kexpr = gen_resource_declaration(); + } break; + case _Z_UNDECL_KEXPR: { + d._body._undecl_kexpr = gen_forget_resource_declaration(); + } break; + case _Z_DECL_SUBSCRIBER: { + d._body._decl_subscriber = gen_subscriber_declaration(); + } break; + case _Z_UNDECL_SUBSCRIBER: { + d._body._undecl_subscriber = gen_forget_subscriber_declaration(); + } break; + case _Z_DECL_QUERYABLE: { + d._body._decl_queryable = gen_queryable_declaration(); + } break; + case _Z_UNDECL_QUERYABLE: { + d._body._undecl_queryable = gen_forget_queryable_declaration(); + } break; + default: + assert(false); } - return e_qd; -} - -void assert_eq_queryable_declaration(_z_qle_decl_t *left, _z_qle_decl_t *right, uint8_t header) { - assert_eq_res_key(&left->_key, &right->_key, header); - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_I) == true) { - printf("Complete (%zu:%zu), ", left->_complete, right->_complete); - assert(left->_complete == right->_complete); - printf("Distance (%zu:%zu), ", left->_distance, right->_distance); - assert(left->_distance == right->_distance); - } + return d; } -void queryable_declaration(void) { - printf("\n>> Queryable declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); +void assert_eq_declaration(const _z_declaration_t *left, const _z_declaration_t *right) { + printf("Declaration -> "); + printf("Header (%x:%x), ", left->_tag, right->_tag); + assert(left->_tag == right->_tag); - // Initialize - uint8_t e_hdr = 0; - _z_qle_decl_t e_qd = gen_queryable_declaration(&e_hdr); - - // Encode - int8_t res = _z_qle_decl_encode(&wbf, e_hdr, &e_qd); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_qle_decl_t d_qd; - res = _z_qle_decl_decode(&d_qd, &zbf, e_hdr); - assert(res == _Z_RES_OK); - - printf(" "); - assert_eq_queryable_declaration(&e_qd, &d_qd, e_hdr); - printf("\n"); - - // Free - _z_msg_clear_declaration_queryable(&e_qd); - _z_msg_clear_declaration_queryable(&d_qd); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Forget Resource declaration ------------------*/ -_z_forget_res_decl_t gen_forget_resource_declaration(void) { - _z_forget_res_decl_t e_frd; - - e_frd._rid = gen_zint(); - - return e_frd; -} - -void assert_eq_forget_resource_declaration(_z_forget_res_decl_t *left, _z_forget_res_decl_t *right) { - printf("RID (%zu:%zu)", left->_rid, right->_rid); - assert(left->_rid == right->_rid); -} - -void forget_resource_declaration(void) { - printf("\n>> Forget resource declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_forget_res_decl_t e_frd = gen_forget_resource_declaration(); - - // Encode - int8_t res = _z_forget_res_decl_encode(&wbf, &e_frd); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_forget_res_decl_t d_frd; - res = _z_forget_res_decl_decode(&d_frd, &zbf); - assert(res == _Z_RES_OK); - - printf(" "); - assert_eq_forget_resource_declaration(&e_frd, &d_frd); - printf("\n"); - - // Free - // NOTE: forget_res_decl does not involve any heap allocation - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Forget Publisher declaration ------------------*/ -_z_forget_pub_decl_t gen_forget_publisher_declaration(uint8_t *header) { - _z_forget_pub_decl_t e_fpd; - - e_fpd._key = gen_res_key(); - _Z_SET_FLAG(*header, (e_fpd._key._suffix) ? _Z_FLAG_Z_K : 0); - - return e_fpd; -} - -void assert_eq_forget_publisher_declaration(_z_forget_pub_decl_t *left, _z_forget_pub_decl_t *right, uint8_t header) { - assert_eq_res_key(&left->_key, &right->_key, header); -} - -void forget_publisher_declaration(void) { - printf("\n>> Forget publisher declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - uint8_t e_hdr = 0; - _z_forget_pub_decl_t e_fpd = gen_forget_publisher_declaration(&e_hdr); - - // Encode - int8_t res = _z_forget_pub_decl_encode(&wbf, e_hdr, &e_fpd); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_forget_pub_decl_t d_fpd; - res = _z_forget_pub_decl_decode(&d_fpd, &zbf, e_hdr); - assert(res == _Z_RES_OK); - - printf(" "); - assert_eq_forget_publisher_declaration(&e_fpd, &d_fpd, e_hdr); - printf("\n"); - - // Free - _z_msg_clear_declaration_forget_publisher(&e_fpd); - _z_msg_clear_declaration_forget_publisher(&d_fpd); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Forget Subscriber declaration ------------------*/ -_z_forget_sub_decl_t gen_forget_subscriber_declaration(uint8_t *header) { - _z_forget_sub_decl_t e_fsd; - - e_fsd._key = gen_res_key(); - _Z_SET_FLAG(*header, (e_fsd._key._suffix) ? _Z_FLAG_Z_K : 0); - - return e_fsd; -} - -void assert_eq_forget_subscriber_declaration(_z_forget_sub_decl_t *left, _z_forget_sub_decl_t *right, uint8_t header) { - assert_eq_res_key(&left->_key, &right->_key, header); -} - -void forget_subscriber_declaration(void) { - printf("\n>> Forget subscriber declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - uint8_t e_hdr = 0; - _z_forget_sub_decl_t e_fsd = gen_forget_subscriber_declaration(&e_hdr); - - // Encode - int8_t res = _z_forget_sub_decl_encode(&wbf, e_hdr, &e_fsd); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_forget_sub_decl_t d_fsd; - res = _z_forget_sub_decl_decode(&d_fsd, &zbf, e_hdr); - assert(res == _Z_RES_OK); - - printf(" "); - assert_eq_forget_subscriber_declaration(&e_fsd, &d_fsd, e_hdr); - printf("\n"); - - // Free - _z_msg_clear_declaration_forget_subscriber(&e_fsd); - _z_msg_clear_declaration_forget_subscriber(&d_fsd); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Forget Queryable declaration ------------------*/ -_z_forget_qle_decl_t gen_forget_queryable_declaration(uint8_t *header) { - _z_forget_qle_decl_t e_fqd; - - e_fqd._key = gen_res_key(); - _Z_SET_FLAG(*header, (e_fqd._key._suffix) ? _Z_FLAG_Z_K : 0); - - return e_fqd; -} - -void assert_eq_forget_queryable_declaration(_z_forget_qle_decl_t *left, _z_forget_qle_decl_t *right, uint8_t header) { - assert_eq_res_key(&left->_key, &right->_key, header); -} - -void forget_queryable_declaration(void) { - printf("\n>> Forget queryable declaration\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - uint8_t e_hdr = 0; - _z_forget_qle_decl_t e_fqd = gen_forget_queryable_declaration(&e_hdr); - - // Encode - int8_t res = _z_forget_qle_decl_encode(&wbf, e_hdr, &e_fqd); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_forget_qle_decl_t d_fqd; - res = _z_forget_qle_decl_decode(&d_fqd, &zbf, e_hdr); - assert(res == _Z_RES_OK); - - printf(" "); - assert_eq_forget_queryable_declaration(&e_fqd, &d_fqd, e_hdr); - printf("\n"); - - // Free - _z_msg_clear_declaration_forget_queryable(&e_fqd); - _z_msg_clear_declaration_forget_queryable(&d_fqd); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Declaration ------------------*/ -_z_declaration_t gen_declaration(void) { - uint8_t decl[] = {_Z_DECL_RESOURCE, _Z_DECL_PUBLISHER, _Z_DECL_SUBSCRIBER, - _Z_DECL_QUERYABLE, _Z_DECL_FORGET_RESOURCE, _Z_DECL_FORGET_PUBLISHER, - _Z_DECL_FORGET_SUBSCRIBER, _Z_DECL_FORGET_QUERYABLE}; - - _z_declaration_t d; - d._header = decl[gen_uint8() % (sizeof(decl) / sizeof(uint8_t))]; - - switch (d._header) { - case _Z_DECL_RESOURCE: - d._body._res = gen_resource_declaration(&d._header); - break; - case _Z_DECL_PUBLISHER: - d._body._pub = gen_publisher_declaration(&d._header); - break; - case _Z_DECL_SUBSCRIBER: - d._body._sub = gen_subscriber_declaration(&d._header); - break; - case _Z_DECL_QUERYABLE: - d._body._qle = gen_queryable_declaration(&d._header); - break; - case _Z_DECL_FORGET_RESOURCE: - d._body._forget_res = gen_forget_resource_declaration(); - break; - case _Z_DECL_FORGET_PUBLISHER: - d._body._forget_pub = gen_forget_publisher_declaration(&d._header); - break; - case _Z_DECL_FORGET_SUBSCRIBER: - d._body._forget_sub = gen_forget_subscriber_declaration(&d._header); - break; - case _Z_DECL_FORGET_QUERYABLE: - d._body._forget_qle = gen_forget_queryable_declaration(&d._header); - break; - } - - return d; -} - -void assert_eq_declaration(_z_declaration_t *left, _z_declaration_t *right) { - printf("Declaration -> "); - printf("Header (%x:%x), ", left->_header, right->_header); - assert(left->_header == right->_header); - - switch (left->_header) { - case _Z_DECL_RESOURCE: - assert_eq_resource_declaration(&left->_body._res, &right->_body._res, left->_header); - break; - case _Z_DECL_PUBLISHER: - assert_eq_publisher_declaration(&left->_body._pub, &right->_body._pub, left->_header); + switch (left->_tag) { + case _Z_DECL_KEXPR: + assert_eq_resource_declaration(&left->_body._decl_kexpr, &right->_body._decl_kexpr); break; case _Z_DECL_SUBSCRIBER: - assert_eq_subscriber_declaration(&left->_body._sub, &right->_body._sub, left->_header); + assert_eq_subscriber_declaration(&left->_body._decl_subscriber, &right->_body._decl_subscriber); break; case _Z_DECL_QUERYABLE: - assert_eq_queryable_declaration(&left->_body._qle, &right->_body._qle, left->_header); - break; - case _Z_DECL_FORGET_RESOURCE: - assert_eq_forget_resource_declaration(&left->_body._forget_res, &right->_body._forget_res); + assert_eq_queryable_declaration(&left->_body._decl_queryable, &right->_body._decl_queryable); break; - case _Z_DECL_FORGET_PUBLISHER: - assert_eq_forget_publisher_declaration(&left->_body._forget_pub, &right->_body._forget_pub, left->_header); + case _Z_UNDECL_KEXPR: + assert_eq_forget_resource_declaration(&left->_body._undecl_kexpr, &right->_body._undecl_kexpr); break; - case _Z_DECL_FORGET_SUBSCRIBER: - assert_eq_forget_subscriber_declaration(&left->_body._forget_sub, &right->_body._forget_sub, left->_header); + case _Z_UNDECL_SUBSCRIBER: + assert_eq_forget_subscriber_declaration(&left->_body._undecl_subscriber, &right->_body._undecl_subscriber); break; - case _Z_DECL_FORGET_QUERYABLE: - assert_eq_forget_queryable_declaration(&left->_body._forget_qle, &right->_body._forget_qle, left->_header); + case _Z_UNDECL_QUERYABLE: + assert_eq_forget_queryable_declaration(&left->_body._undecl_queryable, &right->_body._undecl_queryable); break; + default: + assert(false); } } -/*=============================*/ -/* Zenoh Messages */ -/*=============================*/ -/*------------------ Declare message ------------------*/ -_z_zenoh_message_t gen_declare_message(void) { - _z_declaration_array_t declarations = _z_declaration_array_make(gen_zint() % 16); - - for (_z_zint_t i = 0; i < declarations._len; i++) declarations._val[i] = gen_declaration(); - - return _z_msg_make_declare(declarations); -} - -void assert_eq_declare_message(_z_msg_declare_t *left, _z_msg_declare_t *right) { - assert(left->_declarations._len == right->_declarations._len); - - for (_z_zint_t i = 0; i < left->_declarations._len; i++) { - printf(" "); - assert_eq_declaration(&left->_declarations._val[i], &right->_declarations._val[i]); - printf("\n"); - } -} - -void declare_message(void) { - printf("\n>> Declare message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_zenoh_message_t z_msg = gen_declare_message(); - assert(_Z_MID(z_msg._header) == _Z_MID_DECLARE); - - _z_msg_declare_t e_dcl = z_msg._body._declare; - - // Encode - int8_t res = _z_declare_encode(&wbf, &e_dcl); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_msg_declare_t d_dcl; - res = _z_declare_decode(&d_dcl, &zbf); - assert(res == _Z_RES_OK); - - assert_eq_declare_message(&e_dcl, &d_dcl); - - // Free - _z_msg_clear_declare(&d_dcl); - _z_msg_clear(&z_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Data message ------------------*/ -_z_zenoh_message_t gen_data_message(void) { - _z_keyexpr_t key = gen_res_key(); - - _z_data_info_t info; - if (gen_bool()) { - info = gen_data_info(); - } else { - info._flags = 0; - info._kind = Z_SAMPLE_KIND_PUT; - info._encoding.prefix = Z_ENCODING_PREFIX_EMPTY; - info._encoding.suffix = _z_bytes_empty(); - info._source_id = _z_bytes_empty(); - info._source_sn = 0; - _z_timestamp_reset(&info._tstamp); - } - - _Bool can_be_dropped = gen_bool(); - _z_payload_t payload = gen_payload(1 + gen_zint() % 64); - - return _z_msg_make_data(key, info, payload, can_be_dropped); -} - -void assert_eq_data_message(_z_msg_data_t *left, _z_msg_data_t *right, uint8_t header) { - printf(" "); - assert_eq_res_key(&left->_key, &right->_key, header); - printf("\n"); - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_I) == true) { - printf(" "); - assert_eq_data_info(&left->_info, &right->_info); - printf("\n"); - } - printf(" "); - assert_eq_payload(&left->_payload, &right->_payload); - printf("\n"); -} - -void data_message(void) { - printf("\n>> Data message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_zenoh_message_t z_msg = gen_data_message(); - assert(_Z_MID(z_msg._header) == _Z_MID_DATA); - - _z_msg_data_t e_da = z_msg._body._data; - - // Encode - int8_t res = _z_data_encode(&wbf, z_msg._header, &e_da); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_msg_data_t d_da; - res = _z_data_decode(&d_da, &zbf, z_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_data_message(&e_da, &d_da, z_msg._header); - - // Free - _z_msg_clear_data(&d_da); - _z_msg_clear(&z_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Pull message ------------------*/ -_z_zenoh_message_t gen_pull_message(void) { - _z_keyexpr_t key = gen_res_key(); - _z_zint_t pull_id = gen_zint(); - _z_zint_t max_samples = gen_bool() ? gen_zint() : 0; - _Bool is_final = gen_bool(); - - return _z_msg_make_pull(key, pull_id, max_samples, is_final); -} - -void assert_eq_pull_message(_z_msg_pull_t *left, _z_msg_pull_t *right, uint8_t header) { - printf(" "); - assert_eq_res_key(&left->_key, &right->_key, header); - printf("\n"); - - printf(" Pull ID (%zu:%zu)", left->_pull_id, right->_pull_id); - assert(left->_pull_id == right->_pull_id); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_N) == true) { - printf(" Max samples (%zu:%zu)", left->_max_samples, right->_max_samples); - assert(left->_max_samples == right->_max_samples); - printf("\n"); - } -} - -void pull_message(void) { - printf("\n>> Pull message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_zenoh_message_t z_msg = gen_pull_message(); - assert(_Z_MID(z_msg._header) == _Z_MID_PULL); - - _z_msg_pull_t e_pu = z_msg._body._pull; - - // Encode - int8_t res = _z_pull_encode(&wbf, z_msg._header, &e_pu); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_msg_pull_t d_pu; - res = _z_pull_decode(&d_pu, &zbf, z_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_pull_message(&e_pu, &d_pu, z_msg._header); - - // Free - _z_msg_clear_pull(&d_pu); - _z_msg_clear(&z_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Query message ------------------*/ -_z_zenoh_message_t gen_query_message(void) { - _z_keyexpr_t key = gen_res_key(); - char *parameters = gen_str(gen_uint8() % 16); - _z_zint_t qid = gen_zint(); - - z_query_target_t target; - if (gen_bool()) { - uint8_t tgt[] = {Z_QUERY_TARGET_BEST_MATCHING, Z_QUERY_TARGET_ALL_COMPLETE, Z_QUERY_TARGET_ALL}; - target = tgt[gen_uint8() % (sizeof(tgt) / sizeof(uint8_t))]; - } else { - target = Z_QUERY_TARGET_BEST_MATCHING; - } - - uint8_t con[] = {Z_CONSOLIDATION_MODE_LATEST, Z_CONSOLIDATION_MODE_MONOTONIC, Z_CONSOLIDATION_MODE_NONE}; - z_consolidation_mode_t consolidation; - consolidation = con[gen_uint8() % (sizeof(con) / sizeof(uint8_t))]; - - _z_value_t value; - if (gen_bool()) { - value = gen_value(); - } else { - value.encoding.prefix = Z_ENCODING_PREFIX_EMPTY; - value.encoding.suffix = _z_bytes_empty(); - value.payload = _z_bytes_empty(); - } - - return _z_msg_make_query(key, parameters, qid, target, consolidation, value); -} - -void assert_eq_query_message(_z_msg_query_t *left, _z_msg_query_t *right, uint8_t header) { - printf(" "); - assert_eq_res_key(&left->_key, &right->_key, header); - printf("\n"); - - printf(" Predicate (%s:%s)", left->_parameters, right->_parameters); - assert(_z_str_eq(left->_parameters, right->_parameters) == true); - printf("\n"); - - printf(" Query ID (%zu:%zu)", left->_qid, right->_qid); - assert(left->_qid == right->_qid); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_T) == true) { - printf("Target (%u:%u), ", left->_target, right->_target); - assert(left->_target == right->_target); - printf("\n"); - } - - printf(" Consolidation ( %u:%u)", left->_consolidation, right->_consolidation); - assert(left->_consolidation == right->_consolidation); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_Z_B) == true) { - printf(" "); - assert_eq_data_info(&left->_info, &right->_info); - printf("\n"); - printf(" "); - assert_eq_payload(&left->_payload, &right->_payload); - printf("\n"); - } -} - -void query_message(void) { - printf("\n>> Query message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - uint8_t e_hdr = 0; - _z_zenoh_message_t z_msg = gen_query_message(); - assert(_Z_MID(z_msg._header) == _Z_MID_QUERY); - - _z_msg_query_t e_qy = z_msg._body._query; - - // Encode - int8_t res = _z_query_encode(&wbf, e_hdr, &e_qy); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_msg_query_t d_qy; - res = _z_query_decode(&d_qy, &zbf, e_hdr); - assert(res == _Z_RES_OK); - - assert_eq_query_message(&e_qy, &d_qy, e_hdr); - - // Free - _z_msg_clear_query(&d_qy); - _z_msg_clear(&z_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Unit message ------------------*/ -_z_zenoh_message_t gen_unit_message(void) { - _Bool can_be_dropped = gen_bool(); - return _z_msg_make_unit(can_be_dropped); -} - -/*------------------ Zenoh message ------------------*/ -_z_zenoh_message_t gen_zenoh_message(void) { - _z_zenoh_message_t p_zm; - - uint8_t mids[] = {_Z_MID_DECLARE, _Z_MID_DATA, _Z_MID_PULL, _Z_MID_QUERY, _Z_MID_UNIT}; - uint8_t i = gen_uint8() % (sizeof(mids) / sizeof(uint8_t)); - - switch (mids[i]) { - case _Z_MID_DECLARE: - p_zm = gen_declare_message(); - break; - case _Z_MID_DATA: - p_zm = gen_data_message(); - break; - case _Z_MID_PULL: - p_zm = gen_pull_message(); - break; - case _Z_MID_QUERY: - p_zm = gen_query_message(); - break; - case _Z_MID_UNIT: - p_zm = gen_unit_message(); - break; - default: - assert(0); - break; - } - - if (gen_bool()) - p_zm._attachment = gen_attachment(); - else - p_zm._attachment = NULL; - - if (gen_bool()) - p_zm._reply_context = gen_reply_context(); - else - p_zm._reply_context = NULL; - - return p_zm; -} - -void assert_eq_zenoh_message(_z_zenoh_message_t *left, _z_zenoh_message_t *right) { - // Test message decorators - if (left->_attachment && right->_attachment) { - printf(" "); - assert_eq_attachment(left->_attachment, right->_attachment); - printf("\n"); - } else { - printf(" Attachment: %p:%p\n", (void *)left->_attachment, (void *)right->_attachment); - assert(left->_attachment == right->_attachment); - } - - if (left->_reply_context && right->_reply_context) { - printf(" "); - assert_eq_reply_context(left->_reply_context, right->_reply_context); - printf("\n"); - } else { - printf(" Reply Context: %p:%p\n", (void *)left->_reply_context, (void *)right->_reply_context); - assert(left->_reply_context == right->_reply_context); - } - - // Test message - printf(" Header (%x:%x)", left->_header, right->_header); - assert(left->_header == right->_header); - printf("\n"); - - switch (_Z_MID(left->_header)) { - case _Z_MID_DECLARE: - assert_eq_declare_message(&left->_body._declare, &right->_body._declare); - break; - case _Z_MID_DATA: - assert_eq_data_message(&left->_body._data, &right->_body._data, left->_header); - break; - case _Z_MID_PULL: - assert_eq_pull_message(&left->_body._pull, &right->_body._pull, left->_header); - break; - case _Z_MID_QUERY: - assert_eq_query_message(&left->_body._query, &right->_body._query, left->_header); - break; - case _Z_MID_UNIT: - // Do nothing. Unit messages have no body - break; - default: - assert(0); - break; - } -} - -void zenoh_message(void) { - printf("\n>> Zenoh message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_zenoh_message_t e_zm = gen_zenoh_message(); - - printf(" - "); - switch (_Z_MID(e_zm._header)) { - case _Z_MID_DECLARE: - printf("Declare message"); - break; - case _Z_MID_DATA: - printf("Data message"); - break; - case _Z_MID_PULL: - printf("Pull message"); - break; - case _Z_MID_QUERY: - printf("Query message"); - break; - case _Z_MID_UNIT: - printf("Unit message"); - break; - default: - assert(0); - break; - } - if (e_zm._attachment) { - printf(" Attachment\n"); - print_attachment(e_zm._attachment); - printf("\n"); - } - if (e_zm._reply_context) { - printf(" Reply Context\n"); - print_reply_context(e_zm._reply_context); - printf("\n"); - } - printf("\n"); - - // Encode - int8_t res = _z_zenoh_message_encode(&wbf, &e_zm); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_zenoh_message_t d_zm; - res = _z_zenoh_message_decode(&d_zm, &zbf); - assert(res == _Z_RES_OK); - - assert_eq_zenoh_message(&e_zm, &d_zm); - - // Free - _z_msg_clear(&e_zm); - _z_msg_clear(&d_zm); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*=============================*/ -/* Transport Messages */ -/*=============================*/ -/*------------------ Scout Message ------------------*/ -_z_transport_message_t gen_scout_message(void) { - z_whatami_t what = gen_uint8() % 7; - _Bool request_zid = gen_bool(); - return _z_t_msg_make_scout(what, request_zid); -} - -void assert_eq_scout_message(_z_t_msg_scout_t *left, _z_t_msg_scout_t *right, uint8_t header) { - if (_Z_HAS_FLAG(header, _Z_FLAG_T_W) == true) { - printf(" What (%u:%u)\n", left->_what, right->_what); - assert(left->_what == right->_what); - } -} - -void scout_message(void) { - printf("\n>> Scout message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_scout_message(); - _z_t_msg_scout_t e_sc = t_msg._body._scout; - - // Encode - int8_t res = _z_scout_encode(&wbf, t_msg._header, &e_sc); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_scout_t d_sc; - res = _z_scout_decode(&d_sc, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_scout_message(&e_sc, &d_sc, t_msg._header); - - // Free - _z_t_msg_clear_scout(&d_sc); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Hello Message ------------------*/ -_z_transport_message_t gen_hello_message(void) { - z_whatami_t whatami = 0x04 >> (gen_uint8() % 3); - _z_bytes_t zid = gen_bool() ? gen_bytes(16) : gen_bytes(0); - - _z_locator_array_t locators; - if (gen_bool()) - locators = gen_locator_array((gen_uint8() % 4) + 1); - else - locators = gen_locator_array(0); - - return _z_t_msg_make_hello(whatami, zid, locators); -} - -void assert_eq_hello_message(_z_t_msg_hello_t *left, _z_t_msg_hello_t *right, uint8_t header) { - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - printf(" "); - assert_eq_uint8_array(&left->_zid, &right->_zid); - printf("\n"); - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_W) == true) { - printf(" What (%u:%u)", left->_whatami, right->_whatami); - assert(left->_whatami == right->_whatami); - printf("\n"); - } - if (_Z_HAS_FLAG(header, _Z_FLAG_T_L) == true) { - printf(" "); - assert_eq_locator_array(&left->_locators, &right->_locators); - printf("\n"); - } -} - -void hello_message(void) { - printf("\n>> Hello message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_hello_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_HELLO); - - _z_t_msg_hello_t e_he = t_msg._body._hello; - - // Encode - int8_t res = _z_hello_encode(&wbf, t_msg._header, &e_he); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_hello_t d_he; - res = _z_hello_decode(&d_he, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_hello_message(&e_he, &d_he, t_msg._header); - - // Free - _z_t_msg_clear_hello(&d_he); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Join Message ------------------*/ -_z_transport_message_t gen_join_message(void) { - uint8_t version = gen_uint8(); - z_whatami_t whatami = 0x04 >> (gen_uint8() % 3); - _z_bytes_t zid = gen_bytes(16); - _z_zint_t lease = gen_bool() ? gen_zint() * 1000 : gen_zint(); - _z_zint_t sn_resolution = gen_bool() ? gen_zint() : Z_SN_RESOLUTION; - - _z_conduit_sn_list_t next_sns; - if (gen_bool()) { - next_sns._is_qos = true; - for (uint8_t i = 0; i < Z_PRIORITIES_NUM; i++) { - next_sns._val._qos[i]._reliable = gen_zint(); - next_sns._val._qos[i]._best_effort = gen_zint(); - } - } else { - next_sns._is_qos = false; - next_sns._val._plain._reliable = gen_zint(); - next_sns._val._plain._best_effort = gen_zint(); - } - - return _z_t_msg_make_join(version, whatami, lease, sn_resolution, zid, next_sns); -} - -void assert_eq_join_message(_z_t_msg_join_t *left, _z_t_msg_join_t *right, uint8_t header) { - printf(" Options (%zu:%zu)", left->_options, right->_options); - assert(left->_options == right->_options); - printf("\n"); - - printf(" Version (%u:%u)", left->_version, right->_version); - assert(left->_version == right->_version); - printf("\n"); - - printf(" WhatAmI (%u:%u)", left->_whatami, right->_whatami); - assert(left->_whatami == right->_whatami); - printf("\n"); - - printf(" "); - assert_eq_uint8_array(&left->_zid, &right->_zid); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_S) == true) { - printf(" SN Resolution (%zu:%zu)", left->_sn_resolution, right->_sn_resolution); - assert(left->_sn_resolution == right->_sn_resolution); - printf("\n"); - } - - printf(" Lease (%zu:%zu)", left->_lease, right->_lease); - assert(left->_lease == right->_lease); - printf("\n"); - - printf(" Next SNs: "); - if (_Z_HAS_FLAG(left->_options, _Z_OPT_JOIN_QOS) == true) { - assert(left->_next_sns._is_qos == true); - assert(right->_next_sns._is_qos == true); - - for (uint8_t i = 0; i < Z_PRIORITIES_NUM; i++) { - printf("R:%zu:%zu ", left->_next_sns._val._qos[i]._reliable, right->_next_sns._val._qos[i]._reliable); - assert(left->_next_sns._val._qos[i]._reliable == right->_next_sns._val._qos[i]._reliable); - printf("B:%zu:%zu ", left->_next_sns._val._qos[i]._best_effort, right->_next_sns._val._qos[i]._best_effort); - assert(left->_next_sns._val._qos[i]._best_effort == right->_next_sns._val._qos[i]._best_effort); - } - printf("\n"); - } else { - assert(left->_next_sns._is_qos == false); - assert(right->_next_sns._is_qos == false); - - printf("R: %zu:%zu", left->_next_sns._val._plain._reliable, right->_next_sns._val._plain._reliable); - assert(left->_next_sns._val._plain._reliable == right->_next_sns._val._plain._reliable); - printf("B: %zu:%zu", left->_next_sns._val._plain._best_effort, right->_next_sns._val._plain._best_effort); - assert(left->_next_sns._val._plain._best_effort == right->_next_sns._val._plain._best_effort); - printf("\n"); - } -} - -void join_message(void) { - printf("\n>> Join message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_join_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_JOIN); - - _z_t_msg_join_t e_it = t_msg._body._join; - - // Encode - int8_t res = _z_join_encode(&wbf, t_msg._header, &t_msg._body._join); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_join_t d_it; - res = _z_join_decode(&d_it, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_join_message(&e_it, &d_it, t_msg._header); - - // Free - _z_t_msg_clear_join(&d_it); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Init Message ------------------*/ -_z_transport_message_t gen_init_message(void) { - uint8_t version = gen_uint8(); - z_whatami_t whatami = 0x04 >> (gen_uint8() % 3); - _z_zint_t sn_resolution = gen_bool() ? gen_zint() : Z_SN_RESOLUTION; - _z_bytes_t zid = gen_bytes(16); - _Bool is_qos = gen_bool(); - - if (gen_bool()) { - return _z_t_msg_make_init_syn(version, whatami, sn_resolution, zid, is_qos); - } else { - _z_bytes_t cookie = gen_bytes(64); - return _z_t_msg_make_init_ack(version, whatami, sn_resolution, zid, cookie, is_qos); - } -} - -void assert_eq_init_message(_z_t_msg_init_t *left, _z_t_msg_init_t *right, uint8_t header) { - printf(" Options (%zu:%zu)", left->_options, right->_options); - assert(left->_options == right->_options); - printf("\n"); - - printf(" WhatAmI (%u:%u)", left->_whatami, right->_whatami); - assert(left->_whatami == right->_whatami); - printf("\n"); - - printf(" "); - assert_eq_uint8_array(&left->_zid, &right->_zid); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_S) == true) { - printf(" SN Resolution (%zu:%zu)", left->_sn_resolution, right->_sn_resolution); - assert(left->_sn_resolution == right->_sn_resolution); - printf("\n"); - } - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == true) { - printf(" "); - assert_eq_uint8_array(&left->_cookie, &right->_cookie); - printf("\n"); - } else { - printf(" Version (%u:%u)", left->_version, right->_version); - assert(left->_version == right->_version); - printf("\n"); - } -} - -void init_message(void) { - printf("\n>> Init message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_init_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_INIT); - - _z_t_msg_init_t e_it = t_msg._body._init; - - // Encode - int8_t res = _z_init_encode(&wbf, t_msg._header, &e_it); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_init_t d_it; - res = _z_init_decode(&d_it, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_init_message(&e_it, &d_it, t_msg._header); - - // Free - _z_t_msg_clear_init(&d_it); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Open Message ------------------*/ -_z_transport_message_t gen_open_message(void) { - _z_zint_t lease = gen_bool() ? gen_zint() * 1000 : gen_zint(); - _z_zint_t initial_sn = gen_zint(); - - if (gen_bool()) { - _z_bytes_t cookie = gen_bytes(64); - return _z_t_msg_make_open_syn(lease, initial_sn, cookie); - } else { - return _z_t_msg_make_open_ack(lease, initial_sn); - } -} - -void assert_eq_open_message(_z_t_msg_open_t *left, _z_t_msg_open_t *right, uint8_t header) { - printf(" Lease (%zu:%zu)", left->_lease, right->_lease); - assert(left->_lease == right->_lease); - printf("\n"); - - printf(" Initial SN (%zu:%zu)", left->_initial_sn, right->_initial_sn); - assert(left->_initial_sn == right->_initial_sn); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_A) == false) { - printf(" "); - assert_eq_uint8_array(&left->_cookie, &right->_cookie); - printf("\n"); - } -} - -void open_message(void) { - printf("\n>> Open message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_open_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_OPEN); - - _z_t_msg_open_t e_op = t_msg._body._open; - - // Encode - int8_t res = _z_open_encode(&wbf, t_msg._header, &e_op); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_open_t d_op; - res = _z_open_decode(&d_op, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_open_message(&e_op, &d_op, t_msg._header); - - // Free - _z_t_msg_clear_open(&d_op); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Close Message ------------------*/ -_z_transport_message_t gen_close_message(void) { - uint8_t reason = gen_uint8(); - _z_bytes_t zid = gen_bool() ? gen_bytes(16) : gen_bytes(0); - _Bool link_only = gen_bool(); - - return _z_t_msg_make_close(reason, zid, link_only); -} - -void assert_eq_close_message(_z_t_msg_close_t *left, _z_t_msg_close_t *right, uint8_t header) { - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - printf(" "); - assert_eq_uint8_array(&left->_zid, &right->_zid); - printf("\n"); - } - - printf(" Reason (%u:%u)", left->_reason, right->_reason); - assert(left->_reason == right->_reason); - printf("\n"); -} - -void close_message(void) { - printf("\n>> Close message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_close_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_CLOSE); - - _z_t_msg_close_t e_cl = t_msg._body._close; - - // Encode - int8_t res = _z_close_encode(&wbf, t_msg._header, &e_cl); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_close_t d_cl; - res = _z_close_decode(&d_cl, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_close_message(&e_cl, &d_cl, t_msg._header); - - // Free - _z_t_msg_clear_close(&d_cl); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ Sync Message ------------------*/ -_z_transport_message_t gen_sync_message(void) { - _z_zint_t sn = gen_zint(); - _Bool is_reliable = gen_bool(); - _z_zint_t count = gen_zint(); - - return _z_t_msg_make_sync(sn, is_reliable, count); -} - -void assert_eq_sync_message(_z_t_msg_sync_t *left, _z_t_msg_sync_t *right, uint8_t header) { - printf(" SN (%zu:%zu)", left->_sn, right->_sn); - assert(left->_sn == right->_sn); - printf("\n"); - - if ((_Z_HAS_FLAG(header, _Z_FLAG_T_R) == true) && (_Z_HAS_FLAG(header, _Z_FLAG_T_C) == true)) { - printf(" Count (%zu:%zu)", left->_count, right->_count); - assert(left->_count == right->_count); - printf("\n"); - } -} - -void sync_message(void) { - printf("\n>> Sync message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_sync_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_SYNC); - - _z_t_msg_sync_t e_sy = t_msg._body._sync; - - // Encode - int8_t res = _z_sync_encode(&wbf, t_msg._header, &e_sy); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_sync_t d_sy; - res = _z_sync_decode(&d_sy, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_sync_message(&e_sy, &d_sy, t_msg._header); - - // Free - _z_t_msg_clear_sync(&d_sy); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ AckNack Message ------------------*/ -_z_transport_message_t gen_ack_nack_message(void) { - _z_zint_t sn = gen_zint(); - _z_zint_t mask = gen_bool() ? gen_zint() : 0; - - return _z_t_msg_make_ack_nack(sn, mask); -} - -void assert_eq_ack_nack_message(_z_t_msg_ack_nack_t *left, _z_t_msg_ack_nack_t *right, uint8_t header) { - printf(" SN (%zu:%zu)", left->_sn, right->_sn); - assert(left->_sn == right->_sn); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_M) == true) { - printf(" Mask (%zu:%zu)", left->_mask, right->_mask); - assert(left->_mask == right->_mask); - printf("\n"); - } -} - -void ack_nack_message(void) { - printf("\n>> AckNack message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_ack_nack_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_ACK_NACK); - - _z_t_msg_ack_nack_t e_an = t_msg._body._ack_nack; - - // Encode - int8_t res = _z_ack_nack_encode(&wbf, t_msg._header, &e_an); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_ack_nack_t d_an; - res = _z_ack_nack_decode(&d_an, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_ack_nack_message(&e_an, &d_an, t_msg._header); - - // Free - _z_t_msg_clear_ack_nack(&d_an); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} - -/*------------------ KeepAlive Message ------------------*/ -_z_transport_message_t gen_keep_alive_message(void) { - _z_bytes_t zid = gen_bool() ? gen_bytes(16) : gen_bytes(0); - - return _z_t_msg_make_keep_alive(zid); -} - -void assert_eq_keep_alive_message(_z_t_msg_keep_alive_t *left, _z_t_msg_keep_alive_t *right, uint8_t header) { - if (_Z_HAS_FLAG(header, _Z_FLAG_T_I) == true) { - printf(" "); - assert_eq_uint8_array(&left->_zid, &right->_zid); - printf("\n"); - } -} - -void keep_alive_message(void) { - printf("\n>> KeepAlive message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t t_msg = gen_keep_alive_message(); - _z_t_msg_keep_alive_t e_ka = t_msg._body._keep_alive; - assert(_Z_MID(t_msg._header) == _Z_MID_KEEP_ALIVE); - - // Encode - int8_t res = _z_keep_alive_encode(&wbf, t_msg._header, &e_ka); - assert(res == _Z_RES_OK); - (void)(res); - - // Decode - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_keep_alive_t d_ka; - res = _z_keep_alive_decode(&d_ka, &zbf, t_msg._header); - assert(res == _Z_RES_OK); - - assert_eq_keep_alive_message(&e_ka, &d_ka, t_msg._header); - - // Free - _z_t_msg_clear_keep_alive(&d_ka); - _z_t_msg_clear(&t_msg); - _z_zbuf_clear(&zbf); - _z_wbuf_clear(&wbf); -} +/*------------------ Declare message ------------------*/ +_z_network_message_t gen_declare_message(void) { + _z_declaration_t declaration = gen_declaration(); -/*------------------ PingPong Message ------------------*/ -_z_transport_message_t gen_ping_pong_message(void) { - _z_zint_t hash = gen_zint(); - if (gen_bool()) - return _z_t_msg_make_ping(hash); - else - return _z_t_msg_make_pong(hash); + return _z_n_msg_make_declare(declaration); } -void assert_eq_ping_pong_message(_z_t_msg_ping_pong_t *left, _z_t_msg_ping_pong_t *right) { - printf(" Hash (%zu:%zu)", left->_hash, right->_hash); - assert(left->_hash == right->_hash); +void assert_eq_declare_message(_z_n_msg_declare_t *left, _z_n_msg_declare_t *right) { + printf(" "); + assert_eq_declaration(&left->_decl, &right->_decl); printf("\n"); } -void ping_pong_message(void) { - printf("\n>> PingPong message\n"); +void declare_message(void) { + printf("\n>> Declare message\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_transport_message_t t_msg = gen_ping_pong_message(); - assert(_Z_MID(t_msg._header) == _Z_MID_PING_PONG); - - _z_t_msg_ping_pong_t e_pp = t_msg._body._ping_pong; + _z_network_message_t n_msg = gen_declare_message(); // Encode - int8_t res = _z_ping_pong_encode(&wbf, &e_pp); + int8_t res = _z_network_message_encode(&wbf, &n_msg); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_ping_pong_t d_pp; - res = _z_ping_pong_decode(&d_pp, &zbf); + _z_network_message_t d_dcl = {0}; + res = _z_network_message_decode(&d_dcl, &zbf); assert(res == _Z_RES_OK); - assert_eq_ping_pong_message(&e_pp, &d_pp); + assert_eq_declare_message(&n_msg._body._declare, &d_dcl._body._declare); // Free - _z_t_msg_clear_ping_pong(&d_pp); - _z_t_msg_clear(&t_msg); + _z_n_msg_clear(&d_dcl); + _z_n_msg_clear(&n_msg); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Frame Message ------------------*/ -_z_transport_message_t gen_frame_message(_Bool can_be_fragment) { - _z_zint_t sn = gen_zint(); - _Bool is_reliable = gen_bool(); - _Bool is_fragment = can_be_fragment ? gen_bool() : false; - _Bool is_final = is_fragment ? gen_bool() : false; - - _z_frame_payload_t payload; - if (is_fragment == true) { - payload._fragment = gen_payload(64); +/*=============================*/ +/* Zenoh Messages */ +/*=============================*/ +/*------------------ Push message ------------------*/ +_z_push_body_t gen_push_body(void) { + _Bool isput = gen_bool(); + _z_timestamp_t ts = gen_bool() ? gen_timestamp() : _z_timestamp_null(); + _z_source_info_t sinfo = gen_bool() ? gen_source_info() : _z_source_info_null(); + _z_m_push_commons_t commons = {._source_info = sinfo, ._timestamp = ts}; + if (isput) { + return (_z_push_body_t){._is_put = true, + ._body._put = { + ._commons = commons, + ._payload = gen_bytes(64), + ._encoding = gen_encoding(), + }}; } else { - _z_zint_t num = (gen_zint() % 4) + 1; - payload._messages = _z_vec_make(num); - for (_z_zint_t i = 0; i < num; i++) { - _z_zenoh_message_t e_zm = gen_zenoh_message(); - _z_zenoh_message_t *p_zm = (_z_zenoh_message_t *)z_malloc(sizeof(_z_zenoh_message_t)); - *p_zm = e_zm; - _z_vec_append(&payload._messages, p_zm); - } + return (_z_push_body_t){._is_put = false, ._body._del = {._commons = commons}}; } - - return _z_t_msg_make_frame(sn, payload, is_reliable, is_fragment, is_final); } -void assert_eq_frame_message(_z_t_msg_frame_t *left, _z_t_msg_frame_t *right, uint8_t header) { - printf(" SN (%zu:%zu)", left->_sn, right->_sn); - assert(left->_sn == right->_sn); - printf("\n"); - - if (_Z_HAS_FLAG(header, _Z_FLAG_T_F) == true) { - printf(" "); - assert_eq_payload(&left->_payload._fragment, &right->_payload._fragment); - printf("\n"); +void assert_eq_push_body(const _z_push_body_t *left, const _z_push_body_t *right) { + assert(left->_is_put == right->_is_put); + if (left->_is_put) { + assert_eq_bytes(&left->_body._put._payload, &right->_body._put._payload); + assert_eq_encoding(&left->_body._put._encoding, &right->_body._put._encoding); + assert_eq_timestamp(&left->_body._put._commons._timestamp, &right->_body._put._commons._timestamp); + assert_eq_source_info(&left->_body._put._commons._source_info, &right->_body._put._commons._source_info); } else { - size_t l_len = _z_vec_len(&left->_payload._messages); - size_t r_len = _z_vec_len(&right->_payload._messages); - printf(" Lenght (%zu:%zu)", l_len, r_len); - assert(l_len == r_len); - - for (size_t i = 0; i < l_len; i++) - assert_eq_zenoh_message((_z_zenoh_message_t *)_z_vec_get(&left->_payload._messages, i), - (_z_zenoh_message_t *)_z_vec_get(&right->_payload._messages, i)); + assert_eq_timestamp(&left->_body._del._commons._timestamp, &right->_body._del._commons._timestamp); + assert_eq_source_info(&left->_body._del._commons._source_info, &right->_body._del._commons._source_info); } } -void frame_message(void) { - printf("\n>> Frame message\n"); +void push_body_message(void) { + printf("\n>> Put/Del message\n"); _z_wbuf_t wbf = gen_wbuf(65535); // Initialize - _z_transport_message_t t_msg = gen_frame_message(1); - assert(_Z_MID(t_msg._header) == _Z_MID_FRAME); - - _z_t_msg_frame_t e_fr = t_msg._body._frame; + _z_push_body_t e_da = gen_push_body(); // Encode - int8_t res = _z_frame_encode(&wbf, t_msg._header, &e_fr); + int8_t res = _z_push_body_encode(&wbf, &e_da); assert(res == _Z_RES_OK); (void)(res); // Decode _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_t_msg_frame_t d_fr; - res = _z_frame_decode(&d_fr, &zbf, t_msg._header); + _z_push_body_t d_da = {0}; + uint8_t header = _z_zbuf_read(&zbf); + res = _z_push_body_decode(&d_da, &zbf, header); assert(res == _Z_RES_OK); - assert_eq_frame_message(&e_fr, &d_fr, t_msg._header); + assert_eq_push_body(&e_da, &d_da); - // Frame - _z_t_msg_clear_frame(&d_fr, t_msg._header); - _z_t_msg_clear(&t_msg); + // Free + _z_push_body_clear(&d_da); + _z_push_body_clear(&e_da); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Transport Message ------------------*/ -_z_transport_message_t gen_transport_message(_Bool can_be_fragment) { - _z_transport_message_t e_tm; - - uint8_t mids[] = { - _Z_MID_SCOUT, _Z_MID_HELLO, _Z_MID_JOIN, _Z_MID_INIT, _Z_MID_OPEN, _Z_MID_CLOSE, - _Z_MID_SYNC, _Z_MID_ACK_NACK, _Z_MID_KEEP_ALIVE, _Z_MID_PING_PONG, _Z_MID_FRAME, - }; +/*------------------ Pull message ------------------*/ +_z_msg_pull_t gen_pull_message(void) { return (_z_msg_pull_t){._ext_source_info = _z_source_info_null()}; } - uint8_t i = gen_uint8() % (sizeof(mids) / sizeof(uint8_t)); - switch (mids[i]) { - case _Z_MID_SCOUT: - e_tm = gen_scout_message(); - break; - case _Z_MID_HELLO: - e_tm = gen_hello_message(); - break; - case _Z_MID_JOIN: - e_tm = gen_join_message(); - break; - case _Z_MID_INIT: - e_tm = gen_init_message(); - break; - case _Z_MID_OPEN: - e_tm = gen_open_message(); - break; - case _Z_MID_CLOSE: - e_tm = gen_close_message(); - break; - case _Z_MID_SYNC: - e_tm = gen_sync_message(); - break; - case _Z_MID_ACK_NACK: - e_tm = gen_ack_nack_message(); - break; - case _Z_MID_KEEP_ALIVE: - e_tm = gen_keep_alive_message(); - break; - case _Z_MID_PING_PONG: - e_tm = gen_ping_pong_message(); - break; - case _Z_MID_FRAME: - e_tm = gen_frame_message(can_be_fragment); - break; - default: - assert(0); - break; - } +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); +} - if (gen_bool()) - e_tm._attachment = gen_attachment(); - else - e_tm._attachment = NULL; +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(); - return e_tm; -} + assert(_z_pull_encode(&wbf, &e_pull_msg) == _Z_RES_OK); -void assert_eq_transport_message(_z_transport_message_t *left, _z_transport_message_t *right) { - // Test message decorators - if (left->_attachment && right->_attachment) { - printf(" "); - assert_eq_attachment(left->_attachment, right->_attachment); - printf("\n"); - } else - assert(left->_attachment == right->_attachment); + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); - // Test message - printf(" Header (%x:%x)", left->_header, right->_header); - assert(left->_header == right->_header); - printf("\n"); + _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); - switch (_Z_MID(left->_header)) { - case _Z_MID_SCOUT: - assert_eq_scout_message(&left->_body._scout, &right->_body._scout, left->_header); - break; - case _Z_MID_HELLO: - assert_eq_hello_message(&left->_body._hello, &right->_body._hello, left->_header); - break; - case _Z_MID_JOIN: - assert_eq_join_message(&left->_body._join, &right->_body._join, left->_header); - break; - case _Z_MID_INIT: - assert_eq_init_message(&left->_body._init, &right->_body._init, left->_header); - break; - case _Z_MID_OPEN: - assert_eq_open_message(&left->_body._open, &right->_body._open, left->_header); - break; - case _Z_MID_CLOSE: - assert_eq_close_message(&left->_body._close, &right->_body._close, left->_header); - break; - case _Z_MID_SYNC: - assert_eq_sync_message(&left->_body._sync, &right->_body._sync, left->_header); - break; - case _Z_MID_ACK_NACK: - assert_eq_ack_nack_message(&left->_body._ack_nack, &right->_body._ack_nack, left->_header); - break; - case _Z_MID_KEEP_ALIVE: - assert_eq_keep_alive_message(&left->_body._keep_alive, &right->_body._keep_alive, left->_header); - break; - case _Z_MID_PING_PONG: - assert_eq_ping_pong_message(&left->_body._ping_pong, &right->_body._ping_pong); - break; - case _Z_MID_FRAME: - assert_eq_frame_message(&left->_body._frame, &right->_body._frame, left->_header); - break; - default: - assert(0); - break; - } + _z_msg_pull_clear(&e_pull_msg); + _z_msg_pull_clear(&d_pull_msg); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); } -void transport_message(void) { - printf("\n>> Session message\n"); - _z_wbuf_t wbf = gen_wbuf(65535); - - // Initialize - _z_transport_message_t e_tm = gen_transport_message(1); - printf(" - "); - print_transport_message_type(e_tm._header); - printf("\n"); +_z_msg_query_t gen_query(void) { + return (_z_msg_query_t){ + ._ext_consolidation = (gen_uint8() % 4) - 1, + ._ext_info = gen_source_info(), + ._parameters = gen_bytes(16), + ._ext_value = gen_bool() ? gen_value() : _z_value_null(), + }; +} - // Encode - int8_t res = _z_transport_message_encode(&wbf, &e_tm); - assert(res == _Z_RES_OK); - (void)(res); +void assert_eq_query(const _z_msg_query_t *left, const _z_msg_query_t *right) { + assert(left->_ext_consolidation == right->_ext_consolidation); + assert_eq_source_info(&left->_ext_info, &right->_ext_info); + assert_eq_bytes(&left->_parameters, &right->_parameters); + assert_eq_value(&left->_ext_value, &right->_ext_value); +} - // Decode +void query_message(void) { + printf("\n>> Query message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_msg_query_t expected = gen_query(); + assert(_z_query_encode(&wbf, &expected) == _Z_RES_OK); + _z_msg_query_t decoded; _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); - _z_transport_message_t d_sm; - res = _z_transport_message_decode(&d_sm, &zbf); - assert(res == _Z_RES_OK); + uint8_t header = _z_zbuf_read(&zbf); + int8_t res = _z_query_decode(&decoded, &zbf, header); + assert(_Z_RES_OK == res); + assert_eq_query(&expected, &decoded); + _z_msg_query_clear(&decoded); + _z_msg_query_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} + +_z_msg_err_t gen_err(void) { + return (_z_msg_err_t){ + ._code = gen_uint16(), + ._is_infrastructure = gen_bool(), + ._timestamp = gen_timestamp(), + ._ext_source_info = gen_bool() ? gen_source_info() : _z_source_info_null(), + ._ext_value = gen_bool() ? gen_value() : _z_value_null(), + }; +} - assert_eq_transport_message(&e_tm, &d_sm); +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_source_info(&left->_ext_source_info, &right->_ext_source_info); + assert_eq_value(&left->_ext_value, &right->_ext_value); +} - // Free - _z_t_msg_clear(&e_tm); - _z_t_msg_clear(&d_sm); +void err_message(void) { + printf("\n>> Err message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_msg_err_t expected = gen_err(); + assert(_z_err_encode(&wbf, &expected) == _Z_RES_OK); + _z_msg_err_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); + assert(_Z_RES_OK == _z_err_decode(&decoded, &zbf, header)); + assert_eq_err(&expected, &decoded); + _z_msg_err_clear(&decoded); + _z_msg_err_clear(&expected); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Batch ------------------*/ -void batch(void) { - printf("\n>> Batch\n"); - uint8_t bef_num = (gen_uint8() % 3); - uint8_t frm_num = 2 + (gen_uint8() % 3); - uint8_t aft_num = (gen_uint8() % 3); - uint8_t tot_num = bef_num + frm_num + aft_num; - _z_wbuf_t wbf = gen_wbuf(tot_num * 1024); +_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(), + }; +} - // Initialize - _z_transport_message_t *e_tm = (_z_transport_message_t *)z_malloc(tot_num * sizeof(_z_transport_message_t)); - for (uint8_t i = 0; i < bef_num; i++) { - // Initialize random transport message - e_tm[i] = gen_transport_message(0); - // Encode - int8_t res = _z_transport_message_encode(&wbf, &e_tm[i]); - assert(res == _Z_RES_OK); - (void)(res); - } - for (uint8_t i = bef_num; i < bef_num + frm_num; i++) { - // Initialize a frame message - e_tm[i] = gen_frame_message(0); - // Encode - int8_t res = _z_transport_message_encode(&wbf, &e_tm[i]); - assert(res == _Z_RES_OK); - (void)(res); - } - for (uint8_t i = bef_num + frm_num; i < bef_num + frm_num + aft_num; i++) { - // Initialize random transport message - e_tm[i] = gen_transport_message(0); - // Encode - int8_t res = _z_transport_message_encode(&wbf, &e_tm[i]); - assert(res == _Z_RES_OK); - (void)(res); - } +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); +} - // Decode +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); - for (uint8_t i = 0; i < tot_num; i++) { - _z_transport_message_t d_sm; - int8_t res = _z_transport_message_decode(&d_sm, &zbf); - assert(res == _Z_RES_OK); + 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); +} - printf(" - "); - print_transport_message_type(d_sm._header); - printf("\n"); - assert_eq_transport_message(&e_tm[i], &d_sm); +_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(), + }; +} - // Free - _z_t_msg_clear(&e_tm[i]); - _z_t_msg_clear(&d_sm); - } +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); +} - z_free(e_tm); +void reply_message(void) { + printf("\n>> Reply message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_msg_reply_t expected = gen_reply(); + assert(_z_reply_encode(&wbf, &expected) == _Z_RES_OK); + _z_msg_reply_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); + assert(_Z_RES_OK == _z_reply_decode(&decoded, &zbf, header)); + assert_eq_reply(&expected, &decoded); + _z_msg_reply_clear(&decoded); + _z_msg_reply_clear(&expected); _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); } -/*------------------ Fragmentation ------------------*/ -_z_transport_message_t z_frame_header(_Bool is_reliable, _Bool is_fragment, _Bool is_final, _z_zint_t sn) { - // Create the frame session message that carries the zenoh message - _z_transport_message_t t_msg; - t_msg._attachment = NULL; - t_msg._header = _Z_MID_FRAME; - t_msg._body._frame._sn = sn; - - if (is_reliable == true) { - _Z_SET_FLAG(t_msg._header, _Z_FLAG_T_R); +_z_n_msg_push_t gen_push(void) { + return (_z_n_msg_push_t){ + ._body = gen_push_body(), + ._key = gen_keyexpr(), + ._qos = _z_n_qos_make(gen_bool(), gen_bool(), gen_uint8() % 8), + ._timestamp = gen_timestamp(), }; +} - if (is_fragment == true) { - _Z_SET_FLAG(t_msg._header, _Z_FLAG_T_F); - - if (is_final == true) { - _Z_SET_FLAG(t_msg._header, _Z_FLAG_T_E); - } +void assert_eq_push(const _z_n_msg_push_t *left, const _z_n_msg_push_t *right) { + assert_eq_timestamp(&left->_timestamp, &right->_timestamp); + assert_eq_keyexpr(&left->_key, &right->_key); + assert(left->_qos._val == right->_qos._val); + assert_eq_push_body(&left->_body, &right->_body); +} - // Do not add the payload - t_msg._body._frame._payload._fragment.len = 0; - t_msg._body._frame._payload._fragment.start = NULL; - } else { - // Do not allocate the vector containing the messages - t_msg._body._frame._payload._messages = _z_zenoh_message_vec_make(0); - } +void push_message(void) { + printf("\n>> Push message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_n_msg_push_t expected = gen_push(); + assert(_z_push_encode(&wbf, &expected) == _Z_RES_OK); + _z_n_msg_push_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); + assert(_Z_RES_OK == _z_push_decode(&decoded, &zbf, header)); + assert_eq_push(&expected, &decoded); + _z_n_msg_push_clear(&decoded); + _z_n_msg_push_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - return t_msg; -} - -void z_wbuf_prepare(_z_wbuf_t *wbf) { - // Clear the buffer for serialization - _z_wbuf_reset(wbf); - - for (size_t i = 0; i < _z_wbuf_space_left(wbf); i++) _z_wbuf_put(wbf, 0xff, i); -} - -int8_t z_serialize_zenoh_fragment(_z_wbuf_t *dst, _z_wbuf_t *src, _Bool is_reliable, size_t sn) { - // Assume first that this is not the final fragment - _Bool is_final = false; - do { - // Mark the buffer for the writing operation - size_t w_pos = _z_wbuf_get_wpos(dst); - // Get the frame header - _z_transport_message_t f_hdr = z_frame_header(is_reliable, true, is_final, sn); - // Encode the frame header - int8_t res = _z_transport_message_encode(dst, &f_hdr); - if (res == _Z_RES_OK) { - size_t space_left = _z_wbuf_space_left(dst); - size_t bytes_left = _z_wbuf_len(src); - // Check if it is really the final fragment - if ((is_final == false) && (bytes_left <= space_left)) { - // Revert the buffer - _z_wbuf_set_wpos(dst, w_pos); - // It is really the finally fragment, reserialize the header - is_final = true; - continue; +_z_n_msg_request_t gen_request(void) { + _z_n_msg_request_t request = { + ._rid = gen_uint64(), + ._key = gen_keyexpr(), + ._ext_qos = gen_bool() ? _z_n_qos_make(gen_bool(), gen_bool(), gen_uint8() % 8) : _Z_N_QOS_DEFAULT, + ._ext_timestamp = gen_bool() ? gen_timestamp() : _z_timestamp_null(), + ._ext_target = gen_uint8() % 3, + ._ext_budget = gen_bool() ? gen_uint64() : 0, + ._ext_timeout_ms = gen_bool() ? gen_uint64() : 0, + }; + switch (gen_uint8() % 4) { + 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; + default: { + _z_push_body_t body = gen_push_body(); + if (body._is_put) { + request._tag = _Z_REQUEST_PUT; + request._body._put = body._body._put; + } else { + request._tag = _Z_REQUEST_DEL; + request._body._del = body._body._del; } - // Write the fragment - size_t to_copy = bytes_left <= space_left ? bytes_left : space_left; - printf(" -Bytes left: %zu, Space left: %zu, Fragment size: %zu, Is final: %d\n", bytes_left, space_left, - to_copy, is_final); - return _z_wbuf_siphon(dst, src, to_copy); - } else { - return 0; } - } while (1); -} - -void fragmentation(void) { - printf("\n>> Fragmentation\n"); - size_t len = 16; - _z_wbuf_t wbf = _z_wbuf_make(len, false); - _z_wbuf_t fbf = _z_wbuf_make(len, true); - _z_wbuf_t dbf = _z_wbuf_make(0, true); - - _z_zenoh_message_t e_zm; - - do { - _z_wbuf_reset(&fbf); - // Generate and serialize the message - e_zm = gen_zenoh_message(); - _z_zenoh_message_encode(&fbf, &e_zm); - // Check that the message actually requires fragmentation - if (_z_wbuf_len(&fbf) <= len) - _z_msg_clear(&e_zm); - else - break; - } while (1); - - // Fragment the message - _Bool is_reliable = gen_bool(); - // Fix the sn resoulution to 128 in such a way it requires only 1 byte for encoding - size_t sn_resolution = 128; - size_t sn = sn_resolution - 1; - - printf(" - Message serialized\n"); - print_wbuf(&fbf); - - printf(" - Start fragmenting\n"); - while (_z_wbuf_len(&fbf) > 0) { - // Clear the buffer for serialization - z_wbuf_prepare(&wbf); + } + return request; +} - // Get the fragment sequence number - sn = (sn + 1) % sn_resolution; +void assert_eq_request(const _z_n_msg_request_t *left, const _z_n_msg_request_t *right) { + assert(left->_rid == right->_rid); + assert_eq_keyexpr(&left->_key, &right->_key); + assert(left->_ext_qos._val == right->_ext_qos._val); + assert_eq_timestamp(&left->_ext_timestamp, &right->_ext_timestamp); + assert(left->_ext_target == right->_ext_target); + assert(left->_ext_budget == right->_ext_budget); + assert(left->_ext_timeout_ms == right->_ext_timeout_ms); + assert(left->_tag == right->_tag); + switch (left->_tag) { + case _Z_REQUEST_QUERY: { + assert_eq_query(&left->_body._query, &right->_body._query); + } break; + case _Z_REQUEST_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_REQUEST_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; + case _Z_REQUEST_PULL: { + assert_eq_source_info(&left->_body._pull._ext_source_info, &right->_body._pull._ext_source_info); + } break; + } +} + +void request_message(void) { + printf("\n>> Request message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_n_msg_request_t expected = gen_request(); + assert(_z_request_encode(&wbf, &expected) == _Z_RES_OK); + _z_n_msg_request_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); + int8_t ret = _z_request_decode(&decoded, &zbf, header); + assert(_Z_RES_OK == ret); + assert_eq_request(&expected, &decoded); + _z_n_msg_request_clear(&decoded); + _z_n_msg_request_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - size_t written = _z_wbuf_len(&fbf); - int8_t res = z_serialize_zenoh_fragment(&wbf, &fbf, is_reliable, sn); - assert(res == _Z_RES_OK); - (void)(res); - written = written - _z_wbuf_len(&fbf); +_z_n_msg_response_t gen_response(void) { + _z_n_msg_response_t ret = { + ._key = gen_keyexpr(), + ._request_id = gen_uint64(), + ._ext_qos = _z_n_qos_make(gen_bool(), gen_bool(), gen_uint8() % 8), + ._ext_timestamp = gen_bool() ? gen_timestamp() : _z_timestamp_null(), + ._ext_responder = {._eid = gen_uint16(), ._zid = gen_zid()}, + }; + switch (gen_uint() % 5) { + 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; + 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; + } + } break; + } + return ret; +} - printf(" -Encoded Fragment: "); - print_wbuf(&wbf); +void assert_eq_response(const _z_n_msg_response_t *left, const _z_n_msg_response_t *right) { + assert_eq_keyexpr(&left->_key, &right->_key); + assert_eq_timestamp(&left->_ext_timestamp, &right->_ext_timestamp); + assert(left->_request_id == right->_request_id); + assert(left->_ext_qos._val == right->_ext_qos._val); + assert(left->_ext_responder._eid == right->_ext_responder._eid); + assert(memcmp(left->_ext_responder._zid.id, right->_ext_responder._zid.id, 16) == 0); + assert(left->_tag == right->_tag); + switch (left->_tag) { + case _Z_RESPONSE_BODY_REPLY: { + assert_eq_reply(&left->_body._reply, &right->_body._reply); + } 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; + } +} + +void response_message(void) { + printf("\n>> Response message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_n_msg_response_t expected = gen_response(); + assert(_z_response_encode(&wbf, &expected) == _Z_RES_OK); + _z_n_msg_response_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); + int8_t ret = _z_response_decode(&decoded, &zbf, header); + assert(_Z_RES_OK == ret); + assert_eq_response(&expected, &decoded); + _z_n_msg_response_clear(&decoded); + _z_n_msg_response_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - // Decode the message - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); +_z_n_msg_response_final_t gen_response_final(void) { return (_z_n_msg_response_final_t){._request_id = gen_uint64()}; } +void assert_eq_response_final(const _z_n_msg_response_final_t *left, const _z_n_msg_response_final_t *right) { + assert(left->_request_id == right->_request_id); +} +void response_final_message(void) { + printf("\n>> Request Final message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_n_msg_response_final_t expected = gen_response_final(); + assert(_z_response_final_encode(&wbf, &expected) == _Z_RES_OK); + _z_n_msg_response_final_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + uint8_t header = _z_zbuf_read(&zbf); + int8_t ret = _z_response_final_decode(&decoded, &zbf, header); + assert(_Z_RES_OK == ret); + assert_eq_response_final(&expected, &decoded); + _z_n_msg_response_final_clear(&decoded); + _z_n_msg_response_final_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - _z_transport_message_t r_sm; - res = _z_transport_message_decode(&r_sm, &zbf); - assert(res == _Z_RES_OK); +_z_transport_message_t gen_join(void) { + _z_conduit_sn_list_t conduit = {._is_qos = gen_bool()}; + if (conduit._is_qos) { + for (int i = 0; i < Z_PRIORITIES_NUM; i++) { + conduit._val._qos[i]._best_effort = gen_uint64(); + conduit._val._qos[i]._reliable = gen_uint64(); + } + } else { + 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); +} +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); + assert(left->_lease == right->_lease); + assert(left->_batch_size == right->_batch_size); + assert(left->_whatami == right->_whatami); + assert(left->_req_id_res == right->_req_id_res); + assert(left->_seq_num_res == right->_seq_num_res); + assert(left->_version == right->_version); + assert(left->_next_sn._is_qos == right->_next_sn._is_qos); + if (left->_next_sn._is_qos) { + for (int i = 0; i < Z_PRIORITIES_NUM; i++) { + assert(left->_next_sn._val._qos[i]._best_effort == right->_next_sn._val._qos[i]._best_effort); + assert(left->_next_sn._val._qos[i]._reliable == right->_next_sn._val._qos[i]._reliable); + } + } else { + assert(left->_next_sn._val._plain._best_effort == right->_next_sn._val._plain._best_effort); + assert(left->_next_sn._val._plain._reliable == right->_next_sn._val._plain._reliable); + } +} +void join_message(void) { + printf("\n>> Join message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_join(); + assert(_z_join_encode(&wbf, expected._header, &expected._body._join) == _Z_RES_OK); + _z_t_msg_join_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_join_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_join(&expected._body._join, &decoded); + _z_t_msg_join_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - _z_bytes_t fragment = r_sm._body._frame._payload._fragment; - printf(" -Decoded Fragment length: %zu\n", fragment.len); - assert(fragment.len == written); +_z_transport_message_t gen_init(void) { + if (gen_bool()) { + return _z_t_msg_make_init_syn(gen_uint8() % 3, gen_zid()); + } else { + return _z_t_msg_make_init_ack(gen_uint8() % 3, gen_zid(), gen_bytes(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(memcmp(left->_zid.id, right->_zid.id, 16) == 0); + assert(left->_version == right->_version); + assert(left->_whatami == right->_whatami); +} +void init_message(void) { + printf("\n>> Init message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_init(); + assert(_z_init_encode(&wbf, expected._header, &expected._body._init) == _Z_RES_OK); + _z_t_msg_init_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_init_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_init(&expected._body._init, &decoded); + _z_t_msg_init_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - // Create an iosli for decoding - _z_wbuf_write_bytes(&dbf, fragment.start, 0, fragment.len); +_z_transport_message_t gen_open(void) { + if (gen_bool()) { + return _z_t_msg_make_open_syn(gen_uint(), gen_uint(), gen_bytes(16)); + } else { + return _z_t_msg_make_open_ack(gen_uint(), gen_uint()); + } +} +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(left->_initial_sn == right->_initial_sn); + assert(left->_lease == right->_lease); +} +void open_message(void) { + printf("\n>> open message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_open(); + assert(_z_open_encode(&wbf, expected._header, &expected._body._open) == _Z_RES_OK); + _z_t_msg_open_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_open_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_open(&expected._body._open, &decoded); + _z_t_msg_open_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - print_wbuf(&dbf); +_z_transport_message_t gen_close(void) { return _z_t_msg_make_close(gen_uint(), gen_bool()); } +void assert_eq_close(const _z_t_msg_close_t *left, const _z_t_msg_close_t *right) { + assert(left->_reason == right->_reason); +} +void close_message(void) { + printf("\n>> close message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_close(); + assert(_z_close_encode(&wbf, expected._header, &expected._body._close) == _Z_RES_OK); + _z_t_msg_close_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_close_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_close(&expected._body._close, &decoded); + _z_t_msg_close_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - // Free the read buffer - _z_zbuf_clear(&zbf); +_z_transport_message_t gen_keep_alive(void) { return _z_t_msg_make_keep_alive(); } +void assert_eq_keep_alive(const _z_t_msg_keep_alive_t *left, const _z_t_msg_keep_alive_t *right) { + (void)left; + (void)right; +} +void keep_alive_message(void) { + printf("\n>> keep_alive message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_keep_alive(); + assert(_z_keep_alive_encode(&wbf, expected._header, &expected._body._keep_alive) == _Z_RES_OK); + _z_t_msg_keep_alive_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_keep_alive_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_keep_alive(&expected._body._keep_alive, &decoded); + _z_t_msg_keep_alive_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} +_z_network_message_t gen_net_msg(void) { + switch (gen_uint8() % 5) { + case 0: { + return gen_declare_message(); + } break; + case 1: { + return (_z_network_message_t){._tag = _Z_N_PUSH, ._body._push = gen_push()}; + } break; + case 2: { + return (_z_network_message_t){._tag = _Z_N_REQUEST, ._body._request = gen_request()}; + } break; + case 3: { + return (_z_network_message_t){._tag = _Z_N_RESPONSE, ._body._response = gen_response()}; + } break; + case 4: + default: { + return (_z_network_message_t){._tag = _Z_N_RESPONSE_FINAL, ._body._response_final = gen_response_final()}; + } break; + } +} +void assert_eq_net_msg(const _z_network_message_t *left, const _z_network_message_t *right) { + assert(left->_tag == right->_tag); + switch (left->_tag) { + case _Z_N_DECLARE: { + assert_eq_declaration(&left->_body._declare._decl, &right->_body._declare._decl); + assert_eq_timestamp(&left->_body._declare._ext_timestamp, &right->_body._declare._ext_timestamp); + assert(left->_body._declare._ext_qos._val == right->_body._declare._ext_qos._val); + } break; + case _Z_N_PUSH: { + assert_eq_push(&left->_body._push, &right->_body._push); + } break; + case _Z_N_REQUEST: { + assert_eq_request(&left->_body._request, &right->_body._request); + } break; + case _Z_N_RESPONSE: { + assert_eq_response(&left->_body._response, &right->_body._response); + } break; + case _Z_N_RESPONSE_FINAL: { + assert_eq_response_final(&left->_body._response_final, &right->_body._response_final); + } 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)); + *msg = gen_net_msg(); + _z_network_message_vec_append(&ret, msg); } + return ret; +} - printf(" - Start defragmenting\n"); - print_wbuf(&dbf); - _z_zbuf_t zbf = _z_wbuf_to_zbuf(&dbf); - printf(" Defragmented: "); - print_iosli(&zbf._ios); - printf("\n"); - - _z_zenoh_message_t d_zm; - int8_t res = _z_zenoh_message_decode(&d_zm, &zbf); - assert(res == _Z_RES_OK); +_z_transport_message_t gen_frame(void) { + return _z_t_msg_make_frame(gen_uint(), 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); + assert(left->_messages._len == right->_messages._len); + for (size_t i = 0; i < left->_messages._len; i++) { + assert_eq_net_msg(left->_messages._val[i], right->_messages._val[i]); + } +} +void frame_message(void) { + printf("\n>> frame message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_frame(); + assert(_z_frame_encode(&wbf, expected._header, &expected._body._frame) == _Z_RES_OK); + _z_t_msg_frame_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_frame_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_frame(&expected._body._frame, &decoded); + _z_t_msg_frame_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - assert_eq_zenoh_message(&e_zm, &d_zm); - _z_msg_clear(&e_zm); - _z_msg_clear(&d_zm); +_z_transport_message_t gen_fragment(void) { + return _z_t_msg_make_fragment(gen_uint(), gen_bytes(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); +} +void fragment_message(void) { + printf("\n>> fragment message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_fragment(); + assert(_z_fragment_encode(&wbf, expected._header, &expected._body._fragment) == _Z_RES_OK); + _z_t_msg_fragment_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_fragment_decode(&decoded, &zbf, expected._header); + assert(_Z_RES_OK == ret); + assert_eq_fragment(&expected._body._fragment, &decoded); + _z_t_msg_fragment_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); +} - _z_wbuf_clear(&dbf); +_z_transport_message_t gen_transport(void) { + switch (gen_uint8() % 7) { + case 0: { + return gen_join(); + }; + case 1: { + return gen_init(); + }; + case 2: { + return gen_open(); + }; + case 3: { + return gen_close(); + }; + case 4: { + return gen_keep_alive(); + }; + case 5: { + return gen_frame(); + }; + case 6: + default: { + return gen_fragment(); + }; + } +} +void assert_eq_transport(const _z_transport_message_t *left, const _z_transport_message_t *right) { + assert(left->_header == right->_header); + switch (_Z_MID(left->_header)) { + case _Z_MID_T_JOIN: { + assert_eq_join(&left->_body._join, &right->_body._join); + } break; + case _Z_MID_T_CLOSE: { + assert_eq_close(&left->_body._close, &right->_body._close); + } break; + case _Z_MID_T_INIT: { + assert_eq_init(&left->_body._init, &right->_body._init); + } break; + case _Z_MID_T_OPEN: { + assert_eq_open(&left->_body._open, &right->_body._open); + } break; + case _Z_MID_T_KEEP_ALIVE: { + assert_eq_keep_alive(&left->_body._keep_alive, &right->_body._keep_alive); + } break; + case _Z_MID_T_FRAME: { + assert_eq_frame(&left->_body._frame, &right->_body._frame); + } break; + case _Z_MID_T_FRAGMENT: { + assert_eq_fragment(&left->_body._fragment, &right->_body._fragment); + } break; + default: + assert(false); + } +} +void transport_message(void) { + printf("\n>> transport message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_transport_message_t expected = gen_transport(); + assert(_z_transport_message_encode(&wbf, &expected) == _Z_RES_OK); + _z_transport_message_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_transport_message_decode(&decoded, &zbf); + assert(_Z_RES_OK == ret); + assert_eq_transport(&expected, &decoded); + _z_t_msg_clear(&decoded); + _z_t_msg_clear(&expected); + _z_zbuf_clear(&zbf); _z_wbuf_clear(&wbf); - _z_wbuf_clear(&fbf); +} + +_z_scouting_message_t gen_scouting(void) { + if (gen_bool()) { + return _z_s_msg_make_scout(gen_uint8() % 3, gen_zid()); + } else { + return _z_s_msg_make_hello(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) { + assert(left->_header == right->_header); + switch (_Z_MID(left->_header)) { + case _Z_MID_SCOUT: { + assert(left->_body._scout._version == right->_body._scout._version); + assert(left->_body._scout._what == right->_body._scout._what); + assert(memcmp(left->_body._scout._zid.id, right->_body._scout._zid.id, 16) == 0); + } break; + case _Z_MID_HELLO: { + assert(left->_body._hello._version == right->_body._hello._version); + assert(left->_body._hello._whatami == right->_body._hello._whatami); + assert(memcmp(left->_body._hello._zid.id, right->_body._hello._zid.id, 16) == 0); + assert_eq_locator_array(&left->_body._hello._locators, &right->_body._hello._locators); + } break; + default: + assert(false); + } +} +void scouting_message(void) { + printf("\n>> scouting message\n"); + _z_wbuf_t wbf = gen_wbuf(UINT16_MAX); + _z_scouting_message_t expected = gen_scouting(); + assert(_z_scouting_message_encode(&wbf, &expected) == _Z_RES_OK); + _z_scouting_message_t decoded; + _z_zbuf_t zbf = _z_wbuf_to_zbuf(&wbf); + int8_t ret = _z_scouting_message_decode(&decoded, &zbf); + assert(_Z_RES_OK == ret); + assert_eq_scouting(&expected, &decoded); + _z_s_msg_clear(&decoded); + _z_s_msg_clear(&expected); _z_zbuf_clear(&zbf); + _z_wbuf_clear(&wbf); } /*=============================*/ @@ -2639,50 +1830,52 @@ int main(void) { for (unsigned int i = 0; i < RUNS; i++) { printf("\n\n== RUN %u", i); + // Message fields payload_field(); timestamp_field(); - subinfo_field(); - res_key_field(); - data_info_field(); - - // Message decorators - attachment_decorator(); - reply_contex_decorator(); + keyexpr_field(); // Zenoh declarations resource_declaration(); - publisher_declaration(); subscriber_declaration(); queryable_declaration(); forget_resource_declaration(); - forget_publisher_declaration(); forget_subscriber_declaration(); forget_queryable_declaration(); // Zenoh messages declare_message(); - data_message(); + push_body_message(); pull_message(); query_message(); - zenoh_message(); + err_message(); + ack_message(); + reply_message(); + + // Network messages + push_message(); + request_message(); + response_message(); + response_final_message(); - // Session messages - scout_message(); - hello_message(); + // Transport messages join_message(); init_message(); open_message(); close_message(); - sync_message(); - ack_nack_message(); keep_alive_message(); - ping_pong_message(); frame_message(); + fragment_message(); transport_message(); - batch(); - fragmentation(); + + // Scouting messages + scouting_message(); } return 0; } + +#if defined(_WIN32) || defined(WIN32) +#pragma warning(pop) +#endif diff --git a/tests/z_peer_multicast_test.c b/tests/z_peer_multicast_test.c index 3c5d29a0a..6d803b67b 100644 --- a/tests/z_peer_multicast_test.c +++ b/tests/z_peer_multicast_test.c @@ -14,10 +14,13 @@ #include #include +#include #include #include #include "zenoh-pico.h" +#include "zenoh-pico/collections/bytes.h" +#include "zenoh-pico/protocol/core.h" #define MSG 10 #define MSG_LEN 1024 @@ -68,7 +71,8 @@ int main(int argc, char **argv) { z_owned_session_t s1 = z_open(z_move(config)); assert(z_check(s1)); - z_string_t zid1 = _z_string_from_bytes(&z_loan(s1)._val->_local_zid); + _z_bytes_t id_as_bytes = _z_bytes_wrap(z_loan(s1)._val->_local_zid.id, _z_id_len(z_loan(s1)._val->_local_zid)); + z_string_t zid1 = _z_string_from_bytes(&id_as_bytes); printf("Session 1 with PID: %s\n", zid1.val); _z_string_clear(&zid1); @@ -84,7 +88,8 @@ int main(int argc, char **argv) { z_owned_session_t s2 = z_open(z_move(config)); assert(z_check(s2)); - z_string_t zid2 = _z_string_from_bytes(&z_loan(s2)._val->_local_zid); + id_as_bytes = _z_bytes_wrap(z_loan(s2)._val->_local_zid.id, _z_id_len(z_loan(s2)._val->_local_zid)); + z_string_t zid2 = _z_string_from_bytes(&id_as_bytes); printf("Session 2 with PID: %s\n", zid2.val); _z_string_clear(&zid2); @@ -103,8 +108,8 @@ int main(int argc, char **argv) { 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: %zu %zu %s\n", z_subscriber_loan(sub)._val->_id, (z_zint_t)0, - s1_res); + printf("Declared subscription on session 2: %ju %zu %s\n", (uintmax_t)z_subscriber_loan(sub)._val->_entity_id, + (z_zint_t)0, s1_res); subs2 = _z_list_push(subs2, sub); } @@ -145,7 +150,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: %zu\n", z_subscriber_loan(sub)._val->_id); + printf("Undeclared subscriber on session 2: %ju\n", (uintmax_t)z_subscriber_loan(sub)._val->_entity_id); z_undeclare_subscriber(z_move(*sub)); subs2 = _z_list_pop(subs2, _z_noop_elem_free, NULL); } diff --git a/zenohpico.pc b/zenohpico.pc new file mode 100644 index 000000000..2827509d3 --- /dev/null +++ b/zenohpico.pc @@ -0,0 +1,8 @@ +prefix=/usr/local + +Name: zenohpico +Description: +URL: +Version: 0.10.20230828dev +Cflags: -I${prefix}/ +Libs: -L${prefix}/ -lzenohpico