Squashed 'external/toxcore/c-toxcore/' changes from e2c01e457b..b03b571272

b03b571272 fix: flaky tcp test This only fixes the symptoms, not the real problem. Sometimes or consistently on some platforms a socket might need a moment before it can be written to.
32e67ab4c2 cleanup: use typedef for private message ID's in callback
7b1db6adc1 feat: add message IDs to private group messages
99e0bcc27d refactor: Observers/ignored peers can now send and receive custom packets
b3c3c49d26 fix: Disable IPv6 in Windows cross-compilation tests
e742deddff feat: Check hashes of Windows dependencies when cross-compiling
dfb9a0b02b fix: Test the current Windows Dockerfile, not an old Dockerhub image
14de93ccec chore: Use WineHQ's Wine as Debian Bookworm's crashes
ed37616249 docs: Update the Windows cross-compilation section
9bb79c174f cleanup: Remove a couple of unnecessary misc_tools dependencies
19475adb70 chore: Statically link OpenMP into the cracker fun util on Windows
1be311e51f feat: Build the fun utils when cross-compiling to Windows
88133f8446 chore: Strip Windows binaries
3cc0ae7535 refactor: Copy over all of the required static dependencies
c4fa8f7fb1 feat: Generate .def, .exp and .lib files when building for Windows
74bbac5363 feat: Let CMake create the dll instead of doing so ourselves
246642e9ae feat: Harden Windows cross-compilation
8d431c0d11 chore: Bump Windows build dependency versions
e519f7998b fix: Remove unnecessary wsock32 dependency on Windows
ed2b60c217 chore: Use a specific non-broken slimcc version.
d7f21010a1 chore: Update github actions.
e71a68b7f2 docs: Update the list of CMake options
77e08876ff chore: Remove mod and founder from group API naming scheme
12bc042767 docs: add the experimental api build option to INSTALL.md
e1fa5cae96 refactor: Rename Queries to Query to align with other enums.
be82a3ea30 fix: Correct type for conference offline peer numbers.
0627c36716 test: Add pkgsrc build.
92578afe4b test: Add FreeBSD VM action on GitHub.
52ece0f57b test: Build toxcore on NetBSD (VM).
3fe8ee2c11 chore: Only install tox_private.h on request.
9a8dfa06ab fix: save_compatibility_test failing on big-endian systems
86f5e55578 fix: Don't serve files from websockify.
710eb674a5 fix: Correctly pass extended public keys to group moderation code.
021db7031c refactor: Use `struct`s for extended public/secret keys.
a1e999fd80 chore: Compile libsodium reference implementation with compcert.
fbe3c19cf5 cleanup: correct a few nullable annotations
623e3ee5c3 cleanup: Don't use `memcpy` to cast arbitrary `struct`s to `uint8_t[]`.
c71567dc18 fix: Pass array, not array pointer, to `memcmp`.
9b46a08144 cleanup: Never pass `void*` directly to `memcpy`.
5d7b7a7bbc refactor: Use tox rng to seed the keypair generation.
961891d568 cleanup: Small improvements found by PVS Studio.
8201019f0d chore: Disable NGC saving by default, enable through Tox_Options.
5dd9ee3f65 cleanup: Replace pointer arithmetic with explicit `&arr[i]`.
ca4606d49d refactor: Use strong typedef for NGC peer id.
442213b722 cleanup: Simplify custom packet length check in NGC.
08d3393def fix: Correct a few potential null derefs in bootstrap daemon.
b9877b32b0 fix: Add missing memunlock of local variable when it goes out of scope.
dab5fe44b9 fix: Zero out stack-allocated secret key before return.
f058103299 refactor: Make prune_gc_sanctions_list more obviously correct.
3ba7a0dec9 docs: Add static analysis tool list to README.
8d0811a0f3 docs: Run prettier-markdown on markdown files.
969e3a2bfc refactor: Fix network test not using the strong typedef
93c83fbc7c refactor: Use strong typedef instead of struct for `Socket`.
9fe18b176f fix: Fix some false positive from PVS Studio.
7c44379ccb cleanup: Check that WINXP macro exists before comparing it.
5c93231bef refactor: Make tox mutex non-recursive.
aacff73939 docs: Fix up doxyfile.
d55fc85ff5 docs: Add more documentation to crypto_core.
5bdaaaedb6 refactor: Remove `Tox *` from `tox_dispatch`.
e202341e76 refactor: Don't rely on tox_dispatch passing tox in tests.
34df938f52 chore: Use C++ mode for clang-tidy.
8b05296a78 chore: Check that both gtest and gmock exist for tests.
42010660e1 test: Add slimcc compiler compatibility test.
b473630321 chore: Add some comments to the astyle config.
b7404f24f6 cleanup: Remove implicit bool conversions.
4e2dba4d9f chore: Reformat sources with astyle.
4359e3a6bc chore: Rename C++ headers to .hh suffixes.
0c05566e58 cleanup: Further `#include` cleanups.
8d29935b7a chore: Only check the bootstrap daemon checksum on release.
f70e588bc6 cleanup: Add more `const` where possible.
511bfe39c8 cleanup: Use Bazel modules to enforce proper `#include` hygiene.
1710a0d091 refactor: Move pack/unpack `IP_Port` from DHT into network module.
a975943564 chore: Really fix coverage docker image build.
c08409390f chore: Fix post-submit coverage image.
39aadf8922 fix: Don't use `memcmp` to compare `IP_Port`s.
d94246a906 fix: partially fix a bug that prevented group part messages from sending.
eeaa039222 chore: Fix rpm build; add a CI check for it.
8328449c1a chore: Speed up docker builds a bit by reducing layer count.
d6d67d56f3 cleanup: Add `const` where possible in auto tests.
6aa9e6850d cleanup: Minor cleanup of event unpack code.
bdf460a3a9 refactor: Rename `system_{memory,...}` to `os_{memory,...}`.
203e1af81e fix: a few off by one errors in group autotests
5c093c4888 cleanup: Remove all uses of `SIZEOF_VLA`.
662c2140f3 test: Add goblint static analyser.
8f07755834 cleanup: Use `memzero(x, s)` instead of `memset(x, 0, s)`.
a7258e40cf cleanup: Use explicit 0 instead of `PACKET_ID_PADDING`.
6370d0f15d cleanup: Expand the `Tox_Options` accessor macros.
14a1a0b9bd cleanup: Remove plan9 support.
a05dccad13 test: Add a simple new/delete test for Tox.
1cdcf938b9 cleanup: Add comment after every `#endif`.
ba99d4dc4b test: Fix comment I broke in the events test PR.
e07248debb refactor: Migrate auto_tests to new events API.
bdd42b5452 refactor: Add common msgpack array packer with callback.
3c659f5288 cleanup: Rename group to conference in groupav documentation.
89957be230 cleanup: Ensure handler params are named after callback params.
c650d9d345 refactor: Pass `this` pointer as first param to s11n callbacks.
e7fb91ddb8 refactor: Allow NULL pointers for byte arrays in events.
5e2c8cabc1 cleanup: make some improvements to group moderation test
259de4867e cleanup: Remove `bin_pack_{new,free}`.
21a8ff5895 cleanup: skip a do_gc iteration before removing peers marked for deletion
16809dc36e feat: Add dht_get_nodes_response event to the events system.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: b03b5712720de9a9901ea12fd741f177327a7021
This commit is contained in:
Green Sky 2024-03-07 23:12:55 +01:00
parent 61accfe184
commit aae086cc65
358 changed files with 8093 additions and 5229 deletions

View File

@ -27,6 +27,7 @@ bazel-dbg_task:
- cd /src/workspace && bazel test -k - cd /src/workspace && bazel test -k
--build_tag_filters=-haskell --build_tag_filters=-haskell
--test_tag_filters=-haskell --test_tag_filters=-haskell
--remote_http_cache=http://$CIRRUS_HTTP_CACHE_HOST
-- --
//c-toxcore/... //c-toxcore/...
-//c-toxcore/auto_tests:tcp_relay_test # TODO(robinlinden): Why does this pass locally but not in Cirrus? -//c-toxcore/auto_tests:tcp_relay_test # TODO(robinlinden): Why does this pass locally but not in Cirrus?
@ -47,13 +48,30 @@ cimple_task:
//c-toxcore/... //c-toxcore/...
freebsd_task: freebsd_task:
container: freebsd_instance:
image: toxchat/freebsd:latest image_family: freebsd-14-0
cpu: 2
memory: 4G
kvm: true
configure_script: configure_script:
- PAGER=cat ASSUME_ALWAYS_YES=YES pkg install
cmake
git
gmake
googletest
libconfig
libsodium
libvpx
opus
pkgconf
- git submodule update --init --recursive - git submodule update --init --recursive
- cd .. && mv cirrus-ci-build /work/c-toxcore && mkdir cirrus-ci-build
test_all_script: test_all_script:
- cd /work/c-toxcore && .github/scripts/cmake-freebsd - |
# TODO(iphydf): Investigate FreeBSD failures on these tests.
sed -Ei -e '/\(dht_getnodes_api\)/s/^/#/' auto_tests/CMakeLists.txt
cmake . \
-DMIN_LOGGER_LEVEL=TRACE \
-DMUST_BUILD_TOXAV=ON \
-DNON_HERMETIC_TESTS=ON \
-DTEST_TIMEOUT_SECONDS=50 \
-DUSE_IPV6=OFF \
-DAUTOTEST=ON
cmake --build . --target install
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6

View File

@ -21,7 +21,7 @@ CheckOptions:
- key: readability-identifier-naming.MacroDefinitionCase - key: readability-identifier-naming.MacroDefinitionCase
value: UPPER_CASE value: UPPER_CASE
- key: readability-identifier-naming.MacroDefinitionIgnoredRegexp - key: readability-identifier-naming.MacroDefinitionIgnoredRegexp
value: "^_.*|nullable|non_null|nullptr|static_assert|ck_.*" value: "^_.*|bitwise|force|nullable|non_null|nullptr|static_assert|ck_.*"
- key: readability-identifier-naming.ParameterCase - key: readability-identifier-naming.ParameterCase
value: lower_case value: lower_case
- key: readability-identifier-naming.StructCase - key: readability-identifier-naming.StructCase
@ -36,12 +36,14 @@ CheckOptions:
value: lower_case value: lower_case
- key: llvmlibc-restrict-system-libc-headers.Includes - key: llvmlibc-restrict-system-libc-headers.Includes
value: "arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h" value: "alloca.h,arpa/inet.h,assert.h,ctype.h,errno.h,fcntl.h,getopt.h,libconfig.h,limits.h,linux/if.h,math.h,netdb.h,netinet/in.h,opus.h,pthread.h,signal.h,sodium/crypto_scalarmult_curve25519.h,sodium.h,sodium/randombytes.h,stdarg.h,stdbool.h,stddef.h,stdint.h,stdio.h,stdlib.h,string.h,sys/ioctl.h,syslog.h,sys/resource.h,sys/socket.h,sys/stat.h,sys/time.h,sys/types.h,time.h,unistd.h,vpx/vp8cx.h,vpx/vp8dx.h,vpx/vpx_decoder.h,vpx/vpx_encoder.h,vpx/vpx_image.h"
- key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals - key: hicpp-signed-bitwise.IgnorePositiveIntegerLiterals
value: true value: true
- key: concurrency-mt-unsafe.FunctionSet - key: concurrency-mt-unsafe.FunctionSet
value: posix value: posix
- key: misc-include-cleaner.IgnoreHeaders
value: "pthread.h;stdbool.h;stddef.h;stdint.;stdint.h;stdint...;cstdint;sodium.*;sys/.*;unistd.h;opus.*;vpx.*;attributes.h;tox_struct.h"
- key: readability-function-cognitive-complexity.Threshold - key: readability-function-cognitive-complexity.Threshold
value: 153 # TODO(iphydf): Decrease. tox_new is the highest at the moment. value: 153 # TODO(iphydf): Decrease. tox_new is the highest at the moment.
- key: cppcoreguidelines-avoid-do-while.IgnoreMacros
value: true
- key: readability-simplify-boolean-expr.SimplifyDeMorgan
value: false

View File

@ -18,7 +18,7 @@ docker run \
-e ENABLE_ARCH_i686="$i686" \ -e ENABLE_ARCH_i686="$i686" \
-e ENABLE_ARCH_x86_64="$x86_64" \ -e ENABLE_ARCH_x86_64="$x86_64" \
-e ENABLE_TEST=true \ -e ENABLE_TEST=true \
-e EXTRA_CMAKE_FLAGS="-DBOOTSTRAP_DAEMON=OFF -DMIN_LOGGER_LEVEL=DEBUG -DTEST_TIMEOUT_SECONDS=90 -DAUTOTEST=ON" \ -e EXTRA_CMAKE_FLAGS="-DBOOTSTRAP_DAEMON=OFF -DMIN_LOGGER_LEVEL=DEBUG -DTEST_TIMEOUT_SECONDS=90 -DAUTOTEST=ON -DUSE_IPV6=OFF" \
-e CMAKE_C_FLAGS="$C_FLAGS" \ -e CMAKE_C_FLAGS="$C_FLAGS" \
-e CMAKE_CXX_FLAGS="$CXX_FLAGS" \ -e CMAKE_CXX_FLAGS="$CXX_FLAGS" \
-e CMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \ -e CMAKE_EXE_LINKER_FLAGS="$LD_FLAGS" \
@ -26,4 +26,6 @@ docker run \
-v "$PWD:/toxcore" \ -v "$PWD:/toxcore" \
-v "$PWD/result:/prefix" \ -v "$PWD/result:/prefix" \
--rm \ --rm \
-t \
--pull never \
"toxchat/windows:$WINDOWS_ARCH" "toxchat/windows:$WINDOWS_ARCH"

View File

@ -3,10 +3,11 @@
set -exu -o pipefail set -exu -o pipefail
LOCAL="${1:-}" LOCAL="${1:-}"
CHECK="${2:-}"
readarray -t FILES <<<"$(git ls-files)" readarray -t FILES <<<"$(git ls-files)"
if ! tar c "${FILES[@]}" | docker build -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then if ! tar c "${FILES[@]}" | docker build --build-arg="CHECK=$CHECK" -f other/bootstrap_daemon/docker/Dockerfile -t toxchat/bootstrap-node - 2>&1 | tee docker-build.log; then
grep -o "::error.*::[a-f0-9]* /usr/local/bin/tox-bootstrapd" docker-build.log grep -o "::error.*::[a-f0-9]* /usr/local/bin/tox-bootstrapd" docker-build.log
false false
fi fi

View File

@ -15,16 +15,24 @@ jobs:
analysis: analysis:
strategy: strategy:
fail-fast: false
matrix: matrix:
tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, infer, misra, tcc, tokstyle] tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, goblint, infer, freebsd, misra, modules, pkgsrc, rpm, slimcc, sparse, tcc, tokstyle]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Docker Build
uses: docker/build-push-action@v4
with: with:
file: other/docker/${{ matrix.tool }}/Dockerfile driver: docker
- name: Build toxchat/c-toxcore:sources
uses: docker/build-push-action@v5
with:
file: other/docker/sources/sources.Dockerfile
tags: toxchat/c-toxcore:sources
- name: Docker Build
uses: docker/build-push-action@v5
with:
file: other/docker/${{ matrix.tool }}/${{ matrix.tool }}.Dockerfile
coverage-linux: coverage-linux:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@ -75,7 +83,7 @@ jobs:
- name: Build and test - name: Build and test
run: .github/scripts/cmake-osx run: .github/scripts/cmake-osx
build-msvc: build-windows-msvc:
strategy: strategy:
matrix: matrix:
version: [2019, 2022] version: [2019, 2022]
@ -102,17 +110,77 @@ jobs:
cd _build cd _build
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 --build-config Debug ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 --build-config Debug
build-windows: build-netbsd:
strategy:
matrix:
bits: [32, 64]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Cross compilation - name: Test in NetBSD
run: .github/scripts/cmake-win${{ matrix.bits }} script id: test
uses: vmactions/netbsd-vm@v1
with:
usesh: true
copyback: false
prepare:
/usr/sbin/pkg_add
cmake
googletest
libconfig
libopus
libsodium
libvpx
pkg-config
run: |
# TODO(iphydf): Investigate NetBSD failures on these tests.
sed -Ei -e '/\((TCP|dht_getnodes_api)\)/s/^/#/' auto_tests/CMakeLists.txt
cmake . \
-DMIN_LOGGER_LEVEL=TRACE \
-DMUST_BUILD_TOXAV=ON \
-DNON_HERMETIC_TESTS=ON \
-DTEST_TIMEOUT_SECONDS=90 \
-DUSE_IPV6=OFF \
-DAUTOTEST=ON
cmake --build . --target install
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
build-freebsd:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Test in FreeBSD
id: test
uses: vmactions/freebsd-vm@v1
with:
usesh: true
copyback: false
prepare:
PAGER=cat ASSUME_ALWAYS_YES=YES pkg install
cmake
git
gmake
googletest
libconfig
libsodium
libvpx
opus
pkgconf
run: |
# TODO(iphydf): Investigate FreeBSD failures on these tests.
sed -Ei -e '/\(dht_getnodes_api\)/s/^/#/' auto_tests/CMakeLists.txt
cmake . \
-DMIN_LOGGER_LEVEL=TRACE \
-DMUST_BUILD_TOXAV=ON \
-DNON_HERMETIC_TESTS=ON \
-DTEST_TIMEOUT_SECONDS=50 \
-DUSE_IPV6=OFF \
-DAUTOTEST=ON
cmake --build . --target install
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
mypy: mypy:
runs-on: ubuntu-latest runs-on: ubuntu-latest

View File

@ -8,7 +8,7 @@ jobs:
latest: latest:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
- name: Install libraries - name: Install libraries

View File

@ -25,7 +25,9 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Docker Build - name: Docker Build
run: .github/scripts/tox-bootstrapd-docker local run: .github/scripts/tox-bootstrapd-docker local "$CHECK"
env:
CHECK: "${{ contains(github.event.pull_request.title, 'chore: Release ') && 'sha256sum' || 'echo' }}"
- name: Push latest image to DockerHub - name: Push latest image to DockerHub
if: ${{ github.event_name == 'push' }} if: ${{ github.event_name == 'push' }}
run: docker push toxchat/bootstrap-node:latest run: docker push toxchat/bootstrap-node:latest
@ -46,7 +48,7 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
context: "{{defaultContext}}:other/bootstrap_daemon/websocket" context: "{{defaultContext}}:other/bootstrap_daemon/websocket"
push: ${{ github.event_name == 'push' }} push: ${{ github.event_name == 'push' }}
@ -67,7 +69,7 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
context: "." context: "."
file: .clusterfuzzlite/Dockerfile file: .clusterfuzzlite/Dockerfile
@ -88,7 +90,7 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
file: testing/Dockerfile file: testing/Dockerfile
push: ${{ github.event_name == 'push' }} push: ${{ github.event_name == 'push' }}
@ -108,7 +110,7 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
file: other/emscripten/Dockerfile file: other/emscripten/Dockerfile
push: ${{ github.event_name == 'push' }} push: ${{ github.event_name == 'push' }}
@ -121,21 +123,14 @@ jobs:
steps: steps:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Login to DockerHub - name: Login to DockerHub
if: ${{ github.event_name == 'push' }} if: ${{ github.event_name == 'push' }}
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build toxchat/c-toxcore:sources
uses: docker/build-push-action@v4
with:
file: other/docker/sources/Dockerfile
tags: toxchat/c-toxcore:sources
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
file: other/docker/esp32/Dockerfile file: other/docker/esp32/Dockerfile
push: ${{ github.event_name == 'push' }} push: ${{ github.event_name == 'push' }}
@ -143,9 +138,15 @@ jobs:
cache-from: type=registry,ref=toxchat/c-toxcore:esp32 cache-from: type=registry,ref=toxchat/c-toxcore:esp32
cache-to: type=inline cache-to: type=inline
docker-win32: docker-windows-mingw:
strategy:
matrix:
bits: [32, 64]
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Login to DockerHub - name: Login to DockerHub
@ -154,39 +155,27 @@ jobs:
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push - name: Build and store to local Docker daemon
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
context: "{{defaultContext}}:other/docker/windows" context: other/docker/windows
push: ${{ github.event_name == 'push' }} load: true
tags: toxchat/windows:win32 tags: toxchat/windows:win${{ matrix.bits }}
cache-from: type=registry,ref=toxchat/windows:win32 cache-from: type=registry,ref=toxchat/windows:win${{ matrix.bits }}
cache-to: type=inline
build-args: | build-args: |
SUPPORT_ARCH_i686=true SUPPORT_ARCH_i686=${{ matrix.bits == '32' }}
SUPPORT_ARCH_x86_64=false SUPPORT_ARCH_x86_64=${{ matrix.bits == '64' }}
SUPPORT_TEST=true SUPPORT_TEST=true
- name: Push the stored image to Dockerhub
docker-win64:
runs-on: ubuntu-latest
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
if: ${{ github.event_name == 'push' }} if: ${{ github.event_name == 'push' }}
uses: docker/login-action@v3 uses: docker/build-push-action@v5
with: with:
username: ${{ secrets.DOCKERHUB_USERNAME }} context: other/docker/windows
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: "{{defaultContext}}:other/docker/windows"
push: ${{ github.event_name == 'push' }} push: ${{ github.event_name == 'push' }}
tags: toxchat/windows:win64 tags: toxchat/windows:win${{ matrix.bits }}
cache-from: type=registry,ref=toxchat/windows:win64
cache-to: type=inline
build-args: | build-args: |
SUPPORT_ARCH_i686=false SUPPORT_ARCH_i686=${{ matrix.bits == '32' }}
SUPPORT_ARCH_x86_64=true SUPPORT_ARCH_x86_64=${{ matrix.bits == '64' }}
SUPPORT_TEST=true SUPPORT_TEST=true
- name: Cross-compile
run: .github/scripts/cmake-win${{ matrix.bits }} script

View File

@ -11,7 +11,7 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Docker Build - name: Docker Build
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
file: other/docker/alpine-s390x/Dockerfile file: other/docker/alpine-s390x/Dockerfile
@ -29,14 +29,14 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build toxchat/c-toxcore:sources - name: Build toxchat/c-toxcore:sources
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
file: other/docker/sources/Dockerfile file: other/docker/sources/sources.Dockerfile
tags: toxchat/c-toxcore:sources tags: toxchat/c-toxcore:sources
- name: Build and push - name: Build and push
uses: docker/build-push-action@v4 uses: docker/build-push-action@v5
with: with:
file: other/docker/coverage/Dockerfile file: other/docker/coverage/coverage.Dockerfile
push: ${{ github.event_name == 'push' }} push: ${{ github.event_name == 'push' }}
tags: toxchat/c-toxcore:coverage tags: toxchat/c-toxcore:coverage
cache-from: type=registry,ref=toxchat/c-toxcore:coverage cache-from: type=registry,ref=toxchat/c-toxcore:coverage

View File

@ -1,20 +1,25 @@
--- ---
exclude: exclude:
- "**/*.api.h" # shfmt doesn't support this file.
# shfmt doesn't support this file
- "other/analysis/run-clang-tidy" - "other/analysis/run-clang-tidy"
# Generated file.
- "CHANGELOG.md"
restylers: restylers:
- astyle: - astyle:
image: restyled/restyler-astyle:d7967bcb8b622a98524b7df1da1b02652114cf9a
arguments: ["--options=other/astyle/astylerc"] arguments: ["--options=other/astyle/astylerc"]
include: include:
- "!**/*.cc" - "**/*.c"
- "**/*.h"
- autopep8 - autopep8
- black - black
- clang-format: - clang-format:
image: restyled/restyler-clang-format:13.0.1 image: restyled/restyler-clang-format:v16.0.6
include: include:
- "**/*.cc" - "**/*.cc"
- "**/*.hh"
- prettier-markdown
- prettier-yaml - prettier-yaml
- reorder-python-imports - reorder-python-imports
- shellharden - shellharden

View File

@ -136,18 +136,20 @@ if(MIN_LOGGER_LEVEL)
endif() endif()
endif() endif()
option(EXPERIMENTAL_API "Install experimental header file with unstable API" OFF)
option(USE_IPV6 "Use IPv6 in tests" ON) option(USE_IPV6 "Use IPv6 in tests" ON)
if(NOT USE_IPV6) if(NOT USE_IPV6)
add_definitions(-DUSE_IPV6=0) add_definitions(-DUSE_IPV6=0)
endif() endif()
option(BUILD_MISC_TESTS "Build additional tests and utilities" OFF) option(BUILD_MISC_TESTS "Build additional tests" OFF)
option(BUILD_FUN_UTILS "Build additional just for fun utilities" OFF) option(BUILD_FUN_UTILS "Build additional just for fun utilities" OFF)
option(AUTOTEST "Enable autotests (mainly for CI)" OFF) option(AUTOTEST "Enable autotests (mainly for CI)" OFF)
if(AUTOTEST) if(AUTOTEST)
option(NON_HERMETIC_TESTS "Whether to build and run tests that depend on an internet connection" OFF) option(NON_HERMETIC_TESTS "Whether to build and run tests that depend on an internet connection" OFF)
option(PROXY_TEST "Enable proxy test (needs HTTP/SOCKS5 proxy on port 8080/8081)" OFF) option(PROXY_TEST "Enable proxy test (requires other/proxy/proxy_server.go to be running)" OFF)
endif() endif()
option(BUILD_TOXAV "Whether to build the tox AV library" ON) option(BUILD_TOXAV "Whether to build the tox AV library" ON)
@ -223,6 +225,8 @@ set(toxcore_SOURCES
toxcore/ccompat.h toxcore/ccompat.h
toxcore/crypto_core.c toxcore/crypto_core.c
toxcore/crypto_core.h toxcore/crypto_core.h
toxcore/crypto_core_pack.c
toxcore/crypto_core_pack.h
toxcore/DHT.c toxcore/DHT.c
toxcore/DHT.h toxcore/DHT.h
toxcore/events/conference_connected.c toxcore/events/conference_connected.c
@ -231,6 +235,7 @@ set(toxcore_SOURCES
toxcore/events/conference_peer_list_changed.c toxcore/events/conference_peer_list_changed.c
toxcore/events/conference_peer_name.c toxcore/events/conference_peer_name.c
toxcore/events/conference_title.c toxcore/events/conference_title.c
toxcore/events/dht_get_nodes_response.c
toxcore/events/events_alloc.c toxcore/events/events_alloc.c
toxcore/events/events_alloc.h toxcore/events/events_alloc.h
toxcore/events/file_chunk_request.c toxcore/events/file_chunk_request.c
@ -356,8 +361,11 @@ set(toxcore_PKGCONFIG_REQUIRES ${toxcore_PKGCONFIG_REQUIRES} libsodium)
set(toxcore_API_HEADERS set(toxcore_API_HEADERS
${toxcore_SOURCE_DIR}/toxcore/tox.h^tox ${toxcore_SOURCE_DIR}/toxcore/tox.h^tox
${toxcore_SOURCE_DIR}/toxcore/tox_events.h^tox ${toxcore_SOURCE_DIR}/toxcore/tox_events.h^tox
${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox ${toxcore_SOURCE_DIR}/toxcore/tox_dispatch.h^tox)
if(EXPERIMENTAL_API)
set(toxcore_API_HEADERS ${toxcore_API_HEADERS}
${toxcore_SOURCE_DIR}/toxcore/tox_private.h^tox) ${toxcore_SOURCE_DIR}/toxcore/tox_private.h^tox)
endif()
################################################################################ ################################################################################
# #
@ -446,7 +454,7 @@ elseif(TARGET Threads::Threads)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads)
endif() endif()
if(WIN32) if(WIN32)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi wsock32 ws2_32) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} iphlpapi ws2_32)
endif() endif()
################################################################################ ################################################################################
@ -526,7 +534,7 @@ endfunction()
# The actual unit tests follow. # The actual unit tests follow.
# #
if(GTEST_FOUND) if(TARGET GTest::gtest AND TARGET GTest::gmock)
unit_test(toxav ring_buffer) unit_test(toxav ring_buffer)
unit_test(toxav rtp) unit_test(toxav rtp)
unit_test(toxcore DHT) unit_test(toxcore DHT)

View File

@ -1,6 +1,8 @@
# Installation instructions # Installation instructions
These instructions will guide you through the process of building and installing the toxcore library and its components, as well as getting already pre-built binaries. These instructions will guide you through the process of building and installing
the toxcore library and its components, as well as getting already pre-built
binaries.
## Table of contents ## Table of contents
@ -30,10 +32,15 @@ These instructions will guide you through the process of building and installing
#### Main #### Main
This repository, although called `toxcore`, in fact contains several libraries besides `toxcore` which complement it, as well as several executables. However, note that although these are separate libraries, at the moment, when building the libraries, they are all merged into a single `toxcore` library. Here is the full list of the main components that can be built using the CMake, their dependencies and descriptions. This repository, although called `toxcore`, in fact contains several libraries
besides `toxcore` which complement it, as well as several executables. However,
note that although these are separate libraries, at the moment, when building
the libraries, they are all merged into a single `toxcore` library. Here is the
full list of the main components that can be built using the CMake, their
dependencies and descriptions.
| Name | Type | Dependencies | Platform | Description | | Name | Type | Dependencies | Platform | Description |
|------------------|------------|------------------------------------|----------------|----------------------------------------------------------------------------| | ---------------- | ---------- | ---------------------------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `toxcore` | Library | libsodium, libm, libpthread, librt | Cross-platform | The main Tox library that provides the messenger functionality. | | `toxcore` | Library | libsodium, libm, libpthread, librt | Cross-platform | The main Tox library that provides the messenger functionality. |
| `toxav` | Library | libtoxcore, libopus, libvpx | Cross-platform | Provides audio/video functionality. | | `toxav` | Library | libtoxcore, libopus, libvpx | Cross-platform | Provides audio/video functionality. |
| `toxencryptsave` | Library | libtoxcore, libsodium | Cross-platform | Provides encryption of Tox profiles (savedata), as well as arbitrary data. | | `toxencryptsave` | Library | libtoxcore, libsodium | Cross-platform | Provides encryption of Tox profiles (savedata), as well as arbitrary data. |
@ -43,24 +50,26 @@ This repository, although called `toxcore`, in fact contains several libraries b
#### Secondary #### Secondary
There are some programs that are not built by default which you might find interesting. You need to pass `-DBUILD_FUN_UTILS=ON` to cmake to build them. There are some programs that are not built by default which you might find
interesting. You need to pass `-DBUILD_FUN_UTILS=ON` to cmake to build them.
##### Vanity key generators ##### Vanity key generators
Can be used to generate vanity Tox Ids or DHT bootstrap node public keys. Can be used to generate vanity Tox Ids or DHT bootstrap node public keys.
| Name | Type | Dependencies | Platform | Description | | Name | Type | Dependencies | Platform | Description |
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ---------------- | ---------- | ----------------- | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `cracker` | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded. | | `cracker` | Executable | libsodium, OpenMP | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Multi-threaded. |
| `cracker_simple` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded. | | `cracker_simple` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which starts with a specified byte sequence. Single-threaded. |
| `strkey` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. | | `strkey` | Executable | libsodium | Cross-platform | Tries to find a curve25519 key pair, hex representation of the public key of which contains a specified byte sequence at a specified or any position at all. Single-threaded. |
##### Key file generators ##### Key file generators
Useful for generating Tox profiles from the output of the vanity key generators, as well as generating random Tox profiles. Useful for generating Tox profiles from the output of the vanity key generators,
as well as generating random Tox profiles.
| Name | Type | Dependencies | Platform | Description | | Name | Type | Dependencies | Platform | Description |
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ------------------------- | ---------- | --------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `make-funny-savefile` | Script | python | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair. | | `make-funny-savefile` | Script | python | Cross-platform | Generates a Tox profile file (savedata file) with the provided key pair. |
| `create_bootstrap_keys` | Executable | libsodium | Cross-platform | Generates a keys file for tox-bootstrapd with either the provided or a random key pair. | | `create_bootstrap_keys` | Executable | libsodium | Cross-platform | Generates a keys file for tox-bootstrapd with either the provided or a random key pair. |
| `create_minimal_savedata` | Executable | libsodium | Cross-platform | Generates a minimal Tox profile file (savedata file) with either the provided or a random key pair, printing the generated Tox Id and secret & public key information. | | `create_minimal_savedata` | Executable | libsodium | Cross-platform | Generates a minimal Tox profile file (savedata file) with either the provided or a random key pair, printing the generated Tox Id and secret & public key information. |
@ -70,7 +79,7 @@ Useful for generating Tox profiles from the output of the vanity key generators,
##### Other ##### Other
| Name | Type | Dependencies | Platform | Description | | Name | Type | Dependencies | Platform | Description |
|---------------------------|------------|-----------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | --------------------- | ---------- | ------------ | -------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `bootstrap_node_info` | Script | python3 | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. | | `bootstrap_node_info` | Script | python3 | Cross-platform | Prints version and Message Of The Day (MOTD) information of the specified DHT bootstrap node, given the node doesn't have those disabled. |
| `sign` | Executable | libsodium | Cross-platform | Signs a file with a ed25519 key. | | `sign` | Executable | libsodium | Cross-platform | Signs a file with a ed25519 key. |
@ -80,56 +89,78 @@ Useful for generating Tox profiles from the output of the vanity key generators,
#### Library dependencies #### Library dependencies
Library dependencies are listed in the [components](#components) table. The dependencies need to be satisfied for the components to be built. Note that if you don't have a dependency for some component, e.g. you don't have `libopus` installed required for building `toxav` component, building of that component is silently disabled. Library dependencies are listed in the [components](#components) table. The
dependencies need to be satisfied for the components to be built. Note that if
you don't have a dependency for some component, e.g. you don't have `libopus`
installed required for building `toxav` component, building of that component is
silently disabled.
Be advised that due to the addition of `cmp` as a submodule, you now also need
Be advised that due to the addition of `cmp` as a submodule, you now also need to initialize the git submodules required by toxcore. This can be done by cloning the repo with the addition of `--recurse-submodules` or by running `git submodule update --init` in the root directory of the repo. to initialize the git submodules required by toxcore. This can be done by
cloning the repo with the addition of `--recurse-submodules` or by running
`git submodule update --init` in the root directory of the repo.
#### Compiler requirements #### Compiler requirements
The supported compilers are GCC, Clang and MinGW. The supported compilers are GCC, Clang and MinGW.
In theory, any compiler that fully supports C99 and accepts GCC flags should work. In theory, any compiler that fully supports C99 and accepts GCC flags should
work.
There is a partial and experimental support of Microsoft Visual C++ compiler. We welcome any patches that help improve it. There is a partial and experimental support of Microsoft Visual C++ compiler. We
welcome any patches that help improve it.
You should have a C99 compatible compiler in order to build the main components. The secondary components might require the compiler to support GNU extensions. You should have a C99 compatible compiler in order to build the main components.
The secondary components might require the compiler to support GNU extensions.
#### Build system requirements #### Build system requirements
To build the main components you need to have CMake of at least 2.8.6 version installed. You also need to have pkg-config installed, the build system uses it to find dependency libraries. To build the main components you need to have CMake of at least 2.8.6 version
installed. You also need to have pkg-config installed, the build system uses it
to find dependency libraries.
There is some experimental accommodation for building natively on Windows, i.e. without having to use MSYS/Cygwin and pkg-config, but it uses exact hardcoded paths for finding libraries and supports building only of some of toxcore components, so your mileage might vary. There is some experimental accommodation for building natively on Windows, i.e.
without having to use MSYS/Cygwin and pkg-config, but it uses exact hardcoded
paths for finding libraries and supports building only of some of toxcore
components, so your mileage might vary.
### CMake options ### CMake options
There are some options that are available to configure the build. There are some options that are available to configure the build.
| Name | Description | Expected Value | Default Value | | Name | Description | Expected Value | Default Value |
|------------------------|-----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|---------------------------------------------------| | ----------------------- | --------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | ------------------------------------------------- |
| `AUTOTEST` | Enable autotests (mainly for CI). | ON or OFF | OFF | | `AUTOTEST` | Enable autotests (mainly for CI). | ON or OFF | OFF |
| `BOOTSTRAP_DAEMON` | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF | ON | | `BOOTSTRAP_DAEMON` | Enable building of tox-bootstrapd, the DHT bootstrap node daemon. For Unix-like systems only. | ON or OFF | ON |
| `BUILD_FUN_UTILS` | Build additional just for fun utilities. | ON or OFF | OFF |
| `BUILD_FUZZ_TESTS` | Build fuzzing harnesses. | ON or OFF | OFF | | `BUILD_FUZZ_TESTS` | Build fuzzing harnesses. | ON or OFF | OFF |
| `BUILD_MISC_TESTS` | Build additional tests. | ON or OFF | OFF | | `BUILD_MISC_TESTS` | Build additional tests. | ON or OFF | OFF |
| `BUILD_FUN_UTILS` | Build additional funny utilities. | ON or OFF | OFF |
| `BUILD_TOXAV` | Whether to build the toxav library. | ON or OFF | ON | | `BUILD_TOXAV` | Whether to build the toxav library. | ON or OFF | ON |
| `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed. | Directory path. | Platform-dependent. Refer to CMake documentation. |
| `CMAKE_BUILD_TYPE` | Specifies the build type on single-configuration generators (e.g. make or ninja). | Debug, Release, RelWithDebInfo, MinSizeRel | Empty string. | | `CMAKE_BUILD_TYPE` | Specifies the build type on single-configuration generators (e.g. make or ninja). | Debug, Release, RelWithDebInfo, MinSizeRel | Empty string. |
| `DHT_BOOTSTRAP` | Enable building of `DHT_bootstrap` | ON or OFF | ON | | `CMAKE_INSTALL_PREFIX` | Path to where everything should be installed. | Directory path. | Platform-dependent. Refer to CMake documentation. |
| `DHT_BOOTSTRAP` | Enable building of `DHT_bootstrap`. | ON or OFF | ON |
| `ENABLE_SHARED` | Build shared (dynamic) libraries for all modules. | ON or OFF | ON | | `ENABLE_SHARED` | Build shared (dynamic) libraries for all modules. | ON or OFF | ON |
| `ENABLE_STATIC` | Build static libraries for all modules. | ON or OFF | ON | | `ENABLE_STATIC` | Build static libraries for all modules. | ON or OFF | ON |
| `EXECUTION_TRACE` | Print a function trace during execution (for debugging). | ON or OFF | OFF | | `EXPERIMENTAL_API` | Install experimental header file with unstable API. | ON or OFF | OFF |
| `FLAT_OUTPUT_STRUCTURE` | Whether to produce output artifacts in {bin,lib}. | ON or OFF | OFF |
| `FULLY_STATIC` | Build fully static executables. | ON or OFF | OFF | | `FULLY_STATIC` | Build fully static executables. | ON or OFF | OFF |
| `MIN_LOGGER_LEVEL` | Logging level to use. | TRACE, DEBUG, INFO, WARNING, ERROR or nothing (empty string) for default. | Empty string. | | `MIN_LOGGER_LEVEL` | Logging level to use. | TRACE, DEBUG, INFO, WARNING, ERROR or nothing (empty string) for default. | Empty string. |
| `MSVC_STATIC_SODIUM` | Whether to link libsodium statically for MSVC. | ON or OFF | OFF | | `MSVC_STATIC_SODIUM` | Whether to link libsodium statically for MSVC. | ON or OFF | OFF |
| `MUST_BUILD_TOXAV` | Fail the build if toxav cannot be built. | ON or OFF | OFF | | `MUST_BUILD_TOXAV` | Fail the build if toxav cannot be built. | ON or OFF | OFF |
| `NON_HERMETIC_TESTS` | Whether to build and run tests that depend on an internet connection. | ON or OFF | OFF | | `NON_HERMETIC_TESTS` | Whether to build and run tests that depend on an internet connection. | ON or OFF | OFF |
| `PROXY_TEST` | Enable proxy test (requires `other/proxy/proxy_server.go` to be running). | ON or OFF | OFF |
| `STRICT_ABI` | Enforce strict ABI export in dynamic libraries. | ON or OFF | OFF | | `STRICT_ABI` | Enforce strict ABI export in dynamic libraries. | ON or OFF | OFF |
| `TEST_TIMEOUT_SECONDS` | Limit runtime of each test to the number of seconds specified. | Positive number or nothing (empty string). | Empty string. | | `TEST_TIMEOUT_SECONDS` | Limit runtime of each test to the number of seconds specified. | Positive number or nothing (empty string). | Empty string. |
| `USE_IPV6` | Use IPv6 in tests. | ON or OFF | ON | | `USE_IPV6` | Use IPv6 in tests. | ON or OFF | ON |
You can get this list of option using the following commands You can get this list of option using the following commands
```sh
cmake -B _build -LAH
```
or
```sh ```sh
grep "option(" CMakeLists.txt cmake/* grep "option(" CMakeLists.txt cmake/*
grep "set(.* CACHE" CMakeLists.txt cmake/* grep "set(.* CACHE" CMakeLists.txt cmake/*
@ -150,11 +181,12 @@ cmake \
``` ```
### Building tests ### Building tests
In addition to the integration tests ("autotests") and miscellaneous tests In addition to the integration tests ("autotests") and miscellaneous tests
enabled by cmake variables described above, there are unit tests which will be enabled by cmake variables described above, there are unit tests which will be
built if the source distribution of gtest (the Google Unit Test framework) is built if the source distribution of gtest (the Google Unit Test framework) is
found by cmake in `c-toxcore/third_party`. This can be achieved by running found by cmake in `c-toxcore/third_party`. This can be achieved by running 'git
'git clone https://github.com/google/googletest` from that directory. clone https://github.com/google/googletest` from that directory.
### Build process ### Build process
@ -170,19 +202,33 @@ make
make install make install
``` ```
or shorter
```sh
cmake -B _build
cmake -B _build --target install
```
#### Windows #### Windows
##### Building on Windows host ##### Building on Windows host
###### Microsoft Visual Studio's Developer Command Prompt ###### Microsoft Visual Studio's Developer Command Prompt
In addition to meeting the [requirements](#requirements), you need a version of Visual Studio (the [community edition](https://www.visualstudio.com/vs/visual-studio-express/) is enough) and a CMake version that's compatible with the Visual Studio version you're using. In addition to meeting the [requirements](#requirements), you need a version of
Visual Studio (the
[community edition](https://www.visualstudio.com/vs/visual-studio-express/) is
enough) and a CMake version that's compatible with the Visual Studio version
you're using.
You must also ensure that the msvc versions of dependencies you're using are placed in the correct folders. You must also ensure that the msvc versions of dependencies you're using are
placed in the correct folders.
For libsodium that is `c-toxcore/third_party/libsodium`, and for pthreads-w32, it's `c-toxcore/third_party/pthreads-win32` For libsodium that is `c-toxcore/third_party/libsodium`, and for pthreads-w32,
it's `c-toxcore/third_party/pthreads-win32`
Once all of this is done, from the **Developer Command Prompt for VS**, simply run Once all of this is done, from the **Developer Command Prompt for VS**, simply
run
``` ```
mkdir _build mkdir _build
@ -193,7 +239,8 @@ msbuild ALL_BUILD.vcxproj
###### MSYS/Cygwin ###### MSYS/Cygwin
Download Cygwin ([32-bit](https://cygwin.com/setup-x86.exe)/[64-bit](https://cygwin.com/setup-x86_64.exe)) Download Cygwin
([32-bit](https://cygwin.com/setup-x86.exe)/[64-bit](https://cygwin.com/setup-x86_64.exe))
Search and select exactly these packages in Devel category: Search and select exactly these packages in Devel category:
@ -221,18 +268,24 @@ set -o igncr
Download toxcore source code and extract it to a folder. Download toxcore source code and extract it to a folder.
Open Cygwin Terminal in the toxcore folder and run `./other/windows_build_script_toxcore.sh` to start the build process. Open Cygwin Terminal in the toxcore folder and run
`./other/windows_build_script_toxcore.sh` to start the build process.
Toxcore build result files will appear in `/root/prefix/` relatively to Cygwin folder (default `C:\cygwin64`). Toxcore build result files will appear in `/root/prefix/` relatively to Cygwin
folder (default `C:\cygwin64`).
Dependency versions can be customized in `./other/windows_build_script_toxcore.sh` and described in the section below.
Dependency versions can be customized in
`./other/windows_build_script_toxcore.sh` and described in the section below.
##### Cross-compiling from Linux ##### Cross-compiling from Linux
These cross-compilation instructions were tested on and written for 64-bit Ubuntu 16.04. You could generalize them for any Linux system, the only requirements are that you have Docker version of >= 1.9.0 and you are running 64-bit system. These cross-compilation instructions were tested on and written for 64-bit
Ubuntu 16.04. You could generalize them for any Linux system, the only
requirements are that you have Docker version of >= 1.9.0 and you are running
64-bit system.
The cross-compilation is fully automated by a parameterized [Dockerfile](/other/docker/windows/Dockerfile). The cross-compilation is fully automated by a parameterized
[Dockerfile](/other/docker/windows/Dockerfile).
Install Docker Install Docker
@ -243,17 +296,18 @@ apt-get install docker.io
Get the toxcore source code and navigate to `other/docker/windows`. Get the toxcore source code and navigate to `other/docker/windows`.
Build the container image based on the Dockerfile. The following options are available to customize the building of the container image. Build the container image based on the Dockerfile. The following options are
available to customize the building of the container image.
| Name | Description | Expected Value | Default Value | | Name | Description | Expected Value | Default Value |
|-----------------------|----------------------------------------------------------------|-------------------------------------|---------------| | -------------------------- | ----------------------------------------------------- | ----------------------------------- | ------------- |
| `SUPPORT_ARCH_i686` | Support building 32-bit toxcore. | "true" or "false" (case sensitive). | true | | `SUPPORT_ARCH_i686` | Support building 32-bit toxcore. | "true" or "false" (case sensitive). | true |
| `SUPPORT_ARCH_x86_64` | Support building 64-bit toxcore. | "true" or "false" (case sensitive). | true | | `SUPPORT_ARCH_x86_64` | Support building 64-bit toxcore. | "true" or "false" (case sensitive). | true |
| `SUPPORT_TEST` | Support running toxcore automated tests. | "true" or "false" (case sensitive). | false | | `SUPPORT_TEST` | Support running toxcore automated tests. | "true" or "false" (case sensitive). | false |
| `CROSS_COMPILE` | Cross-compiling. True for Docker, false for Cygwin. | "true" or "false" (case sensitive). | true | | `VERSION_OPUS` | Version of libopus to build toxcore with. | Numeric version number. | 1.4 |
| `VERSION_OPUS` | Version of libopus to build toxcore with. | Numeric version number. | 1.3.1 | | `VERSION_SODIUM` | Version of libsodium to build toxcore with. | Numeric version number. | 1.0.19 |
| `VERSION_SODIUM` | Version of libsodium to build toxcore with. | Numeric version number. | 1.0.18 | | `VERSION_VPX` | Version of libvpx to build toxcore with. | Numeric version number. | 1.14.0 |
| `VERSION_VPX` | Version of libvpx to build toxcore with. | Numeric version number. | 1.11.0 | | `ENABLE_HASH_VERIFICATION` | Verify the hashes of the default dependency versions. | "true" or "false" (case sensitive). | true |
Example of building a container image with options Example of building a container image with options
@ -265,16 +319,16 @@ docker build \
. .
``` ```
Run the container to build toxcore. The following options are available to customize the running of the container image. Run the container to build toxcore. The following options are available to
customize the running of the container image.
| Name | Description | Expected Value | Default Value | | Name | Description | Expected Value | Default Value |
|----------------------|--------------------------------------------------------------------------------------------|-------------------------------------|--------------------------------------------------------------------| | -------------------- | ------------------------------------------------------------------------------------------ | ----------------------------------- | ------------------------------------------ |
| `ALLOW_TEST_FAILURE` | Don't stop if a test suite fails. | "true" or "false" (case sensitive). | `false` | | `ALLOW_TEST_FAILURE` | Don't stop if a test suite fails. | "true" or "false" (case sensitive). | `false` |
| `ENABLE_ARCH_i686` | Build 32-bit toxcore. The image should have been built with `SUPPORT_ARCH_i686` enabled. | "true" or "false" (case sensitive). | `true` | | `ENABLE_ARCH_i686` | Build 32-bit toxcore. The image should have been built with `SUPPORT_ARCH_i686` enabled. | "true" or "false" (case sensitive). | `true` |
| `ENABLE_ARCH_x86_64` | Build 64-bit toxcore. The image should have been built with `SUPPORT_ARCH_x86_64` enabled. | "true" or "false" (case sensitive). | `true` | | `ENABLE_ARCH_x86_64` | Build 64-bit toxcore. The image should have been built with `SUPPORT_ARCH_x86_64` enabled. | "true" or "false" (case sensitive). | `true` |
| `ENABLE_TEST` | Run the test suite. The image should have been built with `SUPPORT_TEST` enabled. | "true" or "false" (case sensitive). | `false` | | `ENABLE_TEST` | Run the test suite. The image should have been built with `SUPPORT_TEST` enabled. | "true" or "false" (case sensitive). | `false` |
| `EXTRA_CMAKE_FLAGS` | Extra arguments to pass to the CMake command when building toxcore. | CMake options. | `-DTEST_TIMEOUT_SECONDS=90` | | `EXTRA_CMAKE_FLAGS` | Extra arguments to pass to the CMake command when building toxcore. | CMake options. | `-DTEST_TIMEOUT_SECONDS=90 -DUSE_IPV6=OFF` |
| `CROSS_COMPILE` | Cross-compiling. True for Docker, false for Cygwin. | "true" or "false" (case sensitive). | `true` |
Example of running the container with options Example of running the container with options
@ -284,14 +338,117 @@ docker run \
-e ALLOW_TEST_FAILURE=true \ -e ALLOW_TEST_FAILURE=true \
-v /path/to/toxcore/sourcecode:/toxcore \ -v /path/to/toxcore/sourcecode:/toxcore \
-v /path/to/where/output/build/result:/prefix \ -v /path/to/where/output/build/result:/prefix \
-t \
--rm \ --rm \
toxcore toxcore
``` ```
After the build succeeds, you should see the built toxcore libraries in `/path/to/where/output/build/result`. After the build succeeds, you should see the built toxcore libraries in
`/path/to/where/output/build/result`.
The file structure should look similar to the following
```
result
├── [4.0K] i686
│   ├── [ 36K] bin
│   │   ├── [636K] DHT_bootstrap.exe
│   │   ├── [572K] cracker.exe
│   │   ├── [359K] cracker_simple.exe
│   │   ├── [378K] create_bootstrap_keys.exe
│   │   ├── [378K] create_minimal_savedata.exe
│   │   ├── [958K] create_savedata.exe
│   │   ├── [ 18K] libtoxcore.def
│   │   ├── [2.6M] libtoxcore.dll
│   │   ├── [ 65K] libtoxcore.exp
│   │   ├── [428K] libtoxcore.lib
│   │   ├── [989K] save-generator.exe
│   │   ├── [381K] sign.exe
│   │   └── [408K] strkey.exe
│   ├── [4.0K] include
│   │   └── [4.0K] tox
│   │   ├── [177K] tox.h
│   │   ├── [ 10K] tox_dispatch.h
│   │   ├── [ 26K] tox_events.h
│   │   ├── [6.4K] tox_private.h
│   │   ├── [ 26K] toxav.h
│   │   └── [ 12K] toxencryptsave.h
│   └── [4.0K] lib
│   ├── [577K] libopus.a
│   ├── [660K] libsodium.a
│   ├── [ 10K] libssp.a
│   ├── [1016K] libtoxcore.a
│   ├── [456K] libtoxcore.dll.a
│   ├── [2.7M] libvpx.a
│   ├── [ 72K] libwinpthread.a
│   └── [4.0K] pkgconfig
│   ├── [ 250] libsodium.pc
│   ├── [ 357] opus.pc
│   ├── [ 247] toxcore.pc
│   └── [ 309] vpx.pc
└── [4.0K] x86_64
├── [ 36K] bin
│   ├── [504K] DHT_bootstrap.exe
│   ├── [474K] cracker.exe
│   ├── [277K] cracker_simple.exe
│   ├── [287K] create_bootstrap_keys.exe
│   ├── [288K] create_minimal_savedata.exe
│   ├── [769K] create_savedata.exe
│   ├── [ 18K] libtoxcore.def
│   ├── [2.4M] libtoxcore.dll
│   ├── [ 64K] libtoxcore.exp
│   ├── [420K] libtoxcore.lib
│   ├── [800K] save-generator.exe
│   ├── [289K] sign.exe
│   └── [317K] strkey.exe
├── [4.0K] include
│   └── [4.0K] tox
│   ├── [177K] tox.h
│   ├── [ 10K] tox_dispatch.h
│   ├── [ 26K] tox_events.h
│   ├── [6.4K] tox_private.h
│   ├── [ 26K] toxav.h
│   └── [ 12K] toxencryptsave.h
└── [4.0K] lib
├── [697K] libopus.a
├── [575K] libsodium.a
├── [ 11K] libssp.a
├── [905K] libtoxcore.a
├── [449K] libtoxcore.dll.a
├── [2.9M] libvpx.a
├── [ 68K] libwinpthread.a
└── [4.0K] pkgconfig
├── [ 252] libsodium.pc
├── [ 359] opus.pc
├── [ 249] toxcore.pc
└── [ 311] vpx.pc
12 directories, 60 files
```
- `libtoxcore.dll` is the shared library. It is fully self-contained, with no
additional dependencies aside from the Windows OS dlls, and can be used in
MSVC, MinGW, Clang, etc. projects. Despite its name, it provides toxcore,
toxav, toxencryptsave -- all of Tox.
- `libtoxcore.a` is the static library. In order to use it, it needs to be
linked against the other provided .a libraries (but not the .dll.a!) and
additionally -liphlpapi and -lws2_32 Windows dlls. It similarly provides all
of Tox APIs.
- `libtoxcore.dll.a` is the MinGW import library for `libtoxcore.dll`.
- `libtoxcore.lib` is the MSVC import library for `libtoxcore.dll`.
- `libtoxcore.exp` and `libtoxcore.def` are the exported by `libtoxcore`
symbols.
- `*.exe` are statically compiled executables -- `DHT_bootstrap` and
[the fun utils](#secondary).
## Pre-built binaries ## Pre-built binaries
### Linux ### Linux
Toxcore is packaged by at least by the following distributions: ALT Linux, [Arch Linux](https://www.archlinux.org/packages/?q=toxcore), [Fedora](https://apps.fedoraproject.org/packages/toxcore), Mageia, openSUSE, PCLinuxOS, ROSA and Slackware, [according to the information from pkgs.org](https://pkgs.org/download/toxcore). Note that this list might be incomplete and some other distributions might package it too. Toxcore is packaged by at least by the following distributions: ALT Linux,
[Arch Linux](https://www.archlinux.org/packages/?q=toxcore),
[Fedora](https://apps.fedoraproject.org/packages/toxcore), Mageia, openSUSE,
PCLinuxOS, ROSA and Slackware,
[according to the information from pkgs.org](https://pkgs.org/download/toxcore).
Note that this list might be incomplete and some other distributions might
package it too.

View File

@ -1,8 +1,14 @@
# ![Project Tox](https://raw.github.com/TokTok/c-toxcore/master/other/tox.png "Project Tox") # ![Project Tox](https://raw.github.com/TokTok/c-toxcore/master/other/tox.png "Project Tox")
**Current Coverage:** [![coverage](https://codecov.io/gh/TokTok/c-toxcore/branch/master/graph/badge.svg?token=BRfCKo02De)](https://codecov.io/gh/TokTok/c-toxcore) **Current Coverage:**
[![coverage](https://codecov.io/gh/TokTok/c-toxcore/branch/master/graph/badge.svg?token=BRfCKo02De)](https://codecov.io/gh/TokTok/c-toxcore)
[**Website**](https://tox.chat) **|** [**Wiki**](https://wiki.tox.chat/) **|** [**Blog**](https://blog.tox.chat/) **|** [**FAQ**](https://wiki.tox.chat/doku.php?id=users:faq) **|** [**Binaries/Downloads**](https://tox.chat/download.html) **|** [**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|** [**Compiling**](/INSTALL.md) [**Website**](https://tox.chat) **|** [**Wiki**](https://wiki.tox.chat/) **|**
[**Blog**](https://blog.tox.chat/) **|**
[**FAQ**](https://wiki.tox.chat/doku.php?id=users:faq) **|**
[**Binaries/Downloads**](https://tox.chat/download.html) **|**
[**Clients**](https://wiki.tox.chat/doku.php?id=clients) **|**
[**Compiling**](/INSTALL.md)
## What is Tox ## What is Tox
@ -16,20 +22,20 @@ and privacy easy to obtain for regular users. It uses
### ![Danger: Experimental](other/tox-warning.png) ### ![Danger: Experimental](other/tox-warning.png)
This is an **experimental** cryptographic network library. It has not been This is an **experimental** cryptographic network library. It has not been
formally audited by an independent third party that specializes in formally audited by an independent third party that specializes in cryptography
cryptography or cryptanalysis. **Use this library at your own risk.** or cryptanalysis. **Use this library at your own risk.**
The underlying crypto library [libsodium](https://doc.libsodium.org/) provides The underlying crypto library [libsodium](https://doc.libsodium.org/) provides
reliable encryption, but the security model has not yet been fully specified. reliable encryption, but the security model has not yet been fully specified.
See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for a See [issue 210](https://github.com/TokTok/c-toxcore/issues/210) for a discussion
discussion on developing a threat model. See other issues for known weaknesses on developing a threat model. See other issues for known weaknesses (e.g.
(e.g. [issue 426](https://github.com/TokTok/c-toxcore/issues/426) describes [issue 426](https://github.com/TokTok/c-toxcore/issues/426) describes what can
what can happen if your secret key is stolen). happen if your secret key is stolen).
## Toxcore Development Roadmap ## Toxcore Development Roadmap
The roadmap and changelog are generated from GitHub issues. You may view them The roadmap and changelog are generated from GitHub issues. You may view them on
on the website, where they are updated at least once every 24 hours: the website, where they are updated at least once every 24 hours:
- Changelog: https://toktok.ltd/changelog/c-toxcore - Changelog: https://toktok.ltd/changelog/c-toxcore
- Roadmap: https://toktok.ltd/roadmap/c-toxcore - Roadmap: https://toktok.ltd/roadmap/c-toxcore
@ -38,7 +44,11 @@ on the website, where they are updated at least once every 24 hours:
Detailed installation instructions can be found in [INSTALL.md](INSTALL.md). Detailed installation instructions can be found in [INSTALL.md](INSTALL.md).
Be advised that due to the addition of `cmp` as a submodule, you now also need to initialize the git submodules required by toxcore. This can be done by cloning the repo with the following command: `git clone --recurse-submodules https://github.com/Toktok/c-toxcore` or by running `git submodule update --init` in the root directory of the repo. Be advised that due to the addition of `cmp` as a submodule, you now also need
to initialize the git submodules required by toxcore. This can be done by
cloning the repo with the following command:
`git clone --recurse-submodules https://github.com/Toktok/c-toxcore` or by
running `git submodule update --init` in the root directory of the repo.
In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium) In a nutshell, if you have [libsodium](https://github.com/jedisct1/libsodium)
installed, run: installed, run:
@ -74,17 +84,17 @@ if (err_new != TOX_ERR_NEW_OK) {
} }
``` ```
Here, we simply exit the program, but in a real client you will probably want Here, we simply exit the program, but in a real client you will probably want to
to do some error handling and proper error reporting to the user. The `NULL` do some error handling and proper error reporting to the user. The `NULL`
argument given to the first parameter of `tox_new` is the `Tox_Options`. It argument given to the first parameter of `tox_new` is the `Tox_Options`. It
contains various write-once network settings and allows you to load a contains various write-once network settings and allows you to load a previously
previously serialised instance. See [toxcore/tox.h](tox.h) for details. serialised instance. See [toxcore/tox.h](tox.h) for details.
### Setting up callbacks ### Setting up callbacks
Toxcore works with callbacks that you can register to listen for certain Toxcore works with callbacks that you can register to listen for certain events.
events. Examples of such events are "friend request received" or "friend sent Examples of such events are "friend request received" or "friend sent a
a message". Search the API for `tox_callback_*` to find all of them. message". Search the API for `tox_callback_*` to find all of them.
Here, we will set up callbacks for receiving friend requests and receiving Here, we will set up callbacks for receiving friend requests and receiving
messages. We will always accept any friend request (because we're a bot), and messages. We will always accept any friend request (because we're a bot), and
@ -172,3 +182,24 @@ the API documentation in [toxcore/tox.h](toxcore/tox.h) for more information.
- [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot) - [Another echo bot](https://wiki.tox.chat/developers/client_examples/echo_bot)
- [minitox](https://github.com/hqwrong/minitox) (A minimal tox client) - [minitox](https://github.com/hqwrong/minitox) (A minimal tox client)
## SAST Tools
This project uses various tools supporting Static Application Security Testing:
- [clang-tidy](https://clang.llvm.org/extra/clang-tidy/): A clang-based C++
"linter" tool.
- [Coverity](https://scan.coverity.com/): A cloud-based static analyzer service
for Java, C/C++, C#, JavaScript, Ruby, or Python that is free for open source
projects.
- [cppcheck](https://cppcheck.sourceforge.io/): A static analyzer for C/C++
code.
- [cpplint](https://github.com/cpplint/cpplint): Static code checker for C++
- [goblint](https://goblint.in.tum.de/): A static analyzer for multi-threaded C
programs, specializing in finding concurrency bugs.
- [infer](https://github.com/facebook/infer): A static analyzer for Java, C,
C++, and Objective-C.
- [PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=website&utm_medium=github&utm_campaign=open_source):
A static analyzer for C, C++, C#, and Java code.
- [tokstyle](https://github.com/TokTok/hs-tokstyle): A style checker for TokTok
C projects.

View File

@ -17,6 +17,8 @@ cc_library(
"//c-toxcore/toxcore:Messenger", "//c-toxcore/toxcore:Messenger",
"//c-toxcore/toxcore:mono_time", "//c-toxcore/toxcore:mono_time",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_dispatch",
"//c-toxcore/toxcore:tox_events",
], ],
) )

View File

@ -240,6 +240,7 @@ endif
EXTRA_DIST += \ EXTRA_DIST += \
$(top_srcdir)/auto_tests/data/save.tox \ $(top_srcdir)/auto_tests/data/save.tox.big \
$(top_srcdir)/auto_tests/data/save.tox.little \
$(top_srcdir)/auto_tests/check_compat.h \ $(top_srcdir)/auto_tests/check_compat.h \
$(top_srcdir)/auto_tests/auto_test_support.h $(top_srcdir)/auto_tests/auto_test_support.h

View File

@ -45,11 +45,11 @@ static uint16_t ports[NUM_PORTS] = {13215, 33445, 25643};
static void test_basic(void) static void test_basic(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
@ -266,13 +266,14 @@ static void kill_tcp_con(struct sec_TCP_con *con)
static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data, static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP_con *con, const uint8_t *data,
uint16_t length) uint16_t length)
{ {
VLA(uint8_t, packet, sizeof(uint16_t) + length + CRYPTO_MAC_SIZE); const uint16_t packet_size = sizeof(uint16_t) + length + CRYPTO_MAC_SIZE;
VLA(uint8_t, packet, packet_size);
uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE); uint16_t c_length = net_htons(length + CRYPTO_MAC_SIZE);
memcpy(packet, &c_length, sizeof(uint16_t)); memcpy(packet, &c_length, sizeof(uint16_t));
int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t)); int len = encrypt_data_symmetric(con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
if ((unsigned int)len != (SIZEOF_VLA(packet) - sizeof(uint16_t))) { if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
return -1; return -1;
} }
@ -282,7 +283,7 @@ static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP
localhost.ip = get_loopback(); localhost.ip = get_loopback();
localhost.port = 0; localhost.port = 0;
ck_assert_msg(net_send(con->ns, logger, con->sock, packet, SIZEOF_VLA(packet), &localhost) == SIZEOF_VLA(packet), ck_assert_msg(net_send(con->ns, logger, con->sock, packet, packet_size, &localhost) == packet_size,
"Failed to send a packet."); "Failed to send a packet.");
return 0; return 0;
} }
@ -303,11 +304,11 @@ static int read_packet_sec_tcp(const Logger *logger, struct sec_TCP_con *con, ui
static void test_some(void) static void test_some(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
@ -498,11 +499,11 @@ static int oob_data_callback(void *object, const uint8_t *public_key, const uint
static void test_client(void) static void test_client(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Logger *logger = logger_new(); Logger *logger = logger_new();
@ -524,8 +525,9 @@ static void test_client(void)
ip_port_tcp_s.ip = get_loopback(); ip_port_tcp_s.ip = get_loopback();
TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr);
do_tcp_connection(logger, mono_time, conn, nullptr); // TCP sockets might need a moment before they can be written to.
c_sleep(50); c_sleep(50);
do_tcp_connection(logger, mono_time, conn, nullptr);
// The connection status should be unconfirmed here because we have finished // The connection status should be unconfirmed here because we have finished
// sending our data and are awaiting a response. // sending our data and are awaiting a response.
@ -559,6 +561,7 @@ static void test_client(void)
ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key, TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key,
f2_secret_key, nullptr); f2_secret_key, nullptr);
c_sleep(50);
// The client should call this function (defined earlier) during the routing process. // The client should call this function (defined earlier) during the routing process.
routing_response_handler(conn, response_callback, (char *)conn + 2); routing_response_handler(conn, response_callback, (char *)conn + 2);
@ -581,7 +584,7 @@ static void test_client(void)
do_tcp_connection(logger, mono_time, conn2, nullptr); do_tcp_connection(logger, mono_time, conn2, nullptr);
c_sleep(50); c_sleep(50);
uint8_t data[5] = {1, 2, 3, 4, 5}; const uint8_t data[5] = {1, 2, 3, 4, 5};
memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(oob_pubkey, f2_public_key, CRYPTO_PUBLIC_KEY_SIZE);
send_oob_packet(logger, conn2, f_public_key, data, 5); send_oob_packet(logger, conn2, f_public_key, data, 5);
send_routing_request(logger, conn, f2_public_key); send_routing_request(logger, conn, f2_public_key);
@ -632,11 +635,11 @@ static void test_client(void)
// Test how the client handles servers that don't respond. // Test how the client handles servers that don't respond.
static void test_client_invalid(void) static void test_client_invalid(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
@ -708,14 +711,13 @@ static int tcp_data_callback(void *object, int id, const uint8_t *data, uint16_t
return 0; return 0;
} }
static void test_tcp_connection(void) static void test_tcp_connection(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
@ -824,11 +826,11 @@ static int tcp_oobdata_callback(void *object, const uint8_t *public_key, unsigne
static void test_tcp_connection2(void) static void test_tcp_connection2(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);

View File

@ -13,7 +13,7 @@
static void test_bucketnum(void) static void test_bucketnum(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
uint8_t key1[CRYPTO_PUBLIC_KEY_SIZE], key2[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t key1[CRYPTO_PUBLIC_KEY_SIZE], key2[CRYPTO_PUBLIC_KEY_SIZE];
random_bytes(rng, key1, sizeof(key1)); random_bytes(rng, key1, sizeof(key1));
@ -50,11 +50,11 @@ static void test_announce_data(void *object, const uint8_t *data, uint16_t lengt
static void test_store_data(void) static void test_store_data(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Logger *log = logger_new(); Logger *log = logger_new();
@ -120,7 +120,6 @@ static void basic_announce_tests(void)
test_store_data(); test_store_data();
} }
int main(void) int main(void)
{ {
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);

View File

@ -5,6 +5,8 @@
#include "../testing/misc_tools.h" #include "../testing/misc_tools.h"
#include "../toxcore/Messenger.h" #include "../toxcore/Messenger.h"
#include "../toxcore/mono_time.h" #include "../toxcore/mono_time.h"
#include "../toxcore/tox_dispatch.h"
#include "../toxcore/tox_events.h"
#include "../toxcore/tox_struct.h" #include "../toxcore/tox_struct.h"
#include "auto_test_support.h" #include "auto_test_support.h"
@ -23,6 +25,7 @@ Run_Auto_Options default_run_auto_options(void)
.graph = GRAPH_COMPLETE, .graph = GRAPH_COMPLETE,
.init_autotox = nullptr, .init_autotox = nullptr,
.tcp_port = 33188, .tcp_port = 33188,
.events = true,
}; };
} }
@ -131,7 +134,15 @@ void iterate_all_wait(AutoTox *autotoxes, uint32_t tox_count, uint32_t wait)
for (uint32_t i = 0; i < tox_count; ++i) { for (uint32_t i = 0; i < tox_count; ++i) {
if (autotoxes[i].alive) { if (autotoxes[i].alive) {
if (autotoxes[i].events) {
Tox_Err_Events_Iterate err;
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
tox_events_free(events);
} else {
tox_iterate(autotoxes[i].tox, &autotoxes[i]); tox_iterate(autotoxes[i].tox, &autotoxes[i]);
}
autotoxes[i].clock += wait; autotoxes[i].clock += wait;
} }
} }
@ -181,6 +192,7 @@ void kill_autotox(AutoTox *autotox)
ck_assert(autotox->alive); ck_assert(autotox->alive);
fprintf(stderr, "Killing #%u\n", autotox->index); fprintf(stderr, "Killing #%u\n", autotox->index);
autotox->alive = false; autotox->alive = false;
tox_dispatch_free(autotox->dispatch);
tox_kill(autotox->tox); tox_kill(autotox->tox);
} }
@ -202,6 +214,11 @@ void reload(AutoTox *autotox)
tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size); tox_options_set_savedata_data(options, autotox->save_state, autotox->save_size);
autotox->tox = tox_new_log(options, nullptr, &autotox->index); autotox->tox = tox_new_log(options, nullptr, &autotox->index);
ck_assert(autotox->tox != nullptr); ck_assert(autotox->tox != nullptr);
autotox->dispatch = tox_dispatch_new(nullptr);
ck_assert(autotox->dispatch != nullptr);
if (autotox->events) {
tox_events_init(autotox->tox);
}
tox_options_free(options); tox_options_free(options);
set_mono_time_callback(autotox); set_mono_time_callback(autotox);
@ -212,6 +229,7 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
Run_Auto_Options *autotest_opts) Run_Auto_Options *autotest_opts)
{ {
autotox->index = index; autotox->index = index;
autotox->events = autotest_opts->events;
Tox_Err_New err = TOX_ERR_NEW_OK; Tox_Err_New err = TOX_ERR_NEW_OK;
@ -259,6 +277,12 @@ static void initialise_autotox(struct Tox_Options *options, AutoTox *autotox, ui
set_mono_time_callback(autotox); set_mono_time_callback(autotox);
autotox->dispatch = tox_dispatch_new(nullptr);
ck_assert(autotox->dispatch != nullptr);
if (autotox->events) {
tox_events_init(autotox->tox);
}
autotox->alive = true; autotox->alive = true;
autotox->save_state = nullptr; autotox->save_state = nullptr;
@ -311,7 +335,7 @@ static void initialise_friend_graph(Graph_Type graph, uint32_t num_toxes, AutoTo
} }
} }
static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts, static void bootstrap_autotoxes(const Tox_Options *options, uint32_t tox_count, const Run_Auto_Options *autotest_opts,
AutoTox *autotoxes) AutoTox *autotoxes)
{ {
const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true; const bool udp_enabled = options != nullptr ? tox_options_get_udp_enabled(options) : true;
@ -339,7 +363,9 @@ static void bootstrap_autotoxes(struct Tox_Options *options, uint32_t tox_count,
} }
} }
void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(AutoTox *autotoxes), typedef void autotox_test_cb(AutoTox *autotoxes);
void run_auto_test(struct Tox_Options *options, uint32_t tox_count, autotox_test_cb *test,
uint32_t state_size, Run_Auto_Options *autotest_opts) uint32_t state_size, Run_Auto_Options *autotest_opts)
{ {
printf("initialising %u toxes\n", tox_count); printf("initialising %u toxes\n", tox_count);
@ -371,6 +397,7 @@ void run_auto_test(struct Tox_Options *options, uint32_t tox_count, void test(Au
test(autotoxes); test(autotoxes);
for (uint32_t i = 0; i < tox_count; ++i) { for (uint32_t i = 0; i < tox_count; ++i) {
tox_dispatch_free(autotoxes[i].dispatch);
tox_kill(autotoxes[i].tox); tox_kill(autotoxes[i].tox);
free(autotoxes[i].state); free(autotoxes[i].state);
free(autotoxes[i].save_state); free(autotoxes[i].save_state);
@ -417,7 +444,6 @@ void print_debug_log(Tox *m, Tox_Log_Level level, const char *file, uint32_t lin
} }
} }
void print_debug_logger(void *context, Logger_Level level, const char *file, int line, const char *func, const char *message, void *userdata) void print_debug_logger(void *context, Logger_Level level, const char *file, int line, const char *func, const char *message, void *userdata)
{ {
print_debug_log(nullptr, (Tox_Log_Level) level, file, (uint32_t) line, func, message, userdata); print_debug_log(nullptr, (Tox_Log_Level) level, file, (uint32_t) line, func, message, userdata);
@ -455,4 +481,3 @@ Tox *tox_new_log(struct Tox_Options *options, Tox_Err_New *err, void *log_user_d
{ {
return tox_new_log_lan(options, err, log_user_data, false); return tox_new_log_lan(options, err, log_user_data, false);
} }

View File

@ -7,9 +7,11 @@
#include "../testing/misc_tools.h" #include "../testing/misc_tools.h"
#include "../toxcore/Messenger.h" #include "../toxcore/Messenger.h"
#include "../toxcore/mono_time.h" #include "../toxcore/mono_time.h"
#include "../toxcore/tox_dispatch.h"
typedef struct AutoTox { typedef struct AutoTox {
Tox *tox; Tox *tox;
Tox_Dispatch *dispatch;
uint32_t index; uint32_t index;
uint64_t clock; uint64_t clock;
@ -17,6 +19,7 @@ typedef struct AutoTox {
size_t save_size; size_t save_size;
uint8_t *save_state; uint8_t *save_state;
bool alive; bool alive;
bool events;
void *state; void *state;
} AutoTox; } AutoTox;
@ -42,6 +45,7 @@ typedef struct Run_Auto_Options {
Graph_Type graph; Graph_Type graph;
void (*init_autotox)(AutoTox *autotox, uint32_t n); void (*init_autotox)(AutoTox *autotox, uint32_t n);
uint16_t tcp_port; uint16_t tcp_port;
bool events;
} Run_Auto_Options; } Run_Auto_Options;
Run_Auto_Options default_run_auto_options(void); Run_Auto_Options default_run_auto_options(void);

View File

@ -23,10 +23,11 @@ typedef struct State {
} State; } State;
static void handle_self_connection_status( static void handle_self_connection_status(
Tox *tox, Tox_Connection connection_status, void *user_data) const Tox_Event_Self_Connection_Status *event, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
if (connection_status != TOX_CONNECTION_NONE) { if (connection_status != TOX_CONNECTION_NONE) {
printf("tox #%u: is now connected\n", autotox->index); printf("tox #%u: is now connected\n", autotox->index);
} else { } else {
@ -35,10 +36,13 @@ static void handle_self_connection_status(
} }
static void handle_friend_connection_status( static void handle_friend_connection_status(
Tox *tox, uint32_t friendnumber, Tox_Connection connection_status, void *user_data) const Tox_Event_Friend_Connection_Status *event, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
const uint32_t friendnumber = tox_event_friend_connection_status_get_friend_number(event);
const Tox_Connection connection_status = tox_event_friend_connection_status_get_connection_status(event);
if (connection_status != TOX_CONNECTION_NONE) { if (connection_status != TOX_CONNECTION_NONE) {
printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber); printf("tox #%u: is now connected to friend %u\n", autotox->index, friendnumber);
} else { } else {
@ -70,28 +74,33 @@ static void audio_callback(void *tox, uint32_t groupnumber, uint32_t peernumber,
} }
static void handle_conference_invite( static void handle_conference_invite(
Tox *tox, uint32_t friendnumber, Tox_Conference_Type type, const Tox_Event_Conference_Invite *event, void *user_data)
const uint8_t *data, size_t length, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
const size_t length = tox_event_conference_invite_get_cookie_length(event);
ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", autotox->index, type); ck_assert_msg(type == TOX_CONFERENCE_TYPE_AV, "tox #%u: wrong conference type: %d", autotox->index, type);
ck_assert_msg(toxav_join_av_groupchat(tox, friendnumber, data, length, audio_callback, user_data) == 0, ck_assert_msg(toxav_join_av_groupchat(autotox->tox, friend_number, cookie, length, audio_callback, user_data) == 0,
"tox #%u: failed to join group", autotox->index); "tox #%u: failed to join group", autotox->index);
} }
static void handle_conference_connected( static void handle_conference_connected(
Tox *tox, uint32_t conference_number, void *user_data) const Tox_Event_Conference_Connected *event, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) { if (state->invited_next || tox_self_get_friend_list_size(autotox->tox) <= 1) {
return; return;
} }
Tox_Err_Conference_Invite err; Tox_Err_Conference_Invite err;
tox_conference_invite(tox, 1, 0, &err); tox_conference_invite(autotox->tox, 1, 0, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index, ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
err); err);
printf("tox #%u: invited next friend\n", autotox->index); printf("tox #%u: invited next friend\n", autotox->index);
@ -99,7 +108,7 @@ static void handle_conference_connected(
} }
static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes, static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
bool *disconnected) const bool *disconnected)
{ {
uint32_t num_disconnected = 0; uint32_t num_disconnected = 0;
@ -138,7 +147,10 @@ static void disconnect_toxes(uint32_t tox_count, AutoTox *autotoxes,
do { do {
for (uint32_t i = 0; i < tox_count; ++i) { for (uint32_t i = 0; i < tox_count; ++i) {
if (!disconnect_now[i]) { if (!disconnect_now[i]) {
tox_iterate(autotoxes[i].tox, &autotoxes[i]); Tox_Err_Events_Iterate err;
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
tox_events_free(events);
autotoxes[i].clock += 1000; autotoxes[i].clock += 1000;
} }
} }
@ -165,7 +177,7 @@ static bool all_connected_to_group(uint32_t tox_count, AutoTox *autotoxes)
* returns a random index at which a list of booleans is false * returns a random index at which a list of booleans is false
* (some such index is required to exist) * (some such index is required to exist)
*/ */
static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t length) static uint32_t random_false_index(const Random *rng, const bool *list, const uint32_t length)
{ {
uint32_t index; uint32_t index;
@ -185,7 +197,7 @@ static bool all_got_audio(AutoTox *autotoxes, const bool *disabled)
} }
for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
State *state = (State *)autotoxes[i].state; const State *state = (const State *)autotoxes[i].state;
if (disabled[i] ^ (state->received_audio_num if (disabled[i] ^ (state->received_audio_num
!= NUM_AV_GROUP_TOX - num_disabled - 1)) { != NUM_AV_GROUP_TOX - num_disabled - 1)) {
@ -291,7 +303,7 @@ static void do_audio(AutoTox *autotoxes, uint32_t iterations)
static void run_conference_tests(AutoTox *autotoxes) static void run_conference_tests(AutoTox *autotoxes)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
bool disabled[NUM_AV_GROUP_TOX] = {0}; bool disabled[NUM_AV_GROUP_TOX] = {0};
@ -402,10 +414,10 @@ static void test_groupav(AutoTox *autotoxes)
const time_t test_start_time = time(nullptr); const time_t test_start_time = time(nullptr);
for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) { for (uint32_t i = 0; i < NUM_AV_GROUP_TOX; ++i) {
tox_callback_self_connection_status(autotoxes[i].tox, &handle_self_connection_status); tox_events_callback_self_connection_status(autotoxes[i].dispatch, handle_self_connection_status);
tox_callback_friend_connection_status(autotoxes[i].tox, &handle_friend_connection_status); tox_events_callback_friend_connection_status(autotoxes[i].dispatch, handle_friend_connection_status);
tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite); tox_events_callback_conference_invite(autotoxes[i].dispatch, handle_conference_invite);
tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected); tox_events_callback_conference_connected(autotoxes[i].dispatch, handle_conference_connected);
} }
ck_assert_msg(toxav_add_av_groupchat(autotoxes[0].tox, audio_callback, &autotoxes[0]) != UINT32_MAX, ck_assert_msg(toxav_add_av_groupchat(autotoxes[0].tox, audio_callback, &autotoxes[0]) != UINT32_MAX,
@ -414,7 +426,6 @@ static void test_groupav(AutoTox *autotoxes)
ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend"); ck_assert_msg(tox_conference_invite(autotoxes[0].tox, 0, 0, nullptr) != 0, "failed to invite friend");
((State *)autotoxes[0].state)->invited_next = true; ((State *)autotoxes[0].state)->invited_next = true;
printf("waiting for invitations to be made\n"); printf("waiting for invitations to be made\n");
uint32_t invited_count = 0; uint32_t invited_count = 0;

View File

@ -12,12 +12,16 @@ typedef struct State {
#include "auto_test_support.h" #include "auto_test_support.h"
static void handle_conference_invite( static void handle_conference_invite(
Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const Tox_Event_Conference_Invite *event, void *user_data)
const uint8_t *cookie, size_t length, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
const size_t length = tox_event_conference_invite_get_cookie_length(event);
fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n", fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
autotox->index, friend_number, type, (unsigned)length); autotox->index, friend_number, type, (unsigned)length);
fprintf(stderr, "tox%u joining conference\n", autotox->index); fprintf(stderr, "tox%u joining conference\n", autotox->index);
@ -26,7 +30,7 @@ static void handle_conference_invite(
if (friend_number != -1) { if (friend_number != -1) {
Tox_Err_Conference_Join err; Tox_Err_Conference_Join err;
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
"attempting to join the conference returned with an error: %d", err); "attempting to join the conference returned with an error: %d", err);
fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference); fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
@ -37,8 +41,8 @@ static void handle_conference_invite(
static void conference_double_invite_test(AutoTox *autotoxes) static void conference_double_invite_test(AutoTox *autotoxes)
{ {
// Conference callbacks. // Conference callbacks.
tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite); tox_events_callback_conference_invite(autotoxes[0].dispatch, handle_conference_invite);
tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite); tox_events_callback_conference_invite(autotoxes[1].dispatch, handle_conference_invite);
State *state[2]; State *state[2];
state[0] = (State *)autotoxes[0].state; state[0] = (State *)autotoxes[0].state;

View File

@ -12,15 +12,18 @@ typedef struct State {
#include "auto_test_support.h" #include "auto_test_support.h"
static void handle_conference_invite( static void handle_conference_invite(
Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const Tox_Event_Conference_Invite *event, void *user_data)
const uint8_t *cookie, size_t length, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
const size_t length = tox_event_conference_invite_get_cookie_length(event);
if (friend_number != -1) { if (friend_number != -1) {
Tox_Err_Conference_Join err; Tox_Err_Conference_Join err;
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
"attempting to join the conference returned with an error: %d", err); "attempting to join the conference returned with an error: %d", err);
fprintf(stderr, "#%u accepted invite to conference %u\n", autotox->index, state->conference); fprintf(stderr, "#%u accepted invite to conference %u\n", autotox->index, state->conference);
@ -28,7 +31,7 @@ static void handle_conference_invite(
} }
static void handle_conference_connected( static void handle_conference_connected(
Tox *tox, uint32_t conference_number, void *user_data) const Tox_Event_Conference_Connected *event, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
@ -37,7 +40,7 @@ static void handle_conference_connected(
state->connected = true; state->connected = true;
} }
static void wait_connected(AutoTox *autotoxes, AutoTox *autotox, uint32_t friendnumber) static void wait_connected(AutoTox *autotoxes, const AutoTox *autotox, uint32_t friendnumber)
{ {
do { do {
iterate_all_wait(autotoxes, NUM_INVITE_MERGE_TOX, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_INVITE_MERGE_TOX, ITERATION_INTERVAL);
@ -95,8 +98,8 @@ static void conference_invite_merge_test(AutoTox *autotoxes)
// components will cause a split group to merge // components will cause a split group to merge
for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) { for (int i = 0; i < NUM_INVITE_MERGE_TOX; i++) {
tox_callback_conference_invite(autotoxes[i].tox, &handle_conference_invite); tox_events_callback_conference_invite(autotoxes[i].dispatch, handle_conference_invite);
tox_callback_conference_connected(autotoxes[i].tox, &handle_conference_connected); tox_events_callback_conference_connected(autotoxes[i].dispatch, handle_conference_connected);
} }
State *state2 = (State *)autotoxes[2].state; State *state2 = (State *)autotoxes[2].state;

View File

@ -13,34 +13,39 @@ typedef struct State {
#include "auto_test_support.h" #include "auto_test_support.h"
static void handle_conference_invite( static void handle_conference_invite(
Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const Tox_Event_Conference_Invite *event, void *user_data)
const uint8_t *cookie, size_t length, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
const size_t length = tox_event_conference_invite_get_cookie_length(event);
fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n", fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
autotox->index, friend_number, type, (unsigned)length); autotox->index, friend_number, type, (unsigned)length);
fprintf(stderr, "tox%u joining conference\n", autotox->index); fprintf(stderr, "tox%u joining conference\n", autotox->index);
Tox_Err_Conference_Join err; Tox_Err_Conference_Join err;
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); state->conference = tox_conference_join(autotox->tox, friend_number, cookie, length, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK,
"attempting to join the conference returned with an error: %d", err); "attempting to join the conference returned with an error: %d", err);
fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference); fprintf(stderr, "tox%u joined conference %u\n", autotox->index, state->conference);
state->joined = true; state->joined = true;
} }
static void handle_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data) static void handle_peer_list_changed(const Tox_Event_Conference_Peer_List_Changed *event, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t conference_number = tox_event_conference_peer_list_changed_get_conference_number(event);
fprintf(stderr, "handle_peer_list_changed(#%u, %u, _)\n", fprintf(stderr, "handle_peer_list_changed(#%u, %u, _)\n",
autotox->index, conference_number); autotox->index, conference_number);
Tox_Err_Conference_Peer_Query err; Tox_Err_Conference_Peer_Query err;
uint32_t const count = tox_conference_peer_count(tox, conference_number, &err); uint32_t const count = tox_conference_peer_count(autotox->tox, conference_number, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK, ck_assert_msg(err == TOX_ERR_CONFERENCE_PEER_QUERY_OK,
"failed to get conference peer count: err = %d", err); "failed to get conference peer count: err = %d", err);
printf("tox%u has %u peers\n", autotox->index, count); printf("tox%u has %u peers\n", autotox->index, count);
@ -75,10 +80,10 @@ static void rebuild_peer_list(Tox *tox)
static void conference_peer_nick_test(AutoTox *autotoxes) static void conference_peer_nick_test(AutoTox *autotoxes)
{ {
// Conference callbacks. // Conference callbacks.
tox_callback_conference_invite(autotoxes[0].tox, handle_conference_invite); tox_events_callback_conference_invite(autotoxes[0].dispatch, handle_conference_invite);
tox_callback_conference_invite(autotoxes[1].tox, handle_conference_invite); tox_events_callback_conference_invite(autotoxes[1].dispatch, handle_conference_invite);
tox_callback_conference_peer_list_changed(autotoxes[0].tox, handle_peer_list_changed); tox_events_callback_conference_peer_list_changed(autotoxes[0].dispatch, handle_peer_list_changed);
tox_callback_conference_peer_list_changed(autotoxes[1].tox, handle_peer_list_changed); tox_events_callback_conference_peer_list_changed(autotoxes[1].dispatch, handle_peer_list_changed);
// Set the names of the toxes. // Set the names of the toxes.
tox_self_set_name(autotoxes[0].tox, (const uint8_t *)"test-tox-0", 10, nullptr); tox_self_set_name(autotoxes[0].tox, (const uint8_t *)"test-tox-0", 10, nullptr);

View File

@ -3,11 +3,14 @@
#include "../testing/misc_tools.h" #include "../testing/misc_tools.h"
#include "../toxcore/tox.h" #include "../toxcore/tox.h"
#include "../toxcore/tox_dispatch.h"
#include "../toxcore/tox_events.h"
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"
typedef struct State { typedef struct State {
uint32_t id; uint32_t id;
Tox *tox;
bool self_online; bool self_online;
bool friend_online; bool friend_online;
bool invited_next; bool invited_next;
@ -20,46 +23,57 @@ typedef struct State {
uint32_t peers; uint32_t peers;
} State; } State;
static void handle_self_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data) static void handle_self_connection_status(const Tox_Event_Self_Connection_Status *event, void *user_data)
{ {
State *state = (State *)user_data; State *state = (State *)user_data;
const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
fprintf(stderr, "self_connection_status(#%u, %d, _)\n", state->id, connection_status); fprintf(stderr, "self_connection_status(#%u, %d, _)\n", state->id, connection_status);
state->self_online = connection_status != TOX_CONNECTION_NONE; state->self_online = connection_status != TOX_CONNECTION_NONE;
} }
static void handle_friend_connection_status(Tox *tox, uint32_t friend_number, Tox_Connection connection_status, static void handle_friend_connection_status(const Tox_Event_Friend_Connection_Status *event,
void *user_data) void *user_data)
{ {
State *state = (State *)user_data; State *state = (State *)user_data;
const uint32_t friend_number = tox_event_friend_connection_status_get_friend_number(event);
const Tox_Connection connection_status = tox_event_friend_connection_status_get_connection_status(event);
fprintf(stderr, "handle_friend_connection_status(#%u, %u, %d, _)\n", state->id, friend_number, connection_status); fprintf(stderr, "handle_friend_connection_status(#%u, %u, %d, _)\n", state->id, friend_number, connection_status);
state->friend_online = connection_status != TOX_CONNECTION_NONE; state->friend_online = connection_status != TOX_CONNECTION_NONE;
} }
static void handle_conference_invite(Tox *tox, uint32_t friend_number, Tox_Conference_Type type, const uint8_t *cookie, static void handle_conference_invite(const Tox_Event_Conference_Invite *event, void *user_data)
size_t length, void *user_data)
{ {
State *state = (State *)user_data; State *state = (State *)user_data;
const uint32_t friend_number = tox_event_conference_invite_get_friend_number(event);
const Tox_Conference_Type type = tox_event_conference_invite_get_type(event);
const uint8_t *cookie = tox_event_conference_invite_get_cookie(event);
const size_t length = tox_event_conference_invite_get_cookie_length(event);
fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n", fprintf(stderr, "handle_conference_invite(#%u, %u, %d, uint8_t[%u], _)\n",
state->id, friend_number, type, (unsigned)length); state->id, friend_number, type, (unsigned)length);
fprintf(stderr, "tox%u joining conference\n", state->id); fprintf(stderr, "tox%u joining conference\n", state->id);
{ {
Tox_Err_Conference_Join err; Tox_Err_Conference_Join err;
state->conference = tox_conference_join(tox, friend_number, cookie, length, &err); state->conference = tox_conference_join(state->tox, friend_number, cookie, length, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "failed to join a conference: err = %d", err); ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "failed to join a conference: err = %d", err);
fprintf(stderr, "tox%u Joined conference %u\n", state->id, state->conference); fprintf(stderr, "tox%u Joined conference %u\n", state->id, state->conference);
state->joined = true; state->joined = true;
} }
} }
static void handle_conference_message(Tox *tox, uint32_t conference_number, uint32_t peer_number, static void handle_conference_message(const Tox_Event_Conference_Message *event, void *user_data)
Tox_Message_Type type, const uint8_t *message, size_t length, void *user_data)
{ {
State *state = (State *)user_data; State *state = (State *)user_data;
const uint32_t conference_number = tox_event_conference_message_get_conference_number(event);
const uint32_t peer_number = tox_event_conference_message_get_peer_number(event);
const Tox_Message_Type type = tox_event_conference_message_get_type(event);
const uint8_t *message = tox_event_conference_message_get_message(event);
const size_t length = tox_event_conference_message_get_message_length(event);
fprintf(stderr, "handle_conference_message(#%u, %u, %u, %d, uint8_t[%u], _)\n", fprintf(stderr, "handle_conference_message(#%u, %u, %u, %d, uint8_t[%u], _)\n",
state->id, conference_number, peer_number, type, (unsigned)length); state->id, conference_number, peer_number, type, (unsigned)length);
@ -67,15 +81,16 @@ static void handle_conference_message(Tox *tox, uint32_t conference_number, uint
state->received = true; state->received = true;
} }
static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_number, void *user_data) static void handle_conference_peer_list_changed(const Tox_Event_Conference_Peer_List_Changed *event, void *user_data)
{ {
State *state = (State *)user_data; State *state = (State *)user_data;
const uint32_t conference_number = tox_event_conference_peer_list_changed_get_conference_number(event);
fprintf(stderr, "handle_conference_peer_list_changed(#%u, %u, _)\n", fprintf(stderr, "handle_conference_peer_list_changed(#%u, %u, _)\n",
state->id, conference_number); state->id, conference_number);
Tox_Err_Conference_Peer_Query err; Tox_Err_Conference_Peer_Query err;
uint32_t count = tox_conference_peer_count(tox, conference_number, &err); uint32_t count = tox_conference_peer_count(state->tox, conference_number, &err);
if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) { if (err != TOX_ERR_CONFERENCE_PEER_QUERY_OK) {
fprintf(stderr, "ERROR: %d\n", err); fprintf(stderr, "ERROR: %d\n", err);
@ -86,14 +101,14 @@ static void handle_conference_peer_list_changed(Tox *tox, uint32_t conference_nu
state->peers = count; state->peers = count;
} }
static void handle_conference_connected(Tox *tox, uint32_t conference_number, void *user_data) static void handle_conference_connected(const Tox_Event_Conference_Connected *event, void *user_data)
{ {
State *state = (State *)user_data; State *state = (State *)user_data;
// We're tox2, so now we invite tox3. // We're tox2, so now we invite tox3.
if (state->id == 2 && !state->invited_next) { if (state->id == 2 && !state->invited_next) {
Tox_Err_Conference_Invite err; Tox_Err_Conference_Invite err;
tox_conference_invite(tox, 1, state->conference, &err); tox_conference_invite(state->tox, 1, state->conference, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox2 failed to invite tox3: err = %d", err); ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox2 failed to invite tox3: err = %d", err);
state->invited_next = true; state->invited_next = true;
@ -101,6 +116,27 @@ static void handle_conference_connected(Tox *tox, uint32_t conference_number, vo
} }
} }
static void iterate_one(
Tox *tox, State *state, const Tox_Dispatch *dispatch)
{
Tox_Err_Events_Iterate err;
Tox_Events *events = tox_events_iterate(tox, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, state);
tox_events_free(events);
}
static void iterate3_wait(
State *state1, State *state2, State *state3,
const Tox_Dispatch *dispatch, int interval)
{
iterate_one(state1->tox, state1, dispatch);
iterate_one(state2->tox, state2, dispatch);
iterate_one(state3->tox, state3, dispatch);
c_sleep(interval);
}
int main(void) int main(void)
{ {
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);
@ -110,64 +146,51 @@ int main(void)
State state3 = {3}; State state3 = {3};
// Create toxes. // Create toxes.
Tox *tox1 = tox_new_log(nullptr, nullptr, &state1.id); state1.tox = tox_new_log(nullptr, nullptr, &state1.id);
Tox *tox2 = tox_new_log(nullptr, nullptr, &state2.id); state2.tox = tox_new_log(nullptr, nullptr, &state2.id);
Tox *tox3 = tox_new_log(nullptr, nullptr, &state3.id); state3.tox = tox_new_log(nullptr, nullptr, &state3.id);
tox_events_init(state1.tox);
tox_events_init(state2.tox);
tox_events_init(state3.tox);
// tox1 <-> tox2, tox2 <-> tox3 // tox1 <-> tox2, tox2 <-> tox3
uint8_t key[TOX_PUBLIC_KEY_SIZE]; uint8_t key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_public_key(tox2, key); tox_self_get_public_key(state2.tox, key);
tox_friend_add_norequest(tox1, key, nullptr); // tox1 -> tox2 tox_friend_add_norequest(state1.tox, key, nullptr); // tox1 -> tox2
tox_self_get_public_key(tox1, key); tox_self_get_public_key(state1.tox, key);
tox_friend_add_norequest(tox2, key, nullptr); // tox2 -> tox1 tox_friend_add_norequest(state2.tox, key, nullptr); // tox2 -> tox1
tox_self_get_public_key(tox3, key); tox_self_get_public_key(state3.tox, key);
tox_friend_add_norequest(tox2, key, nullptr); // tox2 -> tox3 tox_friend_add_norequest(state2.tox, key, nullptr); // tox2 -> tox3
tox_self_get_public_key(tox2, key); tox_self_get_public_key(state2.tox, key);
tox_friend_add_norequest(tox3, key, nullptr); // tox3 -> tox2 tox_friend_add_norequest(state3.tox, key, nullptr); // tox3 -> tox2
printf("bootstrapping tox2 and tox3 off tox1\n"); printf("bootstrapping tox2 and tox3 off tox1\n");
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_dht_id(tox1, dht_key); tox_self_get_dht_id(state1.tox, dht_key);
const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr); const uint16_t dht_port = tox_self_get_udp_port(state1.tox, nullptr);
tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr); tox_bootstrap(state2.tox, "localhost", dht_port, dht_key, nullptr);
tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr); tox_bootstrap(state3.tox, "localhost", dht_port, dht_key, nullptr);
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
ck_assert(dispatch != nullptr);
// Connection callbacks. // Connection callbacks.
tox_callback_self_connection_status(tox1, handle_self_connection_status); tox_events_callback_self_connection_status(dispatch, handle_self_connection_status);
tox_callback_self_connection_status(tox2, handle_self_connection_status); tox_events_callback_friend_connection_status(dispatch, handle_friend_connection_status);
tox_callback_self_connection_status(tox3, handle_self_connection_status);
tox_callback_friend_connection_status(tox1, handle_friend_connection_status);
tox_callback_friend_connection_status(tox2, handle_friend_connection_status);
tox_callback_friend_connection_status(tox3, handle_friend_connection_status);
// Conference callbacks. // Conference callbacks.
tox_callback_conference_invite(tox1, handle_conference_invite); tox_events_callback_conference_invite(dispatch, handle_conference_invite);
tox_callback_conference_invite(tox2, handle_conference_invite); tox_events_callback_conference_connected(dispatch, handle_conference_connected);
tox_callback_conference_invite(tox3, handle_conference_invite); tox_events_callback_conference_message(dispatch, handle_conference_message);
tox_events_callback_conference_peer_list_changed(dispatch, handle_conference_peer_list_changed);
tox_callback_conference_connected(tox1, handle_conference_connected);
tox_callback_conference_connected(tox2, handle_conference_connected);
tox_callback_conference_connected(tox3, handle_conference_connected);
tox_callback_conference_message(tox1, handle_conference_message);
tox_callback_conference_message(tox2, handle_conference_message);
tox_callback_conference_message(tox3, handle_conference_message);
tox_callback_conference_peer_list_changed(tox1, handle_conference_peer_list_changed);
tox_callback_conference_peer_list_changed(tox2, handle_conference_peer_list_changed);
tox_callback_conference_peer_list_changed(tox3, handle_conference_peer_list_changed);
// Wait for self connection. // Wait for self connection.
fprintf(stderr, "Waiting for toxes to come online\n"); fprintf(stderr, "Waiting for toxes to come online\n");
do { do {
tox_iterate(tox1, &state1); iterate3_wait(&state1, &state2, &state3, dispatch, 100);
tox_iterate(tox2, &state2);
tox_iterate(tox3, &state3);
c_sleep(100);
} while (!state1.self_online || !state2.self_online || !state3.self_online); } while (!state1.self_online || !state2.self_online || !state3.self_online);
fprintf(stderr, "Toxes are online\n"); fprintf(stderr, "Toxes are online\n");
@ -176,11 +199,7 @@ int main(void)
fprintf(stderr, "Waiting for friends to connect\n"); fprintf(stderr, "Waiting for friends to connect\n");
do { do {
tox_iterate(tox1, &state1); iterate3_wait(&state1, &state2, &state3, dispatch, 100);
tox_iterate(tox2, &state2);
tox_iterate(tox3, &state3);
c_sleep(100);
} while (!state1.friend_online || !state2.friend_online || !state3.friend_online); } while (!state1.friend_online || !state2.friend_online || !state3.friend_online);
fprintf(stderr, "Friends are connected\n"); fprintf(stderr, "Friends are connected\n");
@ -188,7 +207,7 @@ int main(void)
{ {
// Create new conference, tox1 is the founder. // Create new conference, tox1 is the founder.
Tox_Err_Conference_New err; Tox_Err_Conference_New err;
state1.conference = tox_conference_new(tox1, &err); state1.conference = tox_conference_new(state1.tox, &err);
state1.joined = true; state1.joined = true;
ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "failed to create a conference: err = %d", err); ck_assert_msg(err == TOX_ERR_CONFERENCE_NEW_OK, "failed to create a conference: err = %d", err);
fprintf(stderr, "Created conference: id = %u\n", state1.conference); fprintf(stderr, "Created conference: id = %u\n", state1.conference);
@ -197,7 +216,7 @@ int main(void)
{ {
// Invite friend. // Invite friend.
Tox_Err_Conference_Invite err; Tox_Err_Conference_Invite err;
tox_conference_invite(tox1, 0, state1.conference, &err); tox_conference_invite(state1.tox, 0, state1.conference, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "failed to invite a friend: err = %d", err); ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "failed to invite a friend: err = %d", err);
state1.invited_next = true; state1.invited_next = true;
fprintf(stderr, "tox1 invited tox2\n"); fprintf(stderr, "tox1 invited tox2\n");
@ -206,11 +225,7 @@ int main(void)
fprintf(stderr, "Waiting for invitation to arrive\n"); fprintf(stderr, "Waiting for invitation to arrive\n");
do { do {
tox_iterate(tox1, &state1); iterate3_wait(&state1, &state2, &state3, dispatch, 100);
tox_iterate(tox2, &state2);
tox_iterate(tox3, &state3);
c_sleep(100);
} while (!state1.joined || !state2.joined || !state3.joined); } while (!state1.joined || !state2.joined || !state3.joined);
fprintf(stderr, "Invitations accepted\n"); fprintf(stderr, "Invitations accepted\n");
@ -218,11 +233,7 @@ int main(void)
fprintf(stderr, "Waiting for peers to come online\n"); fprintf(stderr, "Waiting for peers to come online\n");
do { do {
tox_iterate(tox1, &state1); iterate3_wait(&state1, &state2, &state3, dispatch, 100);
tox_iterate(tox2, &state2);
tox_iterate(tox3, &state3);
c_sleep(100);
} while (state1.peers == 0 || state2.peers == 0 || state3.peers == 0); } while (state1.peers == 0 || state2.peers == 0 || state3.peers == 0);
fprintf(stderr, "All peers are online\n"); fprintf(stderr, "All peers are online\n");
@ -230,7 +241,7 @@ int main(void)
{ {
fprintf(stderr, "tox1 sends a message to the group: \"hello!\"\n"); fprintf(stderr, "tox1 sends a message to the group: \"hello!\"\n");
Tox_Err_Conference_Send_Message err; Tox_Err_Conference_Send_Message err;
tox_conference_send_message(tox1, state1.conference, TOX_MESSAGE_TYPE_NORMAL, tox_conference_send_message(state1.tox, state1.conference, TOX_MESSAGE_TYPE_NORMAL,
(const uint8_t *)"hello!", 7, &err); (const uint8_t *)"hello!", 7, &err);
if (err != TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) { if (err != TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) {
@ -242,18 +253,16 @@ int main(void)
fprintf(stderr, "Waiting for messages to arrive\n"); fprintf(stderr, "Waiting for messages to arrive\n");
do { do {
tox_iterate(tox1, &state1); iterate3_wait(&state1, &state2, &state3, dispatch, 100);
tox_iterate(tox2, &state2);
tox_iterate(tox3, &state3);
c_sleep(100); c_sleep(100);
} while (!state2.received || !state3.received); } while (!state2.received || !state3.received);
fprintf(stderr, "Messages received. Test complete.\n"); fprintf(stderr, "Messages received. Test complete.\n");
tox_kill(tox3); tox_dispatch_free(dispatch);
tox_kill(tox2); tox_kill(state3.tox);
tox_kill(tox1); tox_kill(state2.tox);
tox_kill(state1.tox);
return 0; return 0;
} }

View File

@ -56,13 +56,13 @@ static void handle_conference_invite(
ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", autotox->index, type); ck_assert_msg(type == TOX_CONFERENCE_TYPE_TEXT, "tox #%u: wrong conference type: %d", autotox->index, type);
Tox_Err_Conference_Join err; Tox_Err_Conference_Join err;
uint32_t g_num = tox_conference_join(tox, friendnumber, data, length, &err); uint32_t g_num = tox_conference_join(autotox->tox, friendnumber, data, length, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", autotox->index, err); ck_assert_msg(err == TOX_ERR_CONFERENCE_JOIN_OK, "tox #%u: error joining group: %d", autotox->index, err);
ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", autotox->index); ck_assert_msg(g_num == 0, "tox #%u: group number was not 0", autotox->index);
// Try joining again. We should only be allowed to join once. // Try joining again. We should only be allowed to join once.
tox_conference_join(tox, friendnumber, data, length, &err); tox_conference_join(autotox->tox, friendnumber, data, length, &err);
ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK, ck_assert_msg(err != TOX_ERR_CONFERENCE_JOIN_OK,
"tox #%u: joining groupchat twice should be impossible.", autotox->index); "tox #%u: joining groupchat twice should be impossible.", autotox->index);
} }
@ -73,12 +73,12 @@ static void handle_conference_connected(
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
if (state->invited_next || tox_self_get_friend_list_size(tox) <= 1) { if (state->invited_next || tox_self_get_friend_list_size(autotox->tox) <= 1) {
return; return;
} }
Tox_Err_Conference_Invite err; Tox_Err_Conference_Invite err;
tox_conference_invite(tox, 1, 0, &err); tox_conference_invite(autotox->tox, 1, 0, &err);
ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index, ck_assert_msg(err == TOX_ERR_CONFERENCE_INVITE_OK, "tox #%u failed to invite next friend: err = %d", autotox->index,
err); err);
printf("tox #%u: invited next friend\n", autotox->index); printf("tox #%u: invited next friend\n", autotox->index);
@ -97,7 +97,7 @@ static void handle_conference_message(
} }
static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes, static bool toxes_are_disconnected_from_group(uint32_t tox_count, AutoTox *autotoxes,
bool *disconnected) const bool *disconnected)
{ {
uint32_t num_disconnected = 0; uint32_t num_disconnected = 0;
@ -174,12 +174,11 @@ static bool names_propagated(uint32_t tox_count, AutoTox *autotoxes)
return true; return true;
} }
/** /**
* returns a random index at which a list of booleans is false * returns a random index at which a list of booleans is false
* (some such index is required to exist) * (some such index is required to exist)
*/ */
static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t length) static uint32_t random_false_index(const Random *rng, const bool *list, const uint32_t length)
{ {
uint32_t index; uint32_t index;
@ -192,7 +191,7 @@ static uint32_t random_false_index(const Random *rng, bool *list, const uint32_t
static void run_conference_tests(AutoTox *autotoxes) static void run_conference_tests(AutoTox *autotoxes)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
/* disabling name change propagation check for now, as it occasionally /* disabling name change propagation check for now, as it occasionally
* fails due to disconnections too short to trigger freezing */ * fails due to disconnections too short to trigger freezing */
@ -357,7 +356,6 @@ static void test_many_group(AutoTox *autotoxes)
nullptr) != 0, nullptr) != 0,
"failed to set group title"); "failed to set group title");
printf("waiting for invitations to be made\n"); printf("waiting for invitations to be made\n");
uint32_t invited_count = 0; uint32_t invited_count = 0;
@ -435,6 +433,7 @@ int main(void)
Run_Auto_Options options = default_run_auto_options(); Run_Auto_Options options = default_run_auto_options();
options.graph = GRAPH_LINEAR; options.graph = GRAPH_LINEAR;
options.events = false;
run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, sizeof(State), &options); run_auto_test(nullptr, NUM_GROUP_TOX, test_many_group, sizeof(State), &options);
return 0; return 0;

View File

@ -125,7 +125,7 @@ static void test_fast_known(void)
static void test_endtoend(void) static void test_endtoend(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
// Test 100 random messages and keypairs // Test 100 random messages and keypairs
@ -192,7 +192,7 @@ static void test_endtoend(void)
static void test_large_data(void) static void test_large_data(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
uint8_t k[CRYPTO_SHARED_KEY_SIZE]; uint8_t k[CRYPTO_SHARED_KEY_SIZE];
uint8_t n[CRYPTO_NONCE_SIZE]; uint8_t n[CRYPTO_NONCE_SIZE];
@ -236,7 +236,7 @@ static void test_large_data(void)
static void test_large_data_symmetric(void) static void test_large_data_symmetric(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
uint8_t k[CRYPTO_SYMMETRIC_KEY_SIZE]; uint8_t k[CRYPTO_SYMMETRIC_KEY_SIZE];
@ -271,10 +271,10 @@ static void test_large_data_symmetric(void)
static void test_very_large_data(void) static void test_very_large_data(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
uint8_t nonce[CRYPTO_NONCE_SIZE] = {0}; const uint8_t nonce[CRYPTO_NONCE_SIZE] = {0};
uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t sk[CRYPTO_SECRET_KEY_SIZE]; uint8_t sk[CRYPTO_SECRET_KEY_SIZE];
crypto_new_keypair(rng, pk, sk); crypto_new_keypair(rng, pk, sk);
@ -316,7 +316,7 @@ static void increment_nonce_number_cmp(uint8_t *nonce, uint32_t num)
static void test_increment_nonce(void) static void test_increment_nonce(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
uint8_t n[CRYPTO_NONCE_SIZE]; uint8_t n[CRYPTO_NONCE_SIZE];

Binary file not shown.

View File

@ -72,12 +72,16 @@ static bool all_nodes_crawled(const AutoTox *autotoxes, uint32_t num_toxes, uint
return true; return true;
} }
static void getnodes_response_cb(Tox *tox, const uint8_t *public_key, const char *ip, uint16_t port, void *user_data) static void getnodes_response_cb(const Tox_Event_Dht_Get_Nodes_Response *event, void *user_data)
{ {
ck_assert(user_data != nullptr); ck_assert(user_data != nullptr);
AutoTox *autotoxes = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotoxes->state; State *state = (State *)autotox->state;
const uint8_t *public_key = tox_event_dht_get_nodes_response_get_public_key(event);
const char *ip = (const char *)tox_event_dht_get_nodes_response_get_ip(event);
const uint16_t port = tox_event_dht_get_nodes_response_get_port(event);
if (node_crawled(state->nodes, state->num_nodes, public_key)) { if (node_crawled(state->nodes, state->num_nodes, public_key)) {
return; return;
@ -97,7 +101,7 @@ static void getnodes_response_cb(Tox *tox, const uint8_t *public_key, const char
// ask new node to give us their close nodes to every public key // ask new node to give us their close nodes to every public key
for (size_t i = 0; i < NUM_TOXES; ++i) { for (size_t i = 0; i < NUM_TOXES; ++i) {
tox_dht_get_nodes(tox, public_key, ip, port, state->public_key_list[i], nullptr); tox_dht_get_nodes(autotox->tox, public_key, ip, port, state->public_key_list[i], nullptr);
} }
} }
@ -121,13 +125,12 @@ static void test_dht_getnodes(AutoTox *autotoxes)
ck_assert(public_key_list[i] != nullptr); ck_assert(public_key_list[i] != nullptr);
tox_self_get_dht_id(autotoxes[i].tox, public_key_list[i]); tox_self_get_dht_id(autotoxes[i].tox, public_key_list[i]);
tox_callback_dht_get_nodes_response(autotoxes[i].tox, getnodes_response_cb); tox_events_callback_dht_get_nodes_response(autotoxes[i].dispatch, getnodes_response_cb);
printf("Peer %zu dht closenode count total/announce-capable: %d/%d\n", printf("Peer %zu dht closenode count total/announce-capable: %d/%d\n",
i, i,
tox_dht_get_num_closelist(autotoxes[i].tox), tox_dht_get_num_closelist(autotoxes[i].tox),
tox_dht_get_num_closelist_announce_capable(autotoxes[i].tox) tox_dht_get_num_closelist_announce_capable(autotoxes[i].tox));
);
} }
while (!all_nodes_crawled(autotoxes, NUM_TOXES, public_key_list)) { while (!all_nodes_crawled(autotoxes, NUM_TOXES, public_key_list)) {

View File

@ -168,7 +168,7 @@ static void test_keys(void)
ck_assert(encrypted2a != nullptr); ck_assert(encrypted2a != nullptr);
uint8_t *in_plaintext2a = (uint8_t *)malloc(plaintext_length2a); uint8_t *in_plaintext2a = (uint8_t *)malloc(plaintext_length2a);
ck_assert(in_plaintext2a != nullptr); ck_assert(in_plaintext2a != nullptr);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
random_bytes(rng, in_plaintext2a, plaintext_length2a); random_bytes(rng, in_plaintext2a, plaintext_length2a);
ret = tox_pass_encrypt(in_plaintext2a, plaintext_length2a, key_char, 12, encrypted2a, &encerr); ret = tox_pass_encrypt(in_plaintext2a, plaintext_length2a, key_char, 12, encrypted2a, &encerr);
@ -184,7 +184,6 @@ static void test_keys(void)
free(in_plaintext2a); free(in_plaintext2a);
free(out_plaintext2a); free(out_plaintext2a);
uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH]; uint8_t encrypted2[44 + TOX_PASS_ENCRYPTION_EXTRA_LENGTH];
ret = tox_pass_encrypt(string, 44, key_char, 12, encrypted2, &encerr); ret = tox_pass_encrypt(string, 44, key_char, 12, encrypted2, &encerr);
ck_assert_msg(ret, "generic failure 3: %d", encerr); ck_assert_msg(ret, "generic failure 3: %d", encerr);

View File

@ -53,7 +53,7 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id"); ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
uint8_t empty[TOX_FILE_ID_LENGTH] = {0}; const uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id"); ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
@ -126,7 +126,6 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
Tox_Err_File_Send_Chunk error; Tox_Err_File_Send_Chunk error;
tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error); tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error);
ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK, ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
"could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length); "could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
@ -134,7 +133,6 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
sending_pos += length; sending_pos += length;
} }
static uint8_t num; static uint8_t num;
static bool file_recv; static bool file_recv;
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data,
@ -209,7 +207,6 @@ static void file_transfer_test(void)
file_accepted = file_size = sendf_ok = size_recv = 0; file_accepted = file_size = sendf_ok = size_recv = 0;
file_recv = 0; file_recv = 0;
max_sending = UINT64_MAX; max_sending = UINT64_MAX;
uint64_t totalf_size = 100 * 1024 * 1024;
printf("Starting file streaming transfer test.\n"); printf("Starting file streaming transfer test.\n");
@ -224,7 +221,7 @@ static void file_transfer_test(void)
tox_callback_file_chunk_request(tox2, tox_file_chunk_request); tox_callback_file_chunk_request(tox2, tox_file_chunk_request);
tox_callback_file_recv_control(tox3, file_print_control); tox_callback_file_recv_control(tox3, file_print_control);
tox_callback_file_recv(tox3, tox_file_receive); tox_callback_file_recv(tox3, tox_file_receive);
totalf_size = UINT64_MAX; const uint64_t totalf_size = UINT64_MAX;
Tox_File_Number fnum = tox_file_send( Tox_File_Number fnum = tox_file_send(
tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr); (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);

View File

@ -26,10 +26,16 @@
#define TOX_LOCALHOST "127.0.0.1" #define TOX_LOCALHOST "127.0.0.1"
#endif #endif
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
{ {
Tox *tox = (Tox *)userdata;
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
const uint8_t *data = tox_event_friend_request_get_message(event);
const size_t length = tox_event_friend_request_get_message_length(event);
if (length == 7 && memcmp("Gentoo", data, 7) == 0) { if (length == 7 && memcmp("Gentoo", data, 7) == 0) {
tox_friend_add_norequest(m, public_key, nullptr); tox_friend_add_norequest(tox, public_key, nullptr);
} }
} }
@ -39,9 +45,17 @@ static uint64_t sending_pos;
static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH]; static uint8_t file_cmp_id[TOX_FILE_ID_LENGTH];
static uint32_t file_accepted; static uint32_t file_accepted;
static uint64_t file_size; static uint64_t file_size;
static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_number, uint32_t kind, uint64_t filesize, static void tox_file_receive(const Tox_Event_File_Recv *event, void *userdata)
const uint8_t *filename, size_t filename_length, void *userdata)
{ {
Tox *state_tox = (Tox *)userdata;
const uint32_t friend_number = tox_event_file_recv_get_friend_number(event);
const uint32_t file_number = tox_event_file_recv_get_file_number(event);
const uint32_t kind = tox_event_file_recv_get_kind(event);
const uint64_t filesize = tox_event_file_recv_get_file_size(event);
const uint8_t *filename = tox_event_file_recv_get_filename(event);
const size_t filename_length = tox_event_file_recv_get_filename_length(event);
ck_assert_msg(kind == TOX_FILE_KIND_DATA, "bad kind"); ck_assert_msg(kind == TOX_FILE_KIND_DATA, "bad kind");
ck_assert_msg(filename_length == sizeof("Gentoo.exe") ck_assert_msg(filename_length == sizeof("Gentoo.exe")
@ -49,11 +63,11 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
uint8_t file_id[TOX_FILE_ID_LENGTH]; uint8_t file_id[TOX_FILE_ID_LENGTH];
ck_assert_msg(tox_file_get_file_id(tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error"); ck_assert_msg(tox_file_get_file_id(state_tox, friend_number, file_number, file_id, nullptr), "tox_file_get_file_id error");
ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id"); ck_assert_msg(memcmp(file_id, file_cmp_id, TOX_FILE_ID_LENGTH) == 0, "bad file_id");
uint8_t empty[TOX_FILE_ID_LENGTH] = {0}; const uint8_t empty[TOX_FILE_ID_LENGTH] = {0};
ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id"); ck_assert_msg(memcmp(empty, file_cmp_id, TOX_FILE_ID_LENGTH) != 0, "empty file_id");
@ -64,7 +78,7 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
Tox_Err_File_Seek err_s; Tox_Err_File_Seek err_s;
ck_assert_msg(tox_file_seek(tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error"); ck_assert_msg(tox_file_seek(state_tox, friend_number, file_number, 1337, &err_s), "tox_file_seek error");
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error"); ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_OK, "tox_file_seek wrong error");
@ -74,21 +88,24 @@ static void tox_file_receive(Tox *tox, uint32_t friend_number, uint32_t file_num
Tox_Err_File_Control error; Tox_Err_File_Control error;
ck_assert_msg(tox_file_control(tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error), ck_assert_msg(tox_file_control(state_tox, friend_number, file_number, TOX_FILE_CONTROL_RESUME, &error),
"tox_file_control failed. %i", error); "tox_file_control failed. %i", error);
++file_accepted; ++file_accepted;
Tox_Err_File_Seek err_s; Tox_Err_File_Seek err_s;
ck_assert_msg(!tox_file_seek(tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error"); ck_assert_msg(!tox_file_seek(state_tox, friend_number, file_number, 1234, &err_s), "tox_file_seek no error");
ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error"); ck_assert_msg(err_s == TOX_ERR_FILE_SEEK_DENIED, "tox_file_seek wrong error");
} }
static uint32_t sendf_ok; static uint32_t sendf_ok;
static void file_print_control(Tox *tox, uint32_t friend_number, uint32_t file_number, Tox_File_Control control, static void file_print_control(const Tox_Event_File_Recv_Control *event,
void *userdata) void *userdata)
{ {
const uint32_t file_number = tox_event_file_recv_control_get_file_number(event);
const Tox_File_Control control = tox_event_file_recv_control_get_control(event);
/* First send file num is 0.*/ /* First send file num is 0.*/
if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) { if (file_number == 0 && control == TOX_FILE_CONTROL_RESUME) {
sendf_ok = 1; sendf_ok = 1;
@ -99,12 +116,18 @@ static uint64_t max_sending;
static bool m_send_reached; static bool m_send_reached;
static uint8_t sending_num; static uint8_t sending_num;
static bool file_sending_done; static bool file_sending_done;
static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t file_number, uint64_t position, static void tox_file_chunk_request(const Tox_Event_File_Chunk_Request *event, void *user_data)
size_t length, void *user_data)
{ {
Tox *state_tox = (Tox *)user_data;
const uint32_t friend_number = tox_event_file_chunk_request_get_friend_number(event);
const uint32_t file_number = tox_event_file_chunk_request_get_file_number(event);
const uint64_t position = tox_event_file_chunk_request_get_position(event);
size_t length = tox_event_file_chunk_request_get_length(event);
ck_assert_msg(sendf_ok, "didn't get resume control"); ck_assert_msg(sendf_ok, "didn't get resume control");
ck_assert_msg(sending_pos == position, "bad position %lu", (unsigned long)position); ck_assert_msg(sending_pos == position, "bad position %lu (should be %lu)", (unsigned long)position, (unsigned long)sending_pos);
if (length == 0) { if (length == 0) {
ck_assert_msg(!file_sending_done, "file sending already done"); ck_assert_msg(!file_sending_done, "file sending already done");
@ -124,8 +147,7 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
memset(f_data, sending_num, length); memset(f_data, sending_num, length);
Tox_Err_File_Send_Chunk error; Tox_Err_File_Send_Chunk error;
tox_file_send_chunk(tox, friend_number, file_number, position, f_data, length, &error); tox_file_send_chunk(state_tox, friend_number, file_number, position, f_data, length, &error);
ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK, ck_assert_msg(error == TOX_ERR_FILE_SEND_CHUNK_OK,
"could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length); "could not send chunk, error num=%d pos=%d len=%d", (int)error, (int)position, (int)length);
@ -134,12 +156,14 @@ static void tox_file_chunk_request(Tox *tox, uint32_t friend_number, uint32_t fi
sending_pos += length; sending_pos += length;
} }
static uint8_t num; static uint8_t num;
static bool file_recv; static bool file_recv;
static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uint64_t position, const uint8_t *data, static void write_file(const Tox_Event_File_Recv_Chunk *event, void *user_data)
size_t length, void *user_data)
{ {
const uint64_t position = tox_event_file_recv_chunk_get_position(event);
const uint8_t *data = tox_event_file_recv_chunk_get_data(event);
const size_t length = tox_event_file_recv_chunk_get_data_length(event);
ck_assert_msg(size_recv == position, "bad position"); ck_assert_msg(size_recv == position, "bad position");
if (length == 0) { if (length == 0) {
@ -156,6 +180,17 @@ static void write_file(Tox *tox, uint32_t friendnumber, uint32_t filenumber, uin
size_recv += length; size_recv += length;
} }
static void iterate_and_dispatch(const Tox_Dispatch *dispatch, Tox *tox)
{
Tox_Err_Events_Iterate err;
Tox_Events *events;
events = tox_events_iterate(tox, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, tox);
tox_events_free(events);
}
static void file_transfer_test(void) static void file_transfer_test(void)
{ {
printf("Starting test: few_clients\n"); printf("Starting test: few_clients\n");
@ -171,7 +206,19 @@ static void file_transfer_test(void)
ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances"); ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
tox_callback_friend_request(tox2, accept_friend_request); tox_events_init(tox1);
tox_events_init(tox2);
tox_events_init(tox3);
Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
ck_assert(dispatch1 != nullptr);
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
ck_assert(dispatch2 != nullptr);
Tox_Dispatch *dispatch3 = tox_dispatch_new(nullptr);
ck_assert(dispatch3 != nullptr);
tox_events_callback_friend_request(dispatch2, accept_friend_request);
uint8_t address[TOX_ADDRESS_SIZE]; uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address); tox_self_get_address(tox2, address);
uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr); uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
@ -187,9 +234,9 @@ static void file_transfer_test(void)
printf("Waiting for toxes to come online\n"); printf("Waiting for toxes to come online\n");
do { do {
tox_iterate(tox1, nullptr); iterate_and_dispatch(dispatch1, tox1);
tox_iterate(tox2, nullptr); iterate_and_dispatch(dispatch2, tox2);
tox_iterate(tox3, nullptr); iterate_and_dispatch(dispatch3, tox3);
printf("Connections: self (%d, %d, %d), friends (%d, %d)\n", printf("Connections: self (%d, %d, %d), friends (%d, %d)\n",
tox_self_get_connection_status(tox1), tox_self_get_connection_status(tox1),
@ -210,11 +257,11 @@ static void file_transfer_test(void)
file_recv = 0; file_recv = 0;
max_sending = UINT64_MAX; max_sending = UINT64_MAX;
uint64_t f_time = time(nullptr); uint64_t f_time = time(nullptr);
tox_callback_file_recv_chunk(tox3, write_file); tox_events_callback_file_recv_chunk(dispatch3, write_file);
tox_callback_file_recv_control(tox2, file_print_control); tox_events_callback_file_recv_control(dispatch2, file_print_control);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request); tox_events_callback_file_chunk_request(dispatch2, tox_file_chunk_request);
tox_callback_file_recv_control(tox3, file_print_control); tox_events_callback_file_recv_control(dispatch3, file_print_control);
tox_callback_file_recv(tox3, tox_file_receive); tox_events_callback_file_recv(dispatch3, tox_file_receive);
uint64_t totalf_size = 100 * 1024 * 1024; uint64_t totalf_size = 100 * 1024 * 1024;
uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, (const uint8_t *)"Gentoo.exe", uint32_t fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, (const uint8_t *)"Gentoo.exe",
sizeof("Gentoo.exe"), nullptr); sizeof("Gentoo.exe"), nullptr);
@ -231,9 +278,9 @@ static void file_transfer_test(void)
const size_t max_iterations = INT16_MAX; const size_t max_iterations = INT16_MAX;
for (size_t i = 0; i < max_iterations; i++) { for (size_t i = 0; i < max_iterations; i++) {
tox_iterate(tox1, nullptr); iterate_and_dispatch(dispatch1, tox1);
tox_iterate(tox2, nullptr); iterate_and_dispatch(dispatch2, tox2);
tox_iterate(tox3, nullptr); iterate_and_dispatch(dispatch3, tox3);
if (file_sending_done) { if (file_sending_done) {
ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size && sending_pos == size_recv
@ -274,11 +321,11 @@ static void file_transfer_test(void)
sendf_ok = 0; sendf_ok = 0;
size_recv = 0; size_recv = 0;
file_recv = 0; file_recv = 0;
tox_callback_file_recv_chunk(tox3, write_file); tox_events_callback_file_recv_chunk(dispatch3, write_file);
tox_callback_file_recv_control(tox2, file_print_control); tox_events_callback_file_recv_control(dispatch2, file_print_control);
tox_callback_file_chunk_request(tox2, tox_file_chunk_request); tox_events_callback_file_chunk_request(dispatch2, tox_file_chunk_request);
tox_callback_file_recv_control(tox3, file_print_control); tox_events_callback_file_recv_control(dispatch3, file_print_control);
tox_callback_file_recv(tox3, tox_file_receive); tox_events_callback_file_recv(dispatch3, tox_file_receive);
totalf_size = 0; totalf_size = 0;
fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr, fnum = tox_file_send(tox2, 0, TOX_FILE_KIND_DATA, totalf_size, nullptr,
(const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr); (const uint8_t *)"Gentoo.exe", sizeof("Gentoo.exe"), nullptr);
@ -298,9 +345,9 @@ static void file_transfer_test(void)
c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval))); c_sleep(min_u32(tox1_interval, min_u32(tox2_interval, tox3_interval)));
tox_iterate(tox1, nullptr); iterate_and_dispatch(dispatch1, tox1);
tox_iterate(tox2, nullptr); iterate_and_dispatch(dispatch2, tox2);
tox_iterate(tox3, nullptr); iterate_and_dispatch(dispatch3, tox3);
} while (!file_sending_done); } while (!file_sending_done);
ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size ck_assert_msg(sendf_ok && file_recv && totalf_size == file_size && size_recv == file_size
@ -312,9 +359,12 @@ static void file_transfer_test(void)
printf("file_transfer_test succeeded, took %llu seconds\n", time(nullptr) - cur_time); printf("file_transfer_test succeeded, took %llu seconds\n", time(nullptr) - cur_time);
tox_kill(tox1); tox_dispatch_free(dispatch3);
tox_kill(tox2); tox_dispatch_free(dispatch2);
tox_dispatch_free(dispatch1);
tox_kill(tox3); tox_kill(tox3);
tox_kill(tox2);
tox_kill(tox1);
} }
int main(void) int main(void)

View File

@ -47,8 +47,8 @@ static void test_forwarded_request_cb(void *object, const IP_Port *forwarder,
const uint8_t *sendback, uint16_t sendback_length, const uint8_t *sendback, uint16_t sendback_length,
const uint8_t *data, uint16_t length, void *userdata) const uint8_t *data, uint16_t length, void *userdata)
{ {
Test_Data *test_data = (Test_Data *)object; const Test_Data *test_data = (const Test_Data *)object;
uint8_t *index = (uint8_t *)userdata; const uint8_t *index = (const uint8_t *)userdata;
if (length != 12 || memcmp("hello: ", data, 8) != 0) { if (length != 12 || memcmp("hello: ", data, 8) != 0) {
printf("[%u] got unexpected data of length %d\n", *index, length); printf("[%u] got unexpected data of length %d\n", *index, length);
@ -66,7 +66,7 @@ static void test_forwarded_response_cb(void *object,
const uint8_t *data, uint16_t length, void *userdata) const uint8_t *data, uint16_t length, void *userdata)
{ {
Test_Data *test_data = (Test_Data *)object; Test_Data *test_data = (Test_Data *)object;
uint8_t *index = (uint8_t *)userdata; const uint8_t *index = (const uint8_t *)userdata;
if (length != 12 || memcmp("reply: ", data, 8) != 0) { if (length != 12 || memcmp("reply: ", data, 8) != 0) {
printf("[%u] got unexpected data of length %d\n", *index, length); printf("[%u] got unexpected data of length %d\n", *index, length);
@ -104,9 +104,9 @@ typedef struct Forwarding_Subtox {
static Forwarding_Subtox *new_forwarding_subtox(const Memory *mem, bool no_udp, uint32_t *index, uint16_t port) static Forwarding_Subtox *new_forwarding_subtox(const Memory *mem, bool no_udp, uint32_t *index, uint16_t port)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox)); Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox));
@ -152,11 +152,11 @@ static void kill_forwarding_subtox(const Memory *mem, Forwarding_Subtox *subtox)
static void test_forwarding(void) static void test_forwarding(void)
{ {
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
uint32_t index[NUM_FORWARDER]; uint32_t index[NUM_FORWARDER];
@ -317,7 +317,6 @@ static void test_forwarding(void)
} }
} }
for (uint32_t i = 0; i < NUM_FORWARDER; ++i) { for (uint32_t i = 0; i < NUM_FORWARDER; ++i) {
kill_forwarding_subtox(mem, subtoxes[i]); kill_forwarding_subtox(mem, subtoxes[i]);
} }
@ -325,7 +324,6 @@ static void test_forwarding(void)
tox_kill(relay); tox_kill(relay);
} }
int main(void) int main(void)
{ {
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);

View File

@ -22,12 +22,18 @@ typedef struct State {
bool unused; bool unused;
} State; } State;
static void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, size_t length, static void accept_friend_request(const Tox_Event_Friend_Request *event,
void *userdata) void *userdata)
{ {
AutoTox *autotox = (AutoTox *)userdata;
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
const uint8_t *data = tox_event_friend_request_get_message(event);
const size_t length = tox_event_friend_request_get_message_length(event);
ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0, ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
"unexpected friend request message"); "unexpected friend request message");
tox_friend_add_norequest(tox, public_key, nullptr); tox_friend_add_norequest(autotox->tox, public_key, nullptr);
} }
static void test_friend_request(AutoTox *autotoxes) static void test_friend_request(AutoTox *autotoxes)
@ -35,7 +41,7 @@ static void test_friend_request(AutoTox *autotoxes)
const time_t con_time = time(nullptr); const time_t con_time = time(nullptr);
printf("All toxes add tox1 as friend.\n"); printf("All toxes add tox1 as friend.\n");
tox_callback_friend_request(autotoxes[0].tox, accept_friend_request); tox_events_callback_friend_request(autotoxes[0].dispatch, accept_friend_request);
uint8_t address[TOX_ADDRESS_SIZE]; uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(autotoxes[0].tox, address); tox_self_get_address(autotoxes[0].tox, address);

View File

@ -15,12 +15,36 @@
#define FR_MESSAGE "Gentoo" #define FR_MESSAGE "Gentoo"
static void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *data, size_t length, static void accept_friend_request(const Tox_Event_Friend_Request *event,
void *userdata) void *userdata)
{ {
Tox *state_tox = (Tox *)userdata;
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
const uint8_t *data = tox_event_friend_request_get_message(event);
const size_t length = tox_event_friend_request_get_message_length(event);
ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0, ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0,
"unexpected friend request message"); "unexpected friend request message");
tox_friend_add_norequest(tox, public_key, nullptr); tox_friend_add_norequest(state_tox, public_key, nullptr);
}
static void iterate2_wait(const Tox_Dispatch *dispatch, Tox *tox1, Tox *tox2)
{
Tox_Err_Events_Iterate err;
Tox_Events *events;
events = tox_events_iterate(tox1, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, tox1);
tox_events_free(events);
events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, tox2);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL);
} }
static void test_friend_request(void) static void test_friend_request(void)
@ -33,6 +57,9 @@ static void test_friend_request(void)
ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances"); ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
tox_events_init(tox1);
tox_events_init(tox2);
printf("Bootstrapping tox2 off tox1.\n"); printf("Bootstrapping tox2 off tox1.\n");
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_dht_id(tox1, dht_key); tox_self_get_dht_id(tox1, dht_key);
@ -40,11 +67,11 @@ static void test_friend_request(void)
tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr); tox_bootstrap(tox2, "localhost", dht_port, dht_key, nullptr);
do { Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
tox_iterate(tox1, nullptr); ck_assert(dispatch != nullptr);
tox_iterate(tox2, nullptr);
c_sleep(ITERATION_INTERVAL); do {
iterate2_wait(dispatch, tox1, tox2);
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE || } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE); tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
@ -52,7 +79,7 @@ static void test_friend_request(void)
const time_t con_time = time(nullptr); const time_t con_time = time(nullptr);
printf("Tox1 adds tox2 as friend, tox2 accepts.\n"); printf("Tox1 adds tox2 as friend, tox2 accepts.\n");
tox_callback_friend_request(tox2, accept_friend_request); tox_events_callback_friend_request(dispatch, accept_friend_request);
uint8_t address[TOX_ADDRESS_SIZE]; uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address); tox_self_get_address(tox2, address);
@ -61,16 +88,14 @@ static void test_friend_request(void)
ck_assert_msg(test == 0, "failed to add friend error code: %u", test); ck_assert_msg(test == 0, "failed to add friend error code: %u", test);
do { do {
tox_iterate(tox1, nullptr); iterate2_wait(dispatch, tox1, tox2);
tox_iterate(tox2, nullptr);
c_sleep(ITERATION_INTERVAL);
} while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP || } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP); tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
printf("Tox clients connected took %lu seconds.\n", (unsigned long)(time(nullptr) - con_time)); printf("Tox clients connected took %lu seconds.\n", (unsigned long)(time(nullptr) - con_time));
printf("friend_request_test succeeded, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time)); printf("friend_request_test succeeded, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time));
tox_dispatch_free(dispatch);
tox_kill(tox1); tox_kill(tox1);
tox_kill(tox2); tox_kill(tox2);
} }

View File

@ -43,7 +43,7 @@ typedef struct State {
#define PEER_LIMIT 20 #define PEER_LIMIT 20
static void print_ip(Tox *tox, uint32_t groupnumber, uint32_t peer_id) static void print_ip(const Tox *tox, uint32_t groupnumber, uint32_t peer_id)
{ {
Tox_Err_Group_Peer_Query err; Tox_Err_Group_Peer_Query err;
size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err); size_t length = tox_group_peer_get_ip_address_size(tox, groupnumber, peer_id, &err);
@ -81,32 +81,35 @@ static bool all_group_peers_connected(AutoTox *autotoxes, uint32_t tox_count, ui
return true; return true;
} }
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t groupnumber = tox_event_group_peer_join_get_group_number(event);
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
// we do a connection test here for fun // we do a connection test here for fun
Tox_Err_Group_Peer_Query pq_err; Tox_Err_Group_Peer_Query pq_err;
TOX_CONNECTION connection_status = tox_group_peer_get_connection_status(tox, groupnumber, peer_id, &pq_err); Tox_Connection connection_status = tox_group_peer_get_connection_status(autotox->tox, groupnumber, peer_id, &pq_err);
ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(connection_status != TOX_CONNECTION_NONE); ck_assert(connection_status != TOX_CONNECTION_NONE);
Tox_Group_Role role = tox_group_peer_get_role(tox, groupnumber, peer_id, &pq_err); Tox_Group_Role role = tox_group_peer_get_role(autotox->tox, groupnumber, peer_id, &pq_err);
ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err); ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
Tox_User_Status status = tox_group_peer_get_status(tox, groupnumber, peer_id, &pq_err); Tox_User_Status status = tox_group_peer_get_status(autotox->tox, groupnumber, peer_id, &pq_err);
ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err); ck_assert_msg(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK, "%d", pq_err);
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &pq_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &pq_err);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &pq_err); tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &pq_err);
ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(pq_err == TOX_ERR_GROUP_PEER_QUERY_OK);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
@ -137,35 +140,37 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
} }
fprintf(stderr, "%s joined with IP: ", peer_name); fprintf(stderr, "%s joined with IP: ", peer_name);
print_ip(tox, groupnumber, peer_id); print_ip(autotox->tox, groupnumber, peer_id);
state->peer_id = peer_id; state->peer_id = peer_id;
++state->peer_joined_count; ++state->peer_joined_count;
} }
static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *user_data) static void group_peer_self_join_handler(const Tox_Event_Group_Self_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t groupnumber = tox_event_group_self_join_get_group_number(event);
// make sure we see our own correct peer state on join callback // make sure we see our own correct peer state on join callback
Tox_Err_Group_Self_Query sq_err; Tox_Err_Group_Self_Query sq_err;
size_t self_length = tox_group_self_get_name_size(tox, groupnumber, &sq_err); size_t self_length = tox_group_self_get_name_size(autotox->tox, groupnumber, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
uint8_t self_name[TOX_MAX_NAME_LENGTH]; uint8_t self_name[TOX_MAX_NAME_LENGTH];
tox_group_self_get_name(tox, groupnumber, self_name, &sq_err); tox_group_self_get_name(autotox->tox, groupnumber, self_name, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
TOX_USER_STATUS self_status = tox_group_self_get_status(tox, groupnumber, &sq_err); Tox_User_Status self_status = tox_group_self_get_status(autotox->tox, groupnumber, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
Tox_Group_Role self_role = tox_group_self_get_role(tox, groupnumber, &sq_err); Tox_Group_Role self_role = tox_group_self_get_role(autotox->tox, groupnumber, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
if (state->is_founder) { if (state->is_founder) {
@ -185,36 +190,37 @@ static void group_peer_self_join_handler(Tox *tox, uint32_t groupnumber, void *u
uint8_t group_name[GROUP_NAME_LEN]; uint8_t group_name[GROUP_NAME_LEN];
uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH]; uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
ck_assert(tox_group_get_peer_limit(tox, groupnumber, nullptr) == PEER_LIMIT); ck_assert(tox_group_get_peer_limit(autotox->tox, groupnumber, nullptr) == PEER_LIMIT);
ck_assert(tox_group_get_name_size(tox, groupnumber, nullptr) == GROUP_NAME_LEN); ck_assert(tox_group_get_name_size(autotox->tox, groupnumber, nullptr) == GROUP_NAME_LEN);
ck_assert(tox_group_get_topic_size(tox, groupnumber, nullptr) == TOPIC_LEN); ck_assert(tox_group_get_topic_size(autotox->tox, groupnumber, nullptr) == TOPIC_LEN);
Tox_Err_Group_State_Queries query_err; Tox_Err_Group_State_Query query_err;
tox_group_get_name(tox, groupnumber, group_name, &query_err); tox_group_get_name(autotox->tox, groupnumber, group_name, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", query_err);
ck_assert(memcmp(group_name, GROUP_NAME, GROUP_NAME_LEN) == 0); ck_assert(memcmp(group_name, GROUP_NAME, GROUP_NAME_LEN) == 0);
tox_group_get_topic(tox, groupnumber, topic, &query_err); tox_group_get_topic(autotox->tox, groupnumber, topic, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", query_err);
ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0); ck_assert(memcmp(topic, TOPIC, TOPIC_LEN) == 0);
uint32_t peer_id = tox_group_self_get_peer_id(tox, groupnumber, nullptr); uint32_t peer_id = tox_group_self_get_peer_id(autotox->tox, groupnumber, nullptr);
fprintf(stderr, "self joined with IP: "); fprintf(stderr, "self joined with IP: ");
print_ip(tox, groupnumber, peer_id); print_ip(autotox->tox, groupnumber, peer_id);
++state->self_joined_count; ++state->self_joined_count;
} }
static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type, static void group_peer_exit_handler(const Tox_Event_Group_Peer_Exit *event, void *user_data)
const uint8_t *name, size_t name_length, const uint8_t *part_message,
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint8_t *part_message = tox_event_group_peer_exit_get_part_message(event);
const size_t length = tox_event_group_peer_exit_get_part_message_length(event);
++state->peer_exit_count; ++state->peer_exit_count;
// first exit is a disconnect. second is a real exit with a part message // first exit is a disconnect. second is a real exit with a part message
@ -224,14 +230,16 @@ static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
} }
} }
static void group_peer_name_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *name, static void group_peer_name_handler(const Tox_Event_Group_Peer_Name *event, void *user_data)
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint8_t *name = tox_event_group_peer_name_get_name(event);
const size_t length = tox_event_group_peer_name_get_name_length(event);
// note: we already test the name_get api call elsewhere // note: we already test the name_get api call elsewhere
ck_assert(length == PEER0_NICK2_LEN); ck_assert(length == PEER0_NICK2_LEN);
@ -240,7 +248,7 @@ static void group_peer_name_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
state->peer_nick = true; state->peer_nick = true;
} }
static void group_peer_status_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_USER_STATUS status, static void group_peer_status_handler(const Tox_Event_Group_Peer_Status *event,
void *user_data) void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
@ -248,8 +256,12 @@ static void group_peer_status_handler(Tox *tox, uint32_t groupnumber, uint32_t p
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t groupnumber = tox_event_group_peer_status_get_group_number(event);
const uint32_t peer_id = tox_event_group_peer_status_get_peer_id(event);
const Tox_User_Status status = tox_event_group_peer_status_get_status(event);
Tox_Err_Group_Peer_Query err; Tox_Err_Group_Peer_Query err;
TOX_USER_STATUS cur_status = tox_group_peer_get_status(tox, groupnumber, peer_id, &err); Tox_User_Status cur_status = tox_group_peer_get_status(autotox->tox, groupnumber, peer_id, &err);
ck_assert_msg(cur_status == status, "%d, %d", cur_status, status); ck_assert_msg(cur_status == status, "%d, %d", cur_status, status);
ck_assert(status == TOX_USER_STATUS_BUSY); ck_assert(status == TOX_USER_STATUS_BUSY);
@ -264,15 +276,15 @@ static void group_announce_test(AutoTox *autotoxes)
Tox *tox0 = autotoxes[0].tox; Tox *tox0 = autotoxes[0].tox;
Tox *tox1 = autotoxes[1].tox; Tox *tox1 = autotoxes[1].tox;
State *state0 = (State *)autotoxes[0].state; State *state0 = (State *)autotoxes[0].state;
State *state1 = (State *)autotoxes[1].state; const State *state1 = (const State *)autotoxes[1].state;
tox_callback_group_peer_join(tox0, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
tox_callback_group_peer_join(tox1, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
tox_callback_group_self_join(tox0, group_peer_self_join_handler); tox_events_callback_group_self_join(autotoxes[0].dispatch, group_peer_self_join_handler);
tox_callback_group_self_join(tox1, group_peer_self_join_handler); tox_events_callback_group_self_join(autotoxes[1].dispatch, group_peer_self_join_handler);
tox_callback_group_peer_name(tox1, group_peer_name_handler); tox_events_callback_group_peer_name(autotoxes[1].dispatch, group_peer_name_handler);
tox_callback_group_peer_status(tox1, group_peer_status_handler); tox_events_callback_group_peer_status(autotoxes[1].dispatch, group_peer_status_handler);
tox_callback_group_peer_exit(tox1, group_peer_exit_handler); tox_events_callback_group_peer_exit(autotoxes[1].dispatch, group_peer_exit_handler);
// tox0 makes new group. // tox0 makes new group.
Tox_Err_Group_New err_new; Tox_Err_Group_New err_new;
@ -286,19 +298,19 @@ static void group_announce_test(AutoTox *autotoxes)
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
// changes the state (for sync check purposes) // changes the state (for sync check purposes)
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err; Tox_Err_Group_Set_Peer_Limit limit_set_err;
tox_group_founder_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err); tox_group_set_peer_limit(tox0, groupnumber, PEER_LIMIT, &limit_set_err);
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err); ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
Tox_Err_Group_Topic_Set tp_err; Tox_Err_Group_Topic_Set tp_err;
tox_group_set_topic(tox0, groupnumber, (const uint8_t *)TOPIC, TOPIC_LEN, &tp_err); tox_group_set_topic(tox0, groupnumber, (const uint8_t *)TOPIC, TOPIC_LEN, &tp_err);
ck_assert(tp_err == TOX_ERR_GROUP_TOPIC_SET_OK); ck_assert(tp_err == TOX_ERR_GROUP_TOPIC_SET_OK);
// get the chat id of the new group. // get the chat id of the new group.
Tox_Err_Group_State_Queries err_id; Tox_Err_Group_State_Query err_id;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox0, groupnumber, chat_id, &err_id); tox_group_get_chat_id(tox0, groupnumber, chat_id, &err_id);
ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(err_id == TOX_ERR_GROUP_STATE_QUERY_OK);
// tox1 joins it. // tox1 joins it.
Tox_Err_Group_Join err_join; Tox_Err_Group_Join err_join;
@ -343,7 +355,7 @@ static void group_announce_test(AutoTox *autotoxes)
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
TOX_USER_STATUS self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err); Tox_User_Status self_status = tox_group_self_get_status(tox0, groupnumber, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(self_status == TOX_USER_STATUS_BUSY); ck_assert(self_status == TOX_USER_STATUS_BUSY);
@ -429,10 +441,12 @@ static void group_announce_test(AutoTox *autotoxes)
tox_group_leave(tox1, groupnumber, nullptr, 0, &err_exit); tox_group_leave(tox1, groupnumber, nullptr, 0, &err_exit);
ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK); ck_assert(err_exit == TOX_ERR_GROUP_LEAVE_OK);
while (num_groups1 != 0 || num_groups2 != 0) {
num_groups1 = tox_group_get_number_groups(tox0); num_groups1 = tox_group_get_number_groups(tox0);
num_groups2 = tox_group_get_number_groups(tox1); num_groups2 = tox_group_get_number_groups(tox1);
ck_assert(num_groups1 == num_groups2 && num_groups2 == 0); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
}
printf("All tests passed!\n"); printf("All tests passed!\n");
} }

View File

@ -51,13 +51,15 @@ static bool group_has_full_graph(const AutoTox *autotoxes, uint32_t group_number
return true; return true;
} }
static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data) static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
switch (fail_type) { switch (fail_type) {
case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: { case TOX_GROUP_JOIN_FAIL_PEER_LIMIT: {
state->peer_limit_fail = true; state->peer_limit_fail = true;
@ -79,7 +81,7 @@ static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_J
} }
} }
static void group_self_join_handler(Tox *tox, uint32_t group_number, void *user_data) static void group_self_join_handler(const Tox_Event_Group_Self_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -89,7 +91,7 @@ static void group_self_join_handler(Tox *tox, uint32_t group_number, void *user_
state->connected = true; state->connected = true;
} }
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -105,9 +107,9 @@ static void group_invite_test(AutoTox *autotoxes)
ck_assert_msg(NUM_GROUP_TOXES > 7, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES); ck_assert_msg(NUM_GROUP_TOXES > 7, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
tox_callback_group_join_fail(autotoxes[i].tox, group_join_fail_handler); tox_events_callback_group_join_fail(autotoxes[i].dispatch, group_join_fail_handler);
tox_callback_group_self_join(autotoxes[i].tox, group_self_join_handler); tox_events_callback_group_self_join(autotoxes[i].dispatch, group_self_join_handler);
} }
Tox *tox0 = autotoxes[0].tox; Tox *tox0 = autotoxes[0].tox;
@ -118,12 +120,12 @@ static void group_invite_test(AutoTox *autotoxes)
Tox *tox5 = autotoxes[5].tox; Tox *tox5 = autotoxes[5].tox;
Tox *tox6 = autotoxes[6].tox; Tox *tox6 = autotoxes[6].tox;
State *state0 = (State *)autotoxes[0].state; const State *state0 = (const State *)autotoxes[0].state;
State *state2 = (State *)autotoxes[2].state; const State *state2 = (const State *)autotoxes[2].state;
State *state3 = (State *)autotoxes[3].state; const State *state3 = (const State *)autotoxes[3].state;
State *state4 = (State *)autotoxes[4].state; const State *state4 = (const State *)autotoxes[4].state;
State *state5 = (State *)autotoxes[5].state; const State *state5 = (const State *)autotoxes[5].state;
State *state6 = (State *)autotoxes[6].state; const State *state6 = (const State *)autotoxes[6].state;
Tox_Err_Group_New new_err; Tox_Err_Group_New new_err;
uint32_t groupnumber = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4, uint32_t groupnumber = tox_group_new(tox0, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
@ -132,11 +134,11 @@ static void group_invite_test(AutoTox *autotoxes)
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err); tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err); ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
// peer 1 joins public group with no password // peer 1 joins public group with no password
Tox_Err_Group_Join join_err; Tox_Err_Group_Join join_err;
@ -150,9 +152,9 @@ static void group_invite_test(AutoTox *autotoxes)
printf("Peer 1 joined group\n"); printf("Peer 1 joined group\n");
// founder sets a password // founder sets a password
Tox_Err_Group_Founder_Set_Password pass_set_err; Tox_Err_Group_Set_Password pass_set_err;
tox_group_founder_set_password(tox0, groupnumber, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err); tox_group_set_password(tox0, groupnumber, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "%d", pass_set_err); ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "%d", pass_set_err);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
@ -177,9 +179,9 @@ static void group_invite_test(AutoTox *autotoxes)
printf("Peer 3 successfully blocked with invalid password\n"); printf("Peer 3 successfully blocked with invalid password\n");
// founder sets peer limit to 1 // founder sets peer limit to 1
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err; Tox_Err_Group_Set_Peer_Limit limit_set_err;
tox_group_founder_set_peer_limit(tox0, groupnumber, 1, &limit_set_err); tox_group_set_peer_limit(tox0, groupnumber, 1, &limit_set_err);
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "%d", limit_set_err); ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "%d", limit_set_err);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
@ -194,11 +196,11 @@ static void group_invite_test(AutoTox *autotoxes)
printf("Peer 4 successfully blocked from joining full group\n"); printf("Peer 4 successfully blocked from joining full group\n");
// founder removes password and increases peer limit to 100 // founder removes password and increases peer limit to 100
tox_group_founder_set_password(tox0, groupnumber, nullptr, 0, &pass_set_err); tox_group_set_password(tox0, groupnumber, nullptr, 0, &pass_set_err);
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "%d", pass_set_err); ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "%d", pass_set_err);
tox_group_founder_set_peer_limit(tox0, groupnumber, 100, &limit_set_err); tox_group_set_peer_limit(tox0, groupnumber, 100, &limit_set_err);
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "%d", limit_set_err); ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "%d", limit_set_err);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
@ -213,9 +215,9 @@ static void group_invite_test(AutoTox *autotoxes)
printf("Peer 5 successfully joined the group\n"); printf("Peer 5 successfully joined the group\n");
// founder makes group private // founder makes group private
Tox_Err_Group_Founder_Set_Privacy_State priv_err; Tox_Err_Group_Set_Privacy_State priv_err;
tox_group_founder_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PRIVATE, &priv_err); tox_group_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PRIVATE, &priv_err);
ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "%d", priv_err); ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "%d", priv_err);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, 5000);
@ -231,8 +233,8 @@ static void group_invite_test(AutoTox *autotoxes)
printf("Peer 6 failed to join private group via chat ID\n"); printf("Peer 6 failed to join private group via chat ID\n");
// founder makes group public again // founder makes group public again
tox_group_founder_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PUBLIC, &priv_err); tox_group_set_privacy_state(tox0, groupnumber, TOX_GROUP_PRIVACY_STATE_PUBLIC, &priv_err);
ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "%d", priv_err); ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "%d", priv_err);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);

View File

@ -19,7 +19,7 @@ typedef struct State {
bool peer_joined; bool peer_joined;
bool message_sent; bool message_sent;
bool message_received; bool message_received;
uint32_t pseudo_msg_id; Tox_Group_Message_Id pseudo_msg_id;
bool private_message_received; bool private_message_received;
size_t custom_packets_received; size_t custom_packets_received;
size_t custom_private_packets_received; size_t custom_private_packets_received;
@ -71,28 +71,37 @@ static uint16_t get_message_checksum(const uint8_t *message, uint16_t length)
return sum; return sum;
} }
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length, static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
const uint8_t *group_name, size_t group_name_length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
const size_t length = tox_event_group_invite_get_invite_data_length(event);
printf("invite arrived; accepting\n"); printf("invite arrived; accepting\n");
Tox_Err_Group_Invite_Accept err_accept; Tox_Err_Group_Invite_Accept err_accept;
tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN, tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)PEER0_NICK, PEER0_NICK_LEN,
nullptr, 0, &err_accept); nullptr, 0, &err_accept);
ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK); ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
} }
static void group_join_fail_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Join_Fail fail_type, void *user_data) static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
{ {
const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
printf("join failed: %d\n", fail_type); printf("join failed: %d\n", fail_type);
} }
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
ck_assert_msg(state->peer_joined == false, "Peer timedout"); ck_assert_msg(state->peer_joined == false, "Peer timedout");
printf("peer %u joined, sending message\n", peer_id); printf("peer %u joined, sending message\n", peer_id);
@ -100,9 +109,16 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
state->peer_id = peer_id; state->peer_id = peer_id;
} }
static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data, static void group_custom_private_packet_handler(const Tox_Event_Group_Custom_Private_Packet *event, void *user_data)
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t groupnumber = tox_event_group_custom_private_packet_get_group_number(event);
const uint32_t peer_id = tox_event_group_custom_private_packet_get_peer_id(event);
const uint8_t *data = tox_event_group_custom_private_packet_get_data(event);
const size_t length = tox_event_group_custom_private_packet_get_data_length(event);
ck_assert_msg(length == TEST_CUSTOM_PRIVATE_PACKET_LEN, ck_assert_msg(length == TEST_CUSTOM_PRIVATE_PACKET_LEN,
"Failed to receive custom private packet. Invalid length: %zu\n", length); "Failed to receive custom private packet. Invalid length: %zu\n", length);
@ -111,25 +127,25 @@ static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber,
message_buf[length] = 0; message_buf[length] = 0;
Tox_Err_Group_Peer_Query q_err; Tox_Err_Group_Peer_Query q_err;
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err); tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0); ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
Tox_Err_Group_Self_Query s_err; Tox_Err_Group_Self_Query s_err;
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err); size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
char self_name[TOX_MAX_NAME_LENGTH + 1]; char self_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err); tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
self_name[self_name_len] = 0; self_name[self_name_len] = 0;
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
@ -138,17 +154,21 @@ static void group_custom_private_packet_handler(Tox *tox, uint32_t groupnumber,
printf("%s sent custom private packet to %s: %s\n", peer_name, self_name, message_buf); printf("%s sent custom private packet to %s: %s\n", peer_name, self_name, message_buf);
ck_assert(memcmp(message_buf, TEST_CUSTOM_PRIVATE_PACKET, length) == 0); ck_assert(memcmp(message_buf, TEST_CUSTOM_PRIVATE_PACKET, length) == 0);
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
++state->custom_private_packets_received; ++state->custom_private_packets_received;
} }
static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data, static void group_custom_packet_handler(const Tox_Event_Group_Custom_Packet *event, void *user_data)
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t groupnumber = tox_event_group_custom_packet_get_group_number(event);
const uint32_t peer_id = tox_event_group_custom_packet_get_peer_id(event);
const uint8_t *data = tox_event_group_custom_packet_get_data(event);
const size_t length = tox_event_group_custom_packet_get_data_length(event);
ck_assert_msg(length == TEST_CUSTOM_PACKET_LEN, "Failed to receive custom packet. Invalid length: %zu\n", length); ck_assert_msg(length == TEST_CUSTOM_PACKET_LEN, "Failed to receive custom packet. Invalid length: %zu\n", length);
char message_buf[TOX_MAX_CUSTOM_PACKET_SIZE + 1]; char message_buf[TOX_MAX_CUSTOM_PACKET_SIZE + 1];
@ -156,25 +176,25 @@ static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t
message_buf[length] = 0; message_buf[length] = 0;
Tox_Err_Group_Peer_Query q_err; Tox_Err_Group_Peer_Query q_err;
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err); tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0); ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
Tox_Err_Group_Self_Query s_err; Tox_Err_Group_Self_Query s_err;
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err); size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
char self_name[TOX_MAX_NAME_LENGTH + 1]; char self_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err); tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
self_name[self_name_len] = 0; self_name[self_name_len] = 0;
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
@ -183,32 +203,39 @@ static void group_custom_packet_handler(Tox *tox, uint32_t groupnumber, uint32_t
printf("%s sent custom packet to %s: %s\n", peer_name, self_name, message_buf); printf("%s sent custom packet to %s: %s\n", peer_name, self_name, message_buf);
ck_assert(memcmp(message_buf, TEST_CUSTOM_PACKET, length) == 0); ck_assert(memcmp(message_buf, TEST_CUSTOM_PACKET, length) == 0);
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
++state->custom_packets_received; ++state->custom_packets_received;
} }
static void group_custom_packet_large_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *data, static void group_custom_packet_large_handler(const Tox_Event_Group_Custom_Packet *event, void *user_data)
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint8_t *data = tox_event_group_custom_packet_get_data(event);
const size_t length = tox_event_group_custom_packet_get_data_length(event);
ck_assert_msg(length == TEST_CUSTOM_PACKET_LARGE_LEN, "Failed to receive large custom packet. Invalid length: %zu\n", length); ck_assert_msg(length == TEST_CUSTOM_PACKET_LARGE_LEN, "Failed to receive large custom packet. Invalid length: %zu\n", length);
ck_assert(memcmp(data, TEST_CUSTOM_PACKET_LARGE, length) == 0); ck_assert(memcmp(data, TEST_CUSTOM_PACKET_LARGE, length) == 0);
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
++state->custom_packets_received; ++state->custom_packets_received;
} }
static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type, static void group_message_handler(const Tox_Event_Group_Message *event, void *user_data)
const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t groupnumber = tox_event_group_message_get_group_number(event);
const uint32_t peer_id = tox_event_group_message_get_peer_id(event);
const uint8_t *message = tox_event_group_message_get_message(event);
const size_t length = tox_event_group_message_get_message_length(event);
const uint32_t pseudo_msg_id = tox_event_group_message_get_message_id(event);
ck_assert(!(length == IGNORE_MESSAGE_LEN && memcmp(message, IGNORE_MESSAGE, length) == 0)); ck_assert(!(length == IGNORE_MESSAGE_LEN && memcmp(message, IGNORE_MESSAGE, length) == 0));
ck_assert_msg(length == TEST_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length); ck_assert_msg(length == TEST_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
@ -217,25 +244,25 @@ static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_
message_buf[length] = 0; message_buf[length] = 0;
Tox_Err_Group_Peer_Query q_err; Tox_Err_Group_Peer_Query q_err;
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err); tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0); ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
Tox_Err_Group_Self_Query s_err; Tox_Err_Group_Self_Query s_err;
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err); size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
char self_name[TOX_MAX_NAME_LENGTH + 1]; char self_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err); tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
self_name[self_name_len] = 0; self_name[self_name_len] = 0;
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
@ -244,19 +271,24 @@ static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_
printf("%s sent message to %s:(id:%u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf); printf("%s sent message to %s:(id:%u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
ck_assert(memcmp(message_buf, TEST_MESSAGE, length) == 0); ck_assert(memcmp(message_buf, TEST_MESSAGE, length) == 0);
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
state->message_received = true; state->message_received = true;
state->pseudo_msg_id = pseudo_msg_id; state->pseudo_msg_id = pseudo_msg_id;
} }
static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type, static void group_private_message_handler(const Tox_Event_Group_Private_Message *event, void *user_data)
const uint8_t *message, size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t groupnumber = tox_event_group_private_message_get_group_number(event);
const uint32_t peer_id = tox_event_group_private_message_get_peer_id(event);
const Tox_Message_Type type = tox_event_group_private_message_get_type(event);
const uint8_t *message = tox_event_group_private_message_get_message(event);
const size_t length = tox_event_group_private_message_get_message_length(event);
const Tox_Group_Message_Id pseudo_msg_id = tox_event_group_private_message_get_message_id(event);
ck_assert_msg(length == TEST_PRIVATE_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length); ck_assert_msg(length == TEST_PRIVATE_MESSAGE_LEN, "Failed to receive message. Invalid length: %zu\n", length);
char message_buf[TOX_GROUP_MAX_MESSAGE_LENGTH + 1]; char message_buf[TOX_GROUP_MAX_MESSAGE_LENGTH + 1];
@ -264,46 +296,46 @@ static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32
message_buf[length] = 0; message_buf[length] = 0;
Tox_Err_Group_Peer_Query q_err; Tox_Err_Group_Peer_Query q_err;
size_t peer_name_len = tox_group_peer_get_name_size(tox, groupnumber, peer_id, &q_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, groupnumber, peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_peer_get_name(tox, groupnumber, peer_id, (uint8_t *) peer_name, &q_err); tox_group_peer_get_name(autotox->tox, groupnumber, peer_id, (uint8_t *)peer_name, &q_err);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0); ck_assert(memcmp(peer_name, PEER0_NICK, peer_name_len) == 0);
Tox_Err_Group_Self_Query s_err; Tox_Err_Group_Self_Query s_err;
size_t self_name_len = tox_group_self_get_name_size(tox, groupnumber, &s_err); size_t self_name_len = tox_group_self_get_name_size(autotox->tox, groupnumber, &s_err);
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(self_name_len <= TOX_MAX_NAME_LENGTH);
char self_name[TOX_MAX_NAME_LENGTH + 1]; char self_name[TOX_MAX_NAME_LENGTH + 1];
tox_group_self_get_name(tox, groupnumber, (uint8_t *) self_name, &s_err); tox_group_self_get_name(autotox->tox, groupnumber, (uint8_t *)self_name, &s_err);
self_name[self_name_len] = 0; self_name[self_name_len] = 0;
ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(s_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(memcmp(self_name, PEER1_NICK, self_name_len) == 0); ck_assert(memcmp(self_name, PEER1_NICK, self_name_len) == 0);
printf("%s sent private action to %s: %s\n", peer_name, self_name, message_buf); printf("%s sent private action to %s:(id: %u) %s\n", peer_name, self_name, pseudo_msg_id, message_buf);
ck_assert(memcmp(message_buf, TEST_PRIVATE_MESSAGE, length) == 0); ck_assert(memcmp(message_buf, TEST_PRIVATE_MESSAGE, length) == 0);
ck_assert(type == TOX_MESSAGE_TYPE_ACTION); ck_assert(type == TOX_MESSAGE_TYPE_ACTION);
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
state->private_message_received = true; state->private_message_received = true;
state->pseudo_msg_id = pseudo_msg_id;
} }
static void group_message_handler_lossless_test(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type, static void group_message_handler_lossless_test(const Tox_Event_Group_Message *event, void *user_data)
const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
{ {
const uint8_t *message = tox_event_group_message_get_message(event);
const size_t length = tox_event_group_message_get_message_length(event);
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -325,10 +357,11 @@ static void group_message_handler_lossless_test(Tox *tox, uint32_t groupnumber,
state->lossless_check = true; state->lossless_check = true;
} }
} }
static void group_message_handler_wraparound_test(Tox *tox, uint32_t groupnumber, uint32_t peer_id, static void group_message_handler_wraparound_test(const Tox_Event_Group_Message *event, void *user_data)
TOX_MESSAGE_TYPE type,
const uint8_t *message, size_t length, uint32_t pseudo_msg_id, void *user_data)
{ {
const uint8_t *message = tox_event_group_message_get_message(event);
const size_t length = tox_event_group_message_get_message_length(event);
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -352,11 +385,11 @@ static void group_message_test(AutoTox *autotoxes)
{ {
ck_assert_msg(NUM_GROUP_TOXES >= 2, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES); ck_assert_msg(NUM_GROUP_TOXES >= 2, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
Tox *tox0 = autotoxes[0].tox; Tox *tox0 = autotoxes[0].tox;
Tox *tox1 = autotoxes[1].tox; const Tox *tox1 = autotoxes[1].tox;
State *state0 = (State *)autotoxes[0].state; State *state0 = (State *)autotoxes[0].state;
State *state1 = (State *)autotoxes[1].state; State *state1 = (State *)autotoxes[1].state;
@ -365,15 +398,15 @@ static void group_message_test(AutoTox *autotoxes)
state0->pseudo_msg_id = 0; state0->pseudo_msg_id = 0;
state1->pseudo_msg_id = 1; state1->pseudo_msg_id = 1;
tox_callback_group_invite(tox1, group_invite_handler); tox_events_callback_group_invite(autotoxes[1].dispatch, group_invite_handler);
tox_callback_group_join_fail(tox1, group_join_fail_handler); tox_events_callback_group_join_fail(autotoxes[1].dispatch, group_join_fail_handler);
tox_callback_group_peer_join(tox1, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[1].dispatch, group_peer_join_handler);
tox_callback_group_join_fail(tox0, group_join_fail_handler); tox_events_callback_group_join_fail(autotoxes[0].dispatch, group_join_fail_handler);
tox_callback_group_peer_join(tox0, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[0].dispatch, group_peer_join_handler);
tox_callback_group_message(tox0, group_message_handler); tox_events_callback_group_message(autotoxes[0].dispatch, group_message_handler);
tox_callback_group_custom_packet(tox0, group_custom_packet_handler); tox_events_callback_group_custom_packet(autotoxes[0].dispatch, group_custom_packet_handler);
tox_callback_group_custom_private_packet(tox0, group_custom_private_packet_handler); tox_events_callback_group_custom_private_packet(autotoxes[0].dispatch, group_custom_private_packet_handler);
tox_callback_group_private_message(tox0, group_private_message_handler); tox_events_callback_group_private_message(autotoxes[0].dispatch, group_private_message_handler);
Tox_Err_Group_Send_Message err_send; Tox_Err_Group_Send_Message err_send;
@ -403,7 +436,8 @@ static void group_message_test(AutoTox *autotoxes)
} }
} }
ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u", state0->pseudo_msg_id, state1->pseudo_msg_id); ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u",
state0->pseudo_msg_id, state1->pseudo_msg_id);
// Make sure we're still connected to each friend // Make sure we're still connected to each friend
Tox_Connection conn_1 = tox_friend_get_connection_status(tox0, 0, nullptr); Tox_Connection conn_1 = tox_friend_get_connection_status(tox0, 0, nullptr);
@ -428,14 +462,23 @@ static void group_message_test(AutoTox *autotoxes)
tox_group_set_ignore(tox0, group_number, state0->peer_id, false, &ig_err); tox_group_set_ignore(tox0, group_number, state0->peer_id, false, &ig_err);
ck_assert_msg(ig_err == TOX_ERR_GROUP_SET_IGNORE_OK, "%d", ig_err); ck_assert_msg(ig_err == TOX_ERR_GROUP_SET_IGNORE_OK, "%d", ig_err);
fprintf(stderr, "Sending private message...\n"); fprintf(stderr, "Sending private action...\n");
// tox0 sends a private action to tox1 // tox1 sends a private action to tox0
Tox_Err_Group_Send_Private_Message m_err; Tox_Err_Group_Send_Private_Message m_err;
tox_group_send_private_message(tox1, group_number, state1->peer_id, TOX_MESSAGE_TYPE_ACTION, state1->pseudo_msg_id = tox_group_send_private_message(tox1, group_number, state1->peer_id,
(const uint8_t *)TEST_PRIVATE_MESSAGE, TEST_PRIVATE_MESSAGE_LEN, &m_err); TOX_MESSAGE_TYPE_ACTION, (const uint8_t *)TEST_PRIVATE_MESSAGE,
TEST_PRIVATE_MESSAGE_LEN, &m_err);
ck_assert_msg(m_err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK, "%d", m_err); ck_assert_msg(m_err == TOX_ERR_GROUP_SEND_PRIVATE_MESSAGE_OK, "%d", m_err);
while (!state0->private_message_received) {
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
}
ck_assert_msg(state0->pseudo_msg_id == state1->pseudo_msg_id, "id0:%u id1:%u",
state0->pseudo_msg_id, state1->pseudo_msg_id);
fprintf(stderr, "Sending custom packets...\n"); fprintf(stderr, "Sending custom packets...\n");
// tox0 sends a lossless and lossy custom packet to tox1 // tox0 sends a lossless and lossy custom packet to tox1
@ -464,15 +507,14 @@ static void group_message_test(AutoTox *autotoxes)
ck_assert_msg(cperr == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK, "%d", cperr); ck_assert_msg(cperr == TOX_ERR_GROUP_SEND_CUSTOM_PRIVATE_PACKET_OK, "%d", cperr);
while (!state0->private_message_received || state0->custom_packets_received < 2 while (state0->custom_packets_received < 2 || state0->custom_private_packets_received < 2) {
|| state0->custom_private_packets_received < 2) {
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
} }
// tox0 sends a large max sized lossy custom packet // tox0 sends a large max sized lossy custom packet
// overwrite callback for larger packet // overwrite callback for larger packet
tox_callback_group_custom_packet(tox0, group_custom_packet_large_handler); tox_events_callback_group_custom_packet(autotoxes[0].dispatch, group_custom_packet_large_handler);
tox_group_send_custom_packet(tox1, group_number, false, (const uint8_t *)TEST_CUSTOM_PACKET_LARGE, TEST_CUSTOM_PACKET_LARGE_LEN, tox_group_send_custom_packet(tox1, group_number, false, (const uint8_t *)TEST_CUSTOM_PACKET_LARGE, TEST_CUSTOM_PACKET_LARGE_LEN,
&c_err); &c_err);
@ -486,7 +528,7 @@ static void group_message_test(AutoTox *autotoxes)
fprintf(stderr, "Doing lossless packet test...\n"); fprintf(stderr, "Doing lossless packet test...\n");
tox_callback_group_message(tox1, group_message_handler_lossless_test); tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler_lossless_test);
state1->last_msg_recv = -1; state1->last_msg_recv = -1;
// lossless and packet splitting/reassembly test // lossless and packet splitting/reassembly test
@ -517,7 +559,7 @@ static void group_message_test(AutoTox *autotoxes)
} }
state1->last_msg_recv = -1; state1->last_msg_recv = -1;
tox_callback_group_message(tox1, group_message_handler_wraparound_test); tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler_wraparound_test);
fprintf(stderr, "Doing wraparound test...\n"); fprintf(stderr, "Doing wraparound test...\n");

View File

@ -19,13 +19,13 @@
#define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1) #define GROUP_NAME_LEN (sizeof(GROUP_NAME) - 1)
typedef struct Peer { typedef struct Peer {
char name[TOX_MAX_NAME_LENGTH]; char name[TOX_MAX_NAME_LENGTH + 1];
size_t name_length; size_t name_length;
uint32_t peer_id; uint32_t peer_id;
} Peer; } Peer;
typedef struct State { typedef struct State {
char self_name[TOX_MAX_NAME_LENGTH]; char self_name[TOX_MAX_NAME_LENGTH + 1];
size_t self_name_length; size_t self_name_length;
uint32_t group_number; uint32_t group_number;
@ -38,7 +38,6 @@ typedef struct State {
char mod_name1[TOX_MAX_NAME_LENGTH]; char mod_name1[TOX_MAX_NAME_LENGTH];
char mod_name2[TOX_MAX_NAME_LENGTH]; char mod_name2[TOX_MAX_NAME_LENGTH];
bool observer_check; bool observer_check;
size_t observer_event_count; size_t observer_event_count;
char observer_name1[TOX_MAX_NAME_LENGTH]; char observer_name1[TOX_MAX_NAME_LENGTH];
@ -53,7 +52,7 @@ typedef struct State {
static bool all_peers_connected(AutoTox *autotoxes) static bool all_peers_connected(AutoTox *autotoxes)
{ {
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
State *state = (State *)autotoxes[i].state; const State *state = (const State *)autotoxes[i].state;
if (state->num_peers != NUM_GROUP_TOXES - 1) { if (state->num_peers != NUM_GROUP_TOXES - 1) {
return false; return false;
@ -146,7 +145,7 @@ static size_t get_state_index_by_nick(const AutoTox *autotoxes, size_t num_peers
ck_assert(name != nullptr && name_length <= TOX_MAX_NAME_LENGTH); ck_assert(name != nullptr && name_length <= TOX_MAX_NAME_LENGTH);
for (size_t i = 0; i < num_peers; ++i) { for (size_t i = 0; i < num_peers; ++i) {
State *state = (State *)autotoxes[i].state; const State *state = (const State *)autotoxes[i].state;
if (memcmp(state->self_name, name, name_length) == 0) { if (memcmp(state->self_name, name, name_length) == 0) {
return i; return i;
@ -156,29 +155,33 @@ static size_t get_state_index_by_nick(const AutoTox *autotoxes, size_t num_peers
ck_assert_msg(0, "Failed to find index"); ck_assert_msg(0, "Failed to find index");
} }
static void group_join_fail_handler(Tox *tox, uint32_t group_number, Tox_Group_Join_Fail fail_type, void *user_data) static void group_join_fail_handler(const Tox_Event_Group_Join_Fail *event, void *user_data)
{ {
const Tox_Group_Join_Fail fail_type = tox_event_group_join_fail_get_fail_type(event);
fprintf(stderr, "Failed to join group: %d", fail_type); fprintf(stderr, "Failed to join group: %d", fail_type);
} }
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t group_number = tox_event_group_peer_join_get_group_number(event);
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
ck_assert(state->group_number == group_number); ck_assert(state->group_number == group_number);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
Tox_Err_Group_Peer_Query q_err; Tox_Err_Group_Peer_Query q_err;
size_t peer_name_len = tox_group_peer_get_name_size(tox, group_number, peer_id, &q_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, group_number, peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
tox_group_peer_get_name(tox, group_number, peer_id, (uint8_t *) peer_name, &q_err); tox_group_peer_get_name(autotox->tox, group_number, peer_id, (uint8_t *) peer_name, &q_err);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
@ -193,7 +196,7 @@ static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t pe
ck_assert(state->num_peers < NUM_GROUP_TOXES); ck_assert(state->num_peers < NUM_GROUP_TOXES);
} }
static void handle_mod(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role) static void handle_mod(State *state, const char *peer_name, size_t peer_name_len)
{ {
if (state->mod_event_count == 0) { if (state->mod_event_count == 0) {
ck_assert(memcmp(peer_name, state->mod_name1, peer_name_len) == 0); ck_assert(memcmp(peer_name, state->mod_name1, peer_name_len) == 0);
@ -205,10 +208,9 @@ static void handle_mod(State *state, const char *peer_name, size_t peer_name_len
++state->mod_event_count; ++state->mod_event_count;
state->mod_check = true; state->mod_check = true;
ck_assert(role == TOX_GROUP_ROLE_MODERATOR);
} }
static void handle_observer(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role) static void handle_observer(State *state, const char *peer_name, size_t peer_name_len)
{ {
if (state->observer_event_count == 0) { if (state->observer_event_count == 0) {
ck_assert(memcmp(peer_name, state->observer_name1, peer_name_len) == 0); ck_assert(memcmp(peer_name, state->observer_name1, peer_name_len) == 0);
@ -220,10 +222,9 @@ static void handle_observer(State *state, const char *peer_name, size_t peer_nam
++state->observer_event_count; ++state->observer_event_count;
state->observer_check = true; state->observer_check = true;
ck_assert(role == TOX_GROUP_ROLE_OBSERVER);
} }
static void handle_user(State *state, const char *peer_name, size_t peer_name_len, Tox_Group_Role role) static void handle_user(State *state, const char *peer_name, size_t peer_name_len)
{ {
// event 1: observer1 gets promoted back to user // event 1: observer1 gets promoted back to user
// event 2: observer2 gets promoted to moderator // event 2: observer2 gets promoted to moderator
@ -243,23 +244,25 @@ static void handle_user(State *state, const char *peer_name, size_t peer_name_le
++state->user_event_count; ++state->user_event_count;
state->user_check = true; state->user_check = true;
ck_assert(role == TOX_GROUP_ROLE_USER);
} }
static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t source_peer_id, uint32_t target_peer_id, static void group_mod_event_handler(const Tox_Event_Group_Moderation *event, void *user_data)
Tox_Group_Mod_Event mod_type, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t group_number = tox_event_group_moderation_get_group_number(event);
const uint32_t target_peer_id = tox_event_group_moderation_get_target_peer_id(event);
const Tox_Group_Mod_Event mod_type = tox_event_group_moderation_get_mod_type(event);
ck_assert(state->group_number == group_number); ck_assert(state->group_number == group_number);
char peer_name[TOX_MAX_NAME_LENGTH + 1]; char peer_name[TOX_MAX_NAME_LENGTH + 1];
Tox_Err_Group_Peer_Query q_err; Tox_Err_Group_Peer_Query q_err;
size_t peer_name_len = tox_group_peer_get_name_size(tox, group_number, target_peer_id, &q_err); size_t peer_name_len = tox_group_peer_get_name_size(autotox->tox, group_number, target_peer_id, &q_err);
if (q_err == TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND) { // may occurr on sync attempts if (q_err == TOX_ERR_GROUP_PEER_QUERY_PEER_NOT_FOUND) { // may occurr on sync attempts
return; return;
@ -268,12 +271,13 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
ck_assert_msg(q_err == TOX_ERR_GROUP_PEER_QUERY_OK, "error %d", q_err); ck_assert_msg(q_err == TOX_ERR_GROUP_PEER_QUERY_OK, "error %d", q_err);
ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH); ck_assert(peer_name_len <= TOX_MAX_NAME_LENGTH);
tox_group_peer_get_name(tox, group_number, target_peer_id, (uint8_t *) peer_name, &q_err); tox_group_peer_get_name(autotox->tox, group_number, target_peer_id, (uint8_t *) peer_name, &q_err);
peer_name[peer_name_len] = 0; peer_name[peer_name_len] = 0;
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
Tox_Group_Role role = tox_group_peer_get_role(tox, group_number, target_peer_id, &q_err); Tox_Group_Role role = tox_group_peer_get_role(autotox->tox, group_number, target_peer_id, &q_err);
ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK); ck_assert(q_err == TOX_ERR_GROUP_PEER_QUERY_OK);
ck_assert(role <= TOX_GROUP_ROLE_OBSERVER);
fprintf(stderr, "tox%u: got moderator event %d (%s), role = %s\n", fprintf(stderr, "tox%u: got moderator event %d (%s), role = %s\n",
autotox->index, mod_type, tox_group_mod_event_to_string(mod_type), autotox->index, mod_type, tox_group_mod_event_to_string(mod_type),
@ -281,17 +285,17 @@ static void group_mod_event_handler(Tox *tox, uint32_t group_number, uint32_t so
switch (mod_type) { switch (mod_type) {
case TOX_GROUP_MOD_EVENT_MODERATOR: { case TOX_GROUP_MOD_EVENT_MODERATOR: {
handle_mod(state, peer_name, peer_name_len, role); handle_mod(state, peer_name, peer_name_len);
break; break;
} }
case TOX_GROUP_MOD_EVENT_OBSERVER: { case TOX_GROUP_MOD_EVENT_OBSERVER: {
handle_observer(state, peer_name, peer_name_len, role); handle_observer(state, peer_name, peer_name_len);
break; break;
} }
case TOX_GROUP_MOD_EVENT_USER: { case TOX_GROUP_MOD_EVENT_USER: {
handle_user(state, peer_name, peer_name_len, role); handle_user(state, peer_name, peer_name_len);
break; break;
} }
@ -314,7 +318,7 @@ static void check_self_role(AutoTox *autotoxes, uint32_t peer_id, Tox_Group_Role
Tox_Err_Group_Self_Query sq_err; Tox_Err_Group_Self_Query sq_err;
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
State *state = (State *)autotoxes[i].state; const State *state = (const State *)autotoxes[i].state;
uint32_t self_peer_id = tox_group_self_get_peer_id(autotoxes[i].tox, state->group_number, &sq_err); uint32_t self_peer_id = tox_group_self_get_peer_id(autotoxes[i].tox, state->group_number, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
@ -378,13 +382,13 @@ static void voice_state_message_test(AutoTox *autotox, Tox_Group_Voice_State voi
static bool all_peers_got_voice_state_change(AutoTox *autotoxes, uint32_t num_toxes, static bool all_peers_got_voice_state_change(AutoTox *autotoxes, uint32_t num_toxes,
Tox_Group_Voice_State expected_voice_state) Tox_Group_Voice_State expected_voice_state)
{ {
Tox_Err_Group_State_Queries query_err; Tox_Err_Group_State_Query query_err;
for (uint32_t i = 0; i < num_toxes; ++i) { for (uint32_t i = 0; i < num_toxes; ++i) {
const State *state = (State *)autotoxes[i].state; const State *state = (State *)autotoxes[i].state;
Tox_Group_Voice_State voice_state = tox_group_get_voice_state(autotoxes[i].tox, state->group_number, &query_err); Tox_Group_Voice_State voice_state = tox_group_get_voice_state(autotoxes[i].tox, state->group_number, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (voice_state != expected_voice_state) { if (voice_state != expected_voice_state) {
return false; return false;
@ -398,10 +402,10 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
{ {
// founder sets voice state to Moderator // founder sets voice state to Moderator
const State *state = (State *)autotoxes[0].state; const State *state = (State *)autotoxes[0].state;
Tox_Err_Group_Founder_Set_Voice_State voice_set_err; Tox_Err_Group_Set_Voice_State voice_set_err;
tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_MODERATOR, tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_MODERATOR,
&voice_set_err); &voice_set_err);
ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK); ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
for (uint32_t i = 0; i < num_toxes; ++i) { for (uint32_t i = 0; i < num_toxes; ++i) {
do { do {
@ -411,8 +415,8 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_MODERATOR); voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_MODERATOR);
} }
tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_FOUNDER, &voice_set_err); tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_FOUNDER, &voice_set_err);
ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK); ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
for (uint32_t i = 0; i < num_toxes; ++i) { for (uint32_t i = 0; i < num_toxes; ++i) {
do { do {
@ -422,8 +426,8 @@ static void check_voice_state(AutoTox *autotoxes, uint32_t num_toxes)
voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_FOUNDER); voice_state_message_test(&autotoxes[i], TOX_GROUP_VOICE_STATE_FOUNDER);
} }
tox_group_founder_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_ALL, &voice_set_err); tox_group_set_voice_state(autotoxes[0].tox, state->group_number, TOX_GROUP_VOICE_STATE_ALL, &voice_set_err);
ck_assert(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK); ck_assert(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK);
for (uint32_t i = 0; i < num_toxes; ++i) { for (uint32_t i = 0; i < num_toxes; ++i) {
do { do {
@ -447,9 +451,9 @@ static void group_moderation_test(AutoTox *autotoxes)
snprintf(state->self_name, sizeof(state->self_name), "peer_%zu", i); snprintf(state->self_name, sizeof(state->self_name), "peer_%zu", i);
state->self_name[name_length] = 0; state->self_name[name_length] = 0;
tox_callback_group_join_fail(autotoxes[i].tox, group_join_fail_handler); tox_events_callback_group_join_fail(autotoxes[i].dispatch, group_join_fail_handler);
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
tox_callback_group_moderation(autotoxes[i].tox, group_mod_event_handler); tox_events_callback_group_moderation(autotoxes[i].dispatch, group_mod_event_handler);
} }
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
@ -468,11 +472,11 @@ static void group_moderation_test(AutoTox *autotoxes)
ck_assert_msg(err_new == TOX_ERR_GROUP_NEW_OK, "Failed to create group. error: %d\n", err_new); ck_assert_msg(err_new == TOX_ERR_GROUP_NEW_OK, "Failed to create group. error: %d\n", err_new);
/* Founder gets chat ID */ /* Founder gets chat ID */
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox0, state0->group_number, chat_id, &id_err); tox_group_get_chat_id(tox0, state0->group_number, chat_id, &id_err);
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get chat ID. error: %d", id_err); ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get chat ID. error: %d", id_err);
fprintf(stderr, "Peers attemping to join DHT group via the chat ID\n"); fprintf(stderr, "Peers attemping to join DHT group via the chat ID\n");
@ -512,7 +516,7 @@ static void group_moderation_test(AutoTox *autotoxes)
/* all peers should be user role except founder */ /* all peers should be user role except founder */
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
State *state = (State *)autotoxes[i].state; const State *state = (const State *)autotoxes[i].state;
self_role = tox_group_self_get_role(autotoxes[i].tox, state->group_number, &sq_err); self_role = tox_group_self_get_role(autotoxes[i].tox, state->group_number, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
ck_assert(self_role == TOX_GROUP_ROLE_USER); ck_assert(self_role == TOX_GROUP_ROLE_USER);
@ -521,9 +525,9 @@ static void group_moderation_test(AutoTox *autotoxes)
/* founder sets first peer to moderator */ /* founder sets first peer to moderator */
fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[0].name); fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[0].name);
Tox_Err_Group_Mod_Set_Role role_err; Tox_Err_Group_Set_Role role_err;
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[0].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err); tox_group_set_role(tox0, state0->group_number, state0->peers[0].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
// manually flag the role setter because they don't get a callback // manually flag the role setter because they don't get a callback
state0->mod_check = true; state0->mod_check = true;
@ -537,8 +541,8 @@ static void group_moderation_test(AutoTox *autotoxes)
/* founder sets second and third peer to observer */ /* founder sets second and third peer to observer */
fprintf(stderr, "Founder setting %s to observer\n", state0->peers[1].name); fprintf(stderr, "Founder setting %s to observer\n", state0->peers[1].name);
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[1].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err); tox_group_set_role(tox0, state0->group_number, state0->peers[1].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set observer. error: %d", role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
state0->observer_check = true; state0->observer_check = true;
++state0->observer_event_count; ++state0->observer_event_count;
@ -548,8 +552,8 @@ static void group_moderation_test(AutoTox *autotoxes)
fprintf(stderr, "Founder setting %s to observer\n", state0->peers[2].name); fprintf(stderr, "Founder setting %s to observer\n", state0->peers[2].name);
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err); tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set observer. error: %d", role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set observer. error: %d", role_err);
state0->observer_check = true; state0->observer_check = true;
++state0->observer_event_count; ++state0->observer_event_count;
@ -574,8 +578,8 @@ static void group_moderation_test(AutoTox *autotoxes)
fprintf(stderr, "%s is promoting %s back to user\n", state1->self_name, state0->peers[1].name); fprintf(stderr, "%s is promoting %s back to user\n", state1->self_name, state0->peers[1].name);
tox_group_mod_set_role(tox1, state1->group_number, obs_peer_id, TOX_GROUP_ROLE_USER, &role_err); tox_group_set_role(tox1, state1->group_number, obs_peer_id, TOX_GROUP_ROLE_USER, &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to promote observer back to user. error: %d", ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to promote observer back to user. error: %d",
role_err); role_err);
state1->user_check = true; state1->user_check = true;
@ -587,8 +591,8 @@ static void group_moderation_test(AutoTox *autotoxes)
/* founder assigns third peer to moderator (this triggers two events: user and moderator) */ /* founder assigns third peer to moderator (this triggers two events: user and moderator) */
fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[2].name); fprintf(stderr, "Founder setting %s to moderator\n", state0->peers[2].name);
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err); tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_MODERATOR, &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
state0->mod_check = true; state0->mod_check = true;
++state0->mod_event_count; ++state0->mod_event_count;
@ -600,18 +604,27 @@ static void group_moderation_test(AutoTox *autotoxes)
/* moderator attempts to demote and kick founder */ /* moderator attempts to demote and kick founder */
uint32_t founder_peer_id = get_peer_id_by_nick(state1->peers, NUM_GROUP_TOXES - 1, state0->self_name); uint32_t founder_peer_id = get_peer_id_by_nick(state1->peers, NUM_GROUP_TOXES - 1, state0->self_name);
tox_group_mod_set_role(tox1, state1->group_number, founder_peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err); tox_group_set_role(tox1, state1->group_number, founder_peer_id, TOX_GROUP_ROLE_OBSERVER, &role_err);
ck_assert_msg(role_err != TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Mod set founder to observer"); ck_assert_msg(role_err != TOX_ERR_GROUP_SET_ROLE_OK, "Mod set founder to observer");
Tox_Err_Group_Mod_Kick_Peer k_err; Tox_Err_Group_Kick_Peer k_err;
tox_group_mod_kick_peer(tox1, state1->group_number, founder_peer_id, &k_err); tox_group_kick_peer(tox1, state1->group_number, founder_peer_id, &k_err);
ck_assert_msg(k_err != TOX_ERR_GROUP_MOD_KICK_PEER_OK, "Mod kicked founder"); ck_assert_msg(k_err != TOX_ERR_GROUP_KICK_PEER_OK, "Mod kicked founder");
/* the moderator about to be kicked changes the topic to trigger the founder to
* re-sign and redistribute it after the kick.
*/
const State *state_x = (const State *)autotoxes[idx].state;
Tox *tox_x = autotoxes[idx].tox;
Tox_Err_Group_Topic_Set topic_err;
tox_group_set_topic(tox_x, state_x->group_number, nullptr, 0, &topic_err);
ck_assert(topic_err == TOX_ERR_GROUP_TOPIC_SET_OK);
/* founder kicks moderator (this triggers two events: user and kick) */ /* founder kicks moderator (this triggers two events: user and kick) */
fprintf(stderr, "Founder is kicking %s\n", state0->peers[0].name); fprintf(stderr, "Founder is kicking %s\n", state0->peers[0].name);
tox_group_mod_kick_peer(tox0, state0->group_number, state0->peers[0].peer_id, &k_err); tox_group_kick_peer(tox0, state0->group_number, state0->peers[0].peer_id, &k_err);
ck_assert_msg(k_err == TOX_ERR_GROUP_MOD_KICK_PEER_OK, "Failed to kick peer. error: %d", k_err); ck_assert_msg(k_err == TOX_ERR_GROUP_KICK_PEER_OK, "Failed to kick peer. error: %d", k_err);
state0->kick_check = true; state0->kick_check = true;
check_mod_event(autotoxes, NUM_GROUP_TOXES, TOX_GROUP_MOD_EVENT_KICK); check_mod_event(autotoxes, NUM_GROUP_TOXES, TOX_GROUP_MOD_EVENT_KICK);
@ -619,9 +632,8 @@ static void group_moderation_test(AutoTox *autotoxes)
fprintf(stderr, "All peers successfully received kick event\n"); fprintf(stderr, "All peers successfully received kick event\n");
fprintf(stderr, "Founder is demoting moderator to user\n"); fprintf(stderr, "Founder is demoting moderator to user\n");
tox_group_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_USER, &role_err);
tox_group_mod_set_role(tox0, state0->group_number, state0->peers[2].peer_id, TOX_GROUP_ROLE_USER, &role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to demote peer 3 to User. error: %d", role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to demote peer 3 to User. error: %d", role_err);
state0->user_check = true; state0->user_check = true;
++state0->user_event_count; ++state0->user_event_count;

View File

@ -26,17 +26,23 @@ typedef struct State {
#define PEER0_NICK_LEN (sizeof(PEER0_NICK) -1) #define PEER0_NICK_LEN (sizeof(PEER0_NICK) -1)
#define NEW_USER_STATUS TOX_USER_STATUS_BUSY #define NEW_USER_STATUS TOX_USER_STATUS_BUSY
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length, static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
const uint8_t *group_name, size_t group_name_length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
const size_t length = tox_event_group_invite_get_invite_data_length(event);
Tox_Err_Group_Invite_Accept err_accept; Tox_Err_Group_Invite_Accept err_accept;
tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5, tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)"test2", 5,
nullptr, 0, &err_accept); nullptr, 0, &err_accept);
ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK); ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
} }
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -52,28 +58,28 @@ static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t pe
*/ */
static int has_correct_group_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_chat_id) static int has_correct_group_state(const Tox *tox, uint32_t group_number, const uint8_t *expected_chat_id)
{ {
Tox_Err_Group_State_Queries query_err; Tox_Err_Group_State_Query query_err;
Tox_Group_Privacy_State priv_state = tox_group_get_privacy_state(tox, group_number, &query_err); Tox_Group_Privacy_State priv_state = tox_group_get_privacy_state(tox, group_number, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (priv_state != NEW_PRIV_STATE) { if (priv_state != NEW_PRIV_STATE) {
return -1; return -1;
} }
size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err); size_t pass_len = tox_group_get_password_size(tox, group_number, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE]; uint8_t password[TOX_GROUP_MAX_PASSWORD_SIZE];
tox_group_get_password(tox, group_number, password, &query_err); tox_group_get_password(tox, group_number, password, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (pass_len != PASS_LEN || memcmp(password, PASSWORD, pass_len) != 0) { if (pass_len != PASS_LEN || memcmp(password, PASSWORD, pass_len) != 0) {
return -2; return -2;
} }
size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err); size_t gname_len = tox_group_get_name_size(tox, group_number, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
uint8_t group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH]; uint8_t group_name[TOX_GROUP_MAX_GROUP_NAME_LENGTH];
tox_group_get_name(tox, group_number, group_name, &query_err); tox_group_get_name(tox, group_number, group_name, &query_err);
@ -87,17 +93,17 @@ static int has_correct_group_state(const Tox *tox, uint32_t group_number, const
} }
Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(tox, group_number, &query_err); Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(tox, group_number, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (topic_lock != TOX_GROUP_TOPIC_LOCK_DISABLED) { if (topic_lock != TOX_GROUP_TOPIC_LOCK_DISABLED) {
return -5; return -5;
} }
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox, group_number, chat_id, &id_err); tox_group_get_chat_id(tox, group_number, chat_id, &id_err);
ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) != 0) { if (memcmp(chat_id, expected_chat_id, TOX_GROUP_CHAT_ID_SIZE) != 0) {
return -6; return -6;
@ -120,7 +126,7 @@ static int has_correct_self_state(const Tox *tox, uint32_t group_number, const u
return -1; return -1;
} }
TOX_USER_STATUS self_status = tox_group_self_get_status(tox, group_number, &sq_err); Tox_User_Status self_status = tox_group_self_get_status(tox, group_number, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
if (self_status != NEW_USER_STATUS) { if (self_status != NEW_USER_STATUS) {
@ -151,8 +157,8 @@ static void group_save_test(AutoTox *autotoxes)
ck_assert_msg(NUM_GROUP_TOXES > 1, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES); ck_assert_msg(NUM_GROUP_TOXES > 1, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
tox_callback_group_invite(autotoxes[i].tox, group_invite_handler); tox_events_callback_group_invite(autotoxes[i].dispatch, group_invite_handler);
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
} }
Tox *tox0 = autotoxes[0].tox; Tox *tox0 = autotoxes[0].tox;
@ -168,9 +174,9 @@ static void group_save_test(AutoTox *autotoxes)
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
tox_group_get_chat_id(tox0, group_number, chat_id, &id_err); tox_group_get_chat_id(tox0, group_number, chat_id, &id_err);
ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(id_err == TOX_ERR_GROUP_STATE_QUERY_OK);
uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE]; uint8_t founder_pk[TOX_GROUP_PEER_PUBLIC_KEY_SIZE];
@ -178,7 +184,6 @@ static void group_save_test(AutoTox *autotoxes)
tox_group_self_get_public_key(tox0, group_number, founder_pk, &sq_err); tox_group_self_get_public_key(tox0, group_number, founder_pk, &sq_err);
ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK); ck_assert(sq_err == TOX_ERR_GROUP_SELF_QUERY_OK);
Tox_Err_Group_Invite_Friend err_invite; Tox_Err_Group_Invite_Friend err_invite;
tox_group_invite_friend(tox0, group_number, 0, &err_invite); tox_group_invite_friend(tox0, group_number, 0, &err_invite);
@ -195,21 +200,21 @@ static void group_save_test(AutoTox *autotoxes)
tox_group_set_topic(tox0, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, &top_err); tox_group_set_topic(tox0, group_number, (const uint8_t *)TOPIC, TOPIC_LEN, &top_err);
ck_assert(top_err == TOX_ERR_GROUP_TOPIC_SET_OK); ck_assert(top_err == TOX_ERR_GROUP_TOPIC_SET_OK);
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err; Tox_Err_Group_Set_Topic_Lock lock_set_err;
tox_group_founder_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err); tox_group_set_topic_lock(tox0, group_number, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
ck_assert(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK); ck_assert(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK);
Tox_Err_Group_Founder_Set_Privacy_State priv_err; Tox_Err_Group_Set_Privacy_State priv_err;
tox_group_founder_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err); tox_group_set_privacy_state(tox0, group_number, NEW_PRIV_STATE, &priv_err);
ck_assert(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK); ck_assert(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK);
Tox_Err_Group_Founder_Set_Password pass_set_err; Tox_Err_Group_Set_Password pass_set_err;
tox_group_founder_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err); tox_group_set_password(tox0, group_number, (const uint8_t *)PASSWORD, PASS_LEN, &pass_set_err);
ck_assert(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK); ck_assert(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK);
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err; Tox_Err_Group_Set_Peer_Limit limit_set_err;
tox_group_founder_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err); tox_group_set_peer_limit(tox0, group_number, PEER_LIMIT, &limit_set_err);
ck_assert(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK); ck_assert(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK);
// change self state // change self state
Tox_Err_Group_Self_Name_Set n_err; Tox_Err_Group_Self_Name_Set n_err;
@ -241,8 +246,8 @@ static void group_save_test(AutoTox *autotoxes)
ck_assert(options != nullptr); ck_assert(options != nullptr);
tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE); tox_options_set_savedata_type(options, TOX_SAVEDATA_TYPE_TOX_SAVE);
tox_options_set_savedata_data(options, save, save_length); tox_options_set_savedata_data(options, save, save_length);
tox_options_set_experimental_groups_persistence(options, true);
Tox *new_tox = tox_new_log(options, nullptr, nullptr); Tox *new_tox = tox_new_log(options, nullptr, nullptr);
@ -278,7 +283,11 @@ int main(void)
Run_Auto_Options autotest_opts = default_run_auto_options(); Run_Auto_Options autotest_opts = default_run_auto_options();
autotest_opts.graph = GRAPH_COMPLETE; autotest_opts.graph = GRAPH_COMPLETE;
run_auto_test(nullptr, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts); Tox_Options *opts = tox_options_new(nullptr);
ck_assert(opts != nullptr);
tox_options_set_experimental_groups_persistence(opts, true);
run_auto_test(opts, NUM_GROUP_TOXES, group_save_test, sizeof(State), &autotest_opts);
tox_options_free(opts);
return 0; return 0;
} }

View File

@ -60,66 +60,97 @@ static bool all_group_peers_connected(const AutoTox *autotoxes, uint32_t tox_cou
return true; return true;
} }
static void group_topic_lock_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock, static void group_topic_lock_handler(const Tox_Event_Group_Topic_Lock *event,
void *user_data) void *user_data)
{ {
Tox_Err_Group_State_Queries err; const AutoTox *autotox = (const AutoTox *)user_data;
Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &err); ck_assert(autotox != nullptr);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); const uint32_t groupnumber = tox_event_group_topic_lock_get_group_number(event);
const Tox_Group_Topic_Lock topic_lock = tox_event_group_topic_lock_get_topic_lock(event);
Tox_Err_Group_State_Query err;
Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(autotox->tox, groupnumber, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(current_topic_lock == topic_lock, "topic locks don't match in callback: %d %d", ck_assert_msg(current_topic_lock == topic_lock, "topic locks don't match in callback: %d %d",
topic_lock, current_topic_lock); topic_lock, current_topic_lock);
} }
static void group_voice_state_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Voice_State voice_state, static void group_voice_state_handler(const Tox_Event_Group_Voice_State *event,
void *user_data) void *user_data)
{ {
Tox_Err_Group_State_Queries err; const AutoTox *autotox = (const AutoTox *)user_data;
Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &err); ck_assert(autotox != nullptr);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); const uint32_t groupnumber = tox_event_group_voice_state_get_group_number(event);
const Tox_Group_Voice_State voice_state = tox_event_group_voice_state_get_voice_state(event);
Tox_Err_Group_State_Query err;
Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(autotox->tox, groupnumber, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(current_voice_state == voice_state, "voice states don't match in callback: %d %d", ck_assert_msg(current_voice_state == voice_state, "voice states don't match in callback: %d %d",
voice_state, current_voice_state); voice_state, current_voice_state);
} }
static void group_privacy_state_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Privacy_State privacy_state, static void group_privacy_state_handler(const Tox_Event_Group_Privacy_State *event,
void *user_data) void *user_data)
{ {
Tox_Err_Group_State_Queries err; const AutoTox *autotox = (const AutoTox *)user_data;
Tox_Group_Privacy_State current_pstate = tox_group_get_privacy_state(tox, groupnumber, &err); ck_assert(autotox != nullptr);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); const uint32_t groupnumber = tox_event_group_privacy_state_get_group_number(event);
const Tox_Group_Privacy_State privacy_state = tox_event_group_privacy_state_get_privacy_state(event);
Tox_Err_Group_State_Query err;
Tox_Group_Privacy_State current_pstate = tox_group_get_privacy_state(autotox->tox, groupnumber, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(current_pstate == privacy_state, "privacy states don't match in callback"); ck_assert_msg(current_pstate == privacy_state, "privacy states don't match in callback");
} }
static void group_peer_limit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_limit, void *user_data) static void group_peer_limit_handler(const Tox_Event_Group_Peer_Limit *event, void *user_data)
{ {
Tox_Err_Group_State_Queries err; const AutoTox *autotox = (const AutoTox *)user_data;
uint32_t current_plimit = tox_group_get_peer_limit(tox, groupnumber, &err); ck_assert(autotox != nullptr);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); const uint32_t groupnumber = tox_event_group_peer_limit_get_group_number(event);
const uint32_t peer_limit = tox_event_group_peer_limit_get_peer_limit(event);
Tox_Err_Group_State_Query err;
uint32_t current_plimit = tox_group_get_peer_limit(autotox->tox, groupnumber, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(peer_limit == current_plimit, ck_assert_msg(peer_limit == current_plimit,
"Peer limits don't match in callback: %u, %u\n", peer_limit, current_plimit); "Peer limits don't match in callback: %u, %u\n", peer_limit, current_plimit);
} }
static void group_password_handler(Tox *tox, uint32_t groupnumber, const uint8_t *password, size_t length, static void group_password_handler(const Tox_Event_Group_Password *event,
void *user_data) void *user_data)
{ {
Tox_Err_Group_State_Queries err; AutoTox *autotox = (AutoTox *)user_data;
size_t curr_pwlength = tox_group_get_password_size(tox, groupnumber, &err); ck_assert(autotox != nullptr);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); const uint32_t groupnumber = tox_event_group_password_get_group_number(event);
const uint8_t *password = tox_event_group_password_get_password(event);
const size_t length = tox_event_group_password_get_password_length(event);
Tox_Err_Group_State_Query err;
size_t curr_pwlength = tox_group_get_password_size(autotox->tox, groupnumber, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert(length == curr_pwlength); ck_assert(length == curr_pwlength);
uint8_t current_password[TOX_GROUP_MAX_PASSWORD_SIZE]; uint8_t current_password[TOX_GROUP_MAX_PASSWORD_SIZE];
tox_group_get_password(tox, groupnumber, current_password, &err); tox_group_get_password(autotox->tox, groupnumber, current_password, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(memcmp(current_password, password, length) == 0, ck_assert_msg(memcmp(current_password, password, length) == 0,
"Passwords don't match: %s, %s", password, current_password); "Passwords don't match: %s, %s", password, current_password);
} }
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -137,24 +168,24 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
Tox_Group_Privacy_State priv_state, Tox_Group_Voice_State voice_state, Tox_Group_Privacy_State priv_state, Tox_Group_Voice_State voice_state,
const uint8_t *password, size_t pass_len, Tox_Group_Topic_Lock topic_lock) const uint8_t *password, size_t pass_len, Tox_Group_Topic_Lock topic_lock)
{ {
Tox_Err_Group_State_Queries query_err; Tox_Err_Group_State_Query query_err;
Tox_Group_Privacy_State my_priv_state = tox_group_get_privacy_state(tox, groupnumber, &query_err); Tox_Group_Privacy_State my_priv_state = tox_group_get_privacy_state(tox, groupnumber, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get privacy state: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get privacy state: %d", query_err);
if (my_priv_state != priv_state) { if (my_priv_state != priv_state) {
return -1; return -1;
} }
uint32_t my_peer_limit = tox_group_get_peer_limit(tox, groupnumber, &query_err); uint32_t my_peer_limit = tox_group_get_peer_limit(tox, groupnumber, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get peer limit: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get peer limit: %d", query_err);
if (my_peer_limit != peer_limit) { if (my_peer_limit != peer_limit) {
return -2; return -2;
} }
size_t my_pass_len = tox_group_get_password_size(tox, groupnumber, &query_err); size_t my_pass_len = tox_group_get_password_size(tox, groupnumber, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get password size: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get password size: %d", query_err);
if (my_pass_len != pass_len) { if (my_pass_len != pass_len) {
return -5; return -5;
@ -163,10 +194,10 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
if (password != nullptr && my_pass_len > 0) { if (password != nullptr && my_pass_len > 0) {
ck_assert(my_pass_len <= TOX_GROUP_MAX_PASSWORD_SIZE); ck_assert(my_pass_len <= TOX_GROUP_MAX_PASSWORD_SIZE);
uint8_t my_pass[TOX_GROUP_MAX_PASSWORD_SIZE]; uint8_t my_pass[TOX_GROUP_MAX_PASSWORD_SIZE + 1];
tox_group_get_password(tox, groupnumber, my_pass, &query_err); tox_group_get_password(tox, groupnumber, my_pass, &query_err);
my_pass[my_pass_len] = 0; my_pass[my_pass_len] = 0;
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get password: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get password: %d", query_err);
if (memcmp(my_pass, password, my_pass_len) != 0) { if (memcmp(my_pass, password, my_pass_len) != 0) {
return -6; return -6;
@ -175,7 +206,7 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
/* Group name should never change */ /* Group name should never change */
size_t my_gname_len = tox_group_get_name_size(tox, groupnumber, &query_err); size_t my_gname_len = tox_group_get_name_size(tox, groupnumber, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get group name size: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get group name size: %d", query_err);
if (my_gname_len != GROUP_NAME_LEN) { if (my_gname_len != GROUP_NAME_LEN) {
return -7; return -7;
@ -183,7 +214,7 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
ck_assert(my_gname_len <= TOX_GROUP_MAX_GROUP_NAME_LENGTH); ck_assert(my_gname_len <= TOX_GROUP_MAX_GROUP_NAME_LENGTH);
uint8_t my_gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH]; uint8_t my_gname[TOX_GROUP_MAX_GROUP_NAME_LENGTH + 1];
tox_group_get_name(tox, groupnumber, my_gname, &query_err); tox_group_get_name(tox, groupnumber, my_gname, &query_err);
my_gname[my_gname_len] = 0; my_gname[my_gname_len] = 0;
@ -192,14 +223,14 @@ static int check_group_state(const Tox *tox, uint32_t groupnumber, uint32_t peer
} }
Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &query_err); Tox_Group_Topic_Lock current_topic_lock = tox_group_get_topic_lock(tox, groupnumber, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get topic lock: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get topic lock: %d", query_err);
if (current_topic_lock != topic_lock) { if (current_topic_lock != topic_lock) {
return -9; return -9;
} }
Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &query_err); Tox_Group_Voice_State current_voice_state = tox_group_get_voice_state(tox, groupnumber, &query_err);
ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "Failed to get voice state: %d", query_err); ck_assert_msg(query_err == TOX_ERR_GROUP_STATE_QUERY_OK, "Failed to get voice state: %d", query_err);
if (current_voice_state != voice_state) { if (current_voice_state != voice_state) {
return -10; return -10;
@ -213,26 +244,26 @@ static void set_group_state(Tox *tox, uint32_t groupnumber, uint32_t peer_limit,
Tox_Group_Topic_Lock topic_lock) Tox_Group_Topic_Lock topic_lock)
{ {
Tox_Err_Group_Founder_Set_Peer_Limit limit_set_err; Tox_Err_Group_Set_Peer_Limit limit_set_err;
tox_group_founder_set_peer_limit(tox, groupnumber, peer_limit, &limit_set_err); tox_group_set_peer_limit(tox, groupnumber, peer_limit, &limit_set_err);
ck_assert_msg(limit_set_err == TOX_ERR_GROUP_FOUNDER_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err); ck_assert_msg(limit_set_err == TOX_ERR_GROUP_SET_PEER_LIMIT_OK, "failed to set peer limit: %d", limit_set_err);
Tox_Err_Group_Founder_Set_Privacy_State priv_err; Tox_Err_Group_Set_Privacy_State priv_err;
tox_group_founder_set_privacy_state(tox, groupnumber, priv_state, &priv_err); tox_group_set_privacy_state(tox, groupnumber, priv_state, &priv_err);
ck_assert_msg(priv_err == TOX_ERR_GROUP_FOUNDER_SET_PRIVACY_STATE_OK, "failed to set privacy state: %d", priv_err); ck_assert_msg(priv_err == TOX_ERR_GROUP_SET_PRIVACY_STATE_OK, "failed to set privacy state: %d", priv_err);
Tox_Err_Group_Founder_Set_Password pass_set_err; Tox_Err_Group_Set_Password pass_set_err;
tox_group_founder_set_password(tox, groupnumber, password, pass_len, &pass_set_err); tox_group_set_password(tox, groupnumber, password, pass_len, &pass_set_err);
ck_assert_msg(pass_set_err == TOX_ERR_GROUP_FOUNDER_SET_PASSWORD_OK, "failed to set password: %d", pass_set_err); ck_assert_msg(pass_set_err == TOX_ERR_GROUP_SET_PASSWORD_OK, "failed to set password: %d", pass_set_err);
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err; Tox_Err_Group_Set_Topic_Lock lock_set_err;
tox_group_founder_set_topic_lock(tox, groupnumber, topic_lock, &lock_set_err); tox_group_set_topic_lock(tox, groupnumber, topic_lock, &lock_set_err);
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to set topic lock: %d", ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to set topic lock: %d",
lock_set_err); lock_set_err);
Tox_Err_Group_Founder_Set_Voice_State voice_set_err; Tox_Err_Group_Set_Voice_State voice_set_err;
tox_group_founder_set_voice_state(tox, groupnumber, voice_state, &voice_set_err); tox_group_set_voice_state(tox, groupnumber, voice_state, &voice_set_err);
ck_assert_msg(voice_set_err == TOX_ERR_GROUP_FOUNDER_SET_VOICE_STATE_OK, "failed to set voice state: %d", ck_assert_msg(voice_set_err == TOX_ERR_GROUP_SET_VOICE_STATE_OK, "failed to set voice state: %d",
voice_set_err); voice_set_err);
} }
@ -241,12 +272,12 @@ static void group_state_test(AutoTox *autotoxes)
ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES); ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
tox_callback_group_privacy_state(autotoxes[i].tox, group_privacy_state_handler); tox_events_callback_group_privacy_state(autotoxes[i].dispatch, group_privacy_state_handler);
tox_callback_group_peer_limit(autotoxes[i].tox, group_peer_limit_handler); tox_events_callback_group_peer_limit(autotoxes[i].dispatch, group_peer_limit_handler);
tox_callback_group_password(autotoxes[i].tox, group_password_handler); tox_events_callback_group_password(autotoxes[i].dispatch, group_password_handler);
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
tox_callback_group_voice_state(autotoxes[i].tox, group_voice_state_handler); tox_events_callback_group_voice_state(autotoxes[i].dispatch, group_voice_state_handler);
tox_callback_group_topic_lock(autotoxes[i].tox, group_topic_lock_handler); tox_events_callback_group_topic_lock(autotoxes[i].dispatch, group_topic_lock_handler);
} }
Tox *tox0 = autotoxes[0].tox; Tox *tox0 = autotoxes[0].tox;
@ -263,11 +294,11 @@ static void group_state_test(AutoTox *autotoxes)
(const uint8_t *)PASSWORD, PASS_LEN, TOX_GROUP_TOPIC_LOCK_ENABLED); (const uint8_t *)PASSWORD, PASS_LEN, TOX_GROUP_TOPIC_LOCK_ENABLED);
/* Founder gets the Chat ID and implicitly shares it publicly */ /* Founder gets the Chat ID and implicitly shares it publicly */
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox0, groupnum, chat_id, &id_err); tox_group_get_chat_id(tox0, groupnum, chat_id, &id_err);
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "tox_group_get_chat_id failed %d", id_err); ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "tox_group_get_chat_id failed %d", id_err);
/* All other peers join the group using the Chat ID and password */ /* All other peers join the group using the Chat ID and password */
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {

View File

@ -96,38 +96,42 @@ static void peers_cleanup(Peers *peers)
free(peers); free(peers);
} }
static void group_peer_join_handler(Tox *tox, uint32_t group_number, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
ck_assert(add_peer(state->peers, peer_id) == 0); ck_assert(add_peer(state->peers, peer_id) == 0);
} }
static void group_peer_exit_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, Tox_Group_Exit_Type exit_type, static void group_peer_exit_handler(const Tox_Event_Group_Peer_Exit *event, void *user_data)
const uint8_t *name, size_t name_length, const uint8_t *part_message,
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t peer_id = tox_event_group_peer_exit_get_peer_id(event);
ck_assert(del_peer(state->peers, peer_id) == 0); ck_assert(del_peer(state->peers, peer_id) == 0);
} }
static void group_topic_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic, static void group_topic_handler(const Tox_Event_Group_Topic *event, void *user_data)
size_t length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint8_t *topic = tox_event_group_topic_get_topic(event);
const size_t length = tox_event_group_topic_get_topic_length(event);
ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH); ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH);
memcpy(state->callback_topic, (const char *)topic, length); memcpy(state->callback_topic, (const char *)topic, length);
@ -201,7 +205,7 @@ static void role_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers,
int64_t peer_id = state0->peers->peer_ids[idx]; int64_t peer_id = state0->peers->peer_ids[idx];
if (peer_id >= 0) { if (peer_id >= 0) {
tox_group_mod_set_role(tox0, groupnumber, (uint32_t)peer_id, f_role, nullptr); tox_group_set_role(tox0, groupnumber, (uint32_t)peer_id, f_role, nullptr);
} }
// mods randomly promote or demote one of the non-mods // mods randomly promote or demote one of the non-mods
@ -218,7 +222,7 @@ static void role_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers,
peer_id = state_j->peers->peer_ids[i]; peer_id = state_j->peers->peer_ids[i];
if (peer_id >= 0) { if (peer_id >= 0) {
tox_group_mod_set_role(autotoxes[j].tox, groupnumber, (uint32_t)peer_id, role, nullptr); tox_group_set_role(autotoxes[j].tox, groupnumber, (uint32_t)peer_id, role, nullptr);
} }
} }
} }
@ -260,14 +264,14 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
{ {
uint8_t expected_topic[TOX_GROUP_MAX_TOPIC_LENGTH]; uint8_t expected_topic[TOX_GROUP_MAX_TOPIC_LENGTH];
Tox_Err_Group_State_Queries query_err; Tox_Err_Group_State_Query query_err;
size_t expected_topic_length = tox_group_get_topic_size(autotoxes[0].tox, groupnumber, &query_err); size_t expected_topic_length = tox_group_get_topic_size(autotoxes[0].tox, groupnumber, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
tox_group_get_topic(autotoxes[0].tox, groupnumber, expected_topic, &query_err); tox_group_get_topic(autotoxes[0].tox, groupnumber, expected_topic, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
const State *state0 = (const State *)autotoxes[0].state; const State *state0 = (const State *)autotoxes[0].state;
@ -282,7 +286,7 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
for (size_t i = 1; i < num_peers; ++i) { for (size_t i = 1; i < num_peers; ++i) {
size_t topic_length = tox_group_get_topic_size(autotoxes[i].tox, groupnumber, &query_err); size_t topic_length = tox_group_get_topic_size(autotoxes[i].tox, groupnumber, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (topic_length != expected_topic_length) { if (topic_length != expected_topic_length) {
return false; return false;
@ -291,7 +295,7 @@ static bool all_peers_have_same_topic(const AutoTox *autotoxes, uint32_t num_pee
uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH]; uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
tox_group_get_topic(autotoxes[i].tox, groupnumber, topic, &query_err); tox_group_get_topic(autotoxes[i].tox, groupnumber, topic, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (memcmp(expected_topic, (const char *)topic, topic_length) != 0) { if (memcmp(expected_topic, (const char *)topic, topic_length) != 0) {
return false; return false;
@ -331,13 +335,13 @@ static void topic_spam(const Random *rng, AutoTox *autotoxes, uint32_t num_peers
static void group_sync_test(AutoTox *autotoxes) static void group_sync_test(AutoTox *autotoxes)
{ {
ck_assert(NUM_GROUP_TOXES >= 5); ck_assert(NUM_GROUP_TOXES >= 5);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
tox_callback_group_topic(autotoxes[i].tox, group_topic_handler); tox_events_callback_group_topic(autotoxes[i].dispatch, group_topic_handler);
tox_callback_group_peer_exit(autotoxes[i].tox, group_peer_exit_handler); tox_events_callback_group_peer_exit(autotoxes[i].dispatch, group_peer_exit_handler);
State *state = (State *)autotoxes[i].state; State *state = (State *)autotoxes[i].state;
state->peers = (Peers *)calloc(1, sizeof(Peers)); state->peers = (Peers *)calloc(1, sizeof(Peers));
@ -356,11 +360,11 @@ static void group_sync_test(AutoTox *autotoxes)
fprintf(stderr, "tox0 creats new group and invites all his friends"); fprintf(stderr, "tox0 creats new group and invites all his friends");
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err); tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err); ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
Tox_Err_Group_Join join_err; Tox_Err_Group_Join join_err;
@ -375,9 +379,9 @@ static void group_sync_test(AutoTox *autotoxes)
fprintf(stderr, "%d peers joined the group\n", NUM_GROUP_TOXES); fprintf(stderr, "%d peers joined the group\n", NUM_GROUP_TOXES);
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err; Tox_Err_Group_Set_Topic_Lock lock_set_err;
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err); tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d", ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
lock_set_err); lock_set_err);
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
@ -388,8 +392,8 @@ static void group_sync_test(AutoTox *autotoxes)
iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL); iterate_all_wait(autotoxes, NUM_GROUP_TOXES, ITERATION_INTERVAL);
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err); tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d", ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
lock_set_err); lock_set_err);
do { do {
@ -398,12 +402,12 @@ static void group_sync_test(AutoTox *autotoxes)
&& !all_peers_see_same_roles(autotoxes, NUM_GROUP_TOXES, groupnumber) && !all_peers_see_same_roles(autotoxes, NUM_GROUP_TOXES, groupnumber)
&& state0->peers->num_peers != NUM_GROUP_TOXES - 1); && state0->peers->num_peers != NUM_GROUP_TOXES - 1);
Tox_Err_Group_Mod_Set_Role role_err; Tox_Err_Group_Set_Role role_err;
for (size_t i = 0; i < state0->peers->num_peers; ++i) { for (size_t i = 0; i < state0->peers->num_peers; ++i) {
tox_group_mod_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_MODERATOR, tox_group_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_MODERATOR,
&role_err); &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set moderator. error: %d", role_err);
} }
fprintf(stderr, "founder enabled topic lock and set all peers to moderator role\n"); fprintf(stderr, "founder enabled topic lock and set all peers to moderator role\n");
@ -419,9 +423,9 @@ static void group_sync_test(AutoTox *autotoxes)
fprintf(stderr, "founder demoting %u moderators to user\n", num_demoted); fprintf(stderr, "founder demoting %u moderators to user\n", num_demoted);
for (size_t i = 0; i < num_demoted; ++i) { for (size_t i = 0; i < num_demoted; ++i) {
tox_group_mod_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_USER, tox_group_set_role(tox0, groupnumber, (uint32_t)state0->peers->peer_ids[i], TOX_GROUP_ROLE_USER,
&role_err); &role_err);
ck_assert_msg(role_err == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set user. error: %d", role_err); ck_assert_msg(role_err == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set user. error: %d", role_err);
} }
do { do {

View File

@ -19,32 +19,43 @@ typedef struct State {
uint32_t peer_id[NUM_GROUP_TOXES - 1]; uint32_t peer_id[NUM_GROUP_TOXES - 1];
} State; } State;
static void group_invite_handler(Tox *tox, uint32_t friend_number, const uint8_t *invite_data, size_t length, static void group_invite_handler(const Tox_Event_Group_Invite *event, void *user_data)
const uint8_t *group_name, size_t group_name_length, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
const uint32_t friend_number = tox_event_group_invite_get_friend_number(event);
const uint8_t *invite_data = tox_event_group_invite_get_invite_data(event);
const size_t length = tox_event_group_invite_get_invite_data_length(event);
printf("Accepting friend invite\n"); printf("Accepting friend invite\n");
Tox_Err_Group_Invite_Accept err_accept; Tox_Err_Group_Invite_Accept err_accept;
tox_group_invite_accept(tox, friend_number, invite_data, length, (const uint8_t *)"test", 4, tox_group_invite_accept(autotox->tox, friend_number, invite_data, length, (const uint8_t *)"test", 4,
nullptr, 0, &err_accept); nullptr, 0, &err_accept);
ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK); ck_assert(err_accept == TOX_ERR_GROUP_INVITE_ACCEPT_OK);
} }
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
fprintf(stderr, "joined: %zu, %u\n", state->num_peers, peer_id); fprintf(stderr, "joined: %zu, %u\n", state->num_peers, peer_id);
ck_assert_msg(state->num_peers < NUM_GROUP_TOXES - 1, "%zu", state->num_peers); ck_assert_msg(state->num_peers < NUM_GROUP_TOXES - 1, "%zu", state->num_peers);
state->peer_id[state->num_peers++] = peer_id; state->peer_id[state->num_peers++] = peer_id;
} }
static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type, static void group_private_message_handler(const Tox_Event_Group_Private_Message *event, void *user_data)
const uint8_t *message, size_t length, void *user_data)
{ {
const uint8_t *message = tox_event_group_private_message_get_message(event);
const size_t length = tox_event_group_private_message_get_message_length(event);
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -58,9 +69,11 @@ static void group_private_message_handler(Tox *tox, uint32_t groupnumber, uint32
state->got_code = true; state->got_code = true;
} }
static void group_message_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, TOX_MESSAGE_TYPE type, static void group_message_handler(const Tox_Event_Group_Message *event, void *user_data)
const uint8_t *message, size_t length, uint32_t message_id, void *user_data)
{ {
const uint8_t *message = tox_event_group_message_get_message(event);
const size_t length = tox_event_group_message_get_message_length(event);
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -133,12 +146,12 @@ static void group_tcp_test(AutoTox *autotoxes)
State *state1 = (State *)autotoxes[1].state; State *state1 = (State *)autotoxes[1].state;
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
tox_callback_group_peer_join(autotoxes[i].tox, group_peer_join_handler); tox_events_callback_group_peer_join(autotoxes[i].dispatch, group_peer_join_handler);
tox_callback_group_private_message(autotoxes[i].tox, group_private_message_handler); tox_events_callback_group_private_message(autotoxes[i].dispatch, group_private_message_handler);
} }
tox_callback_group_message(autotoxes[1].tox, group_message_handler); tox_events_callback_group_message(autotoxes[1].dispatch, group_message_handler);
tox_callback_group_invite(autotoxes[1].tox, group_invite_handler); tox_events_callback_group_invite(autotoxes[1].dispatch, group_invite_handler);
Tox_Err_Group_New new_err; Tox_Err_Group_New new_err;
uint32_t groupnumber = tox_group_new(autotoxes[0].tox, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4, uint32_t groupnumber = tox_group_new(autotoxes[0].tox, TOX_GROUP_PRIVACY_STATE_PUBLIC, (const uint8_t *)"test", 4,
@ -147,11 +160,11 @@ static void group_tcp_test(AutoTox *autotoxes)
iterate_group(autotoxes, NUM_GROUP_TOXES, GROUP_ITERATION_INTERVAL); iterate_group(autotoxes, NUM_GROUP_TOXES, GROUP_ITERATION_INTERVAL);
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(autotoxes[0].tox, groupnumber, chat_id, &id_err); tox_group_get_chat_id(autotoxes[0].tox, groupnumber, chat_id, &id_err);
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "%d", id_err); ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "%d", id_err);
printf("Tox 0 created new group...\n"); printf("Tox 0 created new group...\n");
@ -168,7 +181,6 @@ static void group_tcp_test(AutoTox *autotoxes)
printf("%d peers successfully joined. Waiting for code...\n", NUM_GROUP_TOXES); printf("%d peers successfully joined. Waiting for code...\n", NUM_GROUP_TOXES);
printf("Tox 0 sending secret code to all peers\n"); printf("Tox 0 sending secret code to all peers\n");
for (size_t i = 0; i < NUM_GROUP_TOXES - 1; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES - 1; ++i) {
Tox_Err_Group_Send_Private_Message perr; Tox_Err_Group_Send_Private_Message perr;

View File

@ -55,8 +55,11 @@ static bool all_group_peers_connected(const AutoTox *autotoxes, uint32_t tox_cou
return true; return true;
} }
static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, void *user_data) static void group_peer_join_handler(const Tox_Event_Group_Peer_Join *event, void *user_data)
{ {
//const uint32_t group_number = tox_event_group_peer_join_get_group_number(event);
const uint32_t peer_id = tox_event_group_peer_join_get_peer_id(event);
AutoTox *autotox = (AutoTox *)user_data; AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr); ck_assert(autotox != nullptr);
@ -65,28 +68,41 @@ static void group_peer_join_handler(Tox *tox, uint32_t groupnumber, uint32_t pee
state->peer_id = peer_id; state->peer_id = peer_id;
} }
static void group_topic_handler(Tox *tox, uint32_t groupnumber, uint32_t peer_id, const uint8_t *topic, static void group_topic_handler(const Tox_Event_Group_Topic *event, void *user_data)
size_t length, void *user_data)
{ {
ck_assert(length <= TOX_GROUP_MAX_TOPIC_LENGTH); AutoTox *autotox = (AutoTox *)user_data;
ck_assert(autotox != nullptr);
Tox_Err_Group_State_Queries query_err; const uint32_t group_number = tox_event_group_topic_get_group_number(event);
//const uint32_t peer_id = tox_event_group_topic_get_peer_id(event);
const uint8_t *topic = tox_event_group_topic_get_topic(event);
const uint32_t topic_length = tox_event_group_topic_get_topic_length(event);
ck_assert(topic_length <= TOX_GROUP_MAX_TOPIC_LENGTH);
Tox_Err_Group_State_Query query_err;
uint8_t topic2[TOX_GROUP_MAX_TOPIC_LENGTH]; uint8_t topic2[TOX_GROUP_MAX_TOPIC_LENGTH];
tox_group_get_topic(tox, groupnumber, topic2, &query_err); tox_group_get_topic(autotox->tox, group_number, topic2, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err); size_t topic_length_getter = tox_group_get_topic_size(autotox->tox, group_number, &query_err);
ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(query_err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(topic_length == length && memcmp(topic, topic2, length) == 0, ck_assert_msg(topic_length_getter == topic_length && memcmp(topic, topic2, topic_length) == 0,
"topic differs in callback: %s, %s", topic, topic2); "topic differs in callback: %s, %s", topic, topic2);
} }
static void group_topic_lock_handler(Tox *tox, uint32_t groupnumber, Tox_Group_Topic_Lock topic_lock, void *user_data) static void group_topic_lock_handler(const Tox_Event_Group_Topic_Lock *event, void *user_data)
{ {
Tox_Err_Group_State_Queries err; const AutoTox *autotox = (const AutoTox *)user_data;
Tox_Group_Topic_Lock current_lock = tox_group_get_topic_lock(tox, groupnumber, &err); ck_assert(autotox != nullptr);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); const uint32_t group_number = tox_event_group_topic_lock_get_group_number(event);
const Tox_Group_Topic_Lock topic_lock = tox_event_group_topic_lock_get_topic_lock(event);
Tox_Err_Group_State_Query err;
Tox_Group_Topic_Lock current_lock = tox_group_get_topic_lock(autotox->tox, group_number, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
ck_assert_msg(topic_lock == current_lock, "topic locks differ in callback"); ck_assert_msg(topic_lock == current_lock, "topic locks differ in callback");
} }
@ -107,10 +123,10 @@ static bool set_topic(Tox *tox, uint32_t groupnumber, const char *topic, size_t
*/ */
static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expected_topic, size_t expected_length) static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expected_topic, size_t expected_length)
{ {
Tox_Err_Group_State_Queries query_err; Tox_Err_Group_State_Query query_err;
size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err); size_t topic_length = tox_group_get_topic_size(tox, groupnumber, &query_err);
if (query_err != TOX_ERR_GROUP_STATE_QUERIES_OK) { if (query_err != TOX_ERR_GROUP_STATE_QUERY_OK) {
return -1; return -1;
} }
@ -121,7 +137,7 @@ static int check_topic(const Tox *tox, uint32_t groupnumber, const char *expecte
uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH]; uint8_t topic[TOX_GROUP_MAX_TOPIC_LENGTH];
tox_group_get_topic(tox, groupnumber, topic, &query_err); tox_group_get_topic(tox, groupnumber, topic, &query_err);
if (query_err != TOX_ERR_GROUP_STATE_QUERIES_OK) { if (query_err != TOX_ERR_GROUP_STATE_QUERY_OK) {
return -3; return -3;
} }
@ -140,9 +156,9 @@ static void wait_topic_lock(AutoTox *autotoxes, uint32_t groupnumber, Tox_Group_
uint32_t count = 0; uint32_t count = 0;
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
Tox_Err_Group_State_Queries err; Tox_Err_Group_State_Query err;
Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(autotoxes[i].tox, groupnumber, &err); Tox_Group_Topic_Lock topic_lock = tox_group_get_topic_lock(autotoxes[i].tox, groupnumber, &err);
ck_assert(err == TOX_ERR_GROUP_STATE_QUERIES_OK); ck_assert(err == TOX_ERR_GROUP_STATE_QUERY_OK);
if (topic_lock == expected_lock) { if (topic_lock == expected_lock) {
++count; ++count;
@ -205,17 +221,18 @@ static void group_topic_test(AutoTox *autotoxes)
{ {
ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES); ck_assert_msg(NUM_GROUP_TOXES >= 3, "NUM_GROUP_TOXES is too small: %d", NUM_GROUP_TOXES);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
Tox *tox0 = autotoxes[0].tox; Tox *tox0 = autotoxes[0].tox;
Tox_Dispatch *dispatch0 = autotoxes[0].dispatch;
const State *state0 = (const State *)autotoxes[0].state; const State *state0 = (const State *)autotoxes[0].state;
tox_callback_group_peer_join(tox0, group_peer_join_handler); tox_events_callback_group_peer_join(dispatch0, group_peer_join_handler);
for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 0; i < NUM_GROUP_TOXES; ++i) {
tox_callback_group_topic(autotoxes[i].tox, group_topic_handler); tox_events_callback_group_topic(autotoxes[i].dispatch, group_topic_handler);
tox_callback_group_topic_lock(autotoxes[i].tox, group_topic_lock_handler); tox_events_callback_group_topic_lock(autotoxes[i].dispatch, group_topic_lock_handler);
} }
/* Tox1 creates a group and is the founder of a newly created group */ /* Tox1 creates a group and is the founder of a newly created group */
@ -233,11 +250,11 @@ static void group_topic_test(AutoTox *autotoxes)
ck_assert_msg(s_ret, "Founder failed to set topic"); ck_assert_msg(s_ret, "Founder failed to set topic");
/* Founder gets the Chat ID and implicitly shares it publicly */ /* Founder gets the Chat ID and implicitly shares it publicly */
Tox_Err_Group_State_Queries id_err; Tox_Err_Group_State_Query id_err;
uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE]; uint8_t chat_id[TOX_GROUP_CHAT_ID_SIZE];
tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err); tox_group_get_chat_id(tox0, groupnumber, chat_id, &id_err);
ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERIES_OK, "tox_group_get_chat_id failed %d", id_err); ck_assert_msg(id_err == TOX_ERR_GROUP_STATE_QUERY_OK, "tox_group_get_chat_id failed %d", id_err);
/* All other peers join the group using the Chat ID */ /* All other peers join the group using the Chat ID */
for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) { for (size_t i = 1; i < NUM_GROUP_TOXES; ++i) {
@ -257,9 +274,9 @@ static void group_topic_test(AutoTox *autotoxes)
wait_state_topic(autotoxes, groupnumber, TOPIC, TOPIC_LEN); wait_state_topic(autotoxes, groupnumber, TOPIC, TOPIC_LEN);
/* Founder disables topic lock */ /* Founder disables topic lock */
Tox_Err_Group_Founder_Set_Topic_Lock lock_set_err; Tox_Err_Group_Set_Topic_Lock lock_set_err;
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err); tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_DISABLED, &lock_set_err);
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d", ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to disable topic lock: %d",
lock_set_err); lock_set_err);
fprintf(stderr, "Topic lock disabled\n"); fprintf(stderr, "Topic lock disabled\n");
@ -273,9 +290,9 @@ static void group_topic_test(AutoTox *autotoxes)
ck_assert_msg(change_count == NUM_GROUP_TOXES, "%u peers changed the topic with topic lock disabled", change_count); ck_assert_msg(change_count == NUM_GROUP_TOXES, "%u peers changed the topic with topic lock disabled", change_count);
/* founder silences the last peer he saw join */ /* founder silences the last peer he saw join */
Tox_Err_Group_Mod_Set_Role merr; Tox_Err_Group_Set_Role merr;
tox_group_mod_set_role(tox0, groupnumber, state0->peer_id, TOX_GROUP_ROLE_OBSERVER, &merr); tox_group_set_role(tox0, groupnumber, state0->peer_id, TOX_GROUP_ROLE_OBSERVER, &merr);
ck_assert_msg(merr == TOX_ERR_GROUP_MOD_SET_ROLE_OK, "Failed to set %u to observer role: %d", state0->peer_id, merr); ck_assert_msg(merr == TOX_ERR_GROUP_SET_ROLE_OK, "Failed to set %u to observer role: %d", state0->peer_id, merr);
fprintf(stderr, "Random peer is set to observer\n"); fprintf(stderr, "Random peer is set to observer\n");
@ -287,8 +304,8 @@ static void group_topic_test(AutoTox *autotoxes)
ck_assert_msg(change_count == NUM_GROUP_TOXES - 1, "%u peers changed the topic with a silenced peer", change_count); ck_assert_msg(change_count == NUM_GROUP_TOXES - 1, "%u peers changed the topic with a silenced peer", change_count);
/* Founder enables topic lock and sets topic back to original */ /* Founder enables topic lock and sets topic back to original */
tox_group_founder_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err); tox_group_set_topic_lock(tox0, groupnumber, TOX_GROUP_TOPIC_LOCK_ENABLED, &lock_set_err);
ck_assert_msg(lock_set_err == TOX_ERR_GROUP_FOUNDER_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d", ck_assert_msg(lock_set_err == TOX_ERR_GROUP_SET_TOPIC_LOCK_OK, "failed to enable topic lock: %d",
lock_set_err); lock_set_err);
fprintf(stderr, "Topic lock enabled\n"); fprintf(stderr, "Topic lock enabled\n");

View File

@ -18,13 +18,17 @@ typedef struct State {
#define LOSSLESS_PACKET_FILLER 160 #define LOSSLESS_PACKET_FILLER 160
static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data) static void handle_lossless_packet(const Tox_Event_Friend_Lossless_Packet *event, void *user_data)
{ {
//const uint32_t friend_number = tox_event_friend_lossless_packet_get_friend_number(event);
const uint8_t *data = tox_event_friend_lossless_packet_get_data(event);
const uint32_t data_length = tox_event_friend_lossless_packet_get_data_length(event);
uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size()); uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
ck_assert(cmp_packet != nullptr); ck_assert(cmp_packet != nullptr);
memset(cmp_packet, LOSSLESS_PACKET_FILLER, tox_max_custom_packet_size()); memset(cmp_packet, LOSSLESS_PACKET_FILLER, tox_max_custom_packet_size());
if (length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) { if (data_length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
state->custom_packet_received = true; state->custom_packet_received = true;
@ -35,7 +39,7 @@ static void handle_lossless_packet(Tox *tox, uint32_t friend_number, const uint8
static void test_lossless_packet(AutoTox *autotoxes) static void test_lossless_packet(AutoTox *autotoxes)
{ {
tox_callback_friend_lossless_packet(autotoxes[1].tox, &handle_lossless_packet); tox_events_callback_friend_lossless_packet(autotoxes[1].dispatch, &handle_lossless_packet);
const size_t packet_size = tox_max_custom_packet_size() + 1; const size_t packet_size = tox_max_custom_packet_size() + 1;
uint8_t *packet = (uint8_t *)malloc(packet_size); uint8_t *packet = (uint8_t *)malloc(packet_size);
ck_assert(packet != nullptr); ck_assert(packet != nullptr);

View File

@ -18,13 +18,17 @@ typedef struct State {
#define LOSSY_PACKET_FILLER 200 #define LOSSY_PACKET_FILLER 200
static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t *data, size_t length, void *user_data) static void handle_lossy_packet(const Tox_Event_Friend_Lossy_Packet *event, void *user_data)
{ {
//const uint32_t friend_number = tox_event_friend_lossy_packet_get_friend_number(event);
const uint8_t *data = tox_event_friend_lossy_packet_get_data(event);
const uint32_t data_length = tox_event_friend_lossy_packet_get_data_length(event);
uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size()); uint8_t *cmp_packet = (uint8_t *)malloc(tox_max_custom_packet_size());
ck_assert(cmp_packet != nullptr); ck_assert(cmp_packet != nullptr);
memset(cmp_packet, LOSSY_PACKET_FILLER, tox_max_custom_packet_size()); memset(cmp_packet, LOSSY_PACKET_FILLER, tox_max_custom_packet_size());
if (length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) { if (data_length == tox_max_custom_packet_size() && memcmp(data, cmp_packet, tox_max_custom_packet_size()) == 0) {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
state->custom_packet_received = true; state->custom_packet_received = true;
@ -35,7 +39,7 @@ static void handle_lossy_packet(Tox *tox, uint32_t friend_number, const uint8_t
static void test_lossy_packet(AutoTox *autotoxes) static void test_lossy_packet(AutoTox *autotoxes)
{ {
tox_callback_friend_lossy_packet(autotoxes[1].tox, &handle_lossy_packet); tox_events_callback_friend_lossy_packet(autotoxes[1].dispatch, &handle_lossy_packet);
const size_t packet_size = tox_max_custom_packet_size() + 1; const size_t packet_size = tox_max_custom_packet_size() + 1;
uint8_t *packet = (uint8_t *)malloc(packet_size); uint8_t *packet = (uint8_t *)malloc(packet_size);
ck_assert(packet != nullptr); ck_assert(packet != nullptr);

View File

@ -20,7 +20,7 @@ static void test_addr_resolv_localhost(void)
errno = 0; errno = 0;
#endif #endif
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const char localhost[] = "localhost"; const char localhost[] = "localhost";

View File

@ -37,7 +37,7 @@ static void do_onion(Mono_Time *mono_time, Onion *onion)
static int handled_test_1; static int handled_test_1;
static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{ {
Onion *onion = (Onion *)object; const Onion *onion = (const Onion *)object;
const char req_message[] = "Install Gentoo"; const char req_message[] = "Install Gentoo";
uint8_t req_packet[1 + sizeof(req_message)]; uint8_t req_packet[1 + sizeof(req_message)];
@ -99,7 +99,7 @@ static uint8_t test_3_pub_key[CRYPTO_PUBLIC_KEY_SIZE];
static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE]; static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE];
static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{ {
Onion *onion = (Onion *)object; const Onion *onion = (const Onion *)object;
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) { if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
return 1; return 1;
@ -118,7 +118,6 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
return 1; return 1;
} }
if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) { if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
return 1; return 1;
} }
@ -135,7 +134,7 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
void *userdata) void *userdata)
{ {
Onion *onion = (Onion *)object; const Onion *onion = (const Onion *)object;
if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) { if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
return 1; return 1;
@ -154,7 +153,6 @@ static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t
return 1; return 1;
} }
if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) { if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
return 1; return 1;
} }
@ -171,7 +169,7 @@ static uint8_t nonce[CRYPTO_NONCE_SIZE];
static int handled_test_4; static int handled_test_4;
static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata) static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
{ {
Onion *onion = (Onion *)object; const Onion *onion = (const Onion *)object;
if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") + if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") +
CRYPTO_MAC_SIZE)) { CRYPTO_MAC_SIZE)) {
@ -223,11 +221,11 @@ static Networking_Core *new_networking(const Logger *log, const Memory *mem, con
static void test_basic(void) static void test_basic(void)
{ {
uint32_t index[] = { 1, 2, 3 }; uint32_t index[] = { 1, 2, 3 };
const Network *ns = system_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
Logger *log1 = logger_new(); Logger *log1 = logger_new();
@ -288,7 +286,7 @@ static void test_basic(void)
networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1); networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1);
networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1); networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1);
ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing."); ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing.");
uint8_t zeroes[64] = {0}; const uint8_t zeroes[64] = {0};
random_bytes(rng, sb_data, sizeof(sb_data)); random_bytes(rng, sb_data, sizeof(sb_data));
uint64_t s; uint64_t s;
memcpy(&s, sb_data, sizeof(uint64_t)); memcpy(&s, sb_data, sizeof(uint64_t));
@ -407,7 +405,7 @@ static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, u
{ {
IP ip = get_loopback(); IP ip = get_loopback();
ip.ip.v6.uint8[15] = 1; ip.ip.v6.uint8[15] = 1;
const Network *ns = system_network(); const Network *ns = os_network();
Onions *on = (Onions *)malloc(sizeof(Onions)); Onions *on = (Onions *)malloc(sizeof(Onions));
if (!on) { if (!on) {
@ -576,9 +574,9 @@ static void test_announce(void)
{ {
uint32_t index[NUM_ONIONS]; uint32_t index[NUM_ONIONS];
Onions *onions[NUM_ONIONS]; Onions *onions[NUM_ONIONS];
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
for (uint32_t i = 0; i < NUM_ONIONS; ++i) { for (uint32_t i = 0; i < NUM_ONIONS; ++i) {

View File

@ -11,9 +11,13 @@ typedef struct State {
#define NUM_MSGS 40000 #define NUM_MSGS 40000
static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_Type type, static void handle_friend_message(const Tox_Event_Friend_Message *event, void *user_data)
const uint8_t *message, size_t length, void *user_data)
{ {
//const uint32_t friend_number = tox_event_friend_message_get_friend_number(event);
//const Tox_Message_Type type = tox_event_friend_message_get_type(event);
//const uint8_t *message = tox_event_friend_message_get_message(event);
//const uint32_t message_length = tox_event_friend_message_get_message_length(event);
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
state->recv_count++; state->recv_count++;
@ -21,7 +25,7 @@ static void handle_friend_message(Tox *tox, uint32_t friend_number, Tox_Message_
static void net_crypto_overflow_test(AutoTox *autotoxes) static void net_crypto_overflow_test(AutoTox *autotoxes)
{ {
tox_callback_friend_message(autotoxes[0].tox, handle_friend_message); tox_events_callback_friend_message(autotoxes[0].dispatch, handle_friend_message);
printf("sending many messages to tox0\n"); printf("sending many messages to tox0\n");

View File

@ -51,7 +51,7 @@ static bool all_disconnected_from(uint32_t tox_count, AutoTox *autotoxes, uint32
static void test_reconnect(AutoTox *autotoxes) static void test_reconnect(AutoTox *autotoxes)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
const time_t test_start_time = time(nullptr); const time_t test_start_time = time(nullptr);
@ -67,7 +67,12 @@ static void test_reconnect(AutoTox *autotoxes)
do { do {
for (uint16_t i = 0; i < TOX_COUNT; ++i) { for (uint16_t i = 0; i < TOX_COUNT; ++i) {
if (i != disconnect) { if (i != disconnect) {
tox_iterate(autotoxes[i].tox, &autotoxes[i]); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(autotoxes[i].tox, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(autotoxes[i].dispatch, events, &autotoxes[i]);
tox_events_free(events);
autotoxes[i].clock += 1000; autotoxes[i].clock += 1000;
} }
} }

View File

@ -9,7 +9,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#define LOADED_SAVE_FILE "../auto_tests/data/save.tox" #define LOADED_SAVE_FILE_BIG "../auto_tests/data/save.tox.big"
#define LOADED_SAVE_FILE_LITTLE "../auto_tests/data/save.tox.little"
// Information from the save file // Information from the save file
#define EXPECTED_NAME "name" #define EXPECTED_NAME "name"
@ -18,7 +19,7 @@
#define EXPECTED_STATUS_MESSAGE_SIZE strlen(EXPECTED_STATUS_MESSAGE) #define EXPECTED_STATUS_MESSAGE_SIZE strlen(EXPECTED_STATUS_MESSAGE)
#define EXPECTED_NUM_FRIENDS 1 #define EXPECTED_NUM_FRIENDS 1
#define EXPECTED_NOSPAM "4C762C7D" #define EXPECTED_NOSPAM "4C762C7D"
#define EXPECTED_TOX_ID "B70E97D41F69B7F4C42A5BC7BD7A76B95B8030BE1B7C0E9E6FC19FC4ABEB195B4C762C7D800B" #define EXPECTED_TOX_ID "E776E9A993EE3CAE04F5946D9AC66FBBAA8C63A95A94B41942353C6DC1739B4B4C762C7DA7B9"
static size_t get_file_size(const char *save_path) static size_t get_file_size(const char *save_path)
{ {
@ -135,6 +136,13 @@ static void test_save_compatibility(const char *save_path)
tox_kill(tox); tox_kill(tox);
} }
static bool is_little_endian(void)
{
uint16_t x = 1;
return ((uint8_t *)&x)[0] == 1;
}
// cppcheck-suppress constParameter
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char base_path[4096] = {0}; char base_path[4096] = {0};
@ -152,10 +160,15 @@ int main(int argc, char *argv[])
base_path[strrchr(base_path, '/') - base_path] = '\0'; base_path[strrchr(base_path, '/') - base_path] = '\0';
} }
char save_path[4096 + sizeof(LOADED_SAVE_FILE)]; if (is_little_endian()) {
snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE); char save_path[4096 + sizeof(LOADED_SAVE_FILE_LITTLE)];
snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE_LITTLE);
test_save_compatibility(save_path); test_save_compatibility(save_path);
} else {
char save_path[4096 + sizeof(LOADED_SAVE_FILE_BIG)];
snprintf(save_path, sizeof(save_path), "%s/%s", base_path, LOADED_SAVE_FILE_BIG);
test_save_compatibility(save_path);
}
return 0; return 0;
} }

View File

@ -22,13 +22,12 @@ struct test_data {
static void set_random(Tox *m, const Random *rng, bool (*setter)(Tox *, const uint8_t *, size_t, Tox_Err_Set_Info *), size_t length) static void set_random(Tox *m, const Random *rng, bool (*setter)(Tox *, const uint8_t *, size_t, Tox_Err_Set_Info *), size_t length)
{ {
VLA(uint8_t, text, length); VLA(uint8_t, text, length);
uint32_t i;
for (i = 0; i < length; ++i) { for (uint32_t i = 0; i < length; ++i) {
text[i] = random_u08(rng); text[i] = random_u08(rng);
} }
setter(m, text, SIZEOF_VLA(text), nullptr); setter(m, text, length, nullptr);
} }
static void alloc_string(uint8_t **to, size_t length) static void alloc_string(uint8_t **to, size_t length)
@ -44,18 +43,25 @@ static void set_string(uint8_t **to, const uint8_t *from, size_t length)
memcpy(*to, from, length); memcpy(*to, from, length);
} }
static void namechange_callback(Tox *tox, uint32_t friend_number, const uint8_t *name, size_t length, void *user_data) static void namechange_callback(const Tox_Event_Friend_Name *event, void *user_data)
{ {
//const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
const uint8_t *name = tox_event_friend_name_get_name(event);
const uint32_t name_length = tox_event_friend_name_get_name_length(event);
struct test_data *to_compare = (struct test_data *)user_data; struct test_data *to_compare = (struct test_data *)user_data;
set_string(&to_compare->name, name, length); set_string(&to_compare->name, name, name_length);
to_compare->received_name = true; to_compare->received_name = true;
} }
static void statuschange_callback(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, static void statuschange_callback(const Tox_Event_Friend_Status_Message *event, void *user_data)
void *user_data)
{ {
//const uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
const uint8_t *message = tox_event_friend_status_message_get_message(event);
const uint32_t message_length = tox_event_friend_status_message_get_message_length(event);
struct test_data *to_compare = (struct test_data *)user_data; struct test_data *to_compare = (struct test_data *)user_data;
set_string(&to_compare->status_message, message, length); set_string(&to_compare->status_message, message, message_length);
to_compare->received_status_message = true; to_compare->received_status_message = true;
} }
@ -65,6 +71,12 @@ int main(void)
Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr); Tox *const tox1 = tox_new_log(nullptr, nullptr, nullptr);
Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr); Tox *const tox2 = tox_new_log(nullptr, nullptr, nullptr);
ck_assert(tox1 != nullptr);
ck_assert(tox2 != nullptr);
tox_events_init(tox1);
Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
ck_assert(dispatch1 != nullptr);
printf("bootstrapping tox2 off tox1\n"); printf("bootstrapping tox2 off tox1\n");
uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; uint8_t dht_key[TOX_PUBLIC_KEY_SIZE];
@ -86,7 +98,7 @@ int main(void)
ck_assert(reference_name != nullptr); ck_assert(reference_name != nullptr);
ck_assert(reference_status != nullptr); ck_assert(reference_status != nullptr);
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
set_random(tox1, rng, tox_self_set_name, tox_max_name_length()); set_random(tox1, rng, tox_self_set_name, tox_max_name_length());
set_random(tox2, rng, tox_self_set_name, tox_max_name_length()); set_random(tox2, rng, tox_self_set_name, tox_max_name_length());
@ -96,8 +108,8 @@ int main(void)
tox_self_get_name(tox2, reference_name); tox_self_get_name(tox2, reference_name);
tox_self_get_status_message(tox2, reference_status); tox_self_get_status_message(tox2, reference_status);
tox_callback_friend_name(tox1, namechange_callback); tox_events_callback_friend_name(dispatch1, namechange_callback);
tox_callback_friend_status_message(tox1, statuschange_callback); tox_events_callback_friend_status_message(dispatch1, statuschange_callback);
while (true) { while (true) {
if (tox_self_get_connection_status(tox1) && if (tox_self_get_connection_status(tox1) &&
@ -107,7 +119,12 @@ int main(void)
break; break;
} }
tox_iterate(tox1, &to_compare); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox1, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch1, events, &to_compare);
tox_events_free(events);
tox_iterate(tox2, nullptr); tox_iterate(tox2, nullptr);
c_sleep(tox_iteration_interval(tox1)); c_sleep(tox_iteration_interval(tox1));
@ -119,7 +136,12 @@ int main(void)
break; break;
} }
tox_iterate(tox1, &to_compare); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox1, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch1, events, &to_compare);
tox_events_free(events);
tox_iterate(tox2, nullptr); tox_iterate(tox2, nullptr);
c_sleep(tox_iteration_interval(tox1)); c_sleep(tox_iteration_interval(tox1));
@ -146,6 +168,7 @@ int main(void)
"incorrect status message: should be all zeroes"); "incorrect status message: should be all zeroes");
tox_options_free(options); tox_options_free(options);
tox_dispatch_free(dispatch1);
tox_kill(tox1); tox_kill(tox1);
tox_kill(tox2); tox_kill(tox2);
tox_kill(tox_to_compare); tox_kill(tox_to_compare);

View File

@ -32,16 +32,24 @@
#endif #endif
#define TCP_RELAY_PORT 33431 #define TCP_RELAY_PORT 33431
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
{ {
if (length == 7 && memcmp("Gentoo", data, 7) == 0) { Tox *tox = (Tox *)userdata;
tox_friend_add_norequest(m, public_key, nullptr);
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
const uint8_t *message = tox_event_friend_request_get_message(event);
uint32_t message_length = tox_event_friend_request_get_message_length(event);
if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
tox_friend_add_norequest(tox, public_key, nullptr);
} }
} }
static unsigned int connected_t1; static unsigned int connected_t1;
static void tox_connection_status(Tox *tox, Tox_Connection connection_status, void *user_data) static void tox_connection_status(const Tox_Event_Self_Connection_Status *event, void *user_data)
{ {
const Tox_Connection connection_status = tox_event_self_connection_status_get_connection_status(event);
if (connected_t1 && !connection_status) { if (connected_t1 && !connection_status) {
ck_abort_msg("Tox went offline"); ck_abort_msg("Tox went offline");
} }
@ -147,6 +155,9 @@ static void test_few_clients(void)
Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]); Tox *tox1 = tox_new_log(opts1, &t_n_error, &index[0]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
tox_options_free(opts1); tox_options_free(opts1);
tox_events_init(tox1);
Tox_Dispatch *dispatch1 = tox_dispatch_new(nullptr);
ck_assert(dispatch1 != nullptr);
struct Tox_Options *opts2 = tox_options_new(nullptr); struct Tox_Options *opts2 = tox_options_new(nullptr);
tox_options_set_ipv6_enabled(opts2, USE_IPV6); tox_options_set_ipv6_enabled(opts2, USE_IPV6);
@ -154,6 +165,9 @@ static void test_few_clients(void)
tox_options_set_local_discovery_enabled(opts2, false); tox_options_set_local_discovery_enabled(opts2, false);
Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]); Tox *tox2 = tox_new_log(opts2, &t_n_error, &index[1]);
ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error); ck_assert_msg(t_n_error == TOX_ERR_NEW_OK, "Failed to create tox instance: %d", t_n_error);
tox_events_init(tox2);
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
ck_assert(dispatch2 != nullptr);
struct Tox_Options *opts3 = tox_options_new(nullptr); struct Tox_Options *opts3 = tox_options_new(nullptr);
tox_options_set_ipv6_enabled(opts3, USE_IPV6); tox_options_set_ipv6_enabled(opts3, USE_IPV6);
@ -163,7 +177,6 @@ static void test_few_clients(void)
ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances"); ck_assert_msg(tox1 && tox2 && tox3, "Failed to create 3 tox instances");
Time_Data time_data; Time_Data time_data;
ck_assert_msg(pthread_mutex_init(&time_data.lock, nullptr) == 0, "Failed to init time_data mutex"); ck_assert_msg(pthread_mutex_init(&time_data.lock, nullptr) == 0, "Failed to init time_data mutex");
time_data.clock = current_time_monotonic(tox1->mono_time); time_data.clock = current_time_monotonic(tox1->mono_time);
@ -183,8 +196,8 @@ static void test_few_clients(void)
tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr); tox_bootstrap(tox3, "localhost", dht_port, dht_key, nullptr);
connected_t1 = 0; connected_t1 = 0;
tox_callback_self_connection_status(tox1, tox_connection_status); tox_events_callback_self_connection_status(dispatch1, tox_connection_status);
tox_callback_friend_request(tox2, accept_friend_request); tox_events_callback_friend_request(dispatch2, accept_friend_request);
uint8_t address[TOX_ADDRESS_SIZE]; uint8_t address[TOX_ADDRESS_SIZE];
tox_self_get_address(tox2, address); tox_self_get_address(tox2, address);
uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr); uint32_t test = tox_friend_add(tox3, address, (const uint8_t *)"Gentoo", 7, nullptr);
@ -193,8 +206,20 @@ static void test_few_clients(void)
uint8_t off = 1; uint8_t off = 1;
while (true) { while (true) {
tox_iterate(tox1, nullptr); {
tox_iterate(tox2, nullptr); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox1, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch1, events, tox1);
tox_events_free(events);
}
{
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch2, events, tox2);
tox_events_free(events);
}
tox_iterate(tox3, nullptr); tox_iterate(tox3, nullptr);
if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2) if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
@ -220,9 +245,10 @@ static void test_few_clients(void)
// We're done with this callback, so unset it to ensure we don't fail the // We're done with this callback, so unset it to ensure we don't fail the
// test if tox1 goes offline while tox2 and 3 are reloaded. // test if tox1 goes offline while tox2 and 3 are reloaded.
tox_callback_self_connection_status(tox1, nullptr); tox_events_callback_self_connection_status(dispatch1, nullptr);
reload_tox(&tox2, opts2, &index[1]); reload_tox(&tox2, opts2, &index[1]);
tox_events_init(tox2);
reload_tox(&tox3, opts3, &index[2]); reload_tox(&tox3, opts3, &index[2]);
@ -231,8 +257,20 @@ static void test_few_clients(void)
off = 1; off = 1;
while (true) { while (true) {
tox_iterate(tox1, nullptr); {
tox_iterate(tox2, nullptr); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox1, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch1, events, tox1);
tox_events_free(events);
}
{
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch2, events, tox2);
tox_events_free(events);
}
tox_iterate(tox3, nullptr); tox_iterate(tox3, nullptr);
if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2) if (tox_self_get_connection_status(tox1) && tox_self_get_connection_status(tox2)
@ -257,6 +295,9 @@ static void test_few_clients(void)
printf("test_few_clients succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time)); printf("test_few_clients succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
tox_dispatch_free(dispatch1);
tox_dispatch_free(dispatch2);
tox_kill(tox1); tox_kill(tox1);
tox_kill(tox2); tox_kill(tox2);
tox_kill(tox3); tox_kill(tox3);

View File

@ -14,12 +14,15 @@ typedef struct State {
#define MESSAGE_FILLER 'G' #define MESSAGE_FILLER 'G'
static void message_callback( static void message_callback(
Tox *m, uint32_t friendnumber, Tox_Message_Type type, const Tox_Event_Friend_Message *event, void *user_data)
const uint8_t *string, size_t length, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
const Tox_Message_Type type = tox_event_friend_message_get_type(event);
const uint8_t *string = tox_event_friend_message_get_message(event);
const uint32_t length = tox_event_friend_message_get_message_length(event);
if (type != TOX_MESSAGE_TYPE_NORMAL) { if (type != TOX_MESSAGE_TYPE_NORMAL) {
ck_abort_msg("Bad type"); ck_abort_msg("Bad type");
} }
@ -38,7 +41,7 @@ static void message_callback(
static void send_message_test(AutoTox *autotoxes) static void send_message_test(AutoTox *autotoxes)
{ {
tox_callback_friend_message(autotoxes[1].tox, &message_callback); tox_events_callback_friend_message(autotoxes[1].dispatch, &message_callback);
const size_t msgs_len = tox_max_message_length() + 1; const size_t msgs_len = tox_max_message_length() + 1;
uint8_t *msgs = (uint8_t *)malloc(msgs_len); uint8_t *msgs = (uint8_t *)malloc(msgs_len);

View File

@ -15,12 +15,16 @@
#define NICKNAME "Gentoo" #define NICKNAME "Gentoo"
static void nickchange_callback(Tox *tox, uint32_t friendnumber, const uint8_t *string, size_t length, void *userdata) static void nickchange_callback(const Tox_Event_Friend_Name *event, void *user_data)
{ {
ck_assert_msg(length == sizeof(NICKNAME), "Name length not correct: %d != %d", (uint16_t)length, //const uint32_t friend_number = tox_event_friend_name_get_friend_number(event);
const uint8_t *name = tox_event_friend_name_get_name(event);
const uint32_t name_length = tox_event_friend_name_get_name_length(event);
ck_assert_msg(name_length == sizeof(NICKNAME), "Name length not correct: %d != %d", (uint16_t)name_length,
(uint16_t)sizeof(NICKNAME)); (uint16_t)sizeof(NICKNAME));
ck_assert_msg(memcmp(string, NICKNAME, sizeof(NICKNAME)) == 0, "Name not correct: %s", (const char *)string); ck_assert_msg(memcmp(name, NICKNAME, sizeof(NICKNAME)) == 0, "Name not correct: %s", (const char *)name);
bool *nickname_updated = (bool *)userdata; bool *nickname_updated = (bool *)user_data;
*nickname_updated = true; *nickname_updated = true;
} }
@ -34,6 +38,12 @@ static void test_set_name(void)
ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances"); ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
// we only run events on tox2 in this test case
tox_events_init(tox2);
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
ck_assert(dispatch2 != nullptr);
printf("tox1 adds tox2 as friend, tox2 adds tox1\n"); printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_public_key(tox2, public_key); tox_self_get_public_key(tox2, public_key);
@ -50,7 +60,13 @@ static void test_set_name(void)
do { do {
tox_iterate(tox1, nullptr); tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
//tox_dispatch_invoke(dispatch2, events, nullptr);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE || } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE); tox_self_get_connection_status(tox2) == TOX_CONNECTION_NONE);
@ -60,14 +76,20 @@ static void test_set_name(void)
do { do {
tox_iterate(tox1, nullptr); tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
//tox_dispatch_invoke(dispatch2, events, nullptr);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP || } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP); tox_friend_get_connection_status(tox2, 0, nullptr) != TOX_CONNECTION_UDP);
printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time)); printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
tox_callback_friend_name(tox2, nickchange_callback); tox_events_callback_friend_name(dispatch2, nickchange_callback);
Tox_Err_Set_Info err_n; Tox_Err_Set_Info err_n;
bool ret = tox_self_set_name(tox1, (const uint8_t *)NICKNAME, sizeof(NICKNAME), &err_n); bool ret = tox_self_set_name(tox1, (const uint8_t *)NICKNAME, sizeof(NICKNAME), &err_n);
ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %d\n", err_n); ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_name failed because %d\n", err_n);
@ -76,7 +98,13 @@ static void test_set_name(void)
do { do {
tox_iterate(tox1, nullptr); tox_iterate(tox1, nullptr);
tox_iterate(tox2, &nickname_updated);
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch2, events, &nickname_updated);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} while (!nickname_updated); } while (!nickname_updated);
@ -87,6 +115,8 @@ static void test_set_name(void)
printf("test_set_name succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time)); printf("test_set_name succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
tox_dispatch_free(dispatch2);
tox_kill(tox1); tox_kill(tox1);
tox_kill(tox2); tox_kill(tox2);
} }

View File

@ -15,9 +15,13 @@
#define STATUS_MESSAGE "Installing Gentoo" #define STATUS_MESSAGE "Installing Gentoo"
static void status_callback(Tox *tox, uint32_t friend_number, const uint8_t *message, size_t length, void *user_data) static void status_callback(const Tox_Event_Friend_Status_Message *event, void *user_data)
{ {
ck_assert_msg(length == sizeof(STATUS_MESSAGE) && //uint32_t friend_number = tox_event_friend_status_message_get_friend_number(event);
const uint8_t *message = tox_event_friend_status_message_get_message(event);
uint32_t message_length = tox_event_friend_status_message_get_message_length(event);
ck_assert_msg(message_length == sizeof(STATUS_MESSAGE) &&
memcmp(message, STATUS_MESSAGE, sizeof(STATUS_MESSAGE)) == 0, memcmp(message, STATUS_MESSAGE, sizeof(STATUS_MESSAGE)) == 0,
"incorrect data in status callback"); "incorrect data in status callback");
bool *status_updated = (bool *)user_data; bool *status_updated = (bool *)user_data;
@ -34,6 +38,12 @@ static void test_set_status_message(void)
ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances"); ck_assert_msg(tox1 && tox2, "failed to create 2 tox instances");
// we only run events on tox2 in this test case
tox_events_init(tox2);
Tox_Dispatch *dispatch2 = tox_dispatch_new(nullptr);
ck_assert(dispatch2 != nullptr);
printf("tox1 adds tox2 as friend, tox2 adds tox1\n"); printf("tox1 adds tox2 as friend, tox2 adds tox1\n");
uint8_t public_key[TOX_PUBLIC_KEY_SIZE]; uint8_t public_key[TOX_PUBLIC_KEY_SIZE];
tox_self_get_public_key(tox2, public_key); tox_self_get_public_key(tox2, public_key);
@ -50,7 +60,12 @@ static void test_set_status_message(void)
do { do {
tox_iterate(tox1, nullptr); tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
//tox_dispatch_invoke(dispatch2, events, nullptr);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE || } while (tox_self_get_connection_status(tox1) == TOX_CONNECTION_NONE ||
@ -61,7 +76,12 @@ static void test_set_status_message(void)
do { do {
tox_iterate(tox1, nullptr); tox_iterate(tox1, nullptr);
tox_iterate(tox2, nullptr);
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
//tox_dispatch_invoke(dispatch2, events, nullptr);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP || } while (tox_friend_get_connection_status(tox1, 0, nullptr) != TOX_CONNECTION_UDP ||
@ -69,8 +89,8 @@ static void test_set_status_message(void)
printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time)); printf("tox clients connected took %lu seconds\n", (unsigned long)(time(nullptr) - con_time));
tox_events_callback_friend_status_message(dispatch2, status_callback);
Tox_Err_Set_Info err_n; Tox_Err_Set_Info err_n;
tox_callback_friend_status_message(tox2, status_callback);
bool ret = tox_self_set_status_message(tox1, (const uint8_t *)STATUS_MESSAGE, sizeof(STATUS_MESSAGE), bool ret = tox_self_set_status_message(tox1, (const uint8_t *)STATUS_MESSAGE, sizeof(STATUS_MESSAGE),
&err_n); &err_n);
ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %d\n", err_n); ck_assert_msg(ret && err_n == TOX_ERR_SET_INFO_OK, "tox_self_set_status_message failed because %d\n", err_n);
@ -79,7 +99,13 @@ static void test_set_status_message(void)
do { do {
tox_iterate(tox1, nullptr); tox_iterate(tox1, nullptr);
tox_iterate(tox2, &status_updated);
Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch2, events, &status_updated);
tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} while (!status_updated); } while (!status_updated);
@ -92,6 +118,8 @@ static void test_set_status_message(void)
printf("test_set_status_message succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time)); printf("test_set_status_message succeeded, took %lu seconds\n", (unsigned long)(time(nullptr) - cur_time));
tox_dispatch_free(dispatch2);
tox_kill(tox1); tox_kill(tox1);
tox_kill(tox2); tox_kill(tox2);
} }

View File

@ -18,7 +18,7 @@
// Set to true to produce an msgpack file at /tmp/test.mp. // Set to true to produce an msgpack file at /tmp/test.mp.
static const bool want_dump_events = false; static const bool want_dump_events = false;
static void handle_events_friend_message(Tox *tox, const Tox_Event_Friend_Message *event, void *user_data) static void handle_events_friend_message(const Tox_Event_Friend_Message *event, void *user_data)
{ {
bool *success = (bool *)user_data; bool *success = (bool *)user_data;
@ -84,7 +84,7 @@ static bool await_message(Tox **toxes, const Tox_Dispatch *dispatch)
} }
bool success = false; bool success = false;
tox_dispatch_invoke(dispatch, events, toxes[1], &success); tox_dispatch_invoke(dispatch, events, &success);
print_events(sys, events); print_events(sys, events);
if (success) { if (success) {
@ -169,22 +169,9 @@ static void test_tox_events(void)
} }
} }
static void fake_test_unpack(void)
{
// TODO(Green-Sky): add proper unpack tests and/or implement ngc events
(void)tox_group_privacy_state_unpack;
(void)tox_group_privacy_state_unpack;
(void)tox_group_voice_state_unpack;
(void)tox_group_topic_lock_unpack;
(void)tox_group_join_fail_unpack;
(void)tox_group_mod_event_unpack;
(void)tox_group_exit_type_unpack;
}
int main(void) int main(void)
{ {
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);
test_tox_events(); test_tox_events();
fake_test_unpack();
return 0; return 0;
} }

View File

@ -26,16 +26,27 @@
#define TOX_LOCALHOST "127.0.0.1" #define TOX_LOCALHOST "127.0.0.1"
#endif #endif
typedef struct State {
uint32_t to_comp;
Tox *tox;
} State;
static bool enable_broken_tests = false; static bool enable_broken_tests = false;
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
{ {
if (*((uint32_t *)userdata) != 974536) { State *state = (State *)userdata;
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
const uint8_t *message = tox_event_friend_request_get_message(event);
const uint32_t message_length = tox_event_friend_request_get_message_length(event);
if (state->to_comp != 974536) {
return; return;
} }
if (length == 7 && memcmp("Gentoo", data, 7) == 0) { if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
tox_friend_add_norequest(m, public_key, nullptr); tox_friend_add_norequest(state->tox, public_key, nullptr);
} }
} }
@ -46,7 +57,7 @@ static uint16_t tcp_relay_port = 33448;
static void test_many_clients_tcp(void) static void test_many_clients_tcp(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
long long unsigned int cur_time = time(nullptr); long long unsigned int cur_time = time(nullptr);
Tox *toxes[NUM_TOXES_TCP]; Tox *toxes[NUM_TOXES_TCP];
@ -73,7 +84,7 @@ static void test_many_clients_tcp(void)
continue; continue;
} }
ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i); ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], accept_friend_request); tox_events_init(toxes[i]);
uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
tox_self_get_dht_id(toxes[0], dpk); tox_self_get_dht_id(toxes[0], dpk);
Tox_Err_Bootstrap error; Tox_Err_Bootstrap error;
@ -85,6 +96,11 @@ static void test_many_clients_tcp(void)
tox_options_free(opts); tox_options_free(opts);
} }
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
ck_assert(dispatch != nullptr);
tox_events_callback_friend_request(dispatch, accept_friend_request);
struct { struct {
uint16_t tox1; uint16_t tox1;
uint16_t tox2; uint16_t tox2;
@ -131,12 +147,18 @@ loop_top:
} }
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
tox_iterate(toxes[i], &to_comp); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
State state = {to_comp, toxes[i]};
tox_dispatch_invoke(dispatch, events, &state);
tox_events_free(events);
} }
c_sleep(50); c_sleep(50);
} }
tox_dispatch_free(dispatch);
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
tox_kill(toxes[i]); tox_kill(toxes[i]);
} }
@ -148,7 +170,7 @@ loop_top:
static void test_many_clients_tcp_b(void) static void test_many_clients_tcp_b(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
long long unsigned int cur_time = time(nullptr); long long unsigned int cur_time = time(nullptr);
Tox *toxes[NUM_TOXES_TCP]; Tox *toxes[NUM_TOXES_TCP];
@ -167,7 +189,7 @@ static void test_many_clients_tcp_b(void)
index[i] = i + 1; index[i] = i + 1;
toxes[i] = tox_new_log(opts, nullptr, &index[i]); toxes[i] = tox_new_log(opts, nullptr, &index[i]);
ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i); ck_assert_msg(toxes[i] != nullptr, "Failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], accept_friend_request); tox_events_init(toxes[i]);
uint8_t dpk[TOX_PUBLIC_KEY_SIZE]; uint8_t dpk[TOX_PUBLIC_KEY_SIZE];
tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk); tox_self_get_dht_id(toxes[(i % NUM_TCP_RELAYS)], dpk);
ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port + (i % NUM_TCP_RELAYS), dpk, nullptr), ck_assert_msg(tox_add_tcp_relay(toxes[i], TOX_LOCALHOST, tcp_relay_port + (i % NUM_TCP_RELAYS), dpk, nullptr),
@ -179,6 +201,11 @@ static void test_many_clients_tcp_b(void)
tox_options_free(opts); tox_options_free(opts);
} }
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
ck_assert(dispatch != nullptr);
tox_events_callback_friend_request(dispatch, accept_friend_request);
struct { struct {
uint16_t tox1; uint16_t tox1;
uint16_t tox2; uint16_t tox2;
@ -232,12 +259,18 @@ loop_top:
} }
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
tox_iterate(toxes[i], &to_comp); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
State state = {to_comp, toxes[i]};
tox_dispatch_invoke(dispatch, events, &state);
tox_events_free(events);
} }
c_sleep(30); c_sleep(30);
} }
tox_dispatch_free(dispatch);
for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) { for (uint32_t i = 0; i < NUM_TOXES_TCP; ++i) {
tox_kill(toxes[i]); tox_kill(toxes[i]);
} }
@ -245,7 +278,6 @@ loop_top:
printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(nullptr) - cur_time); printf("test_many_clients_tcp_b succeeded, took %llu seconds\n", time(nullptr) - cur_time);
} }
static void tox_suite(void) static void tox_suite(void)
{ {
/* Each tox connects to a single tox TCP */ /* Each tox connects to a single tox TCP */

View File

@ -13,20 +13,25 @@
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"
static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata) static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
{ {
if (length == 7 && memcmp("Gentoo", data, 7) == 0) { Tox *tox = (Tox *)userdata;
tox_friend_add_norequest(m, public_key, nullptr);
}
}
const uint8_t *public_key = tox_event_friend_request_get_public_key(event);
const uint8_t *message = tox_event_friend_request_get_message(event);
const uint32_t message_length = tox_event_friend_request_get_message_length(event);
if (message_length == 7 && memcmp("Gentoo", message, 7) == 0) {
tox_friend_add_norequest(tox, public_key, nullptr);
}
}
#define TCP_TEST_NUM_TOXES 90 #define TCP_TEST_NUM_TOXES 90
#define TCP_TEST_NUM_FRIENDS 50 #define TCP_TEST_NUM_FRIENDS 50
static void test_many_clients(void) static void test_many_clients(void)
{ {
const Random *rng = system_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
time_t cur_time = time(nullptr); time_t cur_time = time(nullptr);
Tox *toxes[TCP_TEST_NUM_TOXES]; Tox *toxes[TCP_TEST_NUM_TOXES];
@ -36,9 +41,14 @@ static void test_many_clients(void)
index[i] = i + 1; index[i] = i + 1;
toxes[i] = tox_new_log(nullptr, nullptr, &index[i]); toxes[i] = tox_new_log(nullptr, nullptr, &index[i]);
ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i); ck_assert_msg(toxes[i] != nullptr, "failed to create tox instances %u", i);
tox_callback_friend_request(toxes[i], accept_friend_request); tox_events_init(toxes[i]);
} }
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
ck_assert(dispatch != nullptr);
tox_events_callback_friend_request(dispatch, accept_friend_request);
struct { struct {
uint16_t tox1; uint16_t tox1;
uint16_t tox2; uint16_t tox2;
@ -112,12 +122,17 @@ loop_top:
} }
for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) { for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
tox_iterate(toxes[i], nullptr); Tox_Err_Events_Iterate err = TOX_ERR_EVENTS_ITERATE_OK;
Tox_Events *events = tox_events_iterate(toxes[i], true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, toxes[i]);
tox_events_free(events);
} }
c_sleep(50); c_sleep(50);
} }
tox_dispatch_free(dispatch);
for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) { for (uint32_t i = 0; i < TCP_TEST_NUM_TOXES; ++i) {
tox_kill(toxes[i]); tox_kill(toxes[i]);
} }

View File

@ -0,0 +1,9 @@
#include "../toxcore/tox.h"
#include "../toxcore/ccompat.h"
int main(void)
{
tox_kill(tox_new(nullptr, nullptr));
return 0;
}

View File

@ -23,7 +23,6 @@
#define TEST_STOP_RESUME_PAYLOAD 1 #define TEST_STOP_RESUME_PAYLOAD 1
#define TEST_PAUSE_RESUME_SEND 1 #define TEST_PAUSE_RESUME_SEND 1
#define ck_assert_call_control(a, b, c) do { \ #define ck_assert_call_control(a, b, c) do { \
Toxav_Err_Call_Control cc_err; \ Toxav_Err_Call_Control cc_err; \
bool ok = toxav_call_control(a, b, c, &cc_err); \ bool ok = toxav_call_control(a, b, c, &cc_err); \
@ -34,7 +33,6 @@
ck_assert(cc_err == TOXAV_ERR_CALL_CONTROL_OK); \ ck_assert(cc_err == TOXAV_ERR_CALL_CONTROL_OK); \
} while (0) } while (0)
typedef struct { typedef struct {
bool incoming; bool incoming;
uint32_t state; uint32_t state;
@ -46,7 +44,6 @@ static void clear_call_control(CallControl *cc)
*cc = empty; *cc = empty;
} }
/** /**
* Callbacks * Callbacks
*/ */
@ -89,7 +86,6 @@ static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const
} }
} }
/** /**
* Iterate helper * Iterate helper
*/ */
@ -207,7 +203,6 @@ static void test_av_flows(void)
c_sleep(20); c_sleep(20);
} }
{ {
Toxav_Err_New error; Toxav_Err_New error;
alice_av = toxav_new(alice, &error); alice_av = toxav_new(alice, &error);

View File

@ -74,7 +74,6 @@ static void t_accept_friend_request_cb(Tox *m, const uint8_t *public_key, const
} }
} }
/** /**
* Iterate helper * Iterate helper
*/ */
@ -299,7 +298,6 @@ static void test_av_three_calls(void)
} }
} }
do { do {
tox_iterate(bootstrap, nullptr); tox_iterate(bootstrap, nullptr);
tox_iterate(alice, nullptr); tox_iterate(alice, nullptr);

View File

@ -17,10 +17,14 @@ typedef struct State {
#include "auto_test_support.h" #include "auto_test_support.h"
static void typing_callback(Tox *m, uint32_t friendnumber, bool typing, void *user_data) static void typing_callback(const Tox_Event_Friend_Typing *event, void *user_data)
{ {
const AutoTox *autotox = (AutoTox *)user_data; const AutoTox *autotox = (AutoTox *)user_data;
State *state = (State *)autotox->state; State *state = (State *)autotox->state;
//const uint32_t friend_number = tox_event_friend_typing_get_friend_number(event);
const bool typing = tox_event_friend_typing_get_typing(event);
state->friend_is_typing = typing; state->friend_is_typing = typing;
} }
@ -28,7 +32,7 @@ static void test_typing(AutoTox *autotoxes)
{ {
time_t cur_time = time(nullptr); time_t cur_time = time(nullptr);
tox_callback_friend_typing(autotoxes[1].tox, &typing_callback); tox_events_callback_friend_typing(autotoxes[1].dispatch, &typing_callback);
tox_self_set_typing(autotoxes[0].tox, 0, true, nullptr); tox_self_set_typing(autotoxes[0].tox, 0, true, nullptr);
do { do {

View File

@ -48,8 +48,8 @@ function(_make_version_script target)
endfunction() endfunction()
option(STRICT_ABI "Enforce strict ABI export in dynamic libraries" OFF) option(STRICT_ABI "Enforce strict ABI export in dynamic libraries" OFF)
if(WIN32 OR APPLE) if((WIN32 AND NOT MINGW) OR APPLE)
# Windows and OSX don't have this linker functionality. # Windows and macOS don't have this linker functionality.
set(STRICT_ABI OFF) set(STRICT_ABI OFF)
endif() endif()

View File

@ -1295,15 +1295,6 @@ HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80 HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML # If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
# documentation will contain a main index with vertical navigation menus that # documentation will contain a main index with vertical navigation menus that
# are dynamically created via JavaScript. If disabled, the navigation index will # are dynamically created via JavaScript. If disabled, the navigation index will
@ -1950,14 +1941,6 @@ LATEX_HIDE_INDICES = NO
LATEX_BIB_STYLE = plain LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute) # The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
# path from which the emoji images will be read. If a relative path is entered, # path from which the emoji images will be read. If a relative path is entered,
# it will be relative to the LATEX_OUTPUT directory. If left blank the # it will be relative to the LATEX_OUTPUT directory. If left blank the
@ -2587,3 +2570,19 @@ GENERATE_LEGEND = YES
# The default value is: YES. # The default value is: YES.
DOT_CLEANUP = YES DOT_CLEANUP = YES
# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the
# clang parser for more accurate parsing at the cost of reduced performance.
# This can be particularly helpful with template rich C++ code for which
# doxygen's built-in parser lacks the necessary type information.
CLANG_ASSISTED_PARSING = NO
# If clang assisted parsing is enabled you can provide the clang parser with
# the path to the directory containing a file called compile_commands.json.
# This file is the compilation database containing the options used when the
# source files were built. This is equivalent to specifying the -p option to a
# clang tool, such as clang-check. These options will then be passed to the
# parser. Any options specified with CLANG_OPTIONS will be added as well.
CLANG_DATABASE_PATH = _build

View File

@ -2,77 +2,122 @@ Group chats.
Note: we assume everyone in the chat trusts each other. Note: we assume everyone in the chat trusts each other.
These group chats work by temporarily adding the 4 "closest" people defined by a distance function These group chats work by temporarily adding the 4 "closest" people defined by a
in group.c in order to form a circle of connected peers. These peers then relay messages to each other. distance function in group.c in order to form a circle of connected peers. These
peers then relay messages to each other.
A friend invites another friend to a group chat by sending them an invite packet. The friend either ignores
the invite or responds with a response packet if he wants to join the chat. The friend invite contains the type
of groupchat (text only, A/V) the friend is being invited to.
A friend invites another friend to a group chat by sending them an invite
packet. The friend either ignores the invite or responds with a response packet
if he wants to join the chat. The friend invite contains the type of groupchat
(text only, A/V) the friend is being invited to.
TODO(irungentoo): write more of this. TODO(irungentoo): write more of this.
## Protocol ## Protocol
Invite packets: Invite packets:
Invite packet:
### Invite packet:
```
[uint8_t id 96][uint8_t id 0][uint16_t group chat number][33 bytes group chat identifier[1 byte type][32 bytes id]] [uint8_t id 96][uint8_t id 0][uint16_t group chat number][33 bytes group chat identifier[1 byte type][32 bytes id]]
```
Response packet ### Response packet
```
[uint8_t id 96][uint8_t id 1][uint16_t group chat number(local)][uint16_t group chat number to join][33 bytes group chat identifier[1 byte type][32 bytes id]] [uint8_t id 96][uint8_t id 1][uint16_t group chat number(local)][uint16_t group chat number to join][33 bytes group chat identifier[1 byte type][32 bytes id]]
```
### Peer online packet:
Peer online packet: ```
[uint8_t id 97][uint16_t group chat number (local)][33 bytes group chat identifier[1 byte type][32 bytes id]] [uint8_t id 97][uint16_t group chat number (local)][33 bytes group chat identifier[1 byte type][32 bytes id]]
```
Peer leave packet: ### Peer leave packet:
```
[uint8_t id 98][uint16_t group chat number][uint8_t id 1] [uint8_t id 98][uint16_t group chat number][uint8_t id 1]
```
Peer query packet: ### Peer query packet:
```
[uint8_t id 98][uint16_t group chat number][uint8_t id 8] [uint8_t id 98][uint16_t group chat number][uint8_t id 8]
```
Peer response packet: ### Peer response packet:
```
[uint8_t id 98][uint16_t group chat number][uint8_t id 9][Repeated times number of peers: [uint16_t peer num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key][uint8_t name length][name]] [uint8_t id 98][uint16_t group chat number][uint8_t id 9][Repeated times number of peers: [uint16_t peer num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key][uint8_t name length][name]]
```
Title response packet: ### Title response packet:
```
[uint8_t id 98][uint16_t group chat number][uint8_t id 10][title] [uint8_t id 98][uint16_t group chat number][uint8_t id 10][title]
```
Message packets: ### Message packets:
```
[uint8_t id 99][uint16_t group chat number][uint16_t peer number][uint32_t message number][uint8_t with a value representing id of message][data] [uint8_t id 99][uint16_t group chat number][uint16_t peer number][uint32_t message number][uint8_t with a value representing id of message][data]
```
Lossy Message packets: ### Lossy Message packets:
```
[uint8_t id 199][uint16_t group chat number][uint16_t peer number][uint16_t message number][uint8_t with a value representing id of message][data] [uint8_t id 199][uint16_t group chat number][uint16_t peer number][uint16_t message number][uint8_t with a value representing id of message][data]
```
Group chat types: ## Group chat types:
0: text
1: AV
- 0: text
- 1: AV
Note: the message number is increased by 1 for each sent message. Note: the message number is increased by 1 for each sent message.
message ids: ## message ids:
0 - ping
sent every ~60 seconds by every peer. ### 0 - ping
No data.
sent every ~60 seconds by every peer. No data.
### 16 - new_peer
16 - new_peer
Tell everyone about a new peer in the chat. Tell everyone about a new peer in the chat.
```
[uint16_t peer_num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key] [uint16_t peer_num][uint8_t 32bytes real public key][uint8_t 32bytes temp DHT public key]
```
17 - kill_peer ### 17 - kill_peer
```
[uint16_t peer_num] [uint16_t peer_num]
```
48 - name change ### 48 - name change
```
[uint8_t name[namelen]] [uint8_t name[namelen]]
```
49 - groupchat title change ### 49 - groupchat title change
```
[uint8_t title[titlelen]] [uint8_t title[titlelen]]
```
64 - chat message ### 64 - chat message
```
[uint8_t message[messagelen]] [uint8_t message[messagelen]]
```
65 - action (/me) ### 65 - action (/me)
```
[uint8_t message[messagelen]] [uint8_t message[messagelen]]
```

View File

@ -1,51 +0,0 @@
This folder contains the input file (``tox.in.h``) that has to be used to generate the ``tox.h`` api with: https://github.com/TokTok/apidsl
# Minimal requirements
There are some minimal requirements to contribute to ``tox.h``:
* unix environment
* ``astyle`` ``>=2.03``
* [``apidsl``](https://github.com/TokTok/apidsl) (you can use provided service with curl instead)
## Quick way
If you want to do it quickly and you don't have time for anything other than copypasting commands, you should have ``curl`` installed.
1. Make sure that you have ``curl`` and ``>=astyle-2.03`` installed
2. Modify [``tox.api.h``](/toxcore/tox.api.h)
3. Run command below ↓
Command to run from ``toxcore`` directory (quick way, involves using curl):
```bash
# For tox.h:
curl -X POST --data-binary @- https://apidsl.herokuapp.com/apidsl \
< toxcore/tox.api.h \
| astyle --options=other/astyle/astylerc \
> toxcore/tox.h
# For toxav.h:
curl -X POST --data-binary @- https://apidsl.herokuapp.com/apidsl \
< toxav/toxav.api.h \
| astyle --options=other/astyle/astylerc \
> toxav/toxav.h
```
You may want to make sure with ``git diff`` that changes made in ``tox.h`` reflect changes in ``tox.in.h``.
And you're done.
## Manually
If you prefer to have more control over what is happening, there are steps below:
1. Install [``apidsl``](https://github.com/TokTok/apidsl)
2. Install ``astyle``, version 2.03 or later.
3. Modify [``tox.api.h``](/toxcore/tox.api.h)
4. Use ``apidsl`` ``??``
5. Parse generated ``tox.h`` with astyle, minimal command for it would be:
```bash
astyle --options=other/astyle/astylerc toxcore/tox.h
```
**Always pass output from ``apidsl`` through astyle.**

View File

@ -8,10 +8,9 @@
phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port); phone_t* initPhone(uint16_t _listen_port, uint16_t _send_port);
``` ```
function initializes sample phone. _listen_port and _send_port are variables only meant function initializes sample phone. `_listen_port` and `_send_port` are variables
for local testing. You will not have to do anything regarding to that since only meant for local testing. You will not have to do anything regarding to that
everything will be started within a messenger. since everything will be started within a messenger.
Phone requires one msi session and two rtp sessions (one for audio and one for Phone requires one msi session and two rtp sessions (one for audio and one for
video). video).
@ -20,26 +19,25 @@ video ).
msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent ); msi_session_t* msi_init_session( void* _core_handler, const uint8_t* _user_agent );
``` ```
initializes msi session. initializes msi session. Params:
Params:
``` ```
void* _core_handler - pointer to an object handling networking, void* _core_handler - pointer to an object handling networking,
const uint8_t* _user_agent - string describing phone client version. const uint8_t* _user_agent - string describing phone client version.
``` ```
Return value: Return value: `msi_session_t*` - pointer to a newly created msi session handler.
msi_session_t* - pointer to a newly created msi session handler.
### msi_session_t reference: ### `msi_session_t` reference:
How to handle msi session: How to handle msi session: Controlling is done via callbacks and action
Controlling is done via callbacks and action handlers. handlers. First register callbacks for every state/action received and make sure
First register callbacks for every state/action received and make sure NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every
NOT TO PLACE SOMETHING LIKE LOOPS THAT TAKES A LOT OF TIME TO EXECUTE; every callback is being called callback is being called directly from event loop. You can find examples in
directly from event loop. You can find examples in phone.c. phone.c.
Register callbacks: Register callbacks:
``` ```
void msi_register_callback_call_started ( MCALLBACK ); void msi_register_callback_call_started ( MCALLBACK );
void msi_register_callback_call_canceled ( MCALLBACK ); void msi_register_callback_call_canceled ( MCALLBACK );
@ -55,10 +53,9 @@ void msi_register_callback_recv_error ( MCALLBACK );
void msi_register_callback_requ_timeout ( MCALLBACK ); void msi_register_callback_requ_timeout ( MCALLBACK );
``` ```
MCALLBACK is defined as: void (*callback) (void* _arg) MCALLBACK is defined as: `void (*callback) (void* _arg)` `msi_session_t*`
msi_session_t* handler is being thrown as \_arg so you can use that and \_agent_handler to get to your own phone handler handler is being thrown as `_arg` so you can use that and `_agent_handler` to
directly from callback. get to your own phone handler directly from callback.
Actions: Actions:
@ -66,80 +63,93 @@ Actions:
int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms ); int msi_invite ( msi_session_t* _session, call_type _call_type, uint32_t _timeoutms );
``` ```
Sends call invite. Before calling/sending invite msi_session_t::_friend_id is needed to be set or else Sends call invite. Before calling/sending invite `msi_session_t::_friend_id` is
it will not work. _call_type is type of the call ( Audio/Video ) and _timeoutms is how long needed to be set or else it will not work. `_call_type` is type of the call (
will poll wait until request is terminated. Audio/Video ) and `_timeoutms` is how long will poll wait until request is
terminated.
``` ```
int msi_hangup ( msi_session_t* _session ); int msi_hangup ( msi_session_t* _session );
``` ```
Hangs up active call Hangs up active call
``` ```
int msi_answer ( msi_session_t* _session, call_type _call_type ); int msi_answer ( msi_session_t* _session, call_type _call_type );
``` ```
Answer incoming call. _call_type set's callee call type.
Answer incoming call. `_call_type` set's callee call type.
``` ```
int msi_cancel ( msi_session_t* _session ); int msi_cancel ( msi_session_t* _session );
``` ```
Cancel current request. Cancel current request.
``` ```
int msi_reject ( msi_session_t* _session ); int msi_reject ( msi_session_t* _session );
``` ```
Reject incoming call.
Reject incoming call.
### Now for rtp: ### Now for rtp:
You will need 2 sessions; one for audio one for video. You will need 2 sessions; one for audio one for video. You start them with:
You start them with:
``` ```
rtp_session_t* rtp_init_session ( int _max_users, int _multi_session ); rtp_session_t* rtp_init_session ( int _max_users, int _multi_session );
``` ```
Params: Params:
``` ```
int _max_users - max users. -1 if undefined int _max_users - max users. -1 if undefined
int _multi_session - any positive number means uses multi session; -1 if not. int _multi_session - any positive number means uses multi session; -1 if not.
``` ```
Return value: Return value:
``` ```
rtp_session_t* - pointer to a newly created rtp session handler. rtp_session_t* - pointer to a newly created rtp session handler.
``` ```
### How to handle rtp session: ### How to handle rtp session:
Take a look at Take a look at
``` ```
void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c void* phone_handle_media_transport_poll ( void* _hmtc_args_p ) in phone.c
``` ```
on example. Basically what you do is just receive a message via: on example. Basically what you do is just receive a message via:
``` ```
struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session ); struct rtp_msg_s* rtp_recv_msg ( rtp_session_t* _session );
``` ```
and then you use payload within the rtp_msg_s struct. Don't forget to deallocate it with: and then you use payload within the `rtp_msg_s` struct. Don't forget to
void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg ); deallocate it with:
`void rtp_free_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg );`
Receiving should be thread safe so don't worry about that. Receiving should be thread safe so don't worry about that.
When you capture and encode a payload you want to send it ( obviously ). When you capture and encode a payload you want to send it ( obviously ).
first create a new message with: first create a new message with:
``` ```
struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length ); struct rtp_msg_s* rtp_msg_new ( rtp_session_t* _session, const uint8_t* _data, uint32_t _length );
``` ```
and then send it with: and then send it with:
``` ```
int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler ); int rtp_send_msg ( rtp_session_t* _session, struct rtp_msg_s* _msg, void* _core_handler );
``` ```
_core_handler is the same network handler as in msi_session_s struct. `_core_handler` is the same network handler as in `msi_session_s` struct.
## A/V initialization: ## A/V initialization:
``` ```
int init_receive_audio(codec_state *cs); int init_receive_audio(codec_state *cs);
int init_receive_video(codec_state *cs); int init_receive_video(codec_state *cs);
@ -156,39 +166,62 @@ In the future, VP8 should be used directly and ffmpeg should be dropped from the
The variable bps is the required bitrate in bits per second. The variable bps is the required bitrate in bits per second.
``` ```
### A/V encoding/decoding: ### A/V encoding/decoding:
``` ```
void *encode_video_thread(void *arg); void *encode_video_thread(void *arg);
``` ```
Spawns the video encoding thread. The argument should hold a pointer to a codec_state.
This function should only be called if video encoding is supported (when init_send_video returns 1). Spawns the video encoding thread. The argument should hold a pointer to a
Each video frame gets encoded into a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe is encoded. `codec_state`. This function should only be called if video encoding is
supported (when `init_send_video` returns 1). Each video frame gets encoded into
a packet, which is sent via RTP. Every 60 frames a new bidirectional interframe
is encoded.
``` ```
void *encode_audio_thread(void *arg); void *encode_audio_thread(void *arg);
``` ```
Spawns the audio encoding thread. The argument should hold a pointer to a codec_state.
This function should only be called if audio encoding is supported (when init_send_audio returns 1). Spawns the audio encoding thread. The argument should hold a pointer to a
Audio frames are read from the selected audio capture device during initialisation. This audio capturing can be rerouted to a different device on the fly. `codec_state`. This function should only be called if audio encoding is
Each audio frame is encoded into a packet, and sent via RTP. All audio frames have the same amount of samples, which is defined in AV_codec.h. supported (when `init_send_audio` returns 1). Audio frames are read from the
selected audio capture device during initialisation. This audio capturing can be
rerouted to a different device on the fly. Each audio frame is encoded into a
packet, and sent via RTP. All audio frames have the same amount of samples,
which is defined in `AV_codec.h`.
``` ```
int video_decoder_refresh(codec_state *cs, int width, int height); int video_decoder_refresh(codec_state *cs, int width, int height);
``` ```
Sets the SDL window dimensions and creates a pixel buffer with the requested size. It also creates a scaling context, which will be used to convert the input image format to YUV420P.
Sets the SDL window dimensions and creates a pixel buffer with the requested
size. It also creates a scaling context, which will be used to convert the input
image format to YUV420P.
``` ```
void *decode_video_thread(void *arg); void *decode_video_thread(void *arg);
``` ```
Spawns a video decoding thread. The argument should hold a pointer to a codec_state. The codec_state is assumed to contain a successfully initialised video decoder.
This function reads video packets and feeds them to the video decoder. If the video frame's resolution has changed, video_decoder_refresh() is called. Afterwards, the frame is displayed on the SDL window. Spawns a video decoding thread. The argument should hold a pointer to a
`codec_state`. The `codec_state` is assumed to contain a successfully
initialised video decoder. This function reads video packets and feeds them to
the video decoder. If the video frame's resolution has changed,
`video_decoder_refresh()` is called. Afterwards, the frame is displayed on the
SDL window.
``` ```
void *decode_audio_thread(void *arg); void *decode_audio_thread(void *arg);
``` ```
Spawns an audio decoding thread. The argument should hold a pointer to a codec_state. The codec_state is assumed to contain a successfully initialised audio decoder.
All received audio packets are pushed into a jitter buffer and are reordered. If there is a missing packet, or a packet has arrived too late, it is treated as a lost packet and the audio decoder is informed of the packet loss. The audio decoder will then try to reconstruct the lost packet, based on information from previous packets.
Audio is played on the default OpenAL output device.
Spawns an audio decoding thread. The argument should hold a pointer to a
`codec_state`. The `codec_state` is assumed to contain a successfully
initialised audio decoder. All received audio packets are pushed into a jitter
buffer and are reordered. If there is a missing packet, or a packet has arrived
too late, it is treated as a lost packet and the audio decoder is informed of
the packet loss. The audio decoder will then try to reconstruct the lost packet,
based on information from previous packets. Audio is played on the default
OpenAL output device.
If you have any more qustions/bug reports/feature request contact the following users on the irc channel #tox-dev on irc.freenode.net: If you have any more qustions/bug reports/feature request contact the following
For RTP and MSI: mannol users on the irc channel #tox-dev on irc.freenode.net: For RTP and MSI: mannol
For audio and video: Martijnvdc For audio and video: Martijnvdc

View File

@ -3,29 +3,29 @@
This document describes the "minpgc" simple persistent conferences This document describes the "minpgc" simple persistent conferences
implementation of PR #1069. implementation of PR #1069.
Many of the ideas derive from isotoxin's persistent conferences Many of the ideas derive from isotoxin's persistent conferences implementation,
implementation, PR #826. PR #826.
## Specification of changes from pre-existing conference specification ## Specification of changes from pre-existing conference specification
We add one new packet type: We add one new packet type:
Rejoin Conference packet Rejoin Conference packet
| Length | Contents | | Length | Contents |
|:-------|:--------------------------------| | :----- | :-------------------- |
| `1` | `uint8_t` (0x64) | | `1` | `uint8_t` (0x64) |
| `33` | Group chat identifier | | `33` | Group chat identifier |
A peer times out from a group if it has been inactive for 60s. When a peer times
out, we flag it as _frozen_. Frozen peers are disregarded for all purposes
except those discussed below - in particular no packets are sent to them except
as described below, they are omitted from the peer lists sent to the client or
in a Peer Response packet, and they are not considered when determining closest
peers for establishing direct connections.
A peer times out from a group if it has been inactive for 60s. When a peer A peer is considered to be active if we receive a group message or Rejoin packet
times out, we flag it as _frozen_. Frozen peers are disregarded for all from it, or a New Peer message for it.
purposes except those discussed below - in particular no packets are sent to
them except as described below, they are omitted from the peer lists sent to
the client or in a Peer Response packet, and they are not considered when
determining closest peers for establishing direct connections.
A peer is considered to be active if we receive a group message or Rejoin
packet from it, or a New Peer message for it.
If a frozen peer is seen to be active, we remove its 'frozen' flag and send a If a frozen peer is seen to be active, we remove its 'frozen' flag and send a
Name group message. (We can hold off on sending this message until the next Name group message. (We can hold off on sending this message until the next
@ -40,77 +40,83 @@ message. (This is current behaviour; it's mentioned here because it's important
and not currently mentioned in the spec.) and not currently mentioned in the spec.)
If we receive a Rejoin packet from a peer we update its DHT pubkey, add a If we receive a Rejoin packet from a peer we update its DHT pubkey, add a
temporary groupchat connection for the peer, and, once the connection is temporary groupchat connection for the peer, and, once the connection is online,
online, send out a New Peer message announcing the peer, and a Name message. send out a New Peer message announcing the peer, and a Name message.
Whenever we make a new friend connection, we check if the public key is that Whenever we make a new friend connection, we check if the public key is that of
of any frozen peer. If so, we send it a Rejoin packet, add a temporary any frozen peer. If so, we send it a Rejoin packet, add a temporary groupchat
groupchat connection for it, and, once the connection is online, send the connection for it, and, once the connection is online, send the peer a Peer
peer a Peer Query packet. Query packet.
We do the same with a peer when we are setting it as frozen if we have a We do the same with a peer when we are setting it as frozen if we have a friend
friend connection to it. connection to it.
The temporary groupchat connections established in sending and handling Rejoin The temporary groupchat connections established in sending and handling Rejoin
packets are not immediately operational (because group numbers are not known); packets are not immediately operational (because group numbers are not known);
rather, an Online packet is sent when we handle a Rejoin packet. rather, an Online packet is sent when we handle a Rejoin packet.
When a connection is set as online as a result of an Online packet, we ping When a connection is set as online as a result of an Online packet, we ping the
the group. group.
When processing the reply to a Peer Query, we update the DHT pubkey of an When processing the reply to a Peer Query, we update the DHT pubkey of an
existing peer if and only if it is frozen or has not had its DHT pubkey existing peer if and only if it is frozen or has not had its DHT pubkey updated
updated since it last stopped being frozen. since it last stopped being frozen.
When we receive a Title Response packet, we set the title if it has never been When we receive a Title Response packet, we set the title if it has never been
set or if at some point since it was last set, there were no unfrozen peers set or if at some point since it was last set, there were no unfrozen peers
(except us). (except us).
## Discussion ## Discussion
### Overview
The intention is to recover seamlessly from splits in the group, the most
common form of which is a single peer temporarily losing all connectivity.
To see how this works, first note that groups (even before the changes ### Overview
discussed here) have the property that for a group to be connected in the
sense that any peer will receive the messages of any other peer and have them The intention is to recover seamlessly from splits in the group, the most common
in their peerlist, it is necessary and sufficient that there is a path of form of which is a single peer temporarily losing all connectivity.
direct group connections between any two peers.
To see how this works, first note that groups (even before the changes discussed
here) have the property that for a group to be connected in the sense that any
peer will receive the messages of any other peer and have them in their
peerlist, it is necessary and sufficient that there is a path of direct group
connections between any two peers.
Now suppose the group is split into two connected components, with each member Now suppose the group is split into two connected components, with each member
of one component frozen according to the members of the other. Suppose there of one component frozen according to the members of the other. Suppose there are
are two peers, one in each component, which are using the above protocol, and two peers, one in each component, which are using the above protocol, and
suppose they establish a friend connection. Then each will rejoin the other, suppose they establish a friend connection. Then each will rejoin the other,
forming a direct group connection. Hence the whole group will become connected forming a direct group connection. Hence the whole group will become connected
(even if all other peers are using the unmodified protocol). (even if all other peers are using the unmodified protocol).
The Peer Query packet sent on rejoining hastens this process. The Peer Query packet sent on rejoining hastens this process.
Peers who leave the group during a split will not be deleted by all peers Peers who leave the group during a split will not be deleted by all peers after
after the merge - but they will be set as frozen due to ping timeouts, which the merge - but they will be set as frozen due to ping timeouts, which is
is sufficient. sufficient.
### Titles ### Titles
If we have a split into components each containing multiple peers, and the
title is changed in one component, then peers will continue to disagree on the If we have a split into components each containing multiple peers, and the title
title after the split. Short of a complicated voting system, this seems the is changed in one component, then peers will continue to disagree on the title
only reasonable behaviour. after the split. Short of a complicated voting system, this seems the only
reasonable behaviour.
### Implementation notes ### Implementation notes
Although I've described the logic in terms of an 'frozen' flag, it might Although I've described the logic in terms of an 'frozen' flag, it might
actually make more sense in the implementation to have a separate list for actually make more sense in the implementation to have a separate list for
frozen peers. frozen peers.
## Saving ## Saving
Saving is implemented by simply saving all live groups with their group numbers Saving is implemented by simply saving all live groups with their group numbers
and full peer info for all peers. On reload, all peers are set as frozen. and full peer info for all peers. On reload, all peers are set as frozen.
Clients needs to support this by understanding that groups may exist on Clients needs to support this by understanding that groups may exist on
start-up. Clients should call `tox_conference_get_chatlist` to obtain them. A start-up. Clients should call `tox_conference_get_chatlist` to obtain them. A
group which is deleted (with `tox_conference_delete`) is removed permanently group which is deleted (with `tox_conference_delete`) is removed permanently and
and will not be saved. will not be saved.
## Limitations ## Limitations
If a peer disconnects from the group for a period short enough that group If a peer disconnects from the group for a period short enough that group
timeouts do not occur, and a name change occurs during this period, then the timeouts do not occur, and a name change occurs during this period, then the
name change will never be propagated. name change will never be propagated.
@ -120,9 +126,8 @@ requesting missed group messages. But this is considered out of scope of this
PR. PR.
If a peer changes its DHT pubkey, the change might not be properly propagated If a peer changes its DHT pubkey, the change might not be properly propagated
under various circumstances - in particular, if connections do not go down under various circumstances - in particular, if connections do not go down long
long enough for the peer to become frozen. enough for the peer to become frozen.
One way to deal with this would be to add a group message announcing the One way to deal with this would be to add a group message announcing the sending
sending peer's current DHT pubkey, and treat it analogously to the Name peer's current DHT pubkey, and treat it analogously to the Name message.
message.

View File

@ -50,7 +50,6 @@ static const char *motd_str = ""; //Change this to anything within 256 bytes(but
#define PORT 33445 #define PORT 33445
static bool manage_keys(DHT *dht) static bool manage_keys(DHT *dht)
{ {
enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE }; enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
@ -61,7 +60,7 @@ static bool manage_keys(DHT *dht)
if (keys_file != nullptr) { if (keys_file != nullptr) {
/* If file was opened successfully -- load keys, /* If file was opened successfully -- load keys,
otherwise save new keys */ otherwise save new keys */
size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); const size_t read_size = fread(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
if (read_size != KEYS_SIZE) { if (read_size != KEYS_SIZE) {
printf("Error while reading the key file\nExiting.\n"); printf("Error while reading the key file\nExiting.\n");
@ -126,7 +125,7 @@ static void print_log(void *context, Logger_Level level, const char *file, int l
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
if (argc == 2 && !tox_strncasecmp(argv[1], "-h", 3)) { if (argc == 2 && tox_strncasecmp(argv[1], "-h", 3) == 0) {
printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]); printf("Usage (connected) : %s [--ipv4|--ipv6] IP PORT KEY\n", argv[0]);
printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]); printf("Usage (unconnected): %s [--ipv4|--ipv6]\n", argv[0]);
return 0; return 0;
@ -134,7 +133,7 @@ int main(int argc, char *argv[])
/* let user override default by cmdline */ /* let user override default by cmdline */
bool ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */ bool ipv6enabled = TOX_ENABLE_IPV6_DEFAULT; /* x */
int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled); const int argvoffset = cmdline_parsefor_ipv46(argc, argv, &ipv6enabled);
if (argvoffset < 0) { if (argvoffset < 0) {
return 1; return 1;
@ -151,9 +150,9 @@ int main(int argc, char *argv[])
logger_callback_log(logger, print_log, nullptr, nullptr); logger_callback_log(logger, print_log, nullptr, nullptr);
} }
const Random *rng = system_random(); const Random *rng = os_random();
const Network *ns = system_network(); const Network *ns = os_network();
const Memory *mem = system_memory(); const Memory *mem = os_memory();
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
const uint16_t start_port = PORT; const uint16_t start_port = PORT;
@ -168,8 +167,9 @@ int main(int argc, char *argv[])
bootstrap_set_callbacks(dht_get_net(dht), (uint32_t)DAEMON_VERSION_NUMBER, (const uint8_t *) motd_str, strlen(motd_str) + 1); bootstrap_set_callbacks(dht_get_net(dht), (uint32_t)DAEMON_VERSION_NUMBER, (const uint8_t *) motd_str, strlen(motd_str) + 1);
#endif #endif
if (!(onion && forwarding && onion_a)) { if (onion == nullptr || forwarding == nullptr || onion_a == nullptr) {
printf("Something failed to initialize.\n"); printf("Something failed to initialize.\n");
// cppcheck-suppress resourceLeak
return 1; return 1;
} }
@ -178,17 +178,19 @@ int main(int argc, char *argv[])
perror("Initialization"); perror("Initialization");
if (!manage_keys(dht)) { if (!manage_keys(dht)) {
// cppcheck-suppress resourceLeak
return 1; return 1;
} }
printf("Public key: "); printf("Public key: ");
#ifdef TCP_RELAY_ENABLED #ifdef TCP_RELAY_ENABLED
#define NUM_PORTS 3 #define NUM_PORTS 3
uint16_t ports[NUM_PORTS] = {443, 3389, PORT}; const uint16_t ports[NUM_PORTS] = {443, 3389, PORT};
TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, ipv6enabled, NUM_PORTS, ports, dht_get_self_secret_key(dht), onion, forwarding); TCP_Server *tcp_s = new_tcp_server(logger, mem, rng, ns, ipv6enabled, NUM_PORTS, ports, dht_get_self_secret_key(dht), onion, forwarding);
if (tcp_s == nullptr) { if (tcp_s == nullptr) {
printf("TCP server failed to initialize.\n"); printf("TCP server failed to initialize.\n");
// cppcheck-suppress resourceLeak
return 1; return 1;
} }
@ -199,6 +201,7 @@ int main(int argc, char *argv[])
if (file == nullptr) { if (file == nullptr) {
printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename); printf("Could not open file \"%s\" for writing. Exiting...\n", public_id_filename);
// cppcheck-suppress resourceLeak
return 1; return 1;
} }
@ -226,7 +229,7 @@ int main(int argc, char *argv[])
const uint16_t port = net_htons((uint16_t)port_conv); const uint16_t port = net_htons((uint16_t)port_conv);
uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]); uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
int res = dht_bootstrap_from_address(dht, argv[argvoffset + 1], const bool res = dht_bootstrap_from_address(dht, argv[argvoffset + 1],
ipv6enabled, port, bootstrap_key); ipv6enabled, port, bootstrap_key);
free(bootstrap_key); free(bootstrap_key);
@ -236,17 +239,17 @@ int main(int argc, char *argv[])
} }
} }
int is_waiting_for_dht_connection = 1; bool is_waiting_for_dht_connection = true;
uint64_t last_lan_discovery = 0; uint64_t last_lan_discovery = 0;
const Broadcast_Info *broadcast = lan_discovery_init(ns); const Broadcast_Info *broadcast = lan_discovery_init(ns);
while (1) { while (true) {
mono_time_update(mono_time); mono_time_update(mono_time);
if (is_waiting_for_dht_connection && dht_isconnected(dht)) { if (is_waiting_for_dht_connection && dht_isconnected(dht)) {
printf("Connected to other bootstrap node successfully.\n"); printf("Connected to other bootstrap node successfully.\n");
is_waiting_for_dht_connection = 0; is_waiting_for_dht_connection = false;
} }
do_dht(dht); do_dht(dht);

View File

@ -3,17 +3,20 @@
CHECKS="*" CHECKS="*"
ERRORS="*" ERRORS="*"
# Can't fix this, because winsock has different HANDLE type than posix.
# Still good to occasionally look at.
ERRORS="$ERRORS,-google-readability-casting"
# Need to investigate or disable and document these. # Need to investigate or disable and document these.
# ========================================================= # =========================================================
# TODO(iphydf): Fix these. # TODO(iphydf): Fix these.
ERRORS="$ERRORS,-cert-err34-c" ERRORS="$ERRORS,-cert-err34-c"
ERRORS="$ERRORS,-readability-suspicious-call-argument" ERRORS="$ERRORS,-readability-suspicious-call-argument"
CHECKS="$CHECKS,-cppcoreguidelines-avoid-goto,-hicpp-avoid-goto"
CHECKS="$CHECKS,-bugprone-incorrect-roundings"
# TODO(iphydf): Fix once cimple 0.0.19 is released. # TODO(iphydf): Fix this by making more functions set error code enums.
CHECKS="$CHECKS,-google-readability-casting"
# TODO(iphydf): Fix these.
CHECKS="$CHECKS,-bugprone-switch-missing-default-case" CHECKS="$CHECKS,-bugprone-switch-missing-default-case"
# TODO(iphydf): We might want some of these. For the ones we don't want, add a # TODO(iphydf): We might want some of these. For the ones we don't want, add a
@ -30,17 +33,22 @@ CHECKS="$CHECKS,-misc-no-recursion"
CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables" CHECKS="$CHECKS,-cppcoreguidelines-avoid-non-const-global-variables"
# TODO(iphydf): Probably fix these. # TODO(iphydf): Probably fix these.
CHECKS="$CHECKS,-cert-err33-c" CHECKS="$CHECKS,-cert-err33-c,-cppcoreguidelines-avoid-magic-numbers,-readability-magic-numbers"
CHECKS="$CHECKS,-cppcoreguidelines-avoid-magic-numbers"
CHECKS="$CHECKS,-readability-magic-numbers"
# TODO(iphydf): We're using a lot of macros for constants. Should we convert
# all of them to enum?
CHECKS="$CHECKS,-modernize-macro-to-enum"
# Documented disabled checks. We don't want these for sure. # Documented disabled checks. We don't want these for sure.
# ========================================================= # =========================================================
# We want to decay many arrays to pointers. In C, we do that all the time.
CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay"
# enum{} breaks comparisons and arithmetic in C++.
CHECKS="$CHECKS,-modernize-macro-to-enum"
# For most things, we do want this, but for some we want to ensure (with msan)
# that struct members are actually initialised with useful non-zero values.
# Initialising them by default takes away that validation.
CHECKS="$CHECKS,-cppcoreguidelines-pro-type-member-init,-hicpp-member-init"
# https://stackoverflow.com/questions/58672959/why-does-clang-tidy-say-vsnprintf-has-an-uninitialized-va-list-argument # https://stackoverflow.com/questions/58672959/why-does-clang-tidy-say-vsnprintf-has-an-uninitialized-va-list-argument
CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized" CHECKS="$CHECKS,-clang-analyzer-valist.Uninitialized"
@ -115,8 +123,7 @@ CHECKS="$CHECKS,-readability-redundant-control-flow"
# ^ # ^
# Trip the checker, which is true, because of integer promotion, but also not # Trip the checker, which is true, because of integer promotion, but also not
# very helpful as a diagnostic. # very helpful as a diagnostic.
CHECKS="$CHECKS,-bugprone-narrowing-conversions" CHECKS="$CHECKS,-bugprone-narrowing-conversions,-cppcoreguidelines-narrowing-conversions"
CHECKS="$CHECKS,-cppcoreguidelines-narrowing-conversions"
# Mistakenly thinks that # Mistakenly thinks that
# const int a = 0, b = 1; # const int a = 0, b = 1;
@ -135,9 +142,51 @@ CHECKS="$CHECKS,-cppcoreguidelines-narrowing-conversions"
# - Turning 'a' and 'b' into pre-processor macros is the only option left, but # - Turning 'a' and 'b' into pre-processor macros is the only option left, but
# #defines and #undefs in the middle of a function hurt the readability and # #defines and #undefs in the middle of a function hurt the readability and
# are less idiomatic than simply using 'const int'. # are less idiomatic than simply using 'const int'.
CHECKS="$CHECKS,-cert-dcl03-c" CHECKS="$CHECKS,-cert-dcl03-c,-hicpp-static-assert,-misc-static-assert"
CHECKS="$CHECKS,-hicpp-static-assert"
CHECKS="$CHECKS,-misc-static-assert" # Doesn't consider use of preprocessor macros as needing a header, breaking
# struct definitions that depend on size macros from e.g. crypto_core.h.
CHECKS="$CHECKS,-misc-include-cleaner"
# A bunch of checks only valid for C++, we turn off for C.
# =========================================================
# We don't use Google's int typedefs.
CHECKS="$CHECKS,-google-runtime-int"
# We write C code, so we use C arrays.
CHECKS="$CHECKS,-cppcoreguidelines-avoid-c-arrays,-hicpp-avoid-c-arrays,-modernize-avoid-c-arrays"
# C loops are ok. This one tells us to use range-for.
CHECKS="$CHECKS,-modernize-loop-convert"
# No auto in C.
CHECKS="$CHECKS,-hicpp-use-auto,-modernize-use-auto"
# Only C style casts in C.
CHECKS="$CHECKS,-cppcoreguidelines-pro-type-cstyle-cast"
# We use malloc (for now), and MISRA checks this too.
CHECKS="$CHECKS,-cppcoreguidelines-no-malloc,-hicpp-no-malloc"
# No owning_ptr<> in C.
CHECKS="$CHECKS,-cppcoreguidelines-owning-memory"
# void foo(void) is good in C.
CHECKS="$CHECKS,-modernize-redundant-void-arg"
# No using-typedefs in C.
CHECKS="$CHECKS,-modernize-use-using"
# No namespaces in C.
CHECKS="$CHECKS,-misc-use-anonymous-namespace"
# No trailing return type in C.
CHECKS="$CHECKS,-modernize-use-trailing-return-type"
# No <cstdint> and friends in C.
CHECKS="$CHECKS,-hicpp-deprecated-headers,-modernize-deprecated-headers"
# We use varargs for logging (we could reconsider, but right now we do).
CHECKS="$CHECKS,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-cert-dcl50-cpp"
# We do want to use the array index operator, even when the index is non-constant.
CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-constant-array-index"
# We don't want to use pointer arithmetic, but this one includes array index
# operators, which we do want to use.
CHECKS="$CHECKS,-cppcoreguidelines-pro-bounds-pointer-arithmetic"
# Can't use constexpr, yet. C will have it eventually, but it'll be years
# until we can use it across all the compilers.
CHECKS="$CHECKS,-cppcoreguidelines-macro-usage"
# These are all very C++ and/or LLVM specific.
CHECKS="$CHECKS,-llvmlibc-*"
set -eux set -eux
@ -154,7 +203,7 @@ copy_files() {
find "${DIRS[@]}" \ find "${DIRS[@]}" \
-maxdepth 1 -type d -exec mkdir -p "$1/{}" \; -maxdepth 1 -type d -exec mkdir -p "$1/{}" \;
find "${DIRS[@]}" \ find "${DIRS[@]}" \
-maxdepth 1 -name "*.c" -exec cp "{}" "$1/{}" \; -maxdepth 1 -name "*.[ch]" -exec cp "{}" "$1/{}" \;
} }
run() { run() {
@ -166,7 +215,7 @@ run() {
ls .clang-tidy ls .clang-tidy
copy_files a copy_files a
if ! find "${DIRS[@]}" \ if ! find "${DIRS[@]}" \
-maxdepth 1 -name "*.c" -print0 \ -maxdepth 1 -name "*.[ch]" -print0 \
| xargs -0 -n15 -P"$(nproc)" clang-tidy \ | xargs -0 -n15 -P"$(nproc)" clang-tidy \
-p="$PWD/_build" \ -p="$PWD/_build" \
--extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \ --extra-arg=-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \
@ -184,5 +233,6 @@ run() {
} }
cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON cmake . -B_build -GNinja -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
sed -i -e 's/-std=c11/-xc++/' _build/compile_commands.json
. other/analysis/variants.sh . other/analysis/variants.sh

View File

@ -1,5 +1,6 @@
# Bracket Style Options # Bracket Style Options
--style=kr --style=kr
--attach-namespaces
# Tab Options # Tab Options
--indent=spaces=4 --indent=spaces=4
@ -9,15 +10,21 @@
# Padding Options # Padding Options
--pad-header --pad-header
--break-blocks
--pad-oper --pad-oper
# Not supported in restyled's astyle.
#--unpad-brackets
--unpad-paren --unpad-paren
--align-pointer=name --align-pointer=name
--align-reference=name --align-reference=name
# Disabled because it causes very large changes and it's unclear whether we
# want all of those.
#--squeeze-ws
# Formatting Options # Formatting Options
--add-braces
--convert-tabs --convert-tabs
--max-code-length=120 --max-code-length=200
--attach-return-type
# Other Options # Other Options
--preserve-date --preserve-date

View File

@ -2,36 +2,6 @@
set -ex set -ex
SOURCE_DIR="$1"
ASTYLE="$2"
# Go to the source root.
if [ -z "$SOURCE_DIR" ]; then
SOURCE_DIR=.
fi
cd "$SOURCE_DIR"
if [ -z "$ASTYLE" ] || ! which "$ASTYLE"; then
ASTYLE=astyle
fi
if ! which "$ASTYLE"; then
# If we couldn't find or install an astyle binary, don't do anything.
echo "Could not find an astyle binary; please install astyle."
exit 1
fi
readarray -t CC_SOURCES <<<"$(find . '(' -name '*.cc' ')')"
CC_SOURCES+=(toxcore/crypto_core.c)
CC_SOURCES+=(toxcore/ping_array.c)
for bin in clang-format-11 clang-format-7 clang-format-6.0 clang-format-5.0 clang-format; do
if which "$bin"; then
"$bin" -i -style='{BasedOnStyle: Google, ColumnLimit: 100}' "${CC_SOURCES[@]}"
break
fi
done
FIND="find ." FIND="find ."
FIND="$FIND '(' -name '*.[ch]' ')'" FIND="$FIND '(' -name '*.[ch]' ')'"
FIND="$FIND -and -not -name '*.api.h'" FIND="$FIND -and -not -name '*.api.h'"
@ -40,7 +10,15 @@ FIND="$FIND -and -not -wholename './third_party/*'"
FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'" FIND="$FIND -and -not -wholename './toxencryptsave/crypto_pwhash*'"
readarray -t C_SOURCES <<<"$(eval "$FIND")" readarray -t C_SOURCES <<<"$(eval "$FIND")"
readarray -t CC_SOURCES <<<"$(find . '(' -name '*.cc' -or -name '*.hh' ')')"
#CC_SOURCES+=(toxcore/crypto_core.c)
#CC_SOURCES+=(toxcore/ping_array.c)
"$ASTYLE" -n --options=other/astyle/astylerc "${C_SOURCES[@]}" # Format C++ sources with clang-format.
clang-format -i "${CC_SOURCES[@]}"
# Format C sources with astyle. We can't use clang-format, because it strongly
# messes up formatting of non_null annotations.
astyle -n --options=other/astyle/astylerc "${C_SOURCES[@]}"
git diff --color=always --exit-code git diff --color=always --exit-code

View File

@ -48,8 +48,9 @@ RUN CC=clang cmake -B_build -H. \
# Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't # Verify checksum from dev-built binary, so we can be sure Docker Hub doesn't
# mess with your binaries. # mess with your binaries.
COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/ COPY other/bootstrap_daemon/docker/tox-bootstrapd.sha256 other/bootstrap_daemon/docker/
RUN SHA256="$(sha256sum /usr/local/bin/tox-bootstrapd)" && \ ARG CHECK=sha256sum
(sha256sum -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256 || \ RUN SHA256="$("$CHECK" /usr/local/bin/tox-bootstrapd)" && \
("$CHECK" -c other/bootstrap_daemon/docker/tox-bootstrapd.sha256 || \
(echo "::error file=other/bootstrap_daemon/docker/tox-bootstrapd.sha256,line=1::$SHA256" && \ (echo "::error file=other/bootstrap_daemon/docker/tox-bootstrapd.sha256,line=1::$SHA256" && \
false)) false))

View File

@ -1 +1 @@
0b904988d79b9576bb88c6c7316d107b5a61bd6119a0992ebd7c1fa43db70abf /usr/local/bin/tox-bootstrapd af58a125e5c80d7a19bc7f32868c1edfdf80f366e3bf778728961a50ce63ee26 /usr/local/bin/tox-bootstrapd

View File

@ -18,7 +18,6 @@
#include <string.h> #include <string.h>
/** /**
* Prints --help message * Prints --help message
*/ */

View File

@ -44,7 +44,7 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS); log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file.\n", NAME_TCP_RELAY_PORTS);
log_write(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS); log_write(LOG_LEVEL_WARNING, "Using default '%s':\n", NAME_TCP_RELAY_PORTS);
uint16_t default_ports[] = {DEFAULT_TCP_RELAY_PORTS}; const uint16_t default_ports[] = {DEFAULT_TCP_RELAY_PORTS};
// Check to avoid calling malloc(0) later on // Check to avoid calling malloc(0) later on
// NOLINTNEXTLINE, clang-tidy: error: suspicious comparison of 'sizeof(expr)' to a constant [bugprone-sizeof-expression,-warnings-as-errors] // NOLINTNEXTLINE, clang-tidy: error: suspicious comparison of 'sizeof(expr)' to a constant [bugprone-sizeof-expression,-warnings-as-errors]
@ -58,6 +58,10 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
// Similar procedure to the one of reading config file below // Similar procedure to the one of reading config file below
*tcp_relay_ports = (uint16_t *)malloc(default_ports_count * sizeof(uint16_t)); *tcp_relay_ports = (uint16_t *)malloc(default_ports_count * sizeof(uint16_t));
if (*tcp_relay_ports == nullptr) {
log_write(LOG_LEVEL_ERROR, "Allocation failure.\n");
return;
}
for (size_t i = 0; i < default_ports_count; ++i) { for (size_t i = 0; i < default_ports_count; ++i) {
@ -73,10 +77,8 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
++*tcp_relay_port_count; ++*tcp_relay_port_count;
} }
// The loop above skips invalid ports, so we adjust the allocated memory size // No ports, so we free the array.
if ((*tcp_relay_port_count) > 0) { if (*tcp_relay_port_count == 0) {
*tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
} else {
free(*tcp_relay_ports); free(*tcp_relay_ports);
*tcp_relay_ports = nullptr; *tcp_relay_ports = nullptr;
} }
@ -90,7 +92,7 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
return; return;
} }
int config_port_count = config_setting_length(ports_array); const int config_port_count = config_setting_length(ports_array);
if (config_port_count == 0) { if (config_port_count == 0) {
log_write(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS); log_write(LOG_LEVEL_ERROR, "'%s' is empty.\n", NAME_TCP_RELAY_PORTS);
@ -98,6 +100,10 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
} }
*tcp_relay_ports = (uint16_t *)malloc(config_port_count * sizeof(uint16_t)); *tcp_relay_ports = (uint16_t *)malloc(config_port_count * sizeof(uint16_t));
if (*tcp_relay_ports == nullptr) {
log_write(LOG_LEVEL_ERROR, "Allocation failure.\n");
return;
}
for (int i = 0; i < config_port_count; ++i) { for (int i = 0; i < config_port_count; ++i) {
config_setting_t *elem = config_setting_get_elem(ports_array, i); config_setting_t *elem = config_setting_get_elem(ports_array, i);
@ -125,16 +131,14 @@ static void parse_tcp_relay_ports_config(config_t *cfg, uint16_t **tcp_relay_por
++*tcp_relay_port_count; ++*tcp_relay_port_count;
} }
// The loop above skips invalid ports, so we adjust the allocated memory size // No ports, so we free the array.
if ((*tcp_relay_port_count) > 0) { if (*tcp_relay_port_count == 0) {
*tcp_relay_ports = (uint16_t *)realloc(*tcp_relay_ports, (*tcp_relay_port_count) * sizeof(uint16_t));
} else {
free(*tcp_relay_ports); free(*tcp_relay_ports);
*tcp_relay_ports = nullptr; *tcp_relay_ports = nullptr;
} }
} }
int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, bool get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port,
int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay,
uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd) uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd)
{ {
@ -156,7 +160,7 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) {
log_write(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); log_write(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg); config_destroy(&cfg);
return 0; return false;
} }
// Get port // Get port
@ -177,6 +181,10 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
const size_t pid_file_path_len = strlen(tmp_pid_file) + 1; const size_t pid_file_path_len = strlen(tmp_pid_file) + 1;
*pid_file_path = (char *)malloc(pid_file_path_len); *pid_file_path = (char *)malloc(pid_file_path_len);
if (*pid_file_path == nullptr) {
log_write(LOG_LEVEL_ERROR, "Allocation failure.\n");
return false;
}
memcpy(*pid_file_path, tmp_pid_file, pid_file_path_len); memcpy(*pid_file_path, tmp_pid_file, pid_file_path_len);
// Get keys file location // Get keys file location
@ -190,6 +198,10 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
const size_t keys_file_path_len = strlen(tmp_keys_file) + 1; const size_t keys_file_path_len = strlen(tmp_keys_file) + 1;
*keys_file_path = (char *)malloc(keys_file_path_len); *keys_file_path = (char *)malloc(keys_file_path_len);
if (*keys_file_path == nullptr) {
log_write(LOG_LEVEL_ERROR, "Allocation failure.\n");
return false;
}
memcpy(*keys_file_path, tmp_keys_file, keys_file_path_len); memcpy(*keys_file_path, tmp_keys_file, keys_file_path_len);
// Get IPv6 option // Get IPv6 option
@ -223,7 +235,7 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
*enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY; *enable_tcp_relay = DEFAULT_ENABLE_TCP_RELAY;
} }
if (*enable_tcp_relay) { if (*enable_tcp_relay != 0) {
parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count); parse_tcp_relay_ports_config(&cfg, tcp_relay_ports, tcp_relay_port_count);
} else { } else {
*tcp_relay_port_count = 0; *tcp_relay_port_count = 0;
@ -237,7 +249,7 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
*enable_motd = DEFAULT_ENABLE_MOTD; *enable_motd = DEFAULT_ENABLE_MOTD;
} }
if (*enable_motd) { if (*enable_motd != 0) {
// Get MOTD // Get MOTD
const char *tmp_motd; const char *tmp_motd;
@ -247,8 +259,8 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
tmp_motd = DEFAULT_MOTD; tmp_motd = DEFAULT_MOTD;
} }
size_t tmp_motd_length = strlen(tmp_motd) + 1; const size_t tmp_motd_length = strlen(tmp_motd) + 1;
size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length; const size_t motd_length = tmp_motd_length > MAX_MOTD_LENGTH ? MAX_MOTD_LENGTH : tmp_motd_length;
*motd = (char *)malloc(motd_length); *motd = (char *)malloc(motd_length);
snprintf(*motd, motd_length, "%s", tmp_motd); snprintf(*motd, motd_length, "%s", tmp_motd);
} }
@ -259,14 +271,14 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_PID_FILE_PATH, *pid_file_path);
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_KEYS_FILE_PATH, *keys_file_path);
log_write(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port); log_write(LOG_LEVEL_INFO, "'%s': %d\n", NAME_PORT, *port);
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 ? "true" : "false"); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV6, *enable_ipv6 != 0 ? "true" : "false");
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback ? "true" : "false"); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_IPV4_FALLBACK, *enable_ipv4_fallback != 0 ? "true" : "false");
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery ? "true" : "false"); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_LAN_DISCOVERY, *enable_lan_discovery != 0 ? "true" : "false");
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay ? "true" : "false"); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_TCP_RELAY, *enable_tcp_relay != 0 ? "true" : "false");
// Show info about tcp ports only if tcp relay is enabled // Show info about tcp ports only if tcp relay is enabled
if (*enable_tcp_relay) { if (*enable_tcp_relay != 0) {
if (*tcp_relay_port_count == 0) { if (*tcp_relay_port_count == 0) {
log_write(LOG_LEVEL_ERROR, "No TCP ports could be read.\n"); log_write(LOG_LEVEL_ERROR, "No TCP ports could be read.\n");
} else { } else {
@ -278,13 +290,13 @@ int get_general_config(const char *cfg_file_path, char **pid_file_path, char **k
} }
} }
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd ? "true" : "false"); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_ENABLE_MOTD, *enable_motd != 0 ? "true" : "false");
if (*enable_motd) { if (*enable_motd != 0) {
log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd); log_write(LOG_LEVEL_INFO, "'%s': %s\n", NAME_MOTD, *motd);
} }
return 1; return true;
} }
/** /**
@ -302,8 +314,12 @@ static uint8_t *bootstrap_hex_string_to_bin(const char *hex_string)
return nullptr; return nullptr;
} }
size_t len = strlen(hex_string) / 2; const size_t len = strlen(hex_string) / 2;
uint8_t *ret = (uint8_t *)malloc(len); uint8_t *ret = (uint8_t *)malloc(len);
if (ret == nullptr) {
log_write(LOG_LEVEL_ERROR, "Allocation failure.\n");
return nullptr;
}
const char *pos = hex_string; const char *pos = hex_string;
@ -316,7 +332,7 @@ static uint8_t *bootstrap_hex_string_to_bin(const char *hex_string)
return ret; return ret;
} }
int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6) bool bootstrap_from_config(const char *cfg_file_path, DHT *dht, bool enable_ipv6)
{ {
const char *const NAME_BOOTSTRAP_NODES = "bootstrap_nodes"; const char *const NAME_BOOTSTRAP_NODES = "bootstrap_nodes";
@ -331,7 +347,7 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6)
if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) { if (config_read_file(&cfg, cfg_file_path) == CONFIG_FALSE) {
log_write(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); log_write(LOG_LEVEL_ERROR, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg));
config_destroy(&cfg); config_destroy(&cfg);
return 0; return false;
} }
config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES); config_setting_t *node_list = config_lookup(&cfg, NAME_BOOTSTRAP_NODES);
@ -340,13 +356,13 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6)
log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n", log_write(LOG_LEVEL_WARNING, "No '%s' setting in the configuration file. Skipping bootstrapping.\n",
NAME_BOOTSTRAP_NODES); NAME_BOOTSTRAP_NODES);
config_destroy(&cfg); config_destroy(&cfg);
return 1; return true;
} }
if (config_setting_length(node_list) == 0) { if (config_setting_length(node_list) == 0) {
log_write(LOG_LEVEL_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n"); log_write(LOG_LEVEL_WARNING, "No bootstrap nodes found. Skipping bootstrapping.\n");
config_destroy(&cfg); config_destroy(&cfg);
return 1; return true;
} }
int bs_port; int bs_port;
@ -357,15 +373,15 @@ int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6)
int i = 0; int i = 0;
while (config_setting_length(node_list)) { while (config_setting_length(node_list) != 0) {
int address_resolved; bool address_resolved;
uint8_t *bs_public_key_bin; uint8_t *bs_public_key_bin;
node = config_setting_get_elem(node_list, 0); node = config_setting_get_elem(node_list, 0);
if (node == nullptr) { if (node == nullptr) {
config_destroy(&cfg); config_destroy(&cfg);
return 0; return false;
} }
// Check that all settings are present // Check that all settings are present
@ -421,5 +437,5 @@ next:
config_destroy(&cfg); config_destroy(&cfg);
return 1; return true;
} }

View File

@ -19,19 +19,19 @@
* also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports` * also, iff `tcp_relay_ports_count` > 0, then you are responsible for freeing `tcp_relay_ports`
* and also `motd` iff `enable_motd` is set. * and also `motd` iff `enable_motd` is set.
* *
* @return 1 on success, * @return true on success,
* 0 on failure, doesn't modify any data pointed by arguments. * false on failure, doesn't modify any data pointed by arguments.
*/ */
int get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port, bool get_general_config(const char *cfg_file_path, char **pid_file_path, char **keys_file_path, int *port,
int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay, int *enable_ipv6, int *enable_ipv4_fallback, int *enable_lan_discovery, int *enable_tcp_relay,
uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd); uint16_t **tcp_relay_ports, int *tcp_relay_port_count, int *enable_motd, char **motd);
/** /**
* Bootstraps off nodes listed in the config file. * Bootstraps off nodes listed in the config file.
* *
* @return 1 on success, some or no bootstrap nodes were added * @return true on success, some or no bootstrap nodes were added
* 0 on failure, an error occurred while parsing the config file. * false on failure, an error occurred while parsing the config file.
*/ */
int bootstrap_from_config(const char *cfg_file_path, DHT *dht, int enable_ipv6); bool bootstrap_from_config(const char *cfg_file_path, DHT *dht, bool enable_ipv6);
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H #endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_CONFIG_H

View File

@ -58,7 +58,6 @@ bool log_close(void)
return true; return true;
} }
bool log_write(LOG_LEVEL level, const char *format, ...) bool log_write(LOG_LEVEL level, const char *format, ...)
{ {
if (current_backend == INVALID_BACKEND) { if (current_backend == INVALID_BACKEND) {

View File

@ -12,7 +12,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "../../../toxcore/ccompat.h" #include "../../../toxcore/attributes.h"
typedef enum LOG_BACKEND { typedef enum LOG_BACKEND {
LOG_BACKEND_STDOUT, LOG_BACKEND_STDOUT,
@ -47,5 +47,4 @@ bool log_close(void);
*/ */
bool log_write(LOG_LEVEL level, const char *format, ...) GNU_PRINTF(2, 3); bool log_write(LOG_LEVEL level, const char *format, ...) GNU_PRINTF(2, 3);
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H #endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_H

View File

@ -10,10 +10,11 @@
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H #ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H #define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H
#include "log.h"
#include <stdarg.h> #include <stdarg.h>
#include "../../../toxcore/attributes.h"
#include "log.h"
void log_backend_stdout_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0); void log_backend_stdout_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0);
#endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H #endif // C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_STDOUT_H

View File

@ -51,7 +51,7 @@ void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args)
va_list args2; va_list args2;
va_copy(args2, args); va_copy(args2, args);
int size = vsnprintf(nullptr, 0, format, args2); const int size = vsnprintf(nullptr, 0, format, args2);
va_end(args2); va_end(args2);
assert(size >= 0); assert(size >= 0);
@ -61,6 +61,9 @@ void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args)
} }
char *buf = (char *)malloc(size + 1); char *buf = (char *)malloc(size + 1);
if (buf == nullptr) {
return;
}
vsnprintf(buf, size + 1, format, args); vsnprintf(buf, size + 1, format, args);
syslog(log_backend_syslog_level(level), "%s", buf); syslog(log_backend_syslog_level(level), "%s", buf);

View File

@ -10,10 +10,11 @@
#ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H #ifndef C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
#define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H #define C_TOXCORE_OTHER_BOOTSTRAP_DAEMON_SRC_LOG_BACKEND_SYSLOG_H
#include "log.h"
#include <stdarg.h> #include <stdarg.h>
#include "../../../toxcore/attributes.h"
#include "log.h"
void log_backend_syslog_open(void); void log_backend_syslog_open(void);
void log_backend_syslog_close(void); void log_backend_syslog_close(void);
void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0); void log_backend_syslog_write(LOG_LEVEL level, const char *format, va_list args) GNU_PRINTF(2, 0);

View File

@ -50,7 +50,6 @@
#include "global.h" #include "global.h"
#include "log.h" #include "log.h"
static void sleep_milliseconds(uint32_t ms) static void sleep_milliseconds(uint32_t ms)
{ {
struct timespec req; struct timespec req;
@ -61,10 +60,10 @@ static void sleep_milliseconds(uint32_t ms)
// Uses the already existing key or creates one if it didn't exist // Uses the already existing key or creates one if it didn't exist
// //
// returns 1 on success // returns true on success
// 0 on failure - no keys were read or stored // false on failure - no keys were read or stored
static int manage_keys(DHT *dht, const char *keys_file_path) static bool manage_keys(DHT *dht, const char *keys_file_path)
{ {
enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE }; enum { KEYS_SIZE = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SECRET_KEY_SIZE };
uint8_t keys[KEYS_SIZE]; uint8_t keys[KEYS_SIZE];
@ -77,7 +76,7 @@ static int manage_keys(DHT *dht, const char *keys_file_path)
if (read_size != KEYS_SIZE) { if (read_size != KEYS_SIZE) {
fclose(keys_file); fclose(keys_file);
return 0; return false;
} }
dht_set_self_public_key(dht, keys); dht_set_self_public_key(dht, keys);
@ -89,21 +88,21 @@ static int manage_keys(DHT *dht, const char *keys_file_path)
keys_file = fopen(keys_file_path, "wb"); keys_file = fopen(keys_file_path, "wb");
if (!keys_file) { if (keys_file == nullptr) {
return 0; return false;
} }
const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file); const size_t write_size = fwrite(keys, sizeof(uint8_t), KEYS_SIZE, keys_file);
if (write_size != KEYS_SIZE) { if (write_size != KEYS_SIZE) {
fclose(keys_file); fclose(keys_file);
return 0; return false;
} }
} }
fclose(keys_file); fclose(keys_file);
return 1; return true;
} }
// Prints public key // Prints public key
@ -164,7 +163,6 @@ static Cli_Status daemonize(LOG_BACKEND log_backend, char *pid_file_path)
return CLI_STATUS_ERROR; return CLI_STATUS_ERROR;
} }
// Change the current working directory // Change the current working directory
if ((chdir("/")) < 0) { if ((chdir("/")) < 0) {
log_write(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "Couldn't change working directory to '/'. Exiting.\n");
@ -222,7 +220,7 @@ int main(int argc, char *argv[])
bool run_in_foreground = false; bool run_in_foreground = false;
// Choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal // Choose backend for printing command line argument parsing output based on whether the daemon is being run from a terminal
LOG_BACKEND log_backend = isatty(STDOUT_FILENO) ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG; LOG_BACKEND log_backend = isatty(STDOUT_FILENO) != 0 ? LOG_BACKEND_STDOUT : LOG_BACKEND_SYSLOG;
log_open(log_backend); log_open(log_backend);
switch (handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground)) { switch (handle_command_line_arguments(argc, argv, &cfg_file_path, &log_backend, &run_in_foreground)) {
@ -283,7 +281,7 @@ int main(int argc, char *argv[])
free(pid_file_path); free(pid_file_path);
IP ip; IP ip;
ip_init(&ip, enable_ipv6); ip_init(&ip, enable_ipv6 != 0);
Logger *logger = logger_new(); Logger *logger = logger_new();
@ -292,16 +290,16 @@ int main(int argc, char *argv[])
} }
const uint16_t end_port = start_port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM); const uint16_t end_port = start_port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM);
const Memory *mem = system_memory(); const Memory *mem = os_memory();
const Random *rng = system_random(); const Random *rng = os_random();
const Network *ns = system_network(); const Network *ns = os_network();
Networking_Core *net = new_networking_ex(logger, mem, ns, &ip, start_port, end_port, nullptr); Networking_Core *net = new_networking_ex(logger, mem, ns, &ip, start_port, end_port, nullptr);
if (net == nullptr) { if (net == nullptr) {
if (enable_ipv6 && enable_ipv4_fallback) { if (enable_ipv6 != 0 && enable_ipv4_fallback != 0) {
log_write(LOG_LEVEL_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n"); log_write(LOG_LEVEL_WARNING, "Couldn't initialize IPv6 networking. Falling back to using IPv4.\n");
enable_ipv6 = 0; enable_ipv6 = 0;
ip_init(&ip, enable_ipv6); ip_init(&ip, enable_ipv6 != 0);
net = new_networking_ex(logger, mem, ns, &ip, start_port, end_port, nullptr); net = new_networking_ex(logger, mem, ns, &ip, start_port, end_port, nullptr);
if (net == nullptr) { if (net == nullptr) {
@ -336,7 +334,7 @@ int main(int argc, char *argv[])
mono_time_update(mono_time); mono_time_update(mono_time);
DHT *const dht = new_dht(logger, mem, rng, ns, mono_time, net, true, enable_lan_discovery); DHT *const dht = new_dht(logger, mem, rng, ns, mono_time, net, true, enable_lan_discovery != 0);
if (dht == nullptr) { if (dht == nullptr) {
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox DHT instance. Exiting.\n");
@ -396,7 +394,7 @@ int main(int argc, char *argv[])
Onion *onion = new_onion(logger, mem, mono_time, rng, dht); Onion *onion = new_onion(logger, mem, mono_time, rng, dht);
if (!onion) { if (onion == nullptr) {
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion. Exiting.\n");
kill_gca(group_announce); kill_gca(group_announce);
kill_announcements(announce); kill_announcements(announce);
@ -413,7 +411,7 @@ int main(int argc, char *argv[])
Onion_Announce *onion_a = new_onion_announce(logger, mem, rng, mono_time, dht); Onion_Announce *onion_a = new_onion_announce(logger, mem, rng, mono_time, dht);
if (!onion_a) { if (onion_a == nullptr) {
log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion Announce. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "Couldn't initialize Tox Onion Announce. Exiting.\n");
kill_gca(group_announce); kill_gca(group_announce);
kill_onion(onion); kill_onion(onion);
@ -431,7 +429,7 @@ int main(int argc, char *argv[])
gca_onion_init(group_announce, onion_a); gca_onion_init(group_announce, onion_a);
if (enable_motd) { if (enable_motd != 0) {
if (bootstrap_set_callbacks(dht_get_net(dht), DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) { if (bootstrap_set_callbacks(dht_get_net(dht), DAEMON_VERSION_NUMBER, (uint8_t *)motd, strlen(motd) + 1) == 0) {
log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n"); log_write(LOG_LEVEL_INFO, "Set MOTD successfully.\n");
free(motd); free(motd);
@ -474,7 +472,7 @@ int main(int argc, char *argv[])
TCP_Server *tcp_server = nullptr; TCP_Server *tcp_server = nullptr;
if (enable_tcp_relay) { if (enable_tcp_relay != 0) {
if (tcp_relay_port_count == 0) { if (tcp_relay_port_count == 0) {
log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n"); log_write(LOG_LEVEL_ERROR, "No TCP relay ports read. Exiting.\n");
kill_onion_announce(onion_a); kill_onion_announce(onion_a);
@ -490,7 +488,7 @@ int main(int argc, char *argv[])
return 1; return 1;
} }
tcp_server = new_tcp_server(logger, mem, rng, ns, enable_ipv6, tcp_server = new_tcp_server(logger, mem, rng, ns, enable_ipv6 != 0,
tcp_relay_port_count, tcp_relay_ports, tcp_relay_port_count, tcp_relay_ports,
dht_get_self_secret_key(dht), onion, forwarding); dht_get_self_secret_key(dht), onion, forwarding);
@ -506,7 +504,7 @@ int main(int argc, char *argv[])
assert(rlim_suggested >= rlim_min); assert(rlim_suggested >= rlim_min);
if (!getrlimit(RLIMIT_NOFILE, &limit)) { if (getrlimit(RLIMIT_NOFILE, &limit) == 0) {
if (limit.rlim_cur < limit.rlim_max) { if (limit.rlim_cur < limit.rlim_max) {
// Some systems have a hard limit of over 1000000 open file descriptors, so let's cap it at something reasonable // Some systems have a hard limit of over 1000000 open file descriptors, so let's cap it at something reasonable
// so that we don't set it to an unreasonably high number. // so that we don't set it to an unreasonably high number.
@ -515,7 +513,7 @@ int main(int argc, char *argv[])
} }
} }
if (!getrlimit(RLIMIT_NOFILE, &limit) && limit.rlim_cur < rlim_min) { if (getrlimit(RLIMIT_NOFILE, &limit) == 0 && limit.rlim_cur < rlim_min) {
log_write(LOG_LEVEL_WARNING, log_write(LOG_LEVEL_WARNING,
"Current limit on the number of files this process can open (%ju) is rather low for the proper functioning of the TCP server. " "Current limit on the number of files this process can open (%ju) is rather low for the proper functioning of the TCP server. "
"Consider raising the limit to at least %ju or the recommended %ju. " "Consider raising the limit to at least %ju or the recommended %ju. "
@ -537,7 +535,7 @@ int main(int argc, char *argv[])
} }
} }
if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6)) { if (bootstrap_from_config(cfg_file_path, dht, enable_ipv6 != 0)) {
log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n"); log_write(LOG_LEVEL_INFO, "List of bootstrap nodes read successfully.\n");
} else { } else {
log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path); log_write(LOG_LEVEL_ERROR, "Couldn't read list of bootstrap nodes in %s. Exiting.\n", cfg_file_path);
@ -559,11 +557,11 @@ int main(int argc, char *argv[])
uint64_t last_lan_discovery = 0; uint64_t last_lan_discovery = 0;
const uint16_t net_htons_port = net_htons(start_port); const uint16_t net_htons_port = net_htons(start_port);
int waiting_for_dht_connection = 1; bool waiting_for_dht_connection = true;
Broadcast_Info *broadcast = nullptr; Broadcast_Info *broadcast = nullptr;
if (enable_lan_discovery) { if (enable_lan_discovery != 0) {
broadcast = lan_discovery_init(ns); broadcast = lan_discovery_init(ns);
log_write(LOG_LEVEL_INFO, "Initialized LAN discovery successfully.\n"); log_write(LOG_LEVEL_INFO, "Initialized LAN discovery successfully.\n");
} }
@ -578,25 +576,25 @@ int main(int argc, char *argv[])
// Prevent the signal handler from being called again before it returns // Prevent the signal handler from being called again before it returns
sigfillset(&sa.sa_mask); sigfillset(&sa.sa_mask);
if (sigaction(SIGINT, &sa, nullptr)) { if (sigaction(SIGINT, &sa, nullptr) != 0) {
log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGINT. Continuing without the signal handler set.\n"); log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGINT. Continuing without the signal handler set.\n");
} }
if (sigaction(SIGTERM, &sa, nullptr)) { if (sigaction(SIGTERM, &sa, nullptr) != 0) {
log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGTERM. Continuing without the signal handler set.\n"); log_write(LOG_LEVEL_WARNING, "Couldn't set signal handler for SIGTERM. Continuing without the signal handler set.\n");
} }
while (!caught_signal) { while (caught_signal == 0) {
mono_time_update(mono_time); mono_time_update(mono_time);
do_dht(dht); do_dht(dht);
if (enable_lan_discovery && mono_time_is_timeout(mono_time, last_lan_discovery, LAN_DISCOVERY_INTERVAL)) { if (enable_lan_discovery != 0 && mono_time_is_timeout(mono_time, last_lan_discovery, LAN_DISCOVERY_INTERVAL)) {
lan_discovery_send(dht_get_net(dht), broadcast, dht_get_self_public_key(dht), net_htons_port); lan_discovery_send(dht_get_net(dht), broadcast, dht_get_self_public_key(dht), net_htons_port);
last_lan_discovery = mono_time_get(mono_time); last_lan_discovery = mono_time_get(mono_time);
} }
if (enable_tcp_relay) { if (enable_tcp_relay != 0) {
do_tcp_server(tcp_server, mono_time); do_tcp_server(tcp_server, mono_time);
} }
@ -604,7 +602,7 @@ int main(int argc, char *argv[])
if (waiting_for_dht_connection && dht_isconnected(dht)) { if (waiting_for_dht_connection && dht_isconnected(dht)) {
log_write(LOG_LEVEL_INFO, "Connected to another bootstrap node successfully.\n"); log_write(LOG_LEVEL_INFO, "Connected to another bootstrap node successfully.\n");
waiting_for_dht_connection = 0; waiting_for_dht_connection = false;
} }
sleep_milliseconds(30); sleep_milliseconds(30);

View File

@ -2,6 +2,6 @@ module github.com/TokTok/c-toxcore/other/bootstrap_daemon/websocket/websockify
go 1.17 go 1.17
require ( require github.com/gorilla/websocket v1.5.1
github.com/gorilla/websocket master
) require golang.org/x/net v0.17.0 // indirect

View File

@ -0,0 +1,42 @@
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -18,6 +18,7 @@ package main
import ( import (
"encoding/hex" "encoding/hex"
"flag" "flag"
"fmt"
"log" "log"
"net" "net"
"net/http" "net/http"
@ -104,7 +105,10 @@ func main() {
if r.Header.Get("Upgrade") == "websocket" { if r.Header.Get("Upgrade") == "websocket" {
serveWs(w, r) serveWs(w, r)
} else { } else {
http.ServeFile(w, r, r.URL.Path[1:]) w.Header().Set("Content-Type", "text/plain")
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "404 Not Found")
} }
}) })
log.Fatal(http.ListenAndServe(*sourceAddr, nil)) log.Fatal(http.ListenAndServe(*sourceAddr, nil))

View File

@ -35,7 +35,7 @@ static int handle_info_request(void *object, const IP_Port *source, const uint8_
uint8_t data[1 + sizeof(bootstrap_version) + MAX_MOTD_LENGTH]; uint8_t data[1 + sizeof(bootstrap_version) + MAX_MOTD_LENGTH];
data[0] = BOOTSTRAP_INFO_PACKET_ID; data[0] = BOOTSTRAP_INFO_PACKET_ID;
memcpy(data + 1, &bootstrap_version, sizeof(bootstrap_version)); memcpy(data + 1, &bootstrap_version, sizeof(bootstrap_version));
uint16_t len = 1 + sizeof(bootstrap_version) + bootstrap_motd_length; const uint16_t len = 1 + sizeof(bootstrap_version) + bootstrap_motd_length;
memcpy(data + 1 + sizeof(bootstrap_version), bootstrap_motd, bootstrap_motd_length); memcpy(data + 1 + sizeof(bootstrap_version), bootstrap_motd, bootstrap_motd_length);
if (sendpacket(nc, source, data, len) == len) { if (sendpacket(nc, source, data, len) == len) {

View File

@ -1,5 +1,6 @@
################################################ ################################################
# autotools-linux # autotools-linux
FROM toxchat/c-toxcore:sources AS sources
FROM ubuntu:22.04 FROM ubuntu:22.04
RUN apt-get update && \ RUN apt-get update && \
@ -24,7 +25,12 @@ USER builder
WORKDIR /home/builder WORKDIR /home/builder
# Copy the sources and run the build. # Copy autotools-specific build scripts not present in the sources image.
# These change less frequently than the sources, thus are copied first.
COPY --chown=builder:builder . /home/builder/c-toxcore/ COPY --chown=builder:builder . /home/builder/c-toxcore/
# Copy the sources and run the build.
COPY --chown=builder:builder --from=sources /src/ /home/builder/c-toxcore/
WORKDIR /home/builder/c-toxcore WORKDIR /home/builder/c-toxcore
RUN CC=gcc .github/scripts/autotools-linux RUN CC=gcc .github/scripts/autotools-linux

View File

@ -0,0 +1,12 @@
**/*
!.github/scripts/autotools-linux
!m4/*
!configure.ac
!*.pc.in
!*.spec.in
!**/Makefile.am
!**/Makefile.inc
!docs/updates/*
!other/DHTnodes
!other/astyle/*
!other/tox.png

View File

@ -2,4 +2,5 @@
set -eux set -eux
BUILD=autotools BUILD=autotools
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/Dockerfile" . other/docker/sources/build
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/$BUILD.Dockerfile" .

View File

@ -1,3 +1,4 @@
FROM toxchat/c-toxcore:sources AS sources
FROM alpine:3.19.0 FROM alpine:3.19.0
RUN ["apk", "add", "--no-cache", \ RUN ["apk", "add", "--no-cache", \
@ -16,6 +17,8 @@ RUN ["apk", "add", "--no-cache", \
ENV CC=clang CXX=clang++ ENV CC=clang CXX=clang++
COPY . /c-toxcore/ COPY --from=sources /src/ /c-toxcore/
COPY other/analysis/run-clang-tidy other/analysis/variants.sh /c-toxcore/other/analysis/
COPY .clang-tidy /c-toxcore/
WORKDIR /c-toxcore WORKDIR /c-toxcore
RUN other/analysis/run-clang-tidy RUN other/analysis/run-clang-tidy

View File

@ -2,4 +2,5 @@
set -eux set -eux
BUILD=clang-tidy BUILD=clang-tidy
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/Dockerfile" . other/docker/sources/build
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/$BUILD.Dockerfile" .

1
other/docker/compcert/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
!/Makefile

View File

@ -1,30 +0,0 @@
FROM toxchat/compcert:latest
WORKDIR /work
COPY auto_tests/ /work/auto_tests/
COPY testing/ /work/testing/
COPY toxav/ /work/toxav/
COPY toxcore/ /work/toxcore/
COPY toxencryptsave/ /work/toxencryptsave/
COPY third_party/ /work/third_party/
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN ccomp \
-o send_message_test \
-Wall -Werror \
-Wno-c11-extensions \
-Wno-unknown-pragmas \
-Wno-unused-variable \
-fstruct-passing -fno-unprototyped -g \
auto_tests/auto_test_support.c \
auto_tests/send_message_test.c \
testing/misc_tools.c \
toxav/*.c \
toxcore/*.c \
toxcore/*/*.c \
toxencryptsave/*.c \
third_party/cmp/*.c \
-D__COMPCERT__ -DDISABLE_VLA -Dinline= \
-lpthread $(pkg-config --cflags --libs libsodium opus vpx) \
&& ./send_message_test | grep 'tox clients connected'

View File

@ -0,0 +1,39 @@
CC := ccomp
CFLAGS := -Wall \
-Wno-c11-extensions \
-Wno-unknown-pragmas \
-Wno-unused-variable \
-fstruct-passing -fno-unprototyped -g \
-Ilibsodium/src/libsodium/include \
$(shell pkg-config --cflags opus vpx)
LDFLAGS := -lpthread $(shell pkg-config --libs opus vpx)
libsodium_SOURCES := $(shell find libsodium/src/libsodium -name "*.c")
libsodium_OBJECTS := $(libsodium_SOURCES:.c=.o)
$(libsodium_OBJECTS): CFLAGS += \
-DDEV_MODE \
-DCONFIGURED \
-D_DEFAULT_SOURCE \
-Ilibsodium/builds/msvc \
-Ilibsodium/src/libsodium/include/sodium
toxcore_SOURCES := $(wildcard \
auto_tests/auto_test_support.c \
auto_tests/send_message_test.c \
testing/misc_tools.c \
toxav/*.c \
toxcore/*.c \
toxcore/*/*.c \
toxencryptsave/*.c \
third_party/cmp/*.c)
toxcore_OBJECTS := $(toxcore_SOURCES:.c=.o)
$(toxcore_OBJECTS): CFLAGS += \
-Werror \
-D__COMPCERT__ \
-DDISABLE_VLA \
-DMIN_LOGGER_LEVEL=LOGGER_LEVEL_TRACE \
-Dinline= \
send_message_test: $(libsodium_OBJECTS) $(toxcore_OBJECTS)
$(CC) -o $@ $+ $(LDFLAGS)

View File

@ -0,0 +1,19 @@
FROM toxchat/c-toxcore:sources AS sources
FROM toxchat/compcert:latest
RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
gdb \
make \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /work
COPY --from=sources /src/ /work/
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN git clone --depth=1 https://github.com/jedisct1/libsodium /work/libsodium
COPY other/docker/compcert/Makefile /work/
RUN make "-j$(nproc)"
RUN ./send_message_test | grep 'tox clients connected'

View File

@ -2,4 +2,5 @@
set -eux set -eux
BUILD=compcert BUILD=compcert
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/Dockerfile" . other/docker/sources/build
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/$BUILD.Dockerfile" .

View File

@ -1,4 +1,4 @@
FROM toxchat/c-toxcore:sources AS src FROM toxchat/c-toxcore:sources AS sources
FROM ubuntu:20.04 AS build FROM ubuntu:20.04 AS build
SHELL ["/bin/bash", "-o", "pipefail", "-c"] SHELL ["/bin/bash", "-o", "pipefail", "-c"]
@ -41,7 +41,7 @@ ENV CC=clang-17 \
PYTHONUNBUFFERED=1 \ PYTHONUNBUFFERED=1 \
PATH=$PATH:/usr/lib/go-1.18/bin PATH=$PATH:/usr/lib/go-1.18/bin
COPY --from=src /src/ /work/ COPY --from=sources /src/ /work/
WORKDIR /work WORKDIR /work
RUN git clone --depth=1 https://github.com/TokTok/toktok-fuzzer /work/testing/fuzzing/toktok-fuzzer RUN git clone --depth=1 https://github.com/TokTok/toktok-fuzzer /work/testing/fuzzing/toktok-fuzzer

View File

@ -4,6 +4,8 @@ set -eux
read -a ci_env <<<"$(bash <(curl -s https://codecov.io/env))" read -a ci_env <<<"$(bash <(curl -s https://codecov.io/env))"
docker build -t toxchat/c-toxcore:sources -f other/docker/sources/Dockerfile . BUILD=coverage
docker build -t toxchat/c-toxcore:coverage -f other/docker/coverage/Dockerfile . other/docker/sources/build
docker build -t "toxchat/c-toxcore:$BUILD" -f "other/docker/$BUILD/$BUILD.Dockerfile" .
docker run "${ci_env[@]}" -e CI=true --name toxcore-coverage --rm -t toxchat/c-toxcore:coverage /usr/local/bin/codecov docker run "${ci_env[@]}" -e CI=true --name toxcore-coverage --rm -t toxchat/c-toxcore:coverage /usr/local/bin/codecov

Some files were not shown because too many files have changed in this diff Show More