Compare commits

...

3 Commits

Author SHA1 Message Date
Green Sky
ac951b2afa
update toxcore, includes ngc mem savings
Some checks failed
ContinuousDelivery / linux-ubuntu (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Has been cancelled
ContinuousDelivery / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Has been cancelled
ContinuousDelivery / windows (push) Has been cancelled
ContinuousDelivery / windows-asan (push) Has been cancelled
ContinuousIntegration / linux (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:arm64-v8a vcpkg_toolkit:arm64-android]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:armeabi-v7a vcpkg_toolkit:arm-neon-android]) (push) Has been cancelled
ContinuousIntegration / android (map[ndk_abi:x86_64 vcpkg_toolkit:x64-android]) (push) Has been cancelled
ContinuousIntegration / macos (push) Has been cancelled
ContinuousIntegration / windows (push) Has been cancelled
ContinuousDelivery / release (push) Has been cancelled
Merge commit '261d2e53b7a513de7eb35e022fe3b2ae4efa835f'
2024-12-19 16:27:50 +01:00
Green Sky
261d2e53b7 Squashed 'external/toxcore/c-toxcore/' changes from 55752a2e2ef..11ab1d2a723
11ab1d2a723 fix: reduce memory usage in group chats by 75% Significantly reduced the memory usage of groups since all message slots are preallocated for every peer for send and receive buffers of buffer size (hundreds of MiB peak when save contained alot of peers to try to connect to)
4f09f4e147c chore: Fix tsan build by moving it to GitHub CI.
6460c25c9e0 refactor: Use `merge_sort` instead of `qsort` for sorting.
c660bbe8c95 test: Fix crypto_test to initialise its plain text buffer.
0204db6184b cleanup: Fix layering check warnings.
df2211e1548 refactor: Use tox memory allocator for temporary buffers in crypto.
ac812871a2e feat: implement the last 2 missing network struct functions and make use of them
29d1043be0b test: friend request test now tests min/max message sizes
93aafd78c1f fix: friend requests with very long messages are no longer dropped
819aa2b2618 feat: Add option to disable DNS lookups in toxcore.
0ac23cee035 fix: windows use of REUSEADDR
7d2811d302d chore(ci): make bazel server shutdown faster
1dc399ba20d chore: Use vcpkg instead of conan in the MSVC build.
14d823165d9 chore: Migrate to conan 2.
bdd17c16787 cleanup: Allocate logger using tox memory allocator.
b396c061515 chore(deps): bump third_party/cmp from `2ac6bca` to `52bfcfa`
2e94da60d09 feat(net): add missing connect to network struct
41fb1839c7b chore: Add check to ensure version numbers agree.
934a8301113 chore: Release 0.2.20
3acef4bf044 fix: Add missing free in dht_get_nodes_response event.

git-subtree-dir: external/toxcore/c-toxcore
git-subtree-split: 11ab1d2a7232eee19b51ce126ccce267d6578903
2024-12-19 16:27:40 +01:00
Green Sky
d71ebb79aa
asan cmake and frame pointer 2024-12-19 16:26:40 +01:00
102 changed files with 1954 additions and 890 deletions

View File

@ -27,9 +27,18 @@ option(TOMATO_TOX_AV "Build tomato with ToxAV" OFF)
if (TOMATO_ASAN) if (TOMATO_ASAN)
if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") if (${CMAKE_CXX_COMPILER_ID} STREQUAL "GNU" OR ${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang")
if (NOT WIN32) # exclude mingw if (NOT WIN32) # exclude mingw
#link_libraries(-fsanitize=address) add_compile_options(-fno-omit-frame-pointer)
link_libraries(-fsanitize=address,undefined) add_compile_options(-fsanitize=address,undefined)
#link_libraries(-fsanitize=undefined) #add_compile_options(-fsanitize=address,undefined,pointer-compare,pointer-subtract)
#add_compile_options(-fhardened)
#add_compile_options(-D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -ftrivial-auto-var-init=zero -fPIE -pie -Wl,-z,relro,-z,now -fstack-protector-strong -fstack-clash-protection -fcf-protection=full)
add_link_options(-fno-omit-frame-pointer)
add_link_options(-fsanitize=address,undefined)
#add_link_options(-fsanitize=address,undefined,pointer-compare,pointer-subtract)
#add_link_options(-fhardened)
#add_link_options(-D_FORTIFY_SOURCE=3 -D_GLIBCXX_ASSERTIONS -ftrivial-auto-var-init=zero -fPIE -pie -Wl,-z,relro,-z,now -fstack-protector-strong -fstack-clash-protection -fcf-protection=full)
link_libraries(-static-libasan) # make it "work" on nix link_libraries(-static-libasan) # make it "work" on nix
message("II enabled ASAN") message("II enabled ASAN")
else() else()

View File

@ -3,20 +3,15 @@ version: 2
workflows: workflows:
version: 2 version: 2
program-analysis: circleci:
jobs: jobs:
# Dynamic analysis in the Bazel build
- bazel-asan - bazel-asan
- bazel-msan - bazel-msan
- bazel-tsan
# Dynamic analysis with CMake
- asan
- tsan
- ubsan
# Static analysis
- clang-analyze - clang-analyze
- cpplint - cpplint
- static-analysis - static-analysis
- cimplefmt
- generate-events
jobs: jobs:
bazel-asan: bazel-asan:
@ -29,20 +24,6 @@ jobs:
- run: .circleci/bazel-test - run: .circleci/bazel-test
//c-toxcore/... //c-toxcore/...
bazel-tsan:
working_directory: /tmp/cirrus-ci-build
docker:
- image: toxchat/toktok-stack:latest-tsan
steps:
- checkout
- run: .circleci/bazel-test
//c-toxcore/...
-//c-toxcore/auto_tests:conference_av_test
-//c-toxcore/auto_tests:conference_test
-//c-toxcore/auto_tests:onion_test
-//c-toxcore/auto_tests:tox_many_test
bazel-msan: bazel-msan:
working_directory: /tmp/cirrus-ci-build working_directory: /tmp/cirrus-ci-build
docker: docker:
@ -53,7 +34,7 @@ jobs:
- run: .circleci/bazel-test - run: .circleci/bazel-test
//c-toxcore/auto_tests:lossless_packet_test //c-toxcore/auto_tests:lossless_packet_test
asan: static-analysis:
working_directory: ~/work working_directory: ~/work
docker: docker:
- image: ubuntu - image: ubuntu
@ -67,6 +48,7 @@ jobs:
clang clang
cmake cmake
git git
libbenchmark-dev
libconfig-dev libconfig-dev
libgmock-dev libgmock-dev
libgtest-dev libgtest-dev
@ -76,39 +58,6 @@ jobs:
llvm-dev llvm-dev
ninja-build ninja-build
pkg-config pkg-config
- checkout
- run: git submodule update --init --recursive
- run: CC=clang .circleci/cmake-asan
tsan:
working_directory: ~/work
docker:
- image: ubuntu
steps:
- run: *apt_install
- checkout
- run: git submodule update --init --recursive
- run: CC=clang .circleci/cmake-tsan
ubsan:
working_directory: ~/work
docker:
- image: ubuntu
steps:
- run: *apt_install
- checkout
- run: git submodule update --init --recursive
- run: CC=clang .circleci/cmake-ubsan
static-analysis:
working_directory: ~/work
docker:
- image: ubuntu
steps:
- run: *apt_install
- run: - run:
apt-get install -y --no-install-recommends apt-get install -y --no-install-recommends
ca-certificates ca-certificates
@ -145,3 +94,22 @@ jobs:
- checkout - checkout
- run: git submodule update --init --recursive - run: git submodule update --init --recursive
- run: other/analysis/run-cpplint - run: other/analysis/run-cpplint
cimplefmt:
working_directory: ~/work
machine: { image: ubuntu-2204:current }
steps:
- checkout
- run: git submodule update --init --recursive
- run: other/docker/cimplefmt/run -u $(find tox* -name "*.[ch]")
generate-events:
working_directory: ~/work
machine: { image: ubuntu-2204:current }
steps:
- checkout
- run: git submodule update --init --recursive
- run: other/event_tooling/run
- run: git diff --exit-code

View File

@ -9,7 +9,9 @@ bazel-opt_task:
- git submodule update --init --recursive - git submodule update --init --recursive
- /src/workspace/tools/inject-repo c-toxcore - /src/workspace/tools/inject-repo c-toxcore
test_all_script: test_all_script:
- cd /src/workspace && bazel test -k - cd /src/workspace && bazel
--max_idle_secs=5
test -k
--remote_cache=http://$CIRRUS_HTTP_CACHE_HOST --remote_cache=http://$CIRRUS_HTTP_CACHE_HOST
--build_tag_filters=-haskell --build_tag_filters=-haskell
--test_tag_filters=-haskell --test_tag_filters=-haskell
@ -27,7 +29,9 @@ bazel-dbg_task:
- git submodule update --init --recursive - git submodule update --init --recursive
- /src/workspace/tools/inject-repo c-toxcore - /src/workspace/tools/inject-repo c-toxcore
test_all_script: test_all_script:
- cd /src/workspace && bazel test -k - cd /src/workspace && bazel
--max_idle_secs=5
test -k
--remote_cache=http://$CIRRUS_HTTP_CACHE_HOST --remote_cache=http://$CIRRUS_HTTP_CACHE_HOST
--build_tag_filters=-haskell --build_tag_filters=-haskell
--test_tag_filters=-haskell --test_tag_filters=-haskell
@ -45,7 +49,9 @@ cimple_task:
- git submodule update --init --recursive - git submodule update --init --recursive
- /src/workspace/tools/inject-repo c-toxcore - /src/workspace/tools/inject-repo c-toxcore
test_all_script: test_all_script:
- cd /src/workspace && bazel test -k - cd /src/workspace && bazel
--max_idle_secs=5
test -k
--remote_cache=http://$CIRRUS_HTTP_CACHE_HOST --remote_cache=http://$CIRRUS_HTTP_CACHE_HOST
--build_tag_filters=haskell --build_tag_filters=haskell
--test_tag_filters=haskell --test_tag_filters=haskell

View File

@ -0,0 +1,12 @@
name: checks
on:
pull_request:
branches: [master]
types: [opened, reopened, synchronize, milestoned]
pull_request_target:
branches: [master]
jobs:
checks:
uses: TokTok/ci-tools/.github/workflows/check-release.yml@master

View File

@ -18,7 +18,7 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
tool: [autotools, clang-tidy, compcert, cppcheck, doxygen, goblint, infer, freebsd, misra, modules, pkgsrc, rpm, slimcc, sparse, 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-22.04
steps: steps:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
@ -34,8 +34,25 @@ jobs:
with: with:
file: other/docker/${{ matrix.tool }}/${{ matrix.tool }}.Dockerfile file: other/docker/${{ matrix.tool }}/${{ matrix.tool }}.Dockerfile
sanitizer:
strategy:
fail-fast: false
matrix:
sanitizer: [asan, tsan, ubsan]
runs-on: ubuntu-22.04
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Run sanitizer
run: other/docker/circleci/run "${{ matrix.sanitizer }}"
coverage-linux: coverage-linux:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -43,28 +60,8 @@ jobs:
- name: Build, test, and upload coverage - name: Build, test, and upload coverage
run: other/docker/coverage/run run: other/docker/coverage/run
generate-events:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Run generate_event_c
run: |
other/event_tooling/run
git diff --exit-code
cimplefmt:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Run cimplefmt
run: other/docker/cimplefmt/run -u $(find tox* -name "*.[ch]")
build-android: build-android:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -111,7 +108,7 @@ jobs:
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-netbsd: build-netbsd:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -146,7 +143,7 @@ jobs:
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
build-freebsd: build-freebsd:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
@ -183,7 +180,7 @@ jobs:
ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6 ctest -j50 --output-on-failure --rerun-failed --repeat until-pass:6
mypy: mypy:
runs-on: ubuntu-latest runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:

View File

@ -1,5 +1,35 @@
## v0.2.20
### Merged PRs:
- [#2788](https://github.com/TokTok/c-toxcore/pull/2788) fix: Add missing free in dht_get_nodes_response event.
- [#2786](https://github.com/TokTok/c-toxcore/pull/2786) cleanup: Fix all `-Wsign-compare` warnings.
- [#2785](https://github.com/TokTok/c-toxcore/pull/2785) fix: wrong comment for closelist
- [#2784](https://github.com/TokTok/c-toxcore/pull/2784) chore: lower cirrus ci timeout drastically
- [#2783](https://github.com/TokTok/c-toxcore/pull/2783) fix: Return an error instead of crashing on nullptr args in NGC.
- [#2782](https://github.com/TokTok/c-toxcore/pull/2782) fix(toxav): pass video bit rate as kbit
- [#2780](https://github.com/TokTok/c-toxcore/pull/2780) chore: Add release-drafter github action.
- [#2779](https://github.com/TokTok/c-toxcore/pull/2779) chore: Use toktok's cmp instead of upstream.
- [#2778](https://github.com/TokTok/c-toxcore/pull/2778) cleanup: Sort apk/apt install commands in Dockerfiles.
- [#2777](https://github.com/TokTok/c-toxcore/pull/2777) chore: Upgrade to FreeBSD 14.1 in cirrus build.
- [#2772](https://github.com/TokTok/c-toxcore/pull/2772) fix: friend_connections leak on allocation failure.
- [#2771](https://github.com/TokTok/c-toxcore/pull/2771) fix: events leak that can occur if allocation fails
- [#2769](https://github.com/TokTok/c-toxcore/pull/2769) chore(ci): new minimum for all android versions is 21
- [#2768](https://github.com/TokTok/c-toxcore/pull/2768) fix: toxav rtp temp buffer allocation size was too large
- [#2762](https://github.com/TokTok/c-toxcore/pull/2762) chore(cmake): set options changes as cache and with force
- [#2761](https://github.com/TokTok/c-toxcore/pull/2761) chore: Fix CI
- [#2757](https://github.com/TokTok/c-toxcore/pull/2757) fix: Use Opus in the CBR mode
- [#2755](https://github.com/TokTok/c-toxcore/pull/2755) chore: Fix Circle CI build failing
- [#2754](https://github.com/TokTok/c-toxcore/pull/2754) docs(toxav): fix docs of toxav.h
- [#2751](https://github.com/TokTok/c-toxcore/pull/2751) chore(deps): bump golang.org/x/net from 0.17.0 to 0.23.0 in /other/bootstrap_daemon/websocket/websockify
- [#2747](https://github.com/TokTok/c-toxcore/pull/2747) fix: Memory leak in the bootstrap daemon
- [#2745](https://github.com/TokTok/c-toxcore/pull/2745) chore: Fix GitHub actions deprecation warnings
- [#2717](https://github.com/TokTok/c-toxcore/pull/2717) cleanup: Remove useless if clause
- [#2692](https://github.com/TokTok/c-toxcore/pull/2692) refactor: Make tox-bootstrapd use bool instead of int
- [#2651](https://github.com/TokTok/c-toxcore/pull/2651) refactor: Make ToxAV independent of toxcore internals.
## v0.2.19 ## v0.2.19
### Merged PRs: ### Merged PRs:
@ -30,6 +60,7 @@
- [#2697](https://github.com/TokTok/c-toxcore/pull/2697) test: Build toxcore on NetBSD (VM). - [#2697](https://github.com/TokTok/c-toxcore/pull/2697) test: Build toxcore on NetBSD (VM).
- [#2696](https://github.com/TokTok/c-toxcore/pull/2696) fix: save_compatibility_test failing on big-endian systems - [#2696](https://github.com/TokTok/c-toxcore/pull/2696) fix: save_compatibility_test failing on big-endian systems
- [#2695](https://github.com/TokTok/c-toxcore/pull/2695) fix: Don't serve files from websockify. - [#2695](https://github.com/TokTok/c-toxcore/pull/2695) fix: Don't serve files from websockify.
- [#2691](https://github.com/TokTok/c-toxcore/pull/2691) chore: Release 0.2.19
- [#2689](https://github.com/TokTok/c-toxcore/pull/2689) fix: Correctly pass extended public keys to group moderation code. - [#2689](https://github.com/TokTok/c-toxcore/pull/2689) fix: Correctly pass extended public keys to group moderation code.
- [#2686](https://github.com/TokTok/c-toxcore/pull/2686) chore: Compile libsodium reference implementation with compcert. - [#2686](https://github.com/TokTok/c-toxcore/pull/2686) chore: Compile libsodium reference implementation with compcert.
- [#2685](https://github.com/TokTok/c-toxcore/pull/2685) cleanup: correct a few nullable annotations - [#2685](https://github.com/TokTok/c-toxcore/pull/2685) cleanup: correct a few nullable annotations
@ -252,6 +283,7 @@
- [#2739](https://github.com/TokTok/c-toxcore/issues/2739) Tox_Options.operating_system is not clear about it being an experimental option - [#2739](https://github.com/TokTok/c-toxcore/issues/2739) Tox_Options.operating_system is not clear about it being an experimental option
- [#2734](https://github.com/TokTok/c-toxcore/issues/2734) error compiling on fedora - [#2734](https://github.com/TokTok/c-toxcore/issues/2734) error compiling on fedora
- [#2649](https://github.com/TokTok/c-toxcore/issues/2649) create_extended_keypair should use Random and be made deterministic for fuzzing - [#2649](https://github.com/TokTok/c-toxcore/issues/2649) create_extended_keypair should use Random and be made deterministic for fuzzing
- [#2462](https://github.com/TokTok/c-toxcore/issues/2462) Fix code scanning alert - Uncontrolled data used in path expression
- [#2358](https://github.com/TokTok/c-toxcore/issues/2358) resolve_bootstrap_node assert hit - [#2358](https://github.com/TokTok/c-toxcore/issues/2358) resolve_bootstrap_node assert hit
- [#2352](https://github.com/TokTok/c-toxcore/issues/2352) SEGV after infinite loop retrying proxy_socks5_read_connection_response - [#2352](https://github.com/TokTok/c-toxcore/issues/2352) SEGV after infinite loop retrying proxy_socks5_read_connection_response
- [#2335](https://github.com/TokTok/c-toxcore/issues/2335) ipv6 disabled on kernel cmdline disrupts Tox = most tests fail - [#2335](https://github.com/TokTok/c-toxcore/issues/2335) ipv6 disabled on kernel cmdline disrupts Tox = most tests fail

View File

@ -44,7 +44,7 @@ set_source_files_properties(
# versions in a synchronised way. # versions in a synchronised way.
set(PROJECT_VERSION_MAJOR "0") set(PROJECT_VERSION_MAJOR "0")
set(PROJECT_VERSION_MINOR "2") set(PROJECT_VERSION_MINOR "2")
set(PROJECT_VERSION_PATCH "19") set(PROJECT_VERSION_PATCH "20")
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
# set .so library version / following libtool scheme # set .so library version / following libtool scheme
@ -323,6 +323,8 @@ set(toxcore_SOURCES
toxcore/ping.h toxcore/ping.h
toxcore/shared_key_cache.c toxcore/shared_key_cache.c
toxcore/shared_key_cache.h toxcore/shared_key_cache.h
toxcore/sort.c
toxcore/sort.h
toxcore/state.c toxcore/state.c
toxcore/state.h toxcore/state.h
toxcore/TCP_client.c toxcore/TCP_client.c
@ -352,7 +354,9 @@ set(toxcore_SOURCES
toxcore/tox_unpack.h toxcore/tox_unpack.h
toxcore/util.c toxcore/util.c
toxcore/util.h) toxcore/util.h)
if(TARGET unofficial-sodium::sodium) if(TARGET libsodium::libsodium)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} libsodium::libsodium)
elseif(TARGET unofficial-sodium::sodium)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} unofficial-sodium::sodium) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} unofficial-sodium::sodium)
else() else()
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${LIBSODIUM_LIBRARIES}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${LIBSODIUM_LIBRARIES})
@ -399,7 +403,9 @@ if(BUILD_TOXAV)
set(toxcore_API_HEADERS ${toxcore_API_HEADERS} set(toxcore_API_HEADERS ${toxcore_API_HEADERS}
${toxcore_SOURCE_DIR}/toxav/toxav.h^toxav) ${toxcore_SOURCE_DIR}/toxav/toxav.h^toxav)
if(MSVC) if(TARGET Opus::opus AND TARGET libvpx::libvpx)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Opus::opus libvpx::libvpx)
elseif(TARGET PkgConfig::OPUS AND TARGET PkgConfig::VPX)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} PkgConfig::OPUS PkgConfig::VPX) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} PkgConfig::OPUS PkgConfig::VPX)
else() else()
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${OPUS_LIBRARIES} ${VPX_LIBRARIES}) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${OPUS_LIBRARIES} ${VPX_LIBRARIES})
@ -452,7 +458,9 @@ if(SOCKET_LIBRARIES)
set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lsocket) set(toxcore_PKGCONFIG_LIBS ${toxcore_PKGCONFIG_LIBS} -lsocket)
endif() endif()
if(TARGET PThreads4W::PThreads4W) if(TARGET pthreads4w::pthreads4w)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} pthreads4w::pthreads4w)
elseif(TARGET PThreads4W::PThreads4W)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} PThreads4W::PThreads4W) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads) elseif(TARGET Threads::Threads)
set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads) set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} Threads::Threads)
@ -510,17 +518,19 @@ install_module(toxcore DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tox)
# #
################################################################################ ################################################################################
add_library(test_util STATIC if(UNITTEST)
toxcore/DHT_test_util.cc add_library(test_util STATIC
toxcore/DHT_test_util.hh toxcore/DHT_test_util.cc
toxcore/crypto_core_test_util.cc toxcore/DHT_test_util.hh
toxcore/crypto_core_test_util.hh toxcore/crypto_core_test_util.cc
toxcore/mem_test_util.cc toxcore/crypto_core_test_util.hh
toxcore/mem_test_util.hh toxcore/mem_test_util.cc
toxcore/network_test_util.cc toxcore/mem_test_util.hh
toxcore/network_test_util.hh toxcore/network_test_util.cc
toxcore/test_util.cc toxcore/network_test_util.hh
toxcore/test_util.hh) toxcore/test_util.cc
toxcore/test_util.hh)
endif()
function(unit_test subdir target) function(unit_test subdir target)
add_executable(unit_${target}_test ${subdir}/${target}_test.cc) add_executable(unit_${target}_test ${subdir}/${target}_test.cc)
@ -530,6 +540,13 @@ function(unit_test subdir target)
else() else()
target_link_libraries(unit_${target}_test PRIVATE toxcore_shared) target_link_libraries(unit_${target}_test PRIVATE toxcore_shared)
endif() endif()
if(TARGET pthreads4w::pthreads4w)
target_link_libraries(unit_${target}_test PRIVATE pthreads4w::pthreads4w)
elseif(TARGET PThreads4W::PThreads4W)
target_link_libraries(unit_${target}_test PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads)
target_link_libraries(unit_${target}_test PRIVATE Threads::Threads)
endif()
target_link_libraries(unit_${target}_test PRIVATE GTest::gtest GTest::gtest_main GTest::gmock) target_link_libraries(unit_${target}_test PRIVATE GTest::gtest GTest::gtest_main GTest::gmock)
set_target_properties(unit_${target}_test PROPERTIES COMPILE_FLAGS "${TEST_CXX_FLAGS}") set_target_properties(unit_${target}_test PROPERTIES COMPILE_FLAGS "${TEST_CXX_FLAGS}")
add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} unit_${target}_test) add_test(NAME ${target} COMMAND ${CROSSCOMPILING_EMULATOR} unit_${target}_test)
@ -583,10 +600,14 @@ if(DHT_BOOTSTRAP)
target_link_libraries(DHT_bootstrap PRIVATE toxcore_shared) target_link_libraries(DHT_bootstrap PRIVATE toxcore_shared)
endif() endif()
target_link_libraries(DHT_bootstrap PRIVATE misc_tools) target_link_libraries(DHT_bootstrap PRIVATE misc_tools)
if(TARGET unofficial-sodium::sodium) if(TARGET libsodium::libsodium)
target_link_libraries(DHT_bootstrap PRIVATE libsodium::libsodium)
elseif(TARGET unofficial-sodium::sodium)
target_link_libraries(DHT_bootstrap PRIVATE unofficial-sodium::sodium) target_link_libraries(DHT_bootstrap PRIVATE unofficial-sodium::sodium)
endif() endif()
if(TARGET PThreads4W::PThreads4W) if(TARGET pthreads4w::pthreads4w)
target_link_libraries(DHT_bootstrap PRIVATE pthreads4w::pthreads4w)
elseif(TARGET PThreads4W::PThreads4W)
target_link_libraries(DHT_bootstrap PRIVATE PThreads4W::PThreads4W) target_link_libraries(DHT_bootstrap PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads) elseif(TARGET Threads::Threads)
target_link_libraries(DHT_bootstrap PRIVATE Threads::Threads) target_link_libraries(DHT_bootstrap PRIVATE Threads::Threads)

View File

@ -7,6 +7,7 @@
"cacheVariables": { "cacheVariables": {
"ENABLE_SHARED": true, "ENABLE_SHARED": true,
"ENABLE_STATIC": true, "ENABLE_STATIC": true,
"FLAT_OUTPUT_STRUCTURE": true,
"AUTOTEST": true, "AUTOTEST": true,
"BUILD_MISC_TESTS": true, "BUILD_MISC_TESTS": true,
"BOOTSTRAP_DAEMON": false, "BOOTSTRAP_DAEMON": false,
@ -17,5 +18,19 @@
"CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" "CMAKE_TOOLCHAIN_FILE": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
} }
} }
],
"buildPresets": [
{
"name": "windows-default",
"configurePreset": "windows-default",
"description": "Build for Windows using default settings"
}
],
"testPresets": [
{
"name": "windows-default",
"configurePreset": "windows-default",
"description": "Run tests for Windows using default settings"
}
] ]
} }

View File

@ -78,6 +78,7 @@ extra_data = {
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_dispatch", "//c-toxcore/toxcore:tox_dispatch",
"//c-toxcore/toxcore:tox_events", "//c-toxcore/toxcore:tox_events",
"//c-toxcore/toxcore:tox_unpack",
"//c-toxcore/toxcore:util", "//c-toxcore/toxcore:util",
"//c-toxcore/toxencryptsave", "//c-toxcore/toxencryptsave",
"@libsodium", "@libsodium",

View File

@ -9,7 +9,9 @@ if(TARGET toxcore_static)
else() else()
target_link_libraries(auto_test_support PRIVATE toxcore_shared) target_link_libraries(auto_test_support PRIVATE toxcore_shared)
endif() endif()
if(TARGET PThreads4W::PThreads4W) if(TARGET pthreads4w::pthreads4w)
target_link_libraries(auto_test_support PRIVATE pthreads4w::pthreads4w)
elseif(TARGET PThreads4W::PThreads4W)
target_link_libraries(auto_test_support PRIVATE PThreads4W::PThreads4W) target_link_libraries(auto_test_support PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads) elseif(TARGET Threads::Threads)
target_link_libraries(auto_test_support PRIVATE Threads::Threads) target_link_libraries(auto_test_support PRIVATE Threads::Threads)
@ -23,7 +25,9 @@ function(auto_test target)
else() else()
target_link_libraries(auto_${target}_test PRIVATE toxcore_shared) target_link_libraries(auto_${target}_test PRIVATE toxcore_shared)
endif() endif()
if(TARGET PThreads4W::PThreads4W) if(TARGET pthreads4w::pthreads4w)
target_link_libraries(auto_${target}_test PRIVATE pthreads4w::pthreads4w)
elseif(TARGET PThreads4W::PThreads4W)
target_link_libraries(auto_${target}_test PRIVATE PThreads4W::PThreads4W) target_link_libraries(auto_${target}_test PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads) elseif(TARGET Threads::Threads)
target_link_libraries(auto_${target}_test PRIVATE Threads::Threads) target_link_libraries(auto_${target}_test PRIVATE Threads::Threads)
@ -98,7 +102,10 @@ if(BUILD_TOXAV)
auto_test(toxav_basic) auto_test(toxav_basic)
auto_test(toxav_many) auto_test(toxav_many)
if(MSVC) if(TARGET libvpx::libvpx)
target_link_libraries(auto_toxav_basic_test PRIVATE libvpx::libvpx)
target_link_libraries(auto_toxav_many_test PRIVATE libvpx::libvpx)
elseif(TARGET PkgConfig::VPX)
target_link_libraries(auto_toxav_basic_test PRIVATE PkgConfig::VPX) target_link_libraries(auto_toxav_basic_test PRIVATE PkgConfig::VPX)
target_link_libraries(auto_toxav_many_test PRIVATE PkgConfig::VPX) target_link_libraries(auto_toxav_many_test PRIVATE PkgConfig::VPX)
else() else()

View File

@ -53,7 +53,7 @@ static void test_basic(void)
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);
Logger *logger = logger_new(); Logger *logger = logger_new(mem);
logger_callback_log(logger, print_debug_logger, nullptr, nullptr); logger_callback_log(logger, print_debug_logger, nullptr, nullptr);
// Attempt to create a new TCP_Server instance. // Attempt to create a new TCP_Server instance.
@ -74,7 +74,7 @@ static void test_basic(void)
for (uint8_t i = 0; i < NUM_PORTS; i++) { for (uint8_t i = 0; i < NUM_PORTS; i++) {
sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP); sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP);
localhost.port = net_htons(ports[i]); localhost.port = net_htons(ports[i]);
bool ret = net_connect(mem, logger, sock, &localhost); bool ret = net_connect(ns, mem, logger, sock, &localhost);
ck_assert_msg(ret, "Failed to connect to created TCP relay server on port %d (%d).", ports[i], errno); ck_assert_msg(ret, "Failed to connect to created TCP relay server on port %d (%d).", ports[i], errno);
// Leave open one connection for the next test. // Leave open one connection for the next test.
@ -102,7 +102,7 @@ static void test_basic(void)
random_nonce(rng, handshake + CRYPTO_PUBLIC_KEY_SIZE); random_nonce(rng, handshake + CRYPTO_PUBLIC_KEY_SIZE);
// Encrypting handshake // Encrypting handshake
int ret = encrypt_data(self_public_key, f_secret_key, handshake + CRYPTO_PUBLIC_KEY_SIZE, handshake_plain, int ret = encrypt_data(mem, self_public_key, f_secret_key, handshake + CRYPTO_PUBLIC_KEY_SIZE, handshake_plain,
TCP_HANDSHAKE_PLAIN_SIZE, handshake + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); TCP_HANDSHAKE_PLAIN_SIZE, handshake + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE),
"encrypt_data() call failed."); "encrypt_data() call failed.");
@ -128,7 +128,7 @@ static void test_basic(void)
uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE]; uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE];
ck_assert_msg(net_recv(ns, logger, sock, response, TCP_SERVER_HANDSHAKE_SIZE, &localhost) == TCP_SERVER_HANDSHAKE_SIZE, ck_assert_msg(net_recv(ns, logger, sock, response, TCP_SERVER_HANDSHAKE_SIZE, &localhost) == TCP_SERVER_HANDSHAKE_SIZE,
"Could/did not receive a server response to the initial handshake."); "Could/did not receive a server response to the initial handshake.");
ret = decrypt_data(self_public_key, f_secret_key, response, response + CRYPTO_NONCE_SIZE, ret = decrypt_data(mem, self_public_key, f_secret_key, response, response + CRYPTO_NONCE_SIZE,
TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, response_plain); TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, response_plain);
ck_assert_msg(ret == TCP_HANDSHAKE_PLAIN_SIZE, "Failed to decrypt handshake response."); ck_assert_msg(ret == TCP_HANDSHAKE_PLAIN_SIZE, "Failed to decrypt handshake response.");
uint8_t f_nonce_r[CRYPTO_NONCE_SIZE]; uint8_t f_nonce_r[CRYPTO_NONCE_SIZE];
@ -143,7 +143,7 @@ static void test_basic(void)
uint8_t r_req[2 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE]; uint8_t r_req[2 + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE];
uint16_t size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE; uint16_t size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE;
size = net_htons(size); size = net_htons(size);
encrypt_data_symmetric(f_shared_key, f_nonce, r_req_p, 1 + CRYPTO_PUBLIC_KEY_SIZE, r_req + 2); encrypt_data_symmetric(mem, f_shared_key, f_nonce, r_req_p, 1 + CRYPTO_PUBLIC_KEY_SIZE, r_req + 2);
increment_nonce(f_nonce); increment_nonce(f_nonce);
memcpy(r_req, &size, 2); memcpy(r_req, &size, 2);
@ -174,7 +174,7 @@ static void test_basic(void)
"Wrong packet size for request response."); "Wrong packet size for request response.");
uint8_t packet_resp_plain[4096]; uint8_t packet_resp_plain[4096];
ret = decrypt_data_symmetric(f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain); ret = decrypt_data_symmetric(mem, f_shared_key, f_nonce_r, packet_resp + 2, recv_data_len - 2, packet_resp_plain);
ck_assert_msg(ret != -1, "Failed to decrypt the TCP server's response."); ck_assert_msg(ret != -1, "Failed to decrypt the TCP server's response.");
increment_nonce(f_nonce_r); increment_nonce(f_nonce_r);
@ -213,7 +213,7 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem,
localhost.ip = get_loopback(); localhost.ip = get_loopback();
localhost.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); localhost.port = net_htons(ports[random_u32(rng) % NUM_PORTS]);
bool ok = net_connect(mem, logger, sock, &localhost); bool ok = net_connect(ns, mem, logger, sock, &localhost);
ck_assert_msg(ok, "Failed to connect to the test TCP relay server."); ck_assert_msg(ok, "Failed to connect to the test TCP relay server.");
uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE];
@ -228,7 +228,7 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem,
memcpy(handshake, sec_c->public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(handshake, sec_c->public_key, CRYPTO_PUBLIC_KEY_SIZE);
random_nonce(rng, handshake + CRYPTO_PUBLIC_KEY_SIZE); random_nonce(rng, handshake + CRYPTO_PUBLIC_KEY_SIZE);
int ret = encrypt_data(tcp_server_public_key(tcp_s), f_secret_key, handshake + CRYPTO_PUBLIC_KEY_SIZE, handshake_plain, int ret = encrypt_data(mem, tcp_server_public_key(tcp_s), f_secret_key, handshake + CRYPTO_PUBLIC_KEY_SIZE, handshake_plain,
TCP_HANDSHAKE_PLAIN_SIZE, handshake + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); TCP_HANDSHAKE_PLAIN_SIZE, handshake + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), ck_assert_msg(ret == TCP_CLIENT_HANDSHAKE_SIZE - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE),
"Failed to encrypt the outgoing handshake."); "Failed to encrypt the outgoing handshake.");
@ -248,7 +248,7 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem,
uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE]; uint8_t response_plain[TCP_HANDSHAKE_PLAIN_SIZE];
ck_assert_msg(net_recv(sec_c->ns, logger, sock, response, TCP_SERVER_HANDSHAKE_SIZE, &localhost) == TCP_SERVER_HANDSHAKE_SIZE, ck_assert_msg(net_recv(sec_c->ns, logger, sock, response, TCP_SERVER_HANDSHAKE_SIZE, &localhost) == TCP_SERVER_HANDSHAKE_SIZE,
"Failed to receive server handshake response."); "Failed to receive server handshake response.");
ret = decrypt_data(tcp_server_public_key(tcp_s), f_secret_key, response, response + CRYPTO_NONCE_SIZE, ret = decrypt_data(mem, tcp_server_public_key(tcp_s), f_secret_key, response, response + CRYPTO_NONCE_SIZE,
TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, response_plain); TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, response_plain);
ck_assert_msg(ret == TCP_HANDSHAKE_PLAIN_SIZE, "Failed to decrypt server handshake response."); ck_assert_msg(ret == TCP_HANDSHAKE_PLAIN_SIZE, "Failed to decrypt server handshake response.");
encrypt_precompute(response_plain, t_secret_key, sec_c->shared_key); encrypt_precompute(response_plain, t_secret_key, sec_c->shared_key);
@ -271,7 +271,7 @@ static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP
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->mem, con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
if ((unsigned int)len != (packet_size - sizeof(uint16_t))) { if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
return -1; return -1;
@ -296,7 +296,7 @@ static int read_packet_sec_tcp(const Logger *logger, struct sec_TCP_con *con, ui
int rlen = net_recv(con->ns, logger, con->sock, data, length, &localhost); int rlen = net_recv(con->ns, logger, con->sock, data, length, &localhost);
ck_assert_msg(rlen == length, "Did not receive packet of correct length. Wanted %i, instead got %i", length, rlen); ck_assert_msg(rlen == length, "Did not receive packet of correct length. Wanted %i, instead got %i", length, rlen);
rlen = decrypt_data_symmetric(con->shared_key, con->recv_nonce, data + 2, length - 2, data); rlen = decrypt_data_symmetric(con->mem, con->shared_key, con->recv_nonce, data + 2, length - 2, data);
ck_assert_msg(rlen != -1, "Failed to decrypt a received packet from the Relay server."); ck_assert_msg(rlen != -1, "Failed to decrypt a received packet from the Relay server.");
increment_nonce(con->recv_nonce); increment_nonce(con->recv_nonce);
return rlen; return rlen;
@ -312,7 +312,7 @@ static void test_some(void)
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);
Logger *logger = logger_new(); Logger *logger = logger_new(mem);
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
@ -506,7 +506,7 @@ static void test_client(void)
const Memory *mem = os_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Logger *logger = logger_new(); Logger *logger = logger_new(mem);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
@ -643,7 +643,7 @@ static void test_client_invalid(void)
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);
Logger *logger = logger_new(); Logger *logger = logger_new(mem);
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE]; uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
@ -721,7 +721,7 @@ static void test_tcp_connection(void)
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);
Logger *logger = logger_new(); Logger *logger = logger_new(mem);
tcp_data_callback_called = 0; tcp_data_callback_called = 0;
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
@ -834,7 +834,7 @@ static void test_tcp_connection2(void)
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);
Logger *logger = logger_new(); Logger *logger = logger_new(mem);
tcp_oobdata_callback_called = 0; tcp_oobdata_callback_called = 0;
tcp_data_callback_called = 0; tcp_data_callback_called = 0;

View File

@ -57,7 +57,7 @@ static void test_store_data(void)
const Memory *mem = os_memory(); const Memory *mem = os_memory();
ck_assert(mem != nullptr); ck_assert(mem != nullptr);
Logger *log = logger_new(); Logger *log = logger_new(mem);
ck_assert(log != nullptr); ck_assert(log != nullptr);
logger_callback_log(log, print_debug_logger, nullptr, nullptr); logger_callback_log(log, print_debug_logger, nullptr, nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);

View File

@ -80,6 +80,9 @@ static const uint8_t test_c[147] = {
static void test_known(void) static void test_known(void)
{ {
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
uint8_t c[147]; uint8_t c[147];
uint8_t m[131]; uint8_t m[131];
@ -88,12 +91,12 @@ static void test_known(void)
ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed");
ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed");
const uint16_t clen = encrypt_data(bobpk, alicesk, test_nonce, test_m, sizeof(test_m) / sizeof(uint8_t), c); const uint16_t clen = encrypt_data(mem, bobpk, alicesk, test_nonce, test_m, sizeof(test_m) / sizeof(uint8_t), c);
ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector");
ck_assert_msg(clen == sizeof(c) / sizeof(uint8_t), "wrong ciphertext length"); ck_assert_msg(clen == sizeof(c) / sizeof(uint8_t), "wrong ciphertext length");
const uint16_t mlen = decrypt_data(bobpk, alicesk, test_nonce, test_c, sizeof(test_c) / sizeof(uint8_t), m); const uint16_t mlen = decrypt_data(mem, bobpk, alicesk, test_nonce, test_c, sizeof(test_c) / sizeof(uint8_t), m);
ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector");
ck_assert_msg(mlen == sizeof(m) / sizeof(uint8_t), "wrong plaintext length"); ck_assert_msg(mlen == sizeof(m) / sizeof(uint8_t), "wrong plaintext length");
@ -101,6 +104,9 @@ static void test_known(void)
static void test_fast_known(void) static void test_fast_known(void)
{ {
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
uint8_t k[CRYPTO_SHARED_KEY_SIZE]; uint8_t k[CRYPTO_SHARED_KEY_SIZE];
uint8_t c[147]; uint8_t c[147];
uint8_t m[131]; uint8_t m[131];
@ -112,12 +118,12 @@ static void test_fast_known(void)
ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed"); ck_assert_msg(sizeof(test_c) == sizeof(c), "sanity check failed");
ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed"); ck_assert_msg(sizeof(test_m) == sizeof(m), "sanity check failed");
const uint16_t clen = encrypt_data_symmetric(k, test_nonce, test_m, sizeof(test_m) / sizeof(uint8_t), c); const uint16_t clen = encrypt_data_symmetric(mem, k, test_nonce, test_m, sizeof(test_m) / sizeof(uint8_t), c);
ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector"); ck_assert_msg(memcmp(test_c, c, sizeof(c)) == 0, "cyphertext doesn't match test vector");
ck_assert_msg(clen == sizeof(c) / sizeof(uint8_t), "wrong ciphertext length"); ck_assert_msg(clen == sizeof(c) / sizeof(uint8_t), "wrong ciphertext length");
const uint16_t mlen = decrypt_data_symmetric(k, test_nonce, test_c, sizeof(test_c) / sizeof(uint8_t), m); const uint16_t mlen = decrypt_data_symmetric(mem, k, test_nonce, test_c, sizeof(test_c) / sizeof(uint8_t), m);
ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector"); ck_assert_msg(memcmp(test_m, m, sizeof(m)) == 0, "decrypted text doesn't match test vector");
ck_assert_msg(mlen == sizeof(m) / sizeof(uint8_t), "wrong plaintext length"); ck_assert_msg(mlen == sizeof(m) / sizeof(uint8_t), "wrong plaintext length");
@ -125,6 +131,8 @@ static void test_fast_known(void)
static void test_endtoend(void) static void test_endtoend(void)
{ {
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
const Random *rng = os_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
@ -166,10 +174,10 @@ static void test_endtoend(void)
ck_assert_msg(memcmp(k1, k2, CRYPTO_SHARED_KEY_SIZE) == 0, "encrypt_precompute: bad"); ck_assert_msg(memcmp(k1, k2, CRYPTO_SHARED_KEY_SIZE) == 0, "encrypt_precompute: bad");
//Encrypt all four ways //Encrypt all four ways
const uint16_t c1len = encrypt_data(pk2, sk1, n, m, mlen, c1); const uint16_t c1len = encrypt_data(mem, pk2, sk1, n, m, mlen, c1);
const uint16_t c2len = encrypt_data(pk1, sk2, n, m, mlen, c2); const uint16_t c2len = encrypt_data(mem, pk1, sk2, n, m, mlen, c2);
const uint16_t c3len = encrypt_data_symmetric(k1, n, m, mlen, c3); const uint16_t c3len = encrypt_data_symmetric(mem, k1, n, m, mlen, c3);
const uint16_t c4len = encrypt_data_symmetric(k2, n, m, mlen, c4); const uint16_t c4len = encrypt_data_symmetric(mem, k2, n, m, mlen, c4);
ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ"); ck_assert_msg(c1len == c2len && c1len == c3len && c1len == c4len, "cyphertext lengths differ");
ck_assert_msg(c1len == mlen + (uint16_t)CRYPTO_MAC_SIZE, "wrong cyphertext length"); ck_assert_msg(c1len == mlen + (uint16_t)CRYPTO_MAC_SIZE, "wrong cyphertext length");
@ -177,10 +185,10 @@ static void test_endtoend(void)
&& memcmp(c1, c4, c1len) == 0, "crypertexts differ"); && memcmp(c1, c4, c1len) == 0, "crypertexts differ");
//Decrypt all four ways //Decrypt all four ways
const uint16_t m1len = decrypt_data(pk2, sk1, n, c1, c1len, m1); const uint16_t m1len = decrypt_data(mem, pk2, sk1, n, c1, c1len, m1);
const uint16_t m2len = decrypt_data(pk1, sk2, n, c1, c1len, m2); const uint16_t m2len = decrypt_data(mem, pk1, sk2, n, c1, c1len, m2);
const uint16_t m3len = decrypt_data_symmetric(k1, n, c1, c1len, m3); const uint16_t m3len = decrypt_data_symmetric(mem, k1, n, c1, c1len, m3);
const uint16_t m4len = decrypt_data_symmetric(k2, n, c1, c1len, m4); const uint16_t m4len = decrypt_data_symmetric(mem, k2, n, c1, c1len, m4);
ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ"); ck_assert_msg(m1len == m2len && m1len == m3len && m1len == m4len, "decrypted text lengths differ");
ck_assert_msg(m1len == mlen, "wrong decrypted text length"); ck_assert_msg(m1len == mlen, "wrong decrypted text length");
@ -192,6 +200,8 @@ static void test_endtoend(void)
static void test_large_data(void) static void test_large_data(void)
{ {
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
const Random *rng = os_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];
@ -216,13 +226,13 @@ static void test_large_data(void)
//Generate key //Generate key
rand_bytes(rng, k, CRYPTO_SHARED_KEY_SIZE); rand_bytes(rng, k, CRYPTO_SHARED_KEY_SIZE);
const uint16_t c1len = encrypt_data_symmetric(k, n, m1, m1_size, c1); const uint16_t c1len = encrypt_data_symmetric(mem, k, n, m1, m1_size, c1);
const uint16_t c2len = encrypt_data_symmetric(k, n, m2, m2_size, c2); const uint16_t c2len = encrypt_data_symmetric(mem, k, n, m2, m2_size, c2);
ck_assert_msg(c1len == m1_size + CRYPTO_MAC_SIZE, "could not encrypt"); ck_assert_msg(c1len == m1_size + CRYPTO_MAC_SIZE, "could not encrypt");
ck_assert_msg(c2len == m2_size + CRYPTO_MAC_SIZE, "could not encrypt"); ck_assert_msg(c2len == m2_size + CRYPTO_MAC_SIZE, "could not encrypt");
const uint16_t m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime); const uint16_t m1plen = decrypt_data_symmetric(mem, k, n, c1, c1len, m1prime);
ck_assert_msg(m1plen == m1_size, "decrypted text lengths differ"); ck_assert_msg(m1plen == m1_size, "decrypted text lengths differ");
ck_assert_msg(memcmp(m1prime, m1, m1_size) == 0, "decrypted texts differ"); ck_assert_msg(memcmp(m1prime, m1, m1_size) == 0, "decrypted texts differ");
@ -236,6 +246,8 @@ static void test_large_data(void)
static void test_large_data_symmetric(void) static void test_large_data_symmetric(void)
{ {
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
const Random *rng = os_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];
@ -256,10 +268,10 @@ static void test_large_data_symmetric(void)
//Generate key //Generate key
new_symmetric_key(rng, k); new_symmetric_key(rng, k);
const uint16_t c1len = encrypt_data_symmetric(k, n, m1, m1_size, c1); const uint16_t c1len = encrypt_data_symmetric(mem, k, n, m1, m1_size, c1);
ck_assert_msg(c1len == m1_size + CRYPTO_MAC_SIZE, "could not encrypt data"); ck_assert_msg(c1len == m1_size + CRYPTO_MAC_SIZE, "could not encrypt data");
const uint16_t m1plen = decrypt_data_symmetric(k, n, c1, c1len, m1prime); const uint16_t m1plen = decrypt_data_symmetric(mem, k, n, c1, c1len, m1prime);
ck_assert_msg(m1plen == m1_size, "decrypted text lengths differ"); ck_assert_msg(m1plen == m1_size, "decrypted text lengths differ");
ck_assert_msg(memcmp(m1prime, m1, m1_size) == 0, "decrypted texts differ"); ck_assert_msg(memcmp(m1prime, m1, m1_size) == 0, "decrypted texts differ");
@ -271,6 +283,8 @@ static void test_large_data_symmetric(void)
static void test_very_large_data(void) static void test_very_large_data(void)
{ {
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
const Random *rng = os_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
@ -287,7 +301,9 @@ static void test_very_large_data(void)
ck_assert(plain != nullptr); ck_assert(plain != nullptr);
ck_assert(encrypted != nullptr); ck_assert(encrypted != nullptr);
encrypt_data(pk, sk, nonce, plain, plain_size, encrypted); memset(plain, 0, plain_size);
encrypt_data(mem, pk, sk, nonce, plain, plain_size, encrypted);
free(encrypted); free(encrypted);
free(plain); free(plain);

View File

@ -3,8 +3,6 @@
#include <string.h> #include <string.h>
#include <sys/types.h> #include <sys/types.h>
#include <sodium.h>
#include "../testing/misc_tools.h" #include "../testing/misc_tools.h"
#include "../toxcore/ccompat.h" #include "../toxcore/ccompat.h"
#include "../toxcore/crypto_core.h" #include "../toxcore/crypto_core.h"
@ -14,13 +12,10 @@
#include "check_compat.h" #include "check_compat.h"
static unsigned char test_salt[TOX_PASS_SALT_LENGTH] = {0xB1, 0xC2, 0x09, 0xEE, 0x50, 0x6C, 0xF0, 0x20, 0xC4, 0xD6, 0xEB, 0xC0, 0x44, 0x51, 0x3B, 0x60, 0x4B, 0x39, 0x4A, 0xCF, 0x09, 0x53, 0x4F, 0xEA, 0x08, 0x41, 0xFA, 0xCA, 0x66, 0xD2, 0x68, 0x7F}; static unsigned char test_salt[TOX_PASS_SALT_LENGTH] = {0xB1, 0xC2, 0x09, 0xEE, 0x50, 0x6C, 0xF0, 0x20, 0xC4, 0xD6, 0xEB, 0xC0, 0x44, 0x51, 0x3B, 0x60, 0x4B, 0x39, 0x4A, 0xCF, 0x09, 0x53, 0x4F, 0xEA, 0x08, 0x41, 0xFA, 0xCA, 0x66, 0xD2, 0x68, 0x7F};
static unsigned char known_key[TOX_PASS_KEY_LENGTH] = {0x29, 0x36, 0x1c, 0x9e, 0x65, 0xbb, 0x46, 0x8b, 0xde, 0xa1, 0xac, 0xf, 0xd5, 0x11, 0x81, 0xc8, 0x29, 0x28, 0x17, 0x23, 0xa6, 0xc3, 0x6b, 0x77, 0x2e, 0xd7, 0xd3, 0x10, 0xeb, 0xd2, 0xf7, 0xc8}; static unsigned char known_key[CRYPTO_SHARED_KEY_SIZE] = {0x7a, 0xfa, 0x95, 0x45, 0x36, 0x8a, 0xa2, 0x5c, 0x40, 0xfd, 0xc0, 0xe2, 0x35, 0x8, 0x7, 0x88, 0xfa, 0xf9, 0x37, 0x86, 0xeb, 0xff, 0x50, 0x4f, 0x3, 0xe2, 0xf6, 0xd9, 0xef, 0x9, 0x17, 0x1};
static const char *pw = "hunter2"; static const char *pw = "hunter2";
static unsigned int pwlen = 7; static unsigned int pwlen = 7;
static unsigned char known_key2[CRYPTO_SHARED_KEY_SIZE] = {0x7a, 0xfa, 0x95, 0x45, 0x36, 0x8a, 0xa2, 0x5c, 0x40, 0xfd, 0xc0, 0xe2, 0x35, 0x8, 0x7, 0x88, 0xfa, 0xf9, 0x37, 0x86, 0xeb, 0xff, 0x50, 0x4f, 0x3, 0xe2, 0xf6, 0xd9, 0xef, 0x9, 0x17, 0x1};
// same as above, except standard opslimit instead of extra ops limit for test_known_kdf, and hash pw before kdf for compat
/* cause I'm shameless */ /* cause I'm shameless */
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(Tox *m, const uint8_t *public_key, const uint8_t *data, size_t length, void *userdata)
{ {
@ -33,20 +28,6 @@ static void accept_friend_request(Tox *m, const uint8_t *public_key, const uint8
} }
} }
static void test_known_kdf(void)
{
unsigned char out[CRYPTO_SHARED_KEY_SIZE];
int16_t res = crypto_pwhash_scryptsalsa208sha256(out,
CRYPTO_SHARED_KEY_SIZE,
pw,
pwlen,
test_salt,
crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE * 8,
crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE);
ck_assert_msg(res != -1, "crypto function failed");
ck_assert_msg(memcmp(out, known_key, CRYPTO_SHARED_KEY_SIZE) == 0, "derived key is wrong");
}
static void test_save_friend(void) static void test_save_friend(void)
{ {
Tox *tox1 = tox_new_log(nullptr, nullptr, nullptr); Tox *tox1 = tox_new_log(nullptr, nullptr, nullptr);
@ -101,7 +82,7 @@ static void test_save_friend(void)
Tox_Pass_Key *key = tox_pass_key_derive((const uint8_t *)"123qweasdzxc", 12, &keyerr); Tox_Pass_Key *key = tox_pass_key_derive((const uint8_t *)"123qweasdzxc", 12, &keyerr);
ck_assert_msg(key != nullptr, "pass key allocation failure"); ck_assert_msg(key != nullptr, "pass key allocation failure");
memcpy((uint8_t *)key, test_salt, TOX_PASS_SALT_LENGTH); memcpy((uint8_t *)key, test_salt, TOX_PASS_SALT_LENGTH);
memcpy((uint8_t *)key + TOX_PASS_SALT_LENGTH, known_key2, TOX_PASS_KEY_LENGTH); memcpy((uint8_t *)key + TOX_PASS_SALT_LENGTH, known_key, TOX_PASS_KEY_LENGTH);
size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH; size2 = size + TOX_PASS_ENCRYPTION_EXTRA_LENGTH;
uint8_t *encdata2 = (uint8_t *)malloc(size2); uint8_t *encdata2 = (uint8_t *)malloc(size2);
ck_assert(encdata2 != nullptr); ck_assert(encdata2 != nullptr);
@ -224,7 +205,6 @@ static void test_keys(void)
int main(void) int main(void)
{ {
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);
test_known_kdf();
test_save_friend(); test_save_friend();
test_keys(); test_keys();

View File

@ -112,7 +112,7 @@ static Forwarding_Subtox *new_forwarding_subtox(const Memory *mem, bool no_udp,
Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox)); Forwarding_Subtox *subtox = (Forwarding_Subtox *)calloc(1, sizeof(Forwarding_Subtox));
ck_assert(subtox != nullptr); ck_assert(subtox != nullptr);
subtox->log = logger_new(); subtox->log = logger_new(mem);
ck_assert(subtox->log != nullptr); ck_assert(subtox->log != nullptr);
logger_callback_log(subtox->log, print_debug_logger, nullptr, index); logger_callback_log(subtox->log, print_debug_logger, nullptr, index);
subtox->mono_time = mono_time_new(mem, nullptr, nullptr); subtox->mono_time = mono_time_new(mem, nullptr, nullptr);

View File

@ -10,44 +10,57 @@
#include "../toxcore/tox.h" #include "../toxcore/tox.h"
#include "../toxcore/util.h" #include "../toxcore/util.h"
#include "../testing/misc_tools.h" #include "../testing/misc_tools.h"
#include "auto_test_support.h" #include "auto_test_support.h"
#include "check_compat.h" #include "check_compat.h"
#define FR_MESSAGE "Gentoo" #define REQUEST_MESSAGE "Hello, I would like to be your friend. Please respond."
static void accept_friend_request(const Tox_Event_Friend_Request *event, typedef struct Callback_Data {
void *userdata) Tox *tox1; // request sender
Tox *tox2; // request receiver
uint8_t message[TOX_MAX_FRIEND_REQUEST_LENGTH];
uint16_t length;
} Callback_Data;
static void accept_friend_request(const Tox_Event_Friend_Request *event, void *userdata)
{ {
Tox *state_tox = (Tox *)userdata; Callback_Data *cb_data = (Callback_Data *)userdata;
const uint8_t *public_key = tox_event_friend_request_get_public_key(event); 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 uint8_t *data = tox_event_friend_request_get_message(event);
const size_t length = tox_event_friend_request_get_message_length(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 == cb_data->length && memcmp(cb_data->message, data, cb_data->length) == 0,
"unexpected friend request message"); "unexpected friend request message");
tox_friend_add_norequest(state_tox, public_key, nullptr);
fprintf(stderr, "Tox2 accepts friend request.\n");
Tox_Err_Friend_Add err;
tox_friend_add_norequest(cb_data->tox2, public_key, &err);
ck_assert_msg(err == TOX_ERR_FRIEND_ADD_OK, "tox_friend_add_norequest failed: %d", err);
} }
static void iterate2_wait(const Tox_Dispatch *dispatch, Tox *tox1, Tox *tox2) static void iterate2_wait(const Tox_Dispatch *dispatch, Callback_Data *cb_data)
{ {
Tox_Err_Events_Iterate err; Tox_Err_Events_Iterate err;
Tox_Events *events; Tox_Events *events;
events = tox_events_iterate(tox1, true, &err); events = tox_events_iterate(cb_data->tox1, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK); ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, tox1); tox_dispatch_invoke(dispatch, events, cb_data);
tox_events_free(events); tox_events_free(events);
events = tox_events_iterate(tox2, true, &err); events = tox_events_iterate(cb_data->tox2, true, &err);
ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK); ck_assert(err == TOX_ERR_EVENTS_ITERATE_OK);
tox_dispatch_invoke(dispatch, events, tox2); tox_dispatch_invoke(dispatch, events, cb_data);
tox_events_free(events); tox_events_free(events);
c_sleep(ITERATION_INTERVAL); c_sleep(ITERATION_INTERVAL);
} }
static void test_friend_request(void) static void test_friend_request(const uint8_t *message, uint16_t length)
{ {
printf("Initialising 2 toxes.\n"); printf("Initialising 2 toxes.\n");
uint32_t index[] = { 1, 2 }; uint32_t index[] = { 1, 2 };
@ -60,7 +73,7 @@ static void test_friend_request(void)
tox_events_init(tox1); tox_events_init(tox1);
tox_events_init(tox2); 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);
const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr); const uint16_t dht_port = tox_self_get_udp_port(tox1, nullptr);
@ -70,25 +83,36 @@ static void test_friend_request(void)
Tox_Dispatch *dispatch = tox_dispatch_new(nullptr); Tox_Dispatch *dispatch = tox_dispatch_new(nullptr);
ck_assert(dispatch != nullptr); ck_assert(dispatch != nullptr);
Callback_Data cb_data = {nullptr};
cb_data.tox1 = tox1;
cb_data.tox2 = tox2;
ck_assert(length <= sizeof(cb_data.message));
memcpy(cb_data.message, message, length);
cb_data.length = length;
do { do {
iterate2_wait(dispatch, tox1, tox2); iterate2_wait(dispatch, &cb_data);
} 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);
printf("Toxes are online, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time)); printf("Toxes are online, took %lu seconds.\n", (unsigned long)(time(nullptr) - cur_time));
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. Waiting for Tox2 to accept.\n");
tox_events_callback_friend_request(dispatch, 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);
const uint32_t test = tox_friend_add(tox1, address, (const uint8_t *)FR_MESSAGE, sizeof(FR_MESSAGE), nullptr); Tox_Err_Friend_Add err;
const uint32_t test = tox_friend_add(tox1, address, message, length, &err);
ck_assert_msg(err == TOX_ERR_FRIEND_ADD_OK, "tox_friend_add failed: %d", err);
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 {
iterate2_wait(dispatch, tox1, tox2); iterate2_wait(dispatch, &cb_data);
} 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);
@ -104,6 +128,20 @@ int main(void)
{ {
setvbuf(stdout, nullptr, _IONBF, 0); setvbuf(stdout, nullptr, _IONBF, 0);
test_friend_request(); fprintf(stderr, "Testing friend request with the smallest allowed message length.\n");
test_friend_request((const uint8_t *)"a", 1);
fprintf(stderr, "Testing friend request with an average sized message length.\n");
test_friend_request((const uint8_t *)REQUEST_MESSAGE, sizeof(REQUEST_MESSAGE) - 1);
uint8_t long_message[TOX_MAX_FRIEND_REQUEST_LENGTH];
for (uint16_t i = 0; i < sizeof(long_message); ++i) {
long_message[i] = 'a';
}
fprintf(stderr, "Testing friend request with the largest allowed message length.\n");
test_friend_request(long_message, sizeof(long_message));
return 0; return 0;
} }

View File

@ -23,12 +23,15 @@ static void test_addr_resolv_localhost(void)
const Network *ns = os_network(); const Network *ns = os_network();
ck_assert(ns != nullptr); ck_assert(ns != nullptr);
const Memory *mem = os_memory();
ck_assert(mem != nullptr);
const char localhost[] = "localhost"; const char localhost[] = "localhost";
IP ip; IP ip;
ip_init(&ip, 0); // ipv6enabled = 0 ip_init(&ip, 0); // ipv6enabled = 0
bool res = addr_resolve_or_parse_ip(ns, localhost, &ip, nullptr); bool res = addr_resolve_or_parse_ip(ns, mem, localhost, &ip, nullptr, true);
int error = net_error(); int error = net_error();
char *strerror = net_new_strerror(error); char *strerror = net_new_strerror(error);
@ -42,14 +45,14 @@ static void test_addr_resolv_localhost(void)
net_ip_ntoa(&ip, &ip_str)); net_ip_ntoa(&ip, &ip_str));
ip_init(&ip, 1); // ipv6enabled = 1 ip_init(&ip, 1); // ipv6enabled = 1
res = addr_resolve_or_parse_ip(ns, localhost, &ip, nullptr); res = addr_resolve_or_parse_ip(ns, mem, localhost, &ip, nullptr, true);
#if USE_IPV6 #if USE_IPV6
int localhost_split = 0; int localhost_split = 0;
if (!net_family_is_ipv6(ip.family)) { if (!net_family_is_ipv6(ip.family)) {
res = addr_resolve_or_parse_ip(ns, "ip6-localhost", &ip, nullptr); res = addr_resolve_or_parse_ip(ns, mem, "ip6-localhost", &ip, nullptr, true);
localhost_split = 1; localhost_split = 1;
} }
@ -75,7 +78,7 @@ static void test_addr_resolv_localhost(void)
ip.family = net_family_unspec(); ip.family = net_family_unspec();
IP extra; IP extra;
ip_reset(&extra); ip_reset(&extra);
res = addr_resolve_or_parse_ip(ns, localhost, &ip, &extra); res = addr_resolve_or_parse_ip(ns, mem, localhost, &ip, &extra, true);
error = net_error(); error = net_error();
strerror = net_new_strerror(error); strerror = net_new_strerror(error);
ck_assert_msg(res, "Resolver failed: %d, %s", error, strerror); ck_assert_msg(res, "Resolver failed: %d, %s", error, strerror);

View File

@ -109,7 +109,7 @@ static int handle_test_3(void *object, const IP_Port *source, const uint8_t *pac
#if 0 #if 0
print_client_id(packet, length); print_client_id(packet, length);
#endif #endif
int len = decrypt_data(test_3_pub_key, dht_get_self_secret_key(onion->dht), int len = decrypt_data(onion->mem, test_3_pub_key, dht_get_self_secret_key(onion->dht),
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
2 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain); 2 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain);
@ -144,7 +144,7 @@ static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t
#if 0 #if 0
print_client_id(packet, length); print_client_id(packet, length);
#endif #endif
int len = decrypt_data(test_3_pub_key, dht_get_self_secret_key(onion->dht), int len = decrypt_data(onion->mem, test_3_pub_key, dht_get_self_secret_key(onion->dht),
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE, packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
1 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain); 1 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain);
@ -182,7 +182,7 @@ static int handle_test_4(void *object, const IP_Port *source, const uint8_t *pac
return 1; return 1;
} }
int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, dht_get_self_secret_key(onion->dht), packet + 1, int len = decrypt_data(onion->mem, packet + 1 + CRYPTO_NONCE_SIZE, dht_get_self_secret_key(onion->dht), packet + 1,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, sizeof("Install gentoo") + CRYPTO_MAC_SIZE, plain); packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, sizeof("Install gentoo") + CRYPTO_MAC_SIZE, plain);
if (len == -1) { if (len == -1) {
@ -202,10 +202,10 @@ static int handle_test_4(void *object, const IP_Port *source, const uint8_t *pac
* Use Onion_Path path to send data of length to dest. * Use Onion_Path path to send data of length to dest.
* Maximum length of data is ONION_MAX_DATA_SIZE. * Maximum length of data is ONION_MAX_DATA_SIZE.
*/ */
static void send_onion_packet(const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length) static void send_onion_packet(const Networking_Core *net, const Memory *mem, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length)
{ {
uint8_t packet[ONION_MAX_PACKET_SIZE]; uint8_t packet[ONION_MAX_PACKET_SIZE];
const int len = create_onion_packet(rng, packet, sizeof(packet), path, dest, data, length); const int len = create_onion_packet(mem, rng, packet, sizeof(packet), path, dest, data, length);
ck_assert_msg(len != -1, "failed to create onion packet"); ck_assert_msg(len != -1, "failed to create onion packet");
ck_assert_msg(sendpacket(net, &path->ip_port1, packet, len) == len, "failed to send onion packet"); ck_assert_msg(sendpacket(net, &path->ip_port1, packet, len) == len, "failed to send onion packet");
} }
@ -228,9 +228,9 @@ static void test_basic(void)
const Random *rng = os_random(); const Random *rng = os_random();
ck_assert(rng != nullptr); ck_assert(rng != nullptr);
Logger *log1 = logger_new(); Logger *log1 = logger_new(mem);
logger_callback_log(log1, print_debug_logger, nullptr, &index[0]); logger_callback_log(log1, print_debug_logger, nullptr, &index[0]);
Logger *log2 = logger_new(); Logger *log2 = logger_new(mem);
logger_callback_log(log2, print_debug_logger, nullptr, &index[1]); logger_callback_log(log2, print_debug_logger, nullptr, &index[1]);
Mono_Time *mono_time1 = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time1 = mono_time_new(mem, nullptr, nullptr);
@ -264,7 +264,7 @@ static void test_basic(void)
nodes[3] = n2; nodes[3] = n2;
Onion_Path path; Onion_Path path;
create_onion_path(rng, onion1->dht, &path, nodes); create_onion_path(rng, onion1->dht, &path, nodes);
send_onion_packet(onion1->net, rng, &path, &nodes[3].ip_port, req_packet, sizeof(req_packet)); send_onion_packet(onion1->net, onion1->mem, rng, &path, &nodes[3].ip_port, req_packet, sizeof(req_packet));
handled_test_1 = 0; handled_test_1 = 0;
@ -291,7 +291,7 @@ static void test_basic(void)
uint64_t s; uint64_t s;
memcpy(&s, sb_data, sizeof(uint64_t)); memcpy(&s, sb_data, sizeof(uint64_t));
memcpy(test_3_pub_key, nodes[3].public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(test_3_pub_key, nodes[3].public_key, CRYPTO_PUBLIC_KEY_SIZE);
int ret = send_announce_request(log1, onion1->net, rng, &path, &nodes[3], int ret = send_announce_request(log1, onion1->mem, onion1->net, rng, &path, &nodes[3],
dht_get_self_public_key(onion1->dht), dht_get_self_public_key(onion1->dht),
dht_get_self_secret_key(onion1->dht), dht_get_self_secret_key(onion1->dht),
zeroes, zeroes,
@ -313,7 +313,7 @@ static void test_basic(void)
memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE); memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE);
onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2)); onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2));
networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1); networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1);
send_announce_request(log1, onion1->net, rng, &path, &nodes[3], send_announce_request(log1, onion1->mem, onion1->net, rng, &path, &nodes[3],
dht_get_self_public_key(onion1->dht), dht_get_self_public_key(onion1->dht),
dht_get_self_secret_key(onion1->dht), dht_get_self_secret_key(onion1->dht),
test_3_ping_id, test_3_ping_id,
@ -329,7 +329,7 @@ static void test_basic(void)
CRYPTO_PUBLIC_KEY_SIZE) != 0); CRYPTO_PUBLIC_KEY_SIZE) != 0);
c_sleep(1000); c_sleep(1000);
Logger *log3 = logger_new(); Logger *log3 = logger_new(mem);
logger_callback_log(log3, print_debug_logger, nullptr, &index[2]); logger_callback_log(log3, print_debug_logger, nullptr, &index[2]);
Mono_Time *mono_time3 = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time3 = mono_time_new(mem, nullptr, nullptr);
@ -338,7 +338,7 @@ static void test_basic(void)
ck_assert_msg((onion3 != nullptr), "Onion failed initializing."); ck_assert_msg((onion3 != nullptr), "Onion failed initializing.");
random_nonce(rng, nonce); random_nonce(rng, nonce);
ret = send_data_request(log3, onion3->net, rng, &path, &nodes[3].ip_port, ret = send_data_request(log3, onion3->mem, onion3->net, rng, &path, &nodes[3].ip_port,
dht_get_self_public_key(onion1->dht), dht_get_self_public_key(onion1->dht),
dht_get_self_public_key(onion1->dht), dht_get_self_public_key(onion1->dht),
nonce, (const uint8_t *)"Install gentoo", sizeof("Install gentoo")); nonce, (const uint8_t *)"Install gentoo", sizeof("Install gentoo"));
@ -412,7 +412,7 @@ static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, u
return nullptr; return nullptr;
} }
on->log = logger_new(); on->log = logger_new(mem);
if (!on->log) { if (!on->log) {
free(on); free(on);

View File

@ -1,15 +1,25 @@
pool: pool:
vmImage: "windows-2019" vmImage: "windows-2019"
jobs: jobs:
- job: "windows_msvc_conan" - job: "vcpkg"
strategy: strategy:
matrix: matrix:
static: static:
conan.shared: "False" ENABLE_STATIC: "ON"
ENABLE_SHARED: "OFF"
shared: shared:
conan.shared: "True" ENABLE_STATIC: "OFF"
ENABLE_SHARED: "ON"
steps: steps:
- bash: python -m pip install conan==1.59.0 - task: Cache@2
inputs:
key: "vcpkg"
path: "_build/vcpkg_installed"
- bash: git submodule update --init --recursive - bash: git submodule update --init --recursive
- bash: conan install -if _build -o with_tests=True -o shared=$(conan.shared) . - bash: cmake --preset windows-default -DENABLE_STATIC=$(ENABLE_STATIC) -DENABLE_SHARED=$(ENABLE_SHARED)
- bash: CONAN_CPU_COUNT=50 CTEST_OUTPUT_ON_FAILURE=1 conan build -bf _build -if _build . || true env:
VCPKG_ROOT: "C:/vcpkg"
VCPKG_DEFAULT_TRIPLET: "x64-windows"
- bash: cmake --build _build --config Release
- bash: ctest --preset windows-default -C Release --parallel 50 ||
ctest --preset windows-default -C Release --rerun-failed --output-on-failure

View File

@ -12,14 +12,20 @@ find_library(SOCKET_LIBRARIES socket)
find_package(pthreads QUIET) find_package(pthreads QUIET)
if(NOT TARGET PThreads4W::PThreads4W) if(NOT TARGET PThreads4W::PThreads4W)
find_package(pthreads4w QUIET)
endif()
if(NOT TARGET pthreads4w::pthreads4w)
set(THREADS_PREFER_PTHREAD_FLAG ON) set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED) find_package(Threads REQUIRED)
endif() endif()
# For toxcore. # For toxcore.
pkg_search_module(LIBSODIUM libsodium IMPORTED_TARGET REQUIRED) pkg_search_module(LIBSODIUM libsodium IMPORTED_TARGET)
if(MSVC) if(MSVC)
find_package(unofficial-sodium REQUIRED) find_package(libsodium)
if(NOT TARGET libsodium::libsodium)
find_package(unofficial-sodium REQUIRED)
endif()
endif() endif()
# For toxav. # For toxav.
@ -27,10 +33,23 @@ pkg_search_module(OPUS opus IMPORTED_TARGET)
if(NOT OPUS_FOUND) if(NOT OPUS_FOUND)
pkg_search_module(OPUS Opus IMPORTED_TARGET) pkg_search_module(OPUS Opus IMPORTED_TARGET)
endif() endif()
if(NOT OPUS_FOUND)
find_package(Opus)
if(TARGET Opus::opus)
set(OPUS_FOUND TRUE)
endif()
endif()
pkg_search_module(VPX vpx IMPORTED_TARGET) pkg_search_module(VPX vpx IMPORTED_TARGET)
if(NOT VPX_FOUND) if(NOT VPX_FOUND)
pkg_search_module(VPX libvpx IMPORTED_TARGET) pkg_search_module(VPX libvpx IMPORTED_TARGET)
endif() endif()
if(NOT VPX_FOUND)
find_package(libvpx)
if(TARGET libvpx::libvpx)
set(VPX_FOUND TRUE)
endif()
endif()
# For tox-bootstrapd. # For tox-bootstrapd.
pkg_search_module(LIBCONFIG libconfig IMPORTED_TARGET) pkg_search_module(LIBCONFIG libconfig IMPORTED_TARGET)

View File

@ -1,87 +0,0 @@
# pylint: disable=not-callable
import os
import re
from conans import CMake
from conans import ConanFile
from conans.tools import collect_libs
from conans.tools import load
class ToxConan(ConanFile):
name = "c-toxcore"
url = "https://tox.chat"
description = "The future of online communications."
license = "GPL-3.0-only"
settings = "os", "compiler", "build_type", "arch"
requires = "libsodium/1.0.18", "opus/1.3.1", "libvpx/1.9.0"
generators = "cmake_find_package"
scm = {"type": "git", "url": "auto", "revision": "auto"}
options = {
"shared": [True, False],
"with_tests": [True, False],
}
default_options = {
"shared": False,
"with_tests": False,
}
_cmake = None
def _create_cmake(self):
if self._cmake is not None:
return self._cmake
self._cmake = CMake(self)
self._cmake.definitions["AUTOTEST"] = self.options.with_tests
self._cmake.definitions["BUILD_MISC_TESTS"] = self.options.with_tests
self._cmake.definitions["TEST_TIMEOUT_SECONDS"] = "300"
self._cmake.definitions[
"CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS"] = self.options.shared
self._cmake.definitions["ENABLE_SHARED"] = self.options.shared
self._cmake.definitions["ENABLE_STATIC"] = not self.options.shared
self._cmake.definitions["MUST_BUILD_TOXAV"] = True
if self.settings.compiler == "Visual Studio":
self._cmake.definitions["MSVC_STATIC_SODIUM"] = True
self._cmake.definitions[
"FLAT_OUTPUT_STRUCTURE"] = self.options.shared
self._cmake.configure()
return self._cmake
def set_version(self):
content = load(os.path.join(self.recipe_folder, "CMakeLists.txt"))
version_major = re.search(r"set\(PROJECT_VERSION_MAJOR \"(.*)\"\)",
content).group(1)
version_minor = re.search(r"set\(PROJECT_VERSION_MINOR \"(.*)\"\)",
content).group(1)
version_patch = re.search(r"set\(PROJECT_VERSION_PATCH \"(.*)\"\)",
content).group(1)
self.version = "%s.%s.%s" % (
version_major.strip(),
version_minor.strip(),
version_patch.strip(),
)
def requirements(self):
if self.settings.os == "Windows":
self.requires("pthreads4w/3.0.0")
def build(self):
cmake = self._create_cmake()
cmake.build()
if self.options.with_tests:
cmake.test(output_on_failure=True)
def package(self):
cmake = self._create_cmake()
cmake.install()
def package_info(self):
self.cpp_info.libs = collect_libs(self)
if self.settings.os == "Windows":
self.cpp_info.system_libs = ["Ws2_32", "Iphlpapi"]

View File

@ -2,7 +2,7 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ([2.65]) AC_PREREQ([2.65])
AC_INIT([tox], [0.2.19]) AC_INIT([tox], [0.2.20])
AC_CONFIG_AUX_DIR(configure_aux) AC_CONFIG_AUX_DIR(configure_aux)
AC_CONFIG_SRCDIR([toxcore/net_crypto.c]) AC_CONFIG_SRCDIR([toxcore/net_crypto.c])
AM_INIT_AUTOMAKE([foreign 1.10 -Wall -Werror subdir-objects tar-ustar]) AM_INIT_AUTOMAKE([foreign 1.10 -Wall -Werror subdir-objects tar-ustar])

View File

@ -21,10 +21,15 @@ cc_binary(
"//c-toxcore/toxcore:Messenger", "//c-toxcore/toxcore:Messenger",
"//c-toxcore/toxcore:TCP_server", "//c-toxcore/toxcore:TCP_server",
"//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:ccompat",
"//c-toxcore/toxcore:crypto_core",
"//c-toxcore/toxcore:forwarding",
"//c-toxcore/toxcore:group_announce",
"//c-toxcore/toxcore:group_onion_announce", "//c-toxcore/toxcore:group_onion_announce",
"//c-toxcore/toxcore:logger", "//c-toxcore/toxcore:logger",
"//c-toxcore/toxcore:mem",
"//c-toxcore/toxcore:mono_time", "//c-toxcore/toxcore:mono_time",
"//c-toxcore/toxcore:network", "//c-toxcore/toxcore:network",
"//c-toxcore/toxcore:onion",
"//c-toxcore/toxcore:onion_announce", "//c-toxcore/toxcore:onion_announce",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
], ],

View File

@ -144,16 +144,16 @@ int main(int argc, char *argv[])
IP ip; IP ip;
ip_init(&ip, ipv6enabled); ip_init(&ip, ipv6enabled);
Logger *logger = logger_new(); const Random *rng = os_random();
const Network *ns = os_network();
const Memory *mem = os_memory();
Logger *logger = logger_new(mem);
if (MIN_LOGGER_LEVEL <= LOGGER_LEVEL_DEBUG) { if (MIN_LOGGER_LEVEL <= LOGGER_LEVEL_DEBUG) {
logger_callback_log(logger, print_log, nullptr, nullptr); logger_callback_log(logger, print_log, nullptr, nullptr);
} }
const Random *rng = os_random();
const Network *ns = os_network();
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;
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);
@ -228,9 +228,12 @@ 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);
// TODO(iphydf): Maybe disable and only use IP addresses?
const bool dns_enabled = true;
uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]); uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]);
const bool 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, dns_enabled, port, bootstrap_key);
free(bootstrap_key); free(bootstrap_key);
if (!res) { if (!res) {

View File

@ -15,7 +15,7 @@ CPPFLAGS+=("-Itoxav")
CPPFLAGS+=("-Itoxencryptsave") CPPFLAGS+=("-Itoxencryptsave")
CPPFLAGS+=("-Ithird_party/cmp") CPPFLAGS+=("-Ithird_party/cmp")
LDFLAGS=("-lopus" "-lsodium" "-lvpx" "-lpthread" "-lconfig" "-lgmock" "-lgtest") LDFLAGS=("-lopus" "-lsodium" "-lvpx" "-lpthread" "-lconfig" "-lgmock" "-lgtest" "-lbenchmark")
LDFLAGS+=("-fuse-ld=gold") LDFLAGS+=("-fuse-ld=gold")
LDFLAGS+=("-Wl,--detect-odr-violations") LDFLAGS+=("-Wl,--detect-odr-violations")
LDFLAGS+=("-Wl,--warn-common") LDFLAGS+=("-Wl,--warn-common")
@ -27,7 +27,7 @@ put() {
if [ "$SKIP_LINES" = "" ]; then if [ "$SKIP_LINES" = "" ]; then
echo "#line 1 \"$1\"" >>amalgamation.cc echo "#line 1 \"$1\"" >>amalgamation.cc
fi fi
cat "$1" >>amalgamation.cc grep -v '^BENCHMARK_MAIN' "$1" >>amalgamation.cc
} }
putmain() { putmain() {

View File

@ -6,16 +6,24 @@ cc_binary(
"src/*.c", "src/*.c",
"src/*.h", "src/*.h",
]), ]),
tags = ["no-windows"],
deps = [ deps = [
"//c-toxcore/other:bootstrap_node_packets", "//c-toxcore/other:bootstrap_node_packets",
"//c-toxcore/toxcore:DHT", "//c-toxcore/toxcore:DHT",
"//c-toxcore/toxcore:LAN_discovery", "//c-toxcore/toxcore:LAN_discovery",
"//c-toxcore/toxcore:TCP_server", "//c-toxcore/toxcore:TCP_server",
"//c-toxcore/toxcore:announce", "//c-toxcore/toxcore:announce",
"//c-toxcore/toxcore:attributes",
"//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:ccompat",
"//c-toxcore/toxcore:crypto_core",
"//c-toxcore/toxcore:forwarding",
"//c-toxcore/toxcore:group_announce",
"//c-toxcore/toxcore:group_onion_announce", "//c-toxcore/toxcore:group_onion_announce",
"//c-toxcore/toxcore:logger", "//c-toxcore/toxcore:logger",
"//c-toxcore/toxcore:mem",
"//c-toxcore/toxcore:mono_time", "//c-toxcore/toxcore:mono_time",
"//c-toxcore/toxcore:network",
"//c-toxcore/toxcore:onion",
"//c-toxcore/toxcore:onion_announce", "//c-toxcore/toxcore:onion_announce",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"@libconfig", "@libconfig",

View File

@ -1 +1 @@
e96f03a89051c5df12c28d0d6941184da2b92742d248bd4c57d31189a0052844 /usr/local/bin/tox-bootstrapd 9ec2993a28988bd147bf8f4f21a824c2fc5dbf7255e391b3ce517d337ebce5c1 /usr/local/bin/tox-bootstrapd

View File

@ -390,6 +390,9 @@ bool bootstrap_from_config(const char *cfg_file_path, DHT *dht, bool enable_ipv6
bool address_resolved; bool address_resolved;
uint8_t *bs_public_key_bin; uint8_t *bs_public_key_bin;
// TODO(iphydf): Maybe disable it and only use IP addresses?
const bool dns_enabled = true;
node = config_setting_get_elem(node_list, 0); node = config_setting_get_elem(node_list, 0);
if (node == nullptr) { if (node == nullptr) {
@ -429,7 +432,7 @@ bool bootstrap_from_config(const char *cfg_file_path, DHT *dht, bool enable_ipv6
} }
bs_public_key_bin = bootstrap_hex_string_to_bin(bs_public_key); bs_public_key_bin = bootstrap_hex_string_to_bin(bs_public_key);
address_resolved = dht_bootstrap_from_address(dht, bs_address, enable_ipv6, net_htons(bs_port), address_resolved = dht_bootstrap_from_address(dht, bs_address, enable_ipv6, dns_enabled, net_htons(bs_port),
bs_public_key_bin); bs_public_key_bin);
free(bs_public_key_bin); free(bs_public_key_bin);

View File

@ -283,16 +283,17 @@ int main(int argc, char *argv[])
IP ip; IP ip;
ip_init(&ip, enable_ipv6); ip_init(&ip, enable_ipv6);
Logger *logger = logger_new(); const Memory *mem = os_memory();
const Random *rng = os_random();
const Network *ns = os_network();
Logger *logger = logger_new(mem);
if (MIN_LOGGER_LEVEL <= LOGGER_LEVEL_DEBUG) { if (MIN_LOGGER_LEVEL <= LOGGER_LEVEL_DEBUG) {
logger_callback_log(logger, toxcore_logger_callback, nullptr, nullptr); logger_callback_log(logger, toxcore_logger_callback, nullptr, nullptr);
} }
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 = os_memory();
const Random *rng = os_random();
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) {

View File

@ -1,18 +1,18 @@
################################################ ################################################
# cmake-asan # cmake-asan
FROM ubuntu:20.04 FROM ubuntu:24.04
RUN apt-get update && \ RUN apt-get update && \
DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \ DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \
clang \ clang \
cmake \ cmake \
libclang-rt-dev \
libconfig-dev \ libconfig-dev \
libgmock-dev \ libgmock-dev \
libgtest-dev \ libgtest-dev \
libopus-dev \ libopus-dev \
libsodium-dev \ libsodium-dev \
libvpx-dev \ libvpx-dev \
llvm-dev \
ninja-build \ ninja-build \
pkg-config \ pkg-config \
&& apt-get clean \ && apt-get clean \
@ -22,8 +22,8 @@ COPY entrypoint.sh /
RUN ["chmod", "755", "/entrypoint.sh"] RUN ["chmod", "755", "/entrypoint.sh"]
WORKDIR /home/builder WORKDIR /home/builder
RUN groupadd -r -g 1000 builder \ RUN groupadd -r -g 987 builder \
&& useradd --no-log-init -r -g builder -u 1000 builder \ && useradd --no-log-init -r -g builder -u 987 builder \
&& chown builder:builder /home/builder && chown builder:builder /home/builder
USER builder USER builder

View File

@ -1,9 +1,9 @@
#!/bin/sh #!/bin/sh
set -eu set -eux
SANITIZER="${1:-asan}" SANITIZER="${1:-asan}"
cp -a /c-toxcore . cp -a /c-toxcore .
cd c-toxcore cd c-toxcore
.circleci/cmake-"$SANITIZER" .circleci/cmake-"$SANITIZER" || (cat /home/builder/c-toxcore/_build/CMakeFiles/CMakeError.log && false)

View File

@ -1,6 +1,14 @@
#!/bin/sh #!/bin/sh
set -eux
SANITIZER="${1:-asan}" SANITIZER="${1:-asan}"
if [ -t 0 ]; then
TTY=true
else
TTY=false
fi
docker build -t toxchat/c-toxcore:circleci other/docker/circleci docker build -t toxchat/c-toxcore:circleci other/docker/circleci
docker run --name toxcore-circleci --rm -it -v "$PWD:/c-toxcore" toxchat/c-toxcore:circleci "$SANITIZER" docker run --name toxcore-circleci --rm --interactive="$TTY" --tty="$TTY" --volume "$PWD:/c-toxcore" toxchat/c-toxcore:circleci "$SANITIZER"

View File

@ -9,6 +9,7 @@ cc_binary(
"main/tox_main.h", "main/tox_main.h",
], ],
deps = [ deps = [
"//c-toxcore/toxcore:ccompat",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_events", "//c-toxcore/toxcore:tox_events",
], ],

View File

@ -50,6 +50,10 @@ module "//c-toxcore/third_party:cmp" {
module "//c-toxcore/toxencryptsave:defines" { module "//c-toxcore/toxencryptsave:defines" {
header "toxencryptsave/defines.h" header "toxencryptsave/defines.h"
} }
module "@benchmark" {
textual header "/usr/include/benchmark/benchmark.h"
use std
}
module "@com_google_googletest//:gtest" { module "@com_google_googletest//:gtest" {
textual header "/usr/include/gmock/gmock.h" textual header "/usr/include/gmock/gmock.h"
textual header "/usr/include/gtest/gtest.h" textual header "/usr/include/gtest/gtest.h"
@ -83,9 +87,9 @@ class Context:
pass pass
def bzl_exports_files( def bzl_exports_files(
self, self,
srcs: list[str], srcs: list[str],
visibility: Optional[list[str]] = None, visibility: Optional[list[str]] = None,
) -> None: ) -> None:
pass pass
@ -110,7 +114,7 @@ class Context:
hdrs, hdrs,
} }
def bzl_cc_test( def bzl_cc_binary(
self, self,
name: str, name: str,
srcs: Iterable[str] = tuple(), srcs: Iterable[str] = tuple(),
@ -161,7 +165,8 @@ def main() -> None:
"load": ctx.bzl_load, "load": ctx.bzl_load,
"exports_files": ctx.bzl_exports_files, "exports_files": ctx.bzl_exports_files,
"cc_library": ctx.bzl_cc_library, "cc_library": ctx.bzl_cc_library,
"cc_test": ctx.bzl_cc_test, "cc_binary": ctx.bzl_cc_binary,
"cc_test": ctx.bzl_cc_binary,
"cc_fuzz_test": ctx.bzl_cc_fuzz_test, "cc_fuzz_test": ctx.bzl_cc_fuzz_test,
"select": ctx.bzl_select, "select": ctx.bzl_select,
"glob": ctx.bzl_glob, "glob": ctx.bzl_glob,

View File

@ -3,6 +3,7 @@ FROM alpine:3.19.0
RUN ["apk", "add", "--no-cache", \ RUN ["apk", "add", "--no-cache", \
"bash", \ "bash", \
"benchmark-dev", \
"clang", \ "clang", \
"gtest-dev", \ "gtest-dev", \
"libconfig-dev", \ "libconfig-dev", \

View File

@ -5,7 +5,7 @@ COPY . /work/c-toxcore-0.2.18
RUN ["tar", "zcf", "c-toxcore.tar.gz", "c-toxcore-0.2.18"] RUN ["tar", "zcf", "c-toxcore.tar.gz", "c-toxcore-0.2.18"]
WORKDIR /work/pkgsrc/chat/toxcore WORKDIR /work/pkgsrc/chat/toxcore
RUN ["sed", "-i", "-e", "s/libtoxcore.so.2.18.0/libtoxcore.so.2.19.0/g", "PLIST"] RUN ["sed", "-i", "-e", "s/libtoxcore.so.2.18.0/libtoxcore.so.2.20.0/g", "PLIST"]
RUN ["bmake", "clean"] RUN ["bmake", "clean"]
RUN ["bmake", "DISTFILES=c-toxcore.tar.gz", "DISTDIR=/work", "NO_CHECKSUM=yes"] RUN ["bmake", "DISTFILES=c-toxcore.tar.gz", "DISTDIR=/work", "NO_CHECKSUM=yes"]
RUN ["bmake", "install"] RUN ["bmake", "install"]

View File

@ -11,6 +11,6 @@
# For a full reference see: # For a full reference see:
# https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info # https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
CURRENT=21 CURRENT=22
REVISION=0 REVISION=0
AGE=19 AGE=20

View File

@ -4,4 +4,5 @@ cc_binary(
name = "grencez_tok5", name = "grencez_tok5",
srcs = ["grencez_tok5.c"], srcs = ["grencez_tok5.c"],
copts = ["-Wno-unused-result"], copts = ["-Wno-unused-result"],
tags = ["no-windows"],
) )

View File

@ -75,7 +75,6 @@ cc_library(
deps = [ deps = [
"//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:ccompat",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"@libsodium",
], ],
) )

View File

@ -8,15 +8,9 @@ if(TARGET toxcore_static)
else() else()
target_link_libraries(misc_tools PRIVATE toxcore_shared) target_link_libraries(misc_tools PRIVATE toxcore_shared)
endif() endif()
if(TARGET unofficial-sodium::sodium) if(TARGET pthreads4w::pthreads4w)
target_link_libraries(misc_tools PRIVATE unofficial-sodium::sodium) target_link_libraries(misc_tools PRIVATE pthreads4w::pthreads4w)
else() elseif(TARGET PThreads4W::PThreads4W)
target_link_libraries(misc_tools PRIVATE ${LIBSODIUM_LIBRARIES})
target_link_directories(misc_tools PUBLIC ${LIBSODIUM_LIBRARY_DIRS})
target_include_directories(misc_tools SYSTEM PRIVATE ${LIBSODIUM_INCLUDE_DIRS})
target_compile_options(misc_tools PRIVATE ${LIBSODIUM_CFLAGS_OTHER})
endif()
if(TARGET PThreads4W::PThreads4W)
target_link_libraries(misc_tools PRIVATE PThreads4W::PThreads4W) target_link_libraries(misc_tools PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads) elseif(TARGET Threads::Threads)
target_link_libraries(misc_tools PRIVATE Threads::Threads) target_link_libraries(misc_tools PRIVATE Threads::Threads)
@ -36,7 +30,9 @@ if(BUILD_MISC_TESTS)
else() else()
target_link_libraries(Messenger_test PRIVATE toxcore_shared) target_link_libraries(Messenger_test PRIVATE toxcore_shared)
endif() endif()
if(TARGET PThreads4W::PThreads4W) if(TARGET pthreads4w::pthreads4w)
target_link_libraries(Messenger_test PRIVATE pthreads4w::pthreads4w)
elseif(TARGET PThreads4W::PThreads4W)
target_link_libraries(Messenger_test PRIVATE PThreads4W::PThreads4W) target_link_libraries(Messenger_test PRIVATE PThreads4W::PThreads4W)
elseif(TARGET Threads::Threads) elseif(TARGET Threads::Threads)
target_link_libraries(Messenger_test PRIVATE Threads::Threads) target_link_libraries(Messenger_test PRIVATE Threads::Threads)

View File

@ -8,10 +8,6 @@ endif
noinst_LTLIBRARIES += libmisc_tools.la noinst_LTLIBRARIES += libmisc_tools.la
libmisc_tools_la_SOURCES = ../testing/misc_tools.c ../testing/misc_tools.h libmisc_tools_la_SOURCES = ../testing/misc_tools.c ../testing/misc_tools.h
libmisc_tools_la_CFLAGS = $(LIBSODIUM_CFLAGS)
libmisc_tools_la_LIBADD = $(LIBSODIUM_LDFLAGS)
if BUILD_TESTING if BUILD_TESTING
noinst_PROGRAMS += Messenger_test noinst_PROGRAMS += Messenger_test

View File

@ -118,10 +118,13 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
// TODO(iphydf): Maybe disable.
const bool dns_enabled = true;
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]);
bool res = dht_bootstrap_from_address(m->dht, argv[argvoffset + 1], bool res = dht_bootstrap_from_address(m->dht, argv[argvoffset + 1],
ipv6enabled, port, bootstrap_key); ipv6enabled, dns_enabled, port, bootstrap_key);
free(bootstrap_key); free(bootstrap_key);
if (!res) { if (!res) {

View File

@ -48,6 +48,7 @@ cc_fuzz_test(
deps = [ deps = [
":fuzz_support", ":fuzz_support",
":fuzz_tox", ":fuzz_tox",
"//c-toxcore/toxcore:crypto_core",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_dispatch", "//c-toxcore/toxcore:tox_dispatch",
"//c-toxcore/toxcore:tox_events", "//c-toxcore/toxcore:tox_events",
@ -102,6 +103,7 @@ cc_test(
deps = [ deps = [
":fuzz_support", ":fuzz_support",
":fuzz_tox", ":fuzz_tox",
"//c-toxcore/toxcore:crypto_core",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_dispatch", "//c-toxcore/toxcore:tox_dispatch",
"//c-toxcore/toxcore:tox_events", "//c-toxcore/toxcore:tox_events",
@ -117,6 +119,7 @@ cc_fuzz_test(
deps = [ deps = [
":fuzz_support", ":fuzz_support",
":fuzz_tox", ":fuzz_tox",
"//c-toxcore/toxcore:crypto_core",
"//c-toxcore/toxcore:tox", "//c-toxcore/toxcore:tox",
"//c-toxcore/toxcore:tox_dispatch", "//c-toxcore/toxcore:tox_dispatch",
"//c-toxcore/toxcore:tox_events", "//c-toxcore/toxcore:tox_events",

View File

@ -4,8 +4,15 @@
#include "fuzz_support.hh" #include "fuzz_support.hh"
#ifdef _WIN32
#include <winsock2.h>
// Comment line here to avoid reordering by source code formatters.
#include <windows.h>
#include <ws2tcpip.h>
#else
#include <arpa/inet.h> #include <arpa/inet.h>
#include <sys/socket.h> #include <sys/socket.h>
#endif
#include <algorithm> #include <algorithm>
#include <cassert> #include <cassert>
@ -111,6 +118,7 @@ static constexpr Network_Funcs fuzz_network_funcs = {
/* .accept = */ ![](Fuzz_System *self, Socket sock) { return Socket{1337}; }, /* .accept = */ ![](Fuzz_System *self, Socket sock) { return Socket{1337}; },
/* .bind = */ ![](Fuzz_System *self, Socket sock, const Network_Addr *addr) { return 0; }, /* .bind = */ ![](Fuzz_System *self, Socket sock, const Network_Addr *addr) { return 0; },
/* .listen = */ ![](Fuzz_System *self, Socket sock, int backlog) { return 0; }, /* .listen = */ ![](Fuzz_System *self, Socket sock, int backlog) { return 0; },
/* .connect = */ ![](Fuzz_System *self, Socket sock, const Network_Addr *addr) { return 0; },
/* .recvbuf = */ /* .recvbuf = */
![](Fuzz_System *self, Socket sock) { ![](Fuzz_System *self, Socket sock) {
assert(sock.value == 42 || sock.value == 1337); assert(sock.value == 42 || sock.value == 1337);
@ -225,6 +233,7 @@ static constexpr Network_Funcs null_network_funcs = {
/* .accept = */ ![](Null_System *self, Socket sock) { return Socket{1337}; }, /* .accept = */ ![](Null_System *self, Socket sock) { return Socket{1337}; },
/* .bind = */ ![](Null_System *self, Socket sock, const Network_Addr *addr) { return 0; }, /* .bind = */ ![](Null_System *self, Socket sock, const Network_Addr *addr) { return 0; },
/* .listen = */ ![](Null_System *self, Socket sock, int backlog) { return 0; }, /* .listen = */ ![](Null_System *self, Socket sock, int backlog) { return 0; },
/* .connect = */ ![](Null_System *self, Socket sock, const Network_Addr *addr) { return 0; },
/* .recvbuf = */ ![](Null_System *self, Socket sock) { return 0; }, /* .recvbuf = */ ![](Null_System *self, Socket sock) { return 0; },
/* .recv = */ /* .recv = */
![](Null_System *self, Socket sock, uint8_t *buf, size_t len) { ![](Null_System *self, Socket sock, uint8_t *buf, size_t len) {
@ -341,6 +350,7 @@ static constexpr Network_Funcs record_network_funcs = {
return 0; return 0;
}, },
/* .listen = */ ![](Record_System *self, Socket sock, int backlog) { return 0; }, /* .listen = */ ![](Record_System *self, Socket sock, int backlog) { return 0; },
/* .connect = */ ![](Record_System *self, Socket sock, const Network_Addr *addr) { return 0; },
/* .recvbuf = */ ![](Record_System *self, Socket sock) { return 0; }, /* .recvbuf = */ ![](Record_System *self, Socket sock) { return 0; },
/* .recv = */ /* .recv = */
![](Record_System *self, Socket sock, uint8_t *buf, size_t len) { ![](Record_System *self, Socket sock, uint8_t *buf, size_t len) {

View File

@ -20,8 +20,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <sodium.h>
#if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
#include <windows.h> #include <windows.h>
#else #else
@ -137,60 +135,3 @@ int cmdline_parsefor_ipv46(int argc, char **argv, bool *ipv6enabled)
return argvoffset; return argvoffset;
} }
static const char *test_rng_name(void)
{
return "test_rng";
}
static uint32_t rng_state;
static uint32_t test_rng_random(void)
{
rng_state = 2624534371 * rng_state + 1;
return rng_state;
}
static void test_rng_buf(void *const buf, const size_t size)
{
uint8_t *p = (uint8_t *)buf;
uint32_t r = 0;
for (size_t i = 0; i < size; i++) {
if ((i % 4) == 0) {
r = test_rng_random();
}
*p = (r >> ((i % 4) * 8)) & 0xff;
++p;
}
}
static uint32_t test_rng_uniform(const uint32_t upper_bound)
{
// XXX: Not uniform! But that's ok for testing purposes.
return test_rng_random() % upper_bound;
}
static void test_rng_stir(void) { }
static int test_rng_close(void)
{
return 0;
}
static randombytes_implementation test_rng = {
test_rng_name,
test_rng_random,
test_rng_stir,
test_rng_uniform,
test_rng_buf,
test_rng_close
};
/* Simple insecure PRNG for testing purposes */
int use_test_rng(uint32_t seed)
{
rng_state = seed;
return randombytes_set_implementation(&test_rng);
}

@ -1 +1 @@
Subproject commit 2ac6bca152987c805c04423ebbba4b750585337f Subproject commit 52bfcfa17d2eb4322da2037ad625f5575129cece

View File

@ -1,4 +1,4 @@
load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test") load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test") load("@rules_fuzzing//fuzzing:cc_defs.bzl", "cc_fuzz_test")
exports_files( exports_files(
@ -100,14 +100,58 @@ cc_test(
size = "small", size = "small",
srcs = ["util_test.cc"], srcs = ["util_test.cc"],
deps = [ deps = [
":crypto_core",
":crypto_core_test_util",
":util", ":util",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
], ],
) )
cc_library(
name = "sort",
srcs = ["sort.c"],
hdrs = ["sort.h"],
deps = [
":attributes",
":ccompat",
":util",
],
)
cc_library(
name = "sort_test_util",
testonly = True,
srcs = ["sort_test_util.cc"],
hdrs = ["sort_test_util.hh"],
deps = [
":sort",
":util",
],
)
cc_test(
name = "sort_test",
size = "small",
srcs = ["sort_test.cc"],
deps = [
":sort",
":sort_test_util",
"@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main",
],
)
cc_binary(
name = "sort_bench",
testonly = True,
srcs = ["sort_bench.cc"],
deps = [
":mem",
":sort",
":sort_test_util",
"@benchmark",
],
)
cc_library( cc_library(
name = "logger", name = "logger",
srcs = ["logger.c"], srcs = ["logger.c"],
@ -121,6 +165,7 @@ cc_library(
deps = [ deps = [
":attributes", ":attributes",
":ccompat", ":ccompat",
":mem",
], ],
) )
@ -170,6 +215,7 @@ cc_library(
deps = [ deps = [
":attributes", ":attributes",
":ccompat", ":ccompat",
":mem",
":util", ":util",
"@libsodium", "@libsodium",
], ],
@ -208,6 +254,7 @@ cc_test(
deps = [ deps = [
":crypto_core", ":crypto_core",
":crypto_core_test_util", ":crypto_core_test_util",
":mem_test_util",
":util", ":util",
"@com_google_googletest//:gtest", "@com_google_googletest//:gtest",
"@com_google_googletest//:gtest_main", "@com_google_googletest//:gtest_main",
@ -332,6 +379,7 @@ cc_library(
hdrs = ["network_test_util.hh"], hdrs = ["network_test_util.hh"],
deps = [ deps = [
":crypto_core", ":crypto_core",
":mem",
":network", ":network",
":test_util", ":test_util",
], ],
@ -435,6 +483,7 @@ cc_library(
":network", ":network",
":ping_array", ":ping_array",
":shared_key_cache", ":shared_key_cache",
":sort",
":state", ":state",
":util", ":util",
], ],
@ -478,10 +527,12 @@ cc_test(
cc_fuzz_test( cc_fuzz_test(
name = "DHT_fuzz_test", name = "DHT_fuzz_test",
size = "small", size = "small",
testonly = True,
srcs = ["DHT_fuzz_test.cc"], srcs = ["DHT_fuzz_test.cc"],
corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"], corpus = ["//tools/toktok-fuzzer/corpus:DHT_fuzz_test"],
deps = [ deps = [
":DHT", ":DHT",
":mem_test_util",
"//c-toxcore/testing/fuzzing:fuzz_support", "//c-toxcore/testing/fuzzing:fuzz_support",
], ],
) )
@ -490,7 +541,11 @@ cc_library(
name = "onion", name = "onion",
srcs = ["onion.c"], srcs = ["onion.c"],
hdrs = ["onion.h"], hdrs = ["onion.h"],
visibility = ["//c-toxcore/auto_tests:__pkg__"], visibility = [
"//c-toxcore/auto_tests:__pkg__",
"//c-toxcore/other:__pkg__",
"//c-toxcore/other/bootstrap_daemon:__pkg__",
],
deps = [ deps = [
":DHT", ":DHT",
":attributes", ":attributes",
@ -509,7 +564,11 @@ cc_library(
name = "forwarding", name = "forwarding",
srcs = ["forwarding.c"], srcs = ["forwarding.c"],
hdrs = ["forwarding.h"], hdrs = ["forwarding.h"],
visibility = ["//c-toxcore/auto_tests:__pkg__"], visibility = [
"//c-toxcore/auto_tests:__pkg__",
"//c-toxcore/other:__pkg__",
"//c-toxcore/other/bootstrap_daemon:__pkg__",
],
deps = [ deps = [
":DHT", ":DHT",
":attributes", ":attributes",
@ -704,6 +763,7 @@ cc_library(
":network", ":network",
":onion", ":onion",
":shared_key_cache", ":shared_key_cache",
":sort",
":timed_auth", ":timed_auth",
":util", ":util",
], ],
@ -777,6 +837,7 @@ cc_library(
":crypto_core", ":crypto_core",
":group_announce", ":group_announce",
":logger", ":logger",
":mem",
":mono_time", ":mono_time",
":network", ":network",
":onion_announce", ":onion_announce",
@ -806,6 +867,7 @@ cc_library(
":onion", ":onion",
":onion_announce", ":onion_announce",
":ping_array", ":ping_array",
":sort",
":timed_auth", ":timed_auth",
":util", ":util",
], ],
@ -971,9 +1033,11 @@ cc_library(
":crypto_core", ":crypto_core",
":friend_connection", ":friend_connection",
":logger", ":logger",
":mem",
":mono_time", ":mono_time",
":net_crypto", ":net_crypto",
":network", ":network",
":sort",
":state", ":state",
":util", ":util",
], ],

View File

@ -9,7 +9,6 @@
#include "DHT.h" #include "DHT.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "LAN_discovery.h" #include "LAN_discovery.h"
@ -24,7 +23,9 @@
#include "ping.h" #include "ping.h"
#include "ping_array.h" #include "ping_array.h"
#include "shared_key_cache.h" #include "shared_key_cache.h"
#include "sort.h"
#include "state.h" #include "state.h"
#include "util.h"
/** The timeout after which a node is discarded completely. */ /** The timeout after which a node is discarded completely. */
#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL) #define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
@ -279,7 +280,7 @@ const uint8_t *dht_get_shared_key_sent(DHT *dht, const uint8_t *public_key)
#define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE) #define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE)
int create_request(const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key, int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
uint8_t *packet, const uint8_t *recv_public_key, uint8_t *packet, const uint8_t *recv_public_key,
const uint8_t *data, uint32_t data_length, uint8_t request_id) const uint8_t *data, uint32_t data_length, uint8_t request_id)
{ {
@ -296,7 +297,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE] = {0}; uint8_t temp[MAX_CRYPTO_REQUEST_SIZE] = {0};
temp[0] = request_id; temp[0] = request_id;
memcpy(temp + 1, data, data_length); memcpy(temp + 1, data, data_length);
const int len = encrypt_data(recv_public_key, send_secret_key, nonce, temp, data_length + 1, const int len = encrypt_data(mem, recv_public_key, send_secret_key, nonce, temp, data_length + 1,
packet + CRYPTO_SIZE); packet + CRYPTO_SIZE);
if (len == -1) { if (len == -1) {
@ -312,7 +313,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint
return len + CRYPTO_SIZE; return len + CRYPTO_SIZE;
} }
int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, int handle_request(const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
uint8_t *request_id, const uint8_t *packet, uint16_t packet_length) uint8_t *request_id, const uint8_t *packet, uint16_t packet_length)
{ {
if (self_public_key == nullptr || public_key == nullptr || data == nullptr || request_id == nullptr if (self_public_key == nullptr || public_key == nullptr || data == nullptr || request_id == nullptr
@ -331,7 +332,7 @@ int handle_request(const uint8_t *self_public_key, const uint8_t *self_secret_ke
memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE); memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2; const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
uint8_t temp[MAX_CRYPTO_REQUEST_SIZE]; uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
int32_t len1 = decrypt_data(public_key, self_secret_key, nonce, int32_t len1 = decrypt_data(mem, public_key, self_secret_key, nonce,
packet + CRYPTO_SIZE, packet_length - CRYPTO_SIZE, temp); packet + CRYPTO_SIZE, packet_length - CRYPTO_SIZE, temp);
if (len1 == -1 || len1 == 0) { if (len1 == -1 || len1 == 0) {
@ -378,7 +379,7 @@ int dht_create_packet(const Memory *mem, const Random *rng,
random_nonce(rng, nonce); random_nonce(rng, nonce);
const int encrypted_length = encrypt_data_symmetric(shared_key, nonce, plain, plain_length, encrypted); const int encrypted_length = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_length, encrypted);
if (encrypted_length < 0) { if (encrypted_length < 0) {
mem_delete(mem, encrypted); mem_delete(mem, encrypted);
@ -755,49 +756,6 @@ int get_close_nodes(
is_lan, want_announce); is_lan, want_announce);
} }
typedef struct DHT_Cmp_Data {
uint64_t cur_time;
const uint8_t *base_public_key;
Client_data entry;
} DHT_Cmp_Data;
non_null()
static int dht_cmp_entry(const void *a, const void *b)
{
const DHT_Cmp_Data *cmp1 = (const DHT_Cmp_Data *)a;
const DHT_Cmp_Data *cmp2 = (const DHT_Cmp_Data *)b;
const Client_data entry1 = cmp1->entry;
const Client_data entry2 = cmp2->entry;
const uint8_t *cmp_public_key = cmp1->base_public_key;
const bool t1 = assoc_timeout(cmp1->cur_time, &entry1.assoc4) && assoc_timeout(cmp1->cur_time, &entry1.assoc6);
const bool t2 = assoc_timeout(cmp2->cur_time, &entry2.assoc4) && assoc_timeout(cmp2->cur_time, &entry2.assoc6);
if (t1 && t2) {
return 0;
}
if (t1) {
return -1;
}
if (t2) {
return 1;
}
const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key);
if (closest == 1) {
return 1;
}
if (closest == 2) {
return -1;
}
return 0;
}
#ifdef CHECK_ANNOUNCE_NODE #ifdef CHECK_ANNOUNCE_NODE
non_null() non_null()
static void set_announce_node_in_list(Client_data *list, uint32_t list_len, const uint8_t *public_key) static void set_announce_node_in_list(Client_data *list, uint32_t list_len, const uint8_t *public_key)
@ -870,7 +828,7 @@ static int handle_data_search_response(void *object, const IP_Port *source,
const uint8_t *public_key = packet + 1; const uint8_t *public_key = packet + 1;
const uint8_t *shared_key = dht_get_shared_key_recv(dht, public_key); const uint8_t *shared_key = dht_get_shared_key_recv(dht, public_key);
if (decrypt_data_symmetric(shared_key, if (decrypt_data_symmetric(dht->mem, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
plain_len + CRYPTO_MAC_SIZE, plain_len + CRYPTO_MAC_SIZE,
@ -914,31 +872,117 @@ static bool store_node_ok(const Client_data *client, uint64_t cur_time, const ui
|| id_closest(comp_public_key, client->public_key, public_key) == 2; || id_closest(comp_public_key, client->public_key, public_key) == 2;
} }
typedef struct Client_data_Cmp {
const Memory *mem;
uint64_t cur_time;
const uint8_t *comp_public_key;
} Client_data_Cmp;
non_null()
static int client_data_cmp(const Client_data_Cmp *cmp, const Client_data *entry1, const Client_data *entry2)
{
const bool t1 = assoc_timeout(cmp->cur_time, &entry1->assoc4) && assoc_timeout(cmp->cur_time, &entry1->assoc6);
const bool t2 = assoc_timeout(cmp->cur_time, &entry2->assoc4) && assoc_timeout(cmp->cur_time, &entry2->assoc6);
if (t1 && t2) {
return 0;
}
if (t1) {
return -1;
}
if (t2) {
return 1;
}
const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
if (closest == 1) {
return 1;
}
if (closest == 2) {
return -1;
}
return 0;
}
non_null()
static bool client_data_less_handler(const void *object, const void *a, const void *b)
{
const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
const Client_data *entry1 = (const Client_data *)a;
const Client_data *entry2 = (const Client_data *)b;
return client_data_cmp(cmp, entry1, entry2) < 0;
}
non_null()
static const void *client_data_get_handler(const void *arr, uint32_t index)
{
const Client_data *entries = (const Client_data *)arr;
return &entries[index];
}
non_null()
static void client_data_set_handler(void *arr, uint32_t index, const void *val)
{
Client_data *entries = (Client_data *)arr;
const Client_data *entry = (const Client_data *)val;
entries[index] = *entry;
}
non_null()
static void *client_data_subarr_handler(void *arr, uint32_t index, uint32_t size)
{
Client_data *entries = (Client_data *)arr;
return &entries[index];
}
non_null()
static void *client_data_alloc_handler(const void *object, uint32_t size)
{
const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
Client_data *tmp = (Client_data *)mem_valloc(cmp->mem, size, sizeof(Client_data));
if (tmp == nullptr) {
return nullptr;
}
return tmp;
}
non_null()
static void client_data_delete_handler(const void *object, void *arr, uint32_t size)
{
const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
mem_delete(cmp->mem, arr);
}
static const Sort_Funcs client_data_cmp_funcs = {
client_data_less_handler,
client_data_get_handler,
client_data_set_handler,
client_data_subarr_handler,
client_data_alloc_handler,
client_data_delete_handler,
};
non_null() non_null()
static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length, static void sort_client_list(const Memory *mem, Client_data *list, uint64_t cur_time, unsigned int length,
const uint8_t *comp_public_key) const uint8_t *comp_public_key)
{ {
// Pass comp_public_key to qsort with each Client_data entry, so the // Pass comp_public_key to merge_sort with each Client_data entry, so the
// comparison function can use it as the base of comparison. // comparison function can use it as the base of comparison.
DHT_Cmp_Data *cmp_list = (DHT_Cmp_Data *)mem_valloc(mem, length, sizeof(DHT_Cmp_Data)); const Client_data_Cmp cmp = {
mem,
cur_time,
comp_public_key,
};
if (cmp_list == nullptr) { merge_sort(list, length, &cmp, &client_data_cmp_funcs);
return;
}
for (uint32_t i = 0; i < length; ++i) {
cmp_list[i].cur_time = cur_time;
cmp_list[i].base_public_key = comp_public_key;
cmp_list[i].entry = list[i];
}
qsort(cmp_list, length, sizeof(DHT_Cmp_Data), dht_cmp_entry);
for (uint32_t i = 0; i < length; ++i) {
list[i] = cmp_list[i].entry;
}
mem_delete(mem, cmp_list);
} }
non_null() non_null()
@ -1381,6 +1425,7 @@ static int handle_getnodes(void *object, const IP_Port *source, const uint8_t *p
uint8_t plain[CRYPTO_NODE_SIZE]; uint8_t plain[CRYPTO_NODE_SIZE];
const uint8_t *shared_key = dht_get_shared_key_recv(dht, packet + 1); const uint8_t *shared_key = dht_get_shared_key_recv(dht, packet + 1);
const int len = decrypt_data_symmetric( const int len = decrypt_data_symmetric(
dht->mem,
shared_key, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
@ -1442,6 +1487,7 @@ static bool handle_sendnodes_core(void *object, const IP_Port *source, const uin
VLA(uint8_t, plain, plain_size); VLA(uint8_t, plain, plain_size);
const uint8_t *shared_key = dht_get_shared_key_sent(dht, packet + 1); const uint8_t *shared_key = dht_get_shared_key_sent(dht, packet + 1);
const int len = decrypt_data_symmetric( const int len = decrypt_data_symmetric(
dht->mem,
shared_key, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
@ -1840,7 +1886,7 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)
return dht_getnodes(dht, ip_port, public_key, dht->self_public_key); return dht_getnodes(dht, ip_port, public_key, dht->self_public_key);
} }
bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled,
uint16_t port, const uint8_t *public_key) uint16_t port, const uint8_t *public_key)
{ {
IP_Port ip_port_v64; IP_Port ip_port_v64;
@ -1855,7 +1901,7 @@ bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled,
ip_extra = &ip_port_v4.ip; ip_extra = &ip_port_v4.ip;
} }
if (addr_resolve_or_parse_ip(dht->ns, address, &ip_port_v64.ip, ip_extra)) { if (addr_resolve_or_parse_ip(dht->ns, dht->mem, address, &ip_port_v64.ip, ip_extra, dns_enabled)) {
ip_port_v64.port = port; ip_port_v64.port = port;
dht_bootstrap(dht, &ip_port_v64, public_key); dht_bootstrap(dht, &ip_port_v64, public_key);
@ -2123,7 +2169,7 @@ static int send_nat_ping(const DHT *dht, const uint8_t *public_key, uint64_t pin
memcpy(data + 1, &ping_id, sizeof(uint64_t)); memcpy(data + 1, &ping_id, sizeof(uint64_t));
/* 254 is NAT ping request packet id */ /* 254 is NAT ping request packet id */
const int len = create_request( const int len = create_request(
dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key, dht->mem, dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key,
data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING); data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
if (len == -1) { if (len == -1) {
@ -2458,7 +2504,7 @@ static int cryptopacket_handle(void *object, const IP_Port *source, const uint8_
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t data[MAX_CRYPTO_REQUEST_SIZE]; uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
uint8_t number; uint8_t number;
const int len = handle_request(dht->self_public_key, dht->self_secret_key, public_key, const int len = handle_request(dht->mem, dht->self_public_key, dht->self_secret_key, public_key,
data, &number, packet, length); data, &number, packet, length);
if (len == -1 || len == 0) { if (len == -1 || len == 0) {

View File

@ -99,7 +99,7 @@ extern "C" {
* @return the length of the created packet on success. * @return the length of the created packet on success.
*/ */
non_null() non_null()
int create_request(const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key, int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
uint8_t *packet, const uint8_t *recv_public_key, uint8_t *packet, const uint8_t *recv_public_key,
const uint8_t *data, uint32_t data_length, uint8_t request_id); const uint8_t *data, uint32_t data_length, uint8_t request_id);
@ -127,7 +127,7 @@ int create_request(const Random *rng, const uint8_t *send_public_key, const uint
*/ */
non_null() non_null()
int handle_request( int handle_request(
const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data, const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
uint8_t *request_id, const uint8_t *packet, uint16_t packet_length); uint8_t *request_id, const uint8_t *packet, uint16_t packet_length);
typedef struct IPPTs { typedef struct IPPTs {
@ -404,12 +404,13 @@ bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key);
* @param address can be a hostname or an IP address (IPv4 or IPv6). * @param address can be a hostname or an IP address (IPv4 or IPv6).
* @param ipv6enabled if false, the resolving sticks STRICTLY to IPv4 addresses. * @param ipv6enabled if false, the resolving sticks STRICTLY to IPv4 addresses.
* Otherwise, the resolving looks for IPv6 addresses first, then IPv4 addresses. * Otherwise, the resolving looks for IPv6 addresses first, then IPv4 addresses.
* @param dns_enabled if false, the resolving does not use DNS, only IP addresses are supported.
* *
* @retval true if the address could be converted into an IP address * @retval true if the address could be converted into an IP address
* @retval false otherwise * @retval false otherwise
*/ */
non_null() non_null()
bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled,
uint16_t port, const uint8_t *public_key); uint16_t port, const uint8_t *public_key);
/** @brief Start sending packets after DHT loaded_friends_list and loaded_clients_list are set. /** @brief Start sending packets after DHT loaded_friends_list and loaded_clients_list are set.

View File

@ -6,19 +6,22 @@
#include <vector> #include <vector>
#include "../testing/fuzzing/fuzz_support.hh" #include "../testing/fuzzing/fuzz_support.hh"
#include "mem_test_util.hh"
namespace { namespace {
void TestHandleRequest(Fuzz_Data &input) void TestHandleRequest(Fuzz_Data &input)
{ {
const Test_Memory mem;
CONSUME_OR_RETURN(const uint8_t *self_public_key, input, CRYPTO_PUBLIC_KEY_SIZE); CONSUME_OR_RETURN(const uint8_t *self_public_key, input, CRYPTO_PUBLIC_KEY_SIZE);
CONSUME_OR_RETURN(const uint8_t *self_secret_key, input, CRYPTO_SECRET_KEY_SIZE); CONSUME_OR_RETURN(const uint8_t *self_secret_key, input, CRYPTO_SECRET_KEY_SIZE);
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t request[MAX_CRYPTO_REQUEST_SIZE]; uint8_t request[MAX_CRYPTO_REQUEST_SIZE];
uint8_t request_id; uint8_t request_id;
handle_request(self_public_key, self_secret_key, public_key, request, &request_id, input.data(), handle_request(mem, self_public_key, self_secret_key, public_key, request, &request_id,
input.size()); input.data(), input.size());
} }
void TestUnpackNodes(Fuzz_Data &input) void TestUnpackNodes(Fuzz_Data &input)
@ -31,7 +34,8 @@ void TestUnpackNodes(Fuzz_Data &input)
const int packed_count = unpack_nodes( const int packed_count = unpack_nodes(
nodes, node_count, &processed_data_len, input.data(), input.size(), tcp_enabled); nodes, node_count, &processed_data_len, input.data(), input.size(), tcp_enabled);
if (packed_count > 0) { if (packed_count > 0) {
Logger *logger = logger_new(); const Memory *mem = os_memory();
Logger *logger = logger_new(mem);
std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6); std::vector<uint8_t> packed(packed_count * PACKED_NODE_SIZE_IP6);
const int packed_size const int packed_size
= pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count); = pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count);

View File

@ -274,6 +274,7 @@ TEST(AddToList, KeepsKeysInOrder)
TEST(Request, CreateAndParse) TEST(Request, CreateAndParse)
{ {
Test_Memory mem;
Test_Random rng; Test_Random rng;
// Peers. // Peers.
@ -293,32 +294,32 @@ TEST(Request, CreateAndParse)
std::vector<uint8_t> outgoing(919); std::vector<uint8_t> outgoing(919);
random_bytes(rng, outgoing.data(), outgoing.size()); random_bytes(rng, outgoing.data(), outgoing.size());
EXPECT_LT(create_request(rng, sender.pk.data(), sender.sk.data(), packet.data(), EXPECT_LT(create_request(mem, rng, sender.pk.data(), sender.sk.data(), packet.data(),
receiver.pk.data(), outgoing.data(), outgoing.size(), sent_pkt_id), receiver.pk.data(), outgoing.data(), outgoing.size(), sent_pkt_id),
0); 0);
// Pop one element so the payload is 918 bytes. Packing should now succeed. // Pop one element so the payload is 918 bytes. Packing should now succeed.
outgoing.pop_back(); outgoing.pop_back();
const int max_sent_length = create_request(rng, sender.pk.data(), sender.sk.data(), const int max_sent_length = create_request(mem, rng, sender.pk.data(), sender.sk.data(),
packet.data(), receiver.pk.data(), outgoing.data(), outgoing.size(), sent_pkt_id); packet.data(), receiver.pk.data(), outgoing.data(), outgoing.size(), sent_pkt_id);
ASSERT_GT(max_sent_length, 0); // success. ASSERT_GT(max_sent_length, 0); // success.
// Check that handle_request rejects packets larger than the maximum created packet size. // Check that handle_request rejects packets larger than the maximum created packet size.
EXPECT_LT(handle_request(receiver.pk.data(), receiver.sk.data(), pk.data(), incoming.data(), EXPECT_LT(handle_request(mem, receiver.pk.data(), receiver.sk.data(), pk.data(),
&recvd_pkt_id, packet.data(), max_sent_length + 1), incoming.data(), &recvd_pkt_id, packet.data(), max_sent_length + 1),
0); 0);
// Now try all possible packet sizes from max (918) to 0. // Now try all possible packet sizes from max (918) to 0.
while (!outgoing.empty()) { while (!outgoing.empty()) {
// Pack: // Pack:
const int sent_length = create_request(rng, sender.pk.data(), sender.sk.data(), const int sent_length = create_request(mem, rng, sender.pk.data(), sender.sk.data(),
packet.data(), receiver.pk.data(), outgoing.data(), outgoing.size(), sent_pkt_id); packet.data(), receiver.pk.data(), outgoing.data(), outgoing.size(), sent_pkt_id);
ASSERT_GT(sent_length, 0); ASSERT_GT(sent_length, 0);
// Unpack: // Unpack:
const int recvd_length = handle_request(receiver.pk.data(), receiver.sk.data(), pk.data(), const int recvd_length = handle_request(mem, receiver.pk.data(), receiver.sk.data(),
incoming.data(), &recvd_pkt_id, packet.data(), sent_length); pk.data(), incoming.data(), &recvd_pkt_id, packet.data(), sent_length);
ASSERT_GE(recvd_length, 0); ASSERT_GE(recvd_length, 0);
EXPECT_EQ( EXPECT_EQ(
@ -334,7 +335,7 @@ TEST(AnnounceNodes, SetAndTest)
Test_Memory mem; Test_Memory mem;
Test_Network ns; Test_Network ns;
Logger *log = logger_new(); Logger *log = logger_new(mem);
ASSERT_NE(log, nullptr); ASSERT_NE(log, nullptr);
Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr);
ASSERT_NE(mono_time, nullptr); ASSERT_NE(mono_time, nullptr);

View File

@ -86,6 +86,8 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \
../toxcore/ping.c \ ../toxcore/ping.c \
../toxcore/shared_key_cache.h \ ../toxcore/shared_key_cache.h \
../toxcore/shared_key_cache.c \ ../toxcore/shared_key_cache.c \
../toxcore/sort.h \
../toxcore/sort.c \
../toxcore/state.h \ ../toxcore/state.h \
../toxcore/state.c \ ../toxcore/state.c \
../toxcore/tox.h \ ../toxcore/tox.h \

View File

@ -3482,7 +3482,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random *
return nullptr; return nullptr;
} }
m->log = logger_new(); m->log = logger_new(mem);
if (m->log == nullptr) { if (m->log == nullptr) {
friendreq_kill(m->fr); friendreq_kill(m->fr);

View File

@ -86,6 +86,8 @@ typedef struct Messenger_Options {
Messenger_State_Plugin *state_plugins; Messenger_State_Plugin *state_plugins;
uint8_t state_plugins_length; uint8_t state_plugins_length;
bool dns_enabled;
} Messenger_Options; } Messenger_Options;
struct Receipts { struct Receipts {

View File

@ -107,12 +107,12 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value)
* @retval false on failure * @retval false on failure
*/ */
non_null() non_null()
static bool connect_sock_to(const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info) static bool connect_sock_to(const Network *ns, const Logger *logger, const Memory *mem, Socket sock, const IP_Port *ip_port, const TCP_Proxy_Info *proxy_info)
{ {
if (proxy_info->proxy_type != TCP_PROXY_NONE) { if (proxy_info->proxy_type != TCP_PROXY_NONE) {
return net_connect(mem, logger, sock, &proxy_info->ip_port); return net_connect(ns, mem, logger, sock, &proxy_info->ip_port);
} else { } else {
return net_connect(mem, logger, sock, ip_port); return net_connect(ns, mem, logger, sock, ip_port);
} }
} }
@ -312,7 +312,7 @@ static int generate_handshake(TCP_Client_Connection *tcp_conn)
memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE); memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE);
memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
random_nonce(tcp_conn->con.rng, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE); random_nonce(tcp_conn->con.rng, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE);
const int len = encrypt_data_symmetric(tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain, const int len = encrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
if (len != sizeof(plain) + CRYPTO_MAC_SIZE) { if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
@ -334,7 +334,7 @@ non_null()
static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data) static int handle_handshake(TCP_Client_Connection *tcp_conn, const uint8_t *data)
{ {
uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE]; uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
const int len = decrypt_data_symmetric(tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE, const int len = decrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE,
TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain); TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
if (len != sizeof(plain)) { if (len != sizeof(plain)) {
@ -617,7 +617,7 @@ TCP_Client_Connection *new_tcp_connection(
return nullptr; return nullptr;
} }
if (!(set_socket_nonblock(ns, sock) && connect_sock_to(logger, mem, sock, ip_port, proxy_info))) { if (!(set_socket_nonblock(ns, sock) && connect_sock_to(ns, logger, mem, sock, ip_port, proxy_info))) {
kill_sock(ns, sock); kill_sock(ns, sock);
return nullptr; return nullptr;
} }

View File

@ -157,7 +157,7 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con
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->mem, con->shared_key, con->sent_nonce, data, length, packet + sizeof(uint16_t));
if ((unsigned int)len != (packet_size - sizeof(uint16_t))) { if ((unsigned int)len != (packet_size - sizeof(uint16_t))) {
return -1; return -1;
@ -305,7 +305,7 @@ int read_packet_tcp_secure_connection(
*next_packet_length = 0; *next_packet_length = 0;
const int len = decrypt_data_symmetric(shared_key, recv_nonce, data_encrypted, len_packet, data); const int len = decrypt_data_symmetric(mem, shared_key, recv_nonce, data_encrypted, len_packet, data);
if (len + CRYPTO_MAC_SIZE != len_packet) { if (len + CRYPTO_MAC_SIZE != len_packet) {
LOGGER_ERROR(logger, "decrypted length %d does not match expected length %d", len + CRYPTO_MAC_SIZE, len_packet); LOGGER_ERROR(logger, "decrypted length %d does not match expected length %d", len + CRYPTO_MAC_SIZE, len_packet);

View File

@ -327,7 +327,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con
uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE]; uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE];
encrypt_precompute(data, self_secret_key, shared_key); encrypt_precompute(data, self_secret_key, shared_key);
uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE]; uint8_t plain[TCP_HANDSHAKE_PLAIN_SIZE];
int len = decrypt_data_symmetric(shared_key, data + CRYPTO_PUBLIC_KEY_SIZE, int len = decrypt_data_symmetric(con->con.mem, shared_key, data + CRYPTO_PUBLIC_KEY_SIZE,
data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain); data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE, plain);
if (len != TCP_HANDSHAKE_PLAIN_SIZE) { if (len != TCP_HANDSHAKE_PLAIN_SIZE) {
@ -347,7 +347,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con
uint8_t response[TCP_SERVER_HANDSHAKE_SIZE]; uint8_t response[TCP_SERVER_HANDSHAKE_SIZE];
random_nonce(con->con.rng, response); random_nonce(con->con.rng, response);
len = encrypt_data_symmetric(shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE, len = encrypt_data_symmetric(con->con.mem, shared_key, response, resp_plain, TCP_HANDSHAKE_PLAIN_SIZE,
response + CRYPTO_NONCE_SIZE); response + CRYPTO_NONCE_SIZE);
if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) { if (len != TCP_HANDSHAKE_PLAIN_SIZE + CRYPTO_MAC_SIZE) {

View File

@ -451,7 +451,7 @@ static int create_reply_plain_store_announce_request(Announcements *announce,
return -1; return -1;
} }
if (decrypt_data_symmetric(shared_key, if (decrypt_data_symmetric(announce->mem, shared_key,
data + CRYPTO_PUBLIC_KEY_SIZE, data + CRYPTO_PUBLIC_KEY_SIZE,
data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
plain_len + CRYPTO_MAC_SIZE, plain_len + CRYPTO_MAC_SIZE,
@ -568,7 +568,7 @@ static int create_reply(Announcements *announce, const IP_Port *source,
VLA(uint8_t, plain, plain_len); VLA(uint8_t, plain, plain_len);
const uint8_t *shared_key = dht_get_shared_key_recv(announce->dht, data + 1); const uint8_t *shared_key = dht_get_shared_key_recv(announce->dht, data + 1);
if (decrypt_data_symmetric(shared_key, if (decrypt_data_symmetric(announce->mem, shared_key,
data + 1 + CRYPTO_PUBLIC_KEY_SIZE, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
data + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, data + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
plain_len + CRYPTO_MAC_SIZE, plain_len + CRYPTO_MAC_SIZE,

View File

@ -13,6 +13,7 @@
#include "attributes.h" #include "attributes.h"
#include "ccompat.h" #include "ccompat.h"
#include "mem.h"
#include "util.h" #include "util.h"
static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES, static_assert(CRYPTO_PUBLIC_KEY_SIZE == crypto_box_PUBLICKEYBYTES,
@ -88,9 +89,10 @@ const uint8_t *get_chat_id(const Extended_Public_Key *key)
} }
#if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) #if !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION)
static uint8_t *crypto_malloc(size_t bytes) non_null()
static uint8_t *crypto_malloc(const Memory *mem, size_t bytes)
{ {
uint8_t *ptr = (uint8_t *)malloc(bytes); uint8_t *ptr = (uint8_t *)mem_balloc(mem, bytes);
if (ptr != nullptr) { if (ptr != nullptr) {
crypto_memlock(ptr, bytes); crypto_memlock(ptr, bytes);
@ -99,15 +101,15 @@ static uint8_t *crypto_malloc(size_t bytes)
return ptr; return ptr;
} }
nullable(1) non_null(1) nullable(2)
static void crypto_free(uint8_t *ptr, size_t bytes) static void crypto_free(const Memory *mem, uint8_t *ptr, size_t bytes)
{ {
if (ptr != nullptr) { if (ptr != nullptr) {
crypto_memzero(ptr, bytes); crypto_memzero(ptr, bytes);
crypto_memunlock(ptr, bytes); crypto_memunlock(ptr, bytes);
} }
free(ptr); mem_delete(mem, ptr);
} }
#endif /* !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */ #endif /* !defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) */
@ -240,7 +242,8 @@ int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
} }
int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], int32_t encrypt_data_symmetric(const Memory *mem,
const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted) const uint8_t *plain, size_t length, uint8_t *encrypted)
{ {
@ -258,12 +261,12 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const size_t size_temp_plain = length + crypto_box_ZEROBYTES; const size_t size_temp_plain = length + crypto_box_ZEROBYTES;
const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES; const size_t size_temp_encrypted = length + crypto_box_MACBYTES + crypto_box_BOXZEROBYTES;
uint8_t *temp_plain = crypto_malloc(size_temp_plain); uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain);
uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted); uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted);
if (temp_plain == nullptr || temp_encrypted == nullptr) { if (temp_plain == nullptr || temp_encrypted == nullptr) {
crypto_free(temp_plain, size_temp_plain); crypto_free(mem, temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted); crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1; return -1;
} }
@ -278,22 +281,23 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce, if (crypto_box_afternm(temp_encrypted, temp_plain, length + crypto_box_ZEROBYTES, nonce,
shared_key) != 0) { shared_key) != 0) {
crypto_free(temp_plain, size_temp_plain); crypto_free(mem, temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted); crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1; return -1;
} }
// Unpad the encrypted message. // Unpad the encrypted message.
memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES); memcpy(encrypted, temp_encrypted + crypto_box_BOXZEROBYTES, length + crypto_box_MACBYTES);
crypto_free(temp_plain, size_temp_plain); crypto_free(mem, temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted); crypto_free(mem, temp_encrypted, size_temp_encrypted);
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
assert(length < INT32_MAX - crypto_box_MACBYTES); assert(length < INT32_MAX - crypto_box_MACBYTES);
return (int32_t)(length + crypto_box_MACBYTES); return (int32_t)(length + crypto_box_MACBYTES);
} }
int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], int32_t decrypt_data_symmetric(const Memory *mem,
const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain) const uint8_t *encrypted, size_t length, uint8_t *plain)
{ {
@ -310,12 +314,12 @@ int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const size_t size_temp_plain = length + crypto_box_ZEROBYTES; const size_t size_temp_plain = length + crypto_box_ZEROBYTES;
const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES; const size_t size_temp_encrypted = length + crypto_box_BOXZEROBYTES;
uint8_t *temp_plain = crypto_malloc(size_temp_plain); uint8_t *temp_plain = crypto_malloc(mem, size_temp_plain);
uint8_t *temp_encrypted = crypto_malloc(size_temp_encrypted); uint8_t *temp_encrypted = crypto_malloc(mem, size_temp_encrypted);
if (temp_plain == nullptr || temp_encrypted == nullptr) { if (temp_plain == nullptr || temp_encrypted == nullptr) {
crypto_free(temp_plain, size_temp_plain); crypto_free(mem, temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted); crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1; return -1;
} }
@ -330,22 +334,23 @@ int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce, if (crypto_box_open_afternm(temp_plain, temp_encrypted, length + crypto_box_BOXZEROBYTES, nonce,
shared_key) != 0) { shared_key) != 0) {
crypto_free(temp_plain, size_temp_plain); crypto_free(mem, temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted); crypto_free(mem, temp_encrypted, size_temp_encrypted);
return -1; return -1;
} }
memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES); memcpy(plain, temp_plain + crypto_box_ZEROBYTES, length - crypto_box_MACBYTES);
crypto_free(temp_plain, size_temp_plain); crypto_free(mem, temp_plain, size_temp_plain);
crypto_free(temp_encrypted, size_temp_encrypted); crypto_free(mem, temp_encrypted, size_temp_encrypted);
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
assert(length > crypto_box_MACBYTES); assert(length > crypto_box_MACBYTES);
assert(length < INT32_MAX); assert(length < INT32_MAX);
return (int32_t)(length - crypto_box_MACBYTES); return (int32_t)(length - crypto_box_MACBYTES);
} }
int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], int32_t encrypt_data(const Memory *mem,
const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted) const uint8_t *plain, size_t length, uint8_t *encrypted)
@ -356,12 +361,13 @@ int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
uint8_t k[crypto_box_BEFORENMBYTES]; uint8_t k[crypto_box_BEFORENMBYTES];
encrypt_precompute(public_key, secret_key, k); encrypt_precompute(public_key, secret_key, k);
const int ret = encrypt_data_symmetric(k, nonce, plain, length, encrypted); const int ret = encrypt_data_symmetric(mem, k, nonce, plain, length, encrypted);
crypto_memzero(k, sizeof(k)); crypto_memzero(k, sizeof(k));
return ret; return ret;
} }
int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], int32_t decrypt_data(const Memory *mem,
const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain) const uint8_t *encrypted, size_t length, uint8_t *plain)
@ -372,7 +378,7 @@ int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
uint8_t k[crypto_box_BEFORENMBYTES]; uint8_t k[crypto_box_BEFORENMBYTES];
encrypt_precompute(public_key, secret_key, k); encrypt_precompute(public_key, secret_key, k);
const int ret = decrypt_data_symmetric(k, nonce, encrypted, length, plain); const int ret = decrypt_data_symmetric(mem, k, nonce, encrypted, length, plain);
crypto_memzero(k, sizeof(k)); crypto_memzero(k, sizeof(k));
return ret; return ret;
} }

View File

@ -16,6 +16,7 @@
#include <stdint.h> #include <stdint.h>
#include "attributes.h" #include "attributes.h"
#include "mem.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -386,7 +387,8 @@ void crypto_derive_public_key(uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
* @return length of encrypted data if everything was fine. * @return length of encrypted data if everything was fine.
*/ */
non_null() non_null()
int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], int32_t encrypt_data(const Memory *mem,
const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted); const uint8_t *plain, size_t length, uint8_t *encrypted);
@ -403,7 +405,8 @@ int32_t encrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
* @return length of plain text data if everything was fine. * @return length of plain text data if everything was fine.
*/ */
non_null() non_null()
int32_t decrypt_data(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE], int32_t decrypt_data(const Memory *mem,
const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE], const uint8_t secret_key[CRYPTO_SECRET_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain); const uint8_t *encrypted, size_t length, uint8_t *plain);
@ -431,7 +434,8 @@ int32_t encrypt_precompute(const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
* @return length of encrypted data if everything was fine. * @return length of encrypted data if everything was fine.
*/ */
non_null() non_null()
int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], int32_t encrypt_data_symmetric(const Memory *mem,
const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *plain, size_t length, uint8_t *encrypted); const uint8_t *plain, size_t length, uint8_t *encrypted);
@ -446,7 +450,8 @@ int32_t encrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
* @return length of plain data if everything was fine. * @return length of plain data if everything was fine.
*/ */
non_null() non_null()
int32_t decrypt_data_symmetric(const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE], int32_t decrypt_data_symmetric(const Memory *mem,
const uint8_t shared_key[CRYPTO_SHARED_KEY_SIZE],
const uint8_t nonce[CRYPTO_NONCE_SIZE], const uint8_t nonce[CRYPTO_NONCE_SIZE],
const uint8_t *encrypted, size_t length, uint8_t *plain); const uint8_t *encrypted, size_t length, uint8_t *plain);

View File

@ -7,6 +7,7 @@
#include <vector> #include <vector>
#include "crypto_core_test_util.hh" #include "crypto_core_test_util.hh"
#include "mem_test_util.hh"
#include "util.h" #include "util.h"
namespace { namespace {
@ -17,8 +18,38 @@ using SecretKey = std::array<uint8_t, CRYPTO_SECRET_KEY_SIZE>;
using Signature = std::array<uint8_t, CRYPTO_SIGNATURE_SIZE>; using Signature = std::array<uint8_t, CRYPTO_SIGNATURE_SIZE>;
using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>; using Nonce = std::array<uint8_t, CRYPTO_NONCE_SIZE>;
TEST(PkEqual, TwoRandomIdsAreNotEqual)
{
std::mt19937 rng;
std::uniform_int_distribution<unsigned short> dist{0, UINT8_MAX};
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE];
std::generate(std::begin(pk1), std::end(pk1), [&]() { return dist(rng); });
std::generate(std::begin(pk2), std::end(pk2), [&]() { return dist(rng); });
EXPECT_FALSE(pk_equal(pk1, pk2));
}
TEST(PkEqual, IdCopyMakesKeysEqual)
{
std::mt19937 rng;
std::uniform_int_distribution<unsigned short> dist{0, UINT8_MAX};
uint8_t pk1[CRYPTO_PUBLIC_KEY_SIZE];
uint8_t pk2[CRYPTO_PUBLIC_KEY_SIZE] = {0};
std::generate(std::begin(pk1), std::end(pk1), [&]() { return dist(rng); });
pk_copy(pk2, pk1);
EXPECT_TRUE(pk_equal(pk1, pk2));
}
TEST(CryptoCore, EncryptLargeData) TEST(CryptoCore, EncryptLargeData)
{ {
Test_Memory mem;
Test_Random rng; Test_Random rng;
Nonce nonce{}; Nonce nonce{};
@ -30,7 +61,8 @@ TEST(CryptoCore, EncryptLargeData)
std::vector<uint8_t> plain(100 * 1024 * 1024); std::vector<uint8_t> plain(100 * 1024 * 1024);
std::vector<uint8_t> encrypted(plain.size() + CRYPTO_MAC_SIZE); std::vector<uint8_t> encrypted(plain.size() + CRYPTO_MAC_SIZE);
encrypt_data(pk.data(), sk.data(), nonce.data(), plain.data(), plain.size(), encrypted.data()); encrypt_data(
mem, pk.data(), sk.data(), nonce.data(), plain.data(), plain.size(), encrypted.data());
} }
TEST(CryptoCore, IncrementNonce) TEST(CryptoCore, IncrementNonce)

View File

@ -158,7 +158,10 @@ static Tox_Event_Dht_Get_Nodes_Response *tox_events_add_dht_get_nodes_response(T
event.type = TOX_EVENT_DHT_GET_NODES_RESPONSE; event.type = TOX_EVENT_DHT_GET_NODES_RESPONSE;
event.data.dht_get_nodes_response = dht_get_nodes_response; event.data.dht_get_nodes_response = dht_get_nodes_response;
tox_events_add(events, &event); if (!tox_events_add(events, &event)) {
tox_event_dht_get_nodes_response_free(dht_get_nodes_response, mem);
return nullptr;
}
return dht_get_nodes_response; return dht_get_nodes_response;
} }

View File

@ -46,7 +46,10 @@ void TestSendForwardRequest(Fuzz_Data &input)
// rest of the fuzz data is input for malloc and network // rest of the fuzz data is input for malloc and network
Fuzz_System sys(input); Fuzz_System sys(input);
Ptr<Logger> logger(logger_new(), logger_kill); Ptr<Logger> logger(logger_new(sys.mem.get()), logger_kill);
if (logger == nullptr) {
return;
}
Ptr<Networking_Core> net(new_networking_ex(logger.get(), sys.mem.get(), sys.ns.get(), &ipp.ip, Ptr<Networking_Core> net(new_networking_ex(logger.get(), sys.mem.get(), sys.ns.get(), &ipp.ip,
ipp.port, ipp.port + 100, nullptr), ipp.port, ipp.port + 100, nullptr),
@ -72,7 +75,10 @@ void TestForwardReply(Fuzz_Data &input)
// rest of the fuzz data is input for malloc and network // rest of the fuzz data is input for malloc and network
Fuzz_System sys(input); Fuzz_System sys(input);
Ptr<Logger> logger(logger_new(), logger_kill); Ptr<Logger> logger(logger_new(sys.mem.get()), logger_kill);
if (logger == nullptr) {
return;
}
Ptr<Networking_Core> net(new_networking_ex(logger.get(), sys.mem.get(), sys.ns.get(), &ipp.ip, Ptr<Networking_Core> net(new_networking_ex(logger.get(), sys.mem.get(), sys.ns.get(), &ipp.ip,
ipp.port, ipp.port + 100, nullptr), ipp.port, ipp.port + 100, nullptr),

View File

@ -875,6 +875,10 @@ void set_friend_request_callback(Friend_Connections *fr_c, fr_request_cb *fr_req
int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data, int send_friend_request_packet(Friend_Connections *fr_c, int friendcon_id, uint32_t nospam_num, const uint8_t *data,
uint16_t length) uint16_t length)
{ {
// TODO(Jfreegman): This max packet size is too large to be handled by receiving clients
// when sent via the onion. We currently limit the length at a higher level, but
// this bounds check should be fixed to represent the max size of a packet that
// the onion client can handle.
if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) { if (1 + sizeof(nospam_num) + length > ONION_CLIENT_MAX_DATA_SIZE || length == 0) {
return -1; return -1;
} }

View File

@ -14,7 +14,8 @@
#include "attributes.h" #include "attributes.h"
#include "friend_connection.h" #include "friend_connection.h"
#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - (1 + sizeof(uint32_t))) // TODO(Jfreegman): This should be the maximum size that an onion client can handle.
#define MAX_FRIEND_REQUEST_DATA_SIZE (ONION_CLIENT_MAX_DATA_SIZE - 100)
typedef struct Friend_Requests Friend_Requests; typedef struct Friend_Requests Friend_Requests;

View File

@ -9,7 +9,7 @@
#include "group.h" #include "group.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h> #include <stdlib.h> // calloc, free
#include <string.h> #include <string.h>
#include "DHT.h" #include "DHT.h"
@ -20,9 +20,11 @@
#include "friend_connection.h" #include "friend_connection.h"
#include "group_common.h" #include "group_common.h"
#include "logger.h" #include "logger.h"
#include "mem.h"
#include "mono_time.h" #include "mono_time.h"
#include "net_crypto.h" #include "net_crypto.h"
#include "network.h" #include "network.h"
#include "sort.h"
#include "state.h" #include "state.h"
#include "util.h" #include "util.h"
@ -957,24 +959,75 @@ static bool delpeer(Group_Chats *g_c, uint32_t groupnumber, int peer_index, void
/** Order peers with friends first and with more recently active earlier */ /** Order peers with friends first and with more recently active earlier */
non_null() non_null()
static int cmp_frozen(const void *a, const void *b) static bool group_peer_less_handler(const void *object, const void *a, const void *b)
{ {
const Group_Peer *pa = (const Group_Peer *)a; const Group_Peer *pa = (const Group_Peer *)a;
const Group_Peer *pb = (const Group_Peer *)b; const Group_Peer *pb = (const Group_Peer *)b;
if (pa->is_friend ^ pb->is_friend) { if (((pa->is_friend ? 1 : 0) ^ (pb->is_friend ? 1 : 0)) != 0) {
return pa->is_friend ? -1 : 1; return pa->is_friend;
} }
return cmp_uint(pb->last_active, pa->last_active); return cmp_uint(pb->last_active, pa->last_active) < 0;
} }
non_null()
static const void *group_peer_get_handler(const void *arr, uint32_t index)
{
const Group_Peer *entries = (const Group_Peer *)arr;
return &entries[index];
}
non_null()
static void group_peer_set_handler(void *arr, uint32_t index, const void *val)
{
Group_Peer *entries = (Group_Peer *)arr;
const Group_Peer *entry = (const Group_Peer *)val;
entries[index] = *entry;
}
non_null()
static void *group_peer_subarr_handler(void *arr, uint32_t index, uint32_t size)
{
Group_Peer *entries = (Group_Peer *)arr;
return &entries[index];
}
non_null()
static void *group_peer_alloc_handler(const void *object, uint32_t size)
{
const Memory *mem = (const Memory *)object;
Group_Peer *tmp = (Group_Peer *)mem_valloc(mem, size, sizeof(Group_Peer));
if (tmp == nullptr) {
return nullptr;
}
return tmp;
}
non_null()
static void group_peer_delete_handler(const void *object, void *arr, uint32_t size)
{
const Memory *mem = (const Memory *)object;
mem_delete(mem, arr);
}
static const Sort_Funcs group_peer_cmp_funcs = {
group_peer_less_handler,
group_peer_get_handler,
group_peer_set_handler,
group_peer_subarr_handler,
group_peer_alloc_handler,
group_peer_delete_handler,
};
/** @brief Delete frozen peers as necessary to ensure at most `g->maxfrozen` remain. /** @brief Delete frozen peers as necessary to ensure at most `g->maxfrozen` remain.
* *
* @retval true if any frozen peers are removed. * @retval true if any frozen peers are removed.
*/ */
non_null() non_null()
static bool delete_old_frozen(Group_c *g) static bool delete_old_frozen(Group_c *g, const Memory *mem)
{ {
if (g->numfrozen <= g->maxfrozen) { if (g->numfrozen <= g->maxfrozen) {
return false; return false;
@ -987,7 +1040,7 @@ static bool delete_old_frozen(Group_c *g)
return true; return true;
} }
qsort(g->frozen, g->numfrozen, sizeof(Group_Peer), cmp_frozen); merge_sort(g->frozen, g->numfrozen, mem, &group_peer_cmp_funcs);
Group_Peer *temp = (Group_Peer *)realloc(g->frozen, g->maxfrozen * sizeof(Group_Peer)); Group_Peer *temp = (Group_Peer *)realloc(g->frozen, g->maxfrozen * sizeof(Group_Peer));
@ -1032,7 +1085,7 @@ static bool freeze_peer(Group_Chats *g_c, uint32_t groupnumber, int peer_index,
++g->numfrozen; ++g->numfrozen;
delete_old_frozen(g); delete_old_frozen(g, g_c->m->mem);
return true; return true;
} }
@ -1519,7 +1572,7 @@ int group_set_max_frozen(const Group_Chats *g_c, uint32_t groupnumber, uint32_t
} }
g->maxfrozen = maxfrozen; g->maxfrozen = maxfrozen;
delete_old_frozen(g); delete_old_frozen(g, g_c->m->mem);
return 0; return 0;
} }

View File

@ -19,7 +19,8 @@ void TestUnpackAnnouncesList(Fuzz_Data &input)
// TODO(iphydf): How do we know the packed size? // TODO(iphydf): How do we know the packed size?
CONSUME1_OR_RETURN(const uint16_t, packed_size, input); CONSUME1_OR_RETURN(const uint16_t, packed_size, input);
Logger *logger = logger_new(); Test_Memory mem;
Logger *logger = logger_new(mem);
if (gca_unpack_announces_list(logger, input.data(), input.size(), announces.data(), max_count) if (gca_unpack_announces_list(logger, input.data(), input.size(), announces.data(), max_count)
!= -1) { != -1) {
// Always allocate at least something to avoid passing nullptr to functions below. // Always allocate at least something to avoid passing nullptr to functions below.
@ -38,7 +39,8 @@ void TestUnpackPublicAnnounce(Fuzz_Data &input)
// TODO(iphydf): How do we know the packed size? // TODO(iphydf): How do we know the packed size?
CONSUME1_OR_RETURN(const uint16_t, packed_size, input); CONSUME1_OR_RETURN(const uint16_t, packed_size, input);
Logger *logger = logger_new(); Test_Memory mem;
Logger *logger = logger_new(mem);
if (gca_unpack_public_announce(logger, input.data(), input.size(), &public_announce) != -1) { if (gca_unpack_public_announce(logger, input.data(), input.size(), &public_announce) != -1) {
// Always allocate at least something to avoid passing nullptr to functions below. // Always allocate at least something to avoid passing nullptr to functions below.
std::vector<uint8_t> packed(packed_size + 1); std::vector<uint8_t> packed(packed_size + 1);
@ -50,7 +52,7 @@ void TestUnpackPublicAnnounce(Fuzz_Data &input)
void TestDoGca(Fuzz_Data &input) void TestDoGca(Fuzz_Data &input)
{ {
Test_Memory mem; Test_Memory mem;
std::unique_ptr<Logger, void (*)(Logger *)> logger(logger_new(), logger_kill); std::unique_ptr<Logger, void (*)(Logger *)> logger(logger_new(mem), logger_kill);
uint64_t clock = 1; uint64_t clock = 1;
std::unique_ptr<Mono_Time, std::function<void(Mono_Time *)>> mono_time( std::unique_ptr<Mono_Time, std::function<void(Mono_Time *)>> mono_time(

View File

@ -118,11 +118,12 @@ TEST_F(Announces, AnnouncesGetAndCleanup)
struct AnnouncesPack : ::testing::Test { struct AnnouncesPack : ::testing::Test {
protected: protected:
std::vector<GC_Announce> announces_; std::vector<GC_Announce> announces_;
Test_Memory mem_;
Logger *logger_ = nullptr; Logger *logger_ = nullptr;
void SetUp() override void SetUp() override
{ {
logger_ = logger_new(); logger_ = logger_new(mem_);
ASSERT_NE(logger_, nullptr); ASSERT_NE(logger_, nullptr);
// Add an announce without TCP relay. // Add an announce without TCP relay.

View File

@ -30,6 +30,7 @@
#include "group_moderation.h" #include "group_moderation.h"
#include "group_pack.h" #include "group_pack.h"
#include "logger.h" #include "logger.h"
#include "mem.h"
#include "mono_time.h" #include "mono_time.h"
#include "net_crypto.h" #include "net_crypto.h"
#include "network.h" #include "network.h"
@ -1473,8 +1474,8 @@ static bool sign_gc_shared_state(GC_Chat *chat)
* Return -2 on decryption failure. * Return -2 on decryption failure.
* Return -3 if plaintext payload length is invalid. * Return -3 if plaintext payload length is invalid.
*/ */
non_null(1, 2, 3, 5, 6) nullable(4) non_null(1, 2, 3, 4, 6, 7) nullable(5)
static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id, static int group_packet_unwrap(const Logger *log, const Memory *mem, const GC_Connection *gconn, uint8_t *data, uint64_t *message_id,
uint8_t *packet_type, const uint8_t *packet, uint16_t length) uint8_t *packet_type, const uint8_t *packet, uint16_t length)
{ {
assert(data != nullptr); assert(data != nullptr);
@ -1492,7 +1493,7 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui
return -1; return -1;
} }
int plain_len = decrypt_data_symmetric(gconn->session_shared_key, packet, packet + CRYPTO_NONCE_SIZE, int plain_len = decrypt_data_symmetric(mem, gconn->session_shared_key, packet, packet + CRYPTO_NONCE_SIZE,
length - CRYPTO_NONCE_SIZE, plain); length - CRYPTO_NONCE_SIZE, plain);
if (plain_len <= 0) { if (plain_len <= 0) {
@ -1533,7 +1534,7 @@ static int group_packet_unwrap(const Logger *log, const GC_Connection *gconn, ui
} }
int group_packet_wrap( int group_packet_wrap(
const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet, const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id, uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id,
uint8_t gp_packet_type, Net_Packet_Type net_packet_type) uint8_t gp_packet_type, Net_Packet_Type net_packet_type)
{ {
@ -1588,7 +1589,7 @@ int group_packet_wrap(
return -2; return -2;
} }
const int enc_len = encrypt_data_symmetric(shared_key, nonce, plain, plain_len, encrypt); const int enc_len = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_len, encrypt);
free(plain); free(plain);
@ -1634,7 +1635,7 @@ static bool send_lossy_group_packet(const GC_Chat *chat, const GC_Connection *gc
} }
const int len = group_packet_wrap( const int len = group_packet_wrap(
chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet, chat->log, chat->mem, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
packet_size, data, length, 0, packet_type, NET_PACKET_GC_LOSSY); packet_size, data, length, 0, packet_type, NET_PACKET_GC_LOSSY);
if (len < 0) { if (len < 0) {
@ -5508,7 +5509,7 @@ static int handle_gc_broadcast(const GC_Session *c, GC_Chat *chat, uint32_t peer
* Return -2 if decryption fails. * Return -2 if decryption fails.
*/ */
non_null() non_null()
static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_sk, const uint8_t *sender_pk, static int unwrap_group_handshake_packet(const Logger *log, const Memory *mem, const uint8_t *self_sk, const uint8_t *sender_pk,
uint8_t *plain, size_t plain_size, const uint8_t *packet, uint16_t length) uint8_t *plain, size_t plain_size, const uint8_t *packet, uint16_t length)
{ {
if (length <= CRYPTO_NONCE_SIZE) { if (length <= CRYPTO_NONCE_SIZE) {
@ -5516,7 +5517,7 @@ static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_
return -1; return -1;
} }
const int plain_len = decrypt_data(sender_pk, self_sk, packet, packet + CRYPTO_NONCE_SIZE, const int plain_len = decrypt_data(mem, sender_pk, self_sk, packet, packet + CRYPTO_NONCE_SIZE,
length - CRYPTO_NONCE_SIZE, plain); length - CRYPTO_NONCE_SIZE, plain);
if (plain_len < 0 || (uint32_t)plain_len != plain_size) { if (plain_len < 0 || (uint32_t)plain_len != plain_size) {
@ -5539,7 +5540,7 @@ static int unwrap_group_handshake_packet(const Logger *log, const uint8_t *self_
*/ */
non_null() non_null()
static int wrap_group_handshake_packet( static int wrap_group_handshake_packet(
const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *self_sk, const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *self_sk,
const uint8_t *target_pk, uint8_t *packet, uint32_t packet_size, const uint8_t *target_pk, uint8_t *packet, uint32_t packet_size,
const uint8_t *data, uint16_t length) const uint8_t *data, uint16_t length)
{ {
@ -5558,7 +5559,7 @@ static int wrap_group_handshake_packet(
return -2; return -2;
} }
const int enc_len = encrypt_data(target_pk, self_sk, nonce, data, length, encrypt); const int enc_len = encrypt_data(mem, target_pk, self_sk, nonce, data, length, encrypt);
if (enc_len < 0 || (size_t)enc_len != encrypt_buf_size) { if (enc_len < 0 || (size_t)enc_len != encrypt_buf_size) {
LOGGER_ERROR(log, "Failed to encrypt group handshake packet (len: %d)", enc_len); LOGGER_ERROR(log, "Failed to encrypt group handshake packet (len: %d)", enc_len);
@ -5622,7 +5623,7 @@ static int make_gc_handshake_packet(const GC_Chat *chat, const GC_Connection *gc
} }
const int enc_len = wrap_group_handshake_packet( const int enc_len = wrap_group_handshake_packet(
chat->log, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc, chat->log, chat->mem, chat->rng, chat->self_public_key.enc, chat->self_secret_key.enc,
gconn->addr.public_key.enc, packet, (uint16_t)packet_size, data, length); gconn->addr.public_key.enc, packet, (uint16_t)packet_size, data, length);
if (enc_len != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + nodes_size) { if (enc_len != GC_MIN_ENCRYPTED_HS_PAYLOAD_SIZE + nodes_size) {
@ -5951,7 +5952,7 @@ static int handle_gc_handshake_packet(GC_Chat *chat, const uint8_t *sender_pk, c
return -1; return -1;
} }
const int plain_len = unwrap_group_handshake_packet(chat->log, chat->self_secret_key.enc, sender_pk, data, const int plain_len = unwrap_group_handshake_packet(chat->log, chat->mem, chat->self_secret_key.enc, sender_pk, data,
data_buf_size, packet, length); data_buf_size, packet, length);
if (plain_len < GC_MIN_HS_PACKET_PAYLOAD_SIZE) { if (plain_len < GC_MIN_HS_PACKET_PAYLOAD_SIZE) {
@ -6181,7 +6182,7 @@ static bool handle_gc_lossless_packet(const GC_Session *c, GC_Chat *chat, const
uint8_t packet_type; uint8_t packet_type;
uint64_t message_id; uint64_t message_id;
const int len = group_packet_unwrap(chat->log, gconn, data, &message_id, &packet_type, packet, length); const int len = group_packet_unwrap(chat->log, chat->mem, gconn, data, &message_id, &packet_type, packet, length);
if (len < 0) { if (len < 0) {
Ip_Ntoa ip_str; Ip_Ntoa ip_str;
@ -6334,7 +6335,7 @@ static bool handle_gc_lossy_packet(const GC_Session *c, GC_Chat *chat, const uin
uint8_t packet_type; uint8_t packet_type;
const int len = group_packet_unwrap(chat->log, gconn, data, nullptr, &packet_type, packet, length); const int len = group_packet_unwrap(chat->log, chat->mem, gconn, data, nullptr, &packet_type, packet, length);
if (len <= 0) { if (len <= 0) {
Ip_Ntoa ip_str; Ip_Ntoa ip_str;

View File

@ -22,6 +22,7 @@
#include "group_common.h" #include "group_common.h"
#include "group_connection.h" #include "group_connection.h"
#include "logger.h" #include "logger.h"
#include "mem.h"
#include "network.h" #include "network.h"
#define GC_PING_TIMEOUT 12 #define GC_PING_TIMEOUT 12
@ -141,9 +142,9 @@ int get_peer_number_of_enc_pk(const GC_Chat *chat, const uint8_t *public_enc_key
* Return -2 if malloc fails. * Return -2 if malloc fails.
* Return -3 if encryption fails. * Return -3 if encryption fails.
*/ */
non_null(1, 2, 3, 4, 5) nullable(7) non_null(1, 2, 3, 4, 5, 6) nullable(8)
int group_packet_wrap( int group_packet_wrap(
const Logger *log, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet, const Logger *log, const Memory *mem, const Random *rng, const uint8_t *self_pk, const uint8_t *shared_key, uint8_t *packet,
uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id, uint16_t packet_size, const uint8_t *data, uint16_t length, uint64_t message_id,
uint8_t gp_packet_type, Net_Packet_Type net_packet_type); uint8_t gp_packet_type, Net_Packet_Type net_packet_type);

View File

@ -52,7 +52,7 @@
#define MAX_GC_PACKET_SIZE (MAX_GC_PACKET_CHUNK_SIZE * 100) #define MAX_GC_PACKET_SIZE (MAX_GC_PACKET_CHUNK_SIZE * 100)
/* Max number of messages to store in the send/recv arrays */ /* Max number of messages to store in the send/recv arrays */
#define GCC_BUFFER_SIZE 8192 #define GCC_BUFFER_SIZE 2048
/** Self UDP status. Must correspond to return values from `ipport_self_copy()`. */ /** Self UDP status. Must correspond to return values from `ipport_self_copy()`. */
typedef enum Self_UDP_Status { typedef enum Self_UDP_Status {

View File

@ -629,7 +629,7 @@ int gcc_encrypt_and_send_lossless_packet(const GC_Chat *chat, const GC_Connectio
} }
const int enc_len = group_packet_wrap( const int enc_len = group_packet_wrap(
chat->log, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet, chat->log, chat->mem, chat->rng, chat->self_public_key.enc, gconn->session_shared_key, packet,
packet_size, data, length, message_id, packet_type, NET_PACKET_GC_LOSSLESS); packet_size, data, length, message_id, packet_type, NET_PACKET_GC_LOSSLESS);
if (enc_len < 0) { if (enc_len < 0) {

View File

@ -191,9 +191,9 @@ struct SanctionsListMod : ::testing::Test {
protected: protected:
Extended_Public_Key pk; Extended_Public_Key pk;
Extended_Secret_Key sk; Extended_Secret_Key sk;
Logger *log = logger_new();
Test_Random rng; Test_Random rng;
Test_Memory mem; Test_Memory mem;
Logger *log = logger_new(mem);
Moderation mod{mem}; Moderation mod{mem};
Mod_Sanction sanctions[2] = {}; Mod_Sanction sanctions[2] = {};

View File

@ -14,6 +14,7 @@
#include "crypto_core.h" #include "crypto_core.h"
#include "group_announce.h" #include "group_announce.h"
#include "logger.h" #include "logger.h"
#include "mem.h"
#include "mono_time.h" #include "mono_time.h"
#include "network.h" #include "network.h"
#include "onion_announce.h" #include "onion_announce.h"
@ -76,7 +77,7 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a)
} }
int create_gca_announce_request( int create_gca_announce_request(
const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id,
const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data, const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data,
const uint8_t *gc_data, uint16_t gc_data_length) const uint8_t *gc_data, uint16_t gc_data_length)
@ -108,7 +109,7 @@ int create_gca_announce_request(
random_nonce(rng, packet + 1); random_nonce(rng, packet + 1);
memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_NONCE_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE);
const int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, const int len = encrypt_data(mem, dest_client_id, secret_key, packet + 1, plain,
encrypted_size, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); encrypted_size, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
const uint32_t full_length = (uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE; const uint32_t full_length = (uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE;

View File

@ -9,6 +9,7 @@
#include "attributes.h" #include "attributes.h"
#include "crypto_core.h" #include "crypto_core.h"
#include "group_announce.h" #include "group_announce.h"
#include "mem.h"
#include "onion_announce.h" #include "onion_announce.h"
non_null() non_null()
@ -16,7 +17,7 @@ void gca_onion_init(GC_Announces_List *group_announce, Onion_Announce *onion_a);
non_null() non_null()
int create_gca_announce_request( int create_gca_announce_request(
const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id,
const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data, const uint8_t *client_id, const uint8_t *data_public_key, uint64_t sendback_data,
const uint8_t *gc_data, uint16_t gc_data_length); const uint8_t *gc_data, uint16_t gc_data_length);

View File

@ -13,69 +13,41 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "attributes.h"
#include "ccompat.h" #include "ccompat.h"
#include "mem.h"
struct Logger { struct Logger {
const Memory *mem;
logger_cb *callback; logger_cb *callback;
void *context; void *context;
void *userdata; void *userdata;
}; };
#ifndef NDEBUG
static const char *logger_level_name(Logger_Level level)
{
switch (level) {
case LOGGER_LEVEL_TRACE:
return "TRACE";
case LOGGER_LEVEL_DEBUG:
return "DEBUG";
case LOGGER_LEVEL_INFO:
return "INFO";
case LOGGER_LEVEL_WARNING:
return "WARNING";
case LOGGER_LEVEL_ERROR:
return "ERROR";
}
return "<unknown>";
}
#endif /* NDEBUG */
non_null(1, 3, 5, 6) nullable(7)
static void logger_stderr_handler(void *context, Logger_Level level, const char *file, int line, const char *func,
const char *message, void *userdata)
{
#ifndef NDEBUG
// GL stands for "global logger".
fprintf(stderr, "[GL] %s %s:%d(%s): %s\n", logger_level_name(level), file, line, func, message);
fprintf(stderr, "Default stderr logger triggered; aborting program\n");
abort();
#endif /* NDEBUG */
}
static const Logger logger_stderr = {
logger_stderr_handler,
nullptr,
nullptr,
};
/* /*
* Public Functions * Public Functions
*/ */
Logger *logger_new(void) Logger *logger_new(const Memory *mem)
{ {
return (Logger *)calloc(1, sizeof(Logger)); Logger *log = (Logger *)mem_alloc(mem, sizeof(Logger));
if (log == nullptr) {
return nullptr;
}
log->mem = mem;
return log;
} }
void logger_kill(Logger *log) void logger_kill(Logger *log)
{ {
free(log); if (log == nullptr) {
return;
}
mem_delete(log->mem, log);
} }
void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata) void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata)
@ -89,7 +61,7 @@ void logger_write(const Logger *log, Logger_Level level, const char *file, int l
const char *format, ...) const char *format, ...)
{ {
if (log == nullptr) { if (log == nullptr) {
log = &logger_stderr; return;
} }
if (log->callback == nullptr) { if (log->callback == nullptr) {

View File

@ -12,6 +12,7 @@
#include <stdint.h> #include <stdint.h>
#include "attributes.h" #include "attributes.h"
#include "mem.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -38,7 +39,8 @@ typedef void logger_cb(void *context, Logger_Level level, const char *file, int
/** /**
* Creates a new logger with logging disabled (callback is NULL) by default. * Creates a new logger with logging disabled (callback is NULL) by default.
*/ */
Logger *logger_new(void); non_null()
Logger *logger_new(const Memory *mem);
/** /**
* Frees all resources associated with the logger. * Frees all resources associated with the logger.

View File

@ -230,7 +230,7 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin
packet[0] = NET_PACKET_COOKIE_REQUEST; packet[0] = NET_PACKET_COOKIE_REQUEST;
memcpy(packet + 1, dht_get_self_public_key(c->dht), CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1, dht_get_self_public_key(c->dht), CRYPTO_PUBLIC_KEY_SIZE);
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
const int len = encrypt_data_symmetric(shared_key, nonce, plain, sizeof(plain), const int len = encrypt_data_symmetric(c->mem, shared_key, nonce, plain, sizeof(plain),
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) { if (len != COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE) {
@ -246,7 +246,7 @@ static int create_cookie_request(const Net_Crypto *c, uint8_t *packet, const uin
* @retval 0 on success. * @retval 0 on success.
*/ */
non_null() non_null()
static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes, static int create_cookie(const Memory *mem, const Random *rng, const Mono_Time *mono_time, uint8_t *cookie, const uint8_t *bytes,
const uint8_t *encryption_key) const uint8_t *encryption_key)
{ {
uint8_t contents[COOKIE_CONTENTS_LENGTH]; uint8_t contents[COOKIE_CONTENTS_LENGTH];
@ -254,7 +254,7 @@ static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t
memcpy(contents, &temp_time, sizeof(temp_time)); memcpy(contents, &temp_time, sizeof(temp_time));
memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH); memcpy(contents + sizeof(temp_time), bytes, COOKIE_DATA_LENGTH);
random_nonce(rng, cookie); random_nonce(rng, cookie);
const int len = encrypt_data_symmetric(encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE); const int len = encrypt_data_symmetric(mem, encryption_key, cookie, contents, sizeof(contents), cookie + CRYPTO_NONCE_SIZE);
if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) { if (len != COOKIE_LENGTH - CRYPTO_NONCE_SIZE) {
return -1; return -1;
@ -269,11 +269,11 @@ static int create_cookie(const Random *rng, const Mono_Time *mono_time, uint8_t
* @retval 0 on success. * @retval 0 on success.
*/ */
non_null() non_null()
static int open_cookie(const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie, static int open_cookie(const Memory *mem, const Mono_Time *mono_time, uint8_t *bytes, const uint8_t *cookie,
const uint8_t *encryption_key) const uint8_t *encryption_key)
{ {
uint8_t contents[COOKIE_CONTENTS_LENGTH]; uint8_t contents[COOKIE_CONTENTS_LENGTH];
const int len = decrypt_data_symmetric(encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE, const int len = decrypt_data_symmetric(mem, encryption_key, cookie, cookie + CRYPTO_NONCE_SIZE,
COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents); COOKIE_LENGTH - CRYPTO_NONCE_SIZE, contents);
if (len != sizeof(contents)) { if (len != sizeof(contents)) {
@ -308,14 +308,14 @@ static int create_cookie_response(const Net_Crypto *c, uint8_t *packet, const ui
memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
if (create_cookie(c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) { if (create_cookie(c->mem, c->rng, c->mono_time, plain, cookie_plain, c->secret_symmetric_key) != 0) {
return -1; return -1;
} }
memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t)); memcpy(plain + COOKIE_LENGTH, request_plain + COOKIE_DATA_LENGTH, sizeof(uint64_t));
packet[0] = NET_PACKET_COOKIE_RESPONSE; packet[0] = NET_PACKET_COOKIE_RESPONSE;
random_nonce(c->rng, packet + 1); random_nonce(c->rng, packet + 1);
const int len = encrypt_data_symmetric(shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE); const int len = encrypt_data_symmetric(c->mem, shared_key, packet + 1, plain, sizeof(plain), packet + 1 + CRYPTO_NONCE_SIZE);
if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) { if (len != COOKIE_RESPONSE_LENGTH - (1 + CRYPTO_NONCE_SIZE)) {
return -1; return -1;
@ -342,7 +342,7 @@ static int handle_cookie_request(const Net_Crypto *c, uint8_t *request_plain, ui
memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE); memcpy(dht_public_key, packet + 1, CRYPTO_PUBLIC_KEY_SIZE);
const uint8_t *tmp_shared_key = dht_get_shared_key_sent(c->dht, dht_public_key); const uint8_t *tmp_shared_key = dht_get_shared_key_sent(c->dht, dht_public_key);
memcpy(shared_key, tmp_shared_key, CRYPTO_SHARED_KEY_SIZE); memcpy(shared_key, tmp_shared_key, CRYPTO_SHARED_KEY_SIZE);
const int len = decrypt_data_symmetric(shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, const int len = decrypt_data_symmetric(c->mem, shared_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, COOKIE_REQUEST_PLAIN_LENGTH + CRYPTO_MAC_SIZE,
request_plain); request_plain);
@ -439,7 +439,7 @@ static int tcp_oob_handle_cookie_request(const Net_Crypto *c, unsigned int tcp_c
* @retval COOKIE_LENGTH on success. * @retval COOKIE_LENGTH on success.
*/ */
non_null() non_null()
static int handle_cookie_response(uint8_t *cookie, uint64_t *number, static int handle_cookie_response(const Memory *mem, uint8_t *cookie, uint64_t *number,
const uint8_t *packet, uint16_t length, const uint8_t *packet, uint16_t length,
const uint8_t *shared_key) const uint8_t *shared_key)
{ {
@ -448,7 +448,7 @@ static int handle_cookie_response(uint8_t *cookie, uint64_t *number,
} }
uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)]; uint8_t plain[COOKIE_LENGTH + sizeof(uint64_t)];
const int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, const int len = decrypt_data_symmetric(mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
length - (1 + CRYPTO_NONCE_SIZE), plain); length - (1 + CRYPTO_NONCE_SIZE), plain);
if (len != sizeof(plain)) { if (len != sizeof(plain)) {
@ -481,13 +481,13 @@ static int create_crypto_handshake(const Net_Crypto *c, uint8_t *packet, const u
memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE); memcpy(cookie_plain, peer_real_pk, CRYPTO_PUBLIC_KEY_SIZE);
memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE); memcpy(cookie_plain + CRYPTO_PUBLIC_KEY_SIZE, peer_dht_pubkey, CRYPTO_PUBLIC_KEY_SIZE);
if (create_cookie(c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE, if (create_cookie(c->mem, c->rng, c->mono_time, plain + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE,
cookie_plain, c->secret_symmetric_key) != 0) { cookie_plain, c->secret_symmetric_key) != 0) {
return -1; return -1;
} }
random_nonce(c->rng, packet + 1 + COOKIE_LENGTH); random_nonce(c->rng, packet + 1 + COOKIE_LENGTH);
const int len = encrypt_data(peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain), const int len = encrypt_data(c->mem, peer_real_pk, c->self_secret_key, packet + 1 + COOKIE_LENGTH, plain, sizeof(plain),
packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE); packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE);
if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) { if (len != HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE)) {
@ -528,7 +528,7 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t
uint8_t cookie_plain[COOKIE_DATA_LENGTH]; uint8_t cookie_plain[COOKIE_DATA_LENGTH];
if (open_cookie(c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) { if (open_cookie(c->mem, c->mono_time, cookie_plain, packet + 1, c->secret_symmetric_key) != 0) {
return false; return false;
} }
@ -540,7 +540,7 @@ static bool handle_crypto_handshake(const Net_Crypto *c, uint8_t *nonce, uint8_t
crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH); crypto_sha512(cookie_hash, packet + 1, COOKIE_LENGTH);
uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH]; uint8_t plain[CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA512_SIZE + COOKIE_LENGTH];
const int len = decrypt_data(cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH, const int len = decrypt_data(c->mem, cookie_plain, c->self_secret_key, packet + 1 + COOKIE_LENGTH,
packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE, packet + 1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE,
HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain); HANDSHAKE_PACKET_LENGTH - (1 + COOKIE_LENGTH + CRYPTO_NONCE_SIZE), plain);
@ -1084,7 +1084,7 @@ static int send_data_packet(Net_Crypto *c, int crypt_connection_id, const uint8_
VLA(uint8_t, packet, packet_size); VLA(uint8_t, packet, packet_size);
packet[0] = NET_PACKET_CRYPTO_DATA; packet[0] = NET_PACKET_CRYPTO_DATA;
memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t)); memcpy(packet + 1, conn->sent_nonce + (CRYPTO_NONCE_SIZE - sizeof(uint16_t)), sizeof(uint16_t));
const int len = encrypt_data_symmetric(conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t)); const int len = encrypt_data_symmetric(c->mem, conn->shared_key, conn->sent_nonce, data, length, packet + 1 + sizeof(uint16_t));
if (len + 1 + sizeof(uint16_t) != packet_size) { if (len + 1 + sizeof(uint16_t) != packet_size) {
LOGGER_ERROR(c->log, "encryption failed: %d", len); LOGGER_ERROR(c->log, "encryption failed: %d", len);
@ -1255,7 +1255,7 @@ static int handle_data_packet(const Net_Crypto *c, int crypt_connection_id, uint
net_unpack_u16(packet + 1, &num); net_unpack_u16(packet + 1, &num);
const uint16_t diff = num - num_cur_nonce; const uint16_t diff = num - num_cur_nonce;
increment_nonce_number(nonce, diff); increment_nonce_number(nonce, diff);
const int len = decrypt_data_symmetric(conn->shared_key, nonce, packet + 1 + sizeof(uint16_t), const int len = decrypt_data_symmetric(c->mem, conn->shared_key, nonce, packet + 1 + sizeof(uint16_t),
length - (1 + sizeof(uint16_t)), data); length - (1 + sizeof(uint16_t)), data);
if ((unsigned int)len != length - crypto_packet_overhead) { if ((unsigned int)len != length - crypto_packet_overhead) {
@ -1662,7 +1662,7 @@ static int handle_packet_cookie_response(Net_Crypto *c, int crypt_connection_id,
uint8_t cookie[COOKIE_LENGTH]; uint8_t cookie[COOKIE_LENGTH];
uint64_t number; uint64_t number;
if (handle_cookie_response(cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) { if (handle_cookie_response(c->mem, cookie, &number, packet, length, conn->shared_key) != sizeof(cookie)) {
return -1; return -1;
} }

View File

@ -513,6 +513,12 @@ static int sys_listen(void *obj, Socket sock, int backlog)
return listen(net_socket_to_native(sock), backlog); return listen(net_socket_to_native(sock), backlog);
} }
non_null()
static int sys_connect(void *obj, Socket sock, const Network_Addr *addr)
{
return connect(net_socket_to_native(sock), (const struct sockaddr *)&addr->addr, addr->size);
}
non_null() non_null()
static int sys_recvbuf(void *obj, Socket sock) static int sys_recvbuf(void *obj, Socket sock)
{ {
@ -586,11 +592,98 @@ static int sys_setsockopt(void *obj, Socket sock, int level, int optname, const
return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen); return setsockopt(net_socket_to_native(sock), level, optname, (const char *)optval, optlen);
} }
// sets and fills an array of addrs for address
// returns the number of entries in addrs
non_null()
static int sys_getaddrinfo(void *obj, const Memory *mem, const char *address, int family, int sock_type, Network_Addr **addrs)
{
assert(addrs != nullptr);
struct addrinfo hints = {0};
hints.ai_family = family;
// different platforms favour a different field
// hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
hints.ai_socktype = sock_type;
// hints.ai_protocol = protocol;
struct addrinfo *infos = nullptr;
const int rc = getaddrinfo(address, nullptr, &hints, &infos);
// Lookup failed.
if (rc != 0) {
// TODO(Green-Sky): log error
return 0;
}
const int32_t max_count = INT32_MAX / sizeof(Network_Addr);
// we count number of "valid" results
int result = 0;
for (struct addrinfo *walker = infos; walker != nullptr && result < max_count; walker = walker->ai_next) {
if (walker->ai_family == family || family == AF_UNSPEC) {
++result;
}
// do we need to check socktype/protocol?
}
assert(max_count >= result);
Network_Addr *tmp_addrs = (Network_Addr *)mem_valloc(mem, result, sizeof(Network_Addr));
if (tmp_addrs == nullptr) {
freeaddrinfo(infos);
return 0;
}
// now we fill in
int i = 0;
for (struct addrinfo *walker = infos; walker != nullptr; walker = walker->ai_next) {
if (walker->ai_family == family || family == AF_UNSPEC) {
tmp_addrs[i].size = sizeof(struct sockaddr_storage);
tmp_addrs[i].addr.ss_family = walker->ai_family;
// according to spec, storage is supposed to be large enough (and source shows they are)
// storage is 128 bytes
assert(walker->ai_addrlen <= tmp_addrs[i].size);
memcpy(&tmp_addrs[i].addr, walker->ai_addr, walker->ai_addrlen);
tmp_addrs[i].size = walker->ai_addrlen;
++i;
}
}
assert(i == result);
freeaddrinfo(infos);
*addrs = tmp_addrs;
// number of entries in addrs
return result;
}
non_null()
static int sys_freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs)
{
if (addrs == nullptr) {
return 0;
}
mem_delete(mem, addrs);
return 0;
}
static const Network_Funcs os_network_funcs = { static const Network_Funcs os_network_funcs = {
sys_close, sys_close,
sys_accept, sys_accept,
sys_bind, sys_bind,
sys_listen, sys_listen,
sys_connect,
sys_recvbuf, sys_recvbuf,
sys_recv, sys_recv,
sys_recvfrom, sys_recvfrom,
@ -600,8 +693,10 @@ static const Network_Funcs os_network_funcs = {
sys_socket_nonblock, sys_socket_nonblock,
sys_getsockopt, sys_getsockopt,
sys_setsockopt, sys_setsockopt,
sys_getaddrinfo,
sys_freeaddrinfo,
}; };
static const Network os_network_obj = {&os_network_funcs}; static const Network os_network_obj = {&os_network_funcs, nullptr};
const Network *os_network(void) const Network *os_network(void)
{ {
@ -882,7 +977,11 @@ bool set_socket_nosigpipe(const Network *ns, Socket sock)
bool set_socket_reuseaddr(const Network *ns, Socket sock) bool set_socket_reuseaddr(const Network *ns, Socket sock)
{ {
int set = 1; int set = 1;
#if defined(OS_WIN32)
return net_setsockopt(ns, sock, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, &set, sizeof(set)) == 0;
#else
return net_setsockopt(ns, sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0; return net_setsockopt(ns, sock, SOL_SOCKET, SO_REUSEADDR, &set, sizeof(set)) == 0;
#endif /* OS_WIN32 */
} }
bool set_socket_dualstack(const Network *ns, Socket sock) bool set_socket_dualstack(const Network *ns, Socket sock)
@ -1815,37 +1914,34 @@ bool addr_parse_ip(const char *address, IP *to)
* prefers v6 if `ip.family` was TOX_AF_UNSPEC and both available * prefers v6 if `ip.family` was TOX_AF_UNSPEC and both available
* Returns in `*extra` an IPv4 address, if family was TOX_AF_UNSPEC and `*to` is TOX_AF_INET6 * Returns in `*extra` an IPv4 address, if family was TOX_AF_UNSPEC and `*to` is TOX_AF_INET6
* *
* @return 0 on failure, `TOX_ADDR_RESOLVE_*` on success. * @return false on failure, true on success.
*/ */
non_null(1, 2, 3) nullable(4) non_null(1, 2, 3, 4) nullable(5)
static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra) static bool addr_resolve(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra)
{ {
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) { if ((true)) {
return 0; return false;
} }
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
if (address == nullptr || to == nullptr) { if (address == nullptr || to == nullptr) {
return 0; return false;
} }
const Family tox_family = to->family; const Family tox_family = to->family;
const int family = make_family(tox_family); const int family = make_family(tox_family);
struct addrinfo hints = {0}; Network_Addr *addrs = nullptr;
hints.ai_family = family; const int rc = ns->funcs->getaddrinfo(ns->obj, mem, address, family, 0, &addrs);
hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses.
struct addrinfo *server = nullptr; // Lookup failed / empty.
if (rc <= 0) {
const int rc = getaddrinfo(address, nullptr, &hints, &server); return false;
// Lookup failed.
if (rc != 0) {
return 0;
} }
assert(addrs != nullptr);
IP ip4; IP ip4;
ip_init(&ip4, false); // ipv6enabled = false ip_init(&ip4, false); // ipv6enabled = false
IP ip6; IP ip6;
@ -1854,16 +1950,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
int result = 0; int result = 0;
bool done = false; bool done = false;
for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) { for (int i = 0; i < rc && !done; ++i) {
switch (walker->ai_family) { switch (addrs[i].addr.ss_family) {
case AF_INET: { case AF_INET: {
if (walker->ai_family == family) { /* AF_INET requested, done */ if (addrs[i].addr.ss_family == family) { /* AF_INET requested, done */
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr; const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
get_ip4(&to->ip.v4, &addr->sin_addr); get_ip4(&to->ip.v4, &addr->sin_addr);
result = TOX_ADDR_RESOLVE_INET; result = TOX_ADDR_RESOLVE_INET;
done = true; done = true;
} else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */ } else if ((result & TOX_ADDR_RESOLVE_INET) == 0) { /* AF_UNSPEC requested, store away */
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr; const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
get_ip4(&ip4.ip.v4, &addr->sin_addr); get_ip4(&ip4.ip.v4, &addr->sin_addr);
result |= TOX_ADDR_RESOLVE_INET; result |= TOX_ADDR_RESOLVE_INET;
} }
@ -1872,16 +1968,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
} }
case AF_INET6: { case AF_INET6: {
if (walker->ai_family == family) { /* AF_INET6 requested, done */ if (addrs[i].addr.ss_family == family) { /* AF_INET6 requested, done */
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { if (addrs[i].size == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr; const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
get_ip6(&to->ip.v6, &addr->sin6_addr); get_ip6(&to->ip.v6, &addr->sin6_addr);
result = TOX_ADDR_RESOLVE_INET6; result = TOX_ADDR_RESOLVE_INET6;
done = true; done = true;
} }
} else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */ } else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */
if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { if (addrs[i].size == sizeof(struct sockaddr_in6)) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr; const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr;
get_ip6(&ip6.ip.v6, &addr->sin6_addr); get_ip6(&ip6.ip.v6, &addr->sin6_addr);
result |= TOX_ADDR_RESOLVE_INET6; result |= TOX_ADDR_RESOLVE_INET6;
} }
@ -1906,37 +2002,34 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr
} }
} }
freeaddrinfo(server); ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return result; return result != 0;
} }
bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra) bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled)
{ {
if (addr_resolve(ns, address, to, extra) == 0) { if (dns_enabled && addr_resolve(ns, mem, address, to, extra)) {
if (!addr_parse_ip(address, to)) { return true;
return false;
}
} }
return true; return addr_parse_ip(address, to);
} }
bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port) bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port)
{ {
struct sockaddr_storage addr = {0}; Network_Addr addr = {{0}};
size_t addrsize;
if (net_family_is_ipv4(ip_port->ip.family)) { if (net_family_is_ipv4(ip_port->ip.family)) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr; struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr.addr;
addrsize = sizeof(struct sockaddr_in); addr.size = sizeof(struct sockaddr_in);
addr4->sin_family = AF_INET; addr4->sin_family = AF_INET;
fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr); fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr);
addr4->sin_port = ip_port->port; addr4->sin_port = ip_port->port;
} else if (net_family_is_ipv6(ip_port->ip.family)) { } else if (net_family_is_ipv6(ip_port->ip.family)) {
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr; struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr.addr;
addrsize = sizeof(struct sockaddr_in6); addr.size = sizeof(struct sockaddr_in6);
addr6->sin6_family = AF_INET6; addr6->sin6_family = AF_INET6;
fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr); fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr);
addr6->sin6_port = ip_port->port; addr6->sin6_port = ip_port->port;
@ -1958,7 +2051,7 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
net_socket_to_native(sock), net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port)); net_socket_to_native(sock), net_ip_ntoa(&ip_port->ip, &ip_str), net_ntohs(ip_port->port));
errno = 0; errno = 0;
if (connect(net_socket_to_native(sock), (struct sockaddr *)&addr, addrsize) == -1) { if (ns->funcs->connect(ns->obj, sock, &addr) == -1) {
const int error = net_error(); const int error = net_error();
// Non-blocking socket: "Operation in progress" means it's connecting. // Non-blocking socket: "Operation in progress" means it's connecting.
@ -1974,7 +2067,7 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
return true; return true;
} }
int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type) int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled)
{ {
assert(node != nullptr); assert(node != nullptr);
@ -1996,6 +2089,10 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
return 1; return 1;
} }
if (!dns_enabled) {
return -1;
}
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
if ((true)) { if ((true)) {
IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port)); IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port));
@ -2010,25 +2107,29 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
} }
#endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */
// It's not an IP address, so now we try doing a DNS lookup. int type = make_socktype(tox_type);
struct addrinfo *infos; // ugly
const int ret = getaddrinfo(node, nullptr, nullptr, &infos); if (tox_type == -1) {
type = 0;
}
if (ret != 0) { // It's not an IP address, so now we try doing a DNS lookup.
Network_Addr *addrs = nullptr;
const int rc = ns->funcs->getaddrinfo(ns->obj, mem, node, AF_UNSPEC, type, &addrs);
// Lookup failed / empty.
if (rc <= 0) {
return -1; return -1;
} }
assert(addrs != nullptr);
// Used to avoid calloc parameter overflow // Used to avoid calloc parameter overflow
const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port); const size_t max_count = min_u64(SIZE_MAX, INT32_MAX) / sizeof(IP_Port);
const int type = make_socktype(tox_type);
size_t count = 0; size_t count = 0;
for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) { for (int i = 0; i < rc && count < max_count; ++i) {
if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) { if (addrs[i].addr.ss_family != AF_INET && addrs[i].addr.ss_family != AF_INET6) {
continue;
}
if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) {
continue; continue;
} }
@ -2038,40 +2139,36 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
assert(count <= max_count); assert(count <= max_count);
if (count == 0) { if (count == 0) {
freeaddrinfo(infos); ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return 0; return 0;
} }
IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port)); IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port));
if (ip_port == nullptr) { if (ip_port == nullptr) {
freeaddrinfo(infos); ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
*res = nullptr; *res = nullptr;
return -1; return -1;
} }
*res = ip_port; *res = ip_port;
for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) { for (int i = 0; i < rc && count < max_count; ++i) {
if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) { if (addrs[i].addr.ss_family == AF_INET) {
continue; const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr;
}
if (cur->ai_family == AF_INET) {
const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr;
ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr; ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr;
} else if (cur->ai_family == AF_INET6) { } else if (addrs[i].addr.ss_family == AF_INET6) {
const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr; const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)&addrs[i].addr;
memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6)); memcpy(ip_port->ip.ip.v6.uint8, addr->sin6_addr.s6_addr, sizeof(IP6));
} else { } else {
continue; continue;
} }
const Family *const family = make_tox_family(cur->ai_family); const Family *const family = make_tox_family(addrs[i].addr.ss_family);
assert(family != nullptr); assert(family != nullptr);
if (family == nullptr) { if (family == nullptr) {
freeaddrinfo(infos); ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return -1; return -1;
} }
@ -2080,7 +2177,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to
++ip_port; ++ip_port;
} }
freeaddrinfo(infos); ns->funcs->freeaddrinfo(ns->obj, mem, addrs);
return count; return count;
} }

View File

@ -39,6 +39,7 @@ typedef int net_close_cb(void *obj, Socket sock);
typedef Socket net_accept_cb(void *obj, Socket sock); typedef Socket net_accept_cb(void *obj, Socket sock);
typedef int net_bind_cb(void *obj, Socket sock, const Network_Addr *addr); typedef int net_bind_cb(void *obj, Socket sock, const Network_Addr *addr);
typedef int net_listen_cb(void *obj, Socket sock, int backlog); typedef int net_listen_cb(void *obj, Socket sock, int backlog);
typedef int net_connect_cb(void *obj, Socket sock, const Network_Addr *addr);
typedef int net_recvbuf_cb(void *obj, Socket sock); typedef int net_recvbuf_cb(void *obj, Socket sock);
typedef int net_recv_cb(void *obj, Socket sock, uint8_t *buf, size_t len); typedef int net_recv_cb(void *obj, Socket sock, uint8_t *buf, size_t len);
typedef int net_recvfrom_cb(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr); typedef int net_recvfrom_cb(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr);
@ -48,8 +49,8 @@ typedef Socket net_socket_cb(void *obj, int domain, int type, int proto);
typedef int net_socket_nonblock_cb(void *obj, Socket sock, bool nonblock); typedef int net_socket_nonblock_cb(void *obj, Socket sock, bool nonblock);
typedef int net_getsockopt_cb(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen); typedef int net_getsockopt_cb(void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen);
typedef int net_setsockopt_cb(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen); typedef int net_setsockopt_cb(void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen);
typedef int net_getaddrinfo_cb(void *obj, int family, Network_Addr **addrs); typedef int net_getaddrinfo_cb(void *obj, const Memory *mem, const char *address, int family, int protocol, Network_Addr **addrs);
typedef int net_freeaddrinfo_cb(void *obj, Network_Addr *addrs); typedef int net_freeaddrinfo_cb(void *obj, const Memory *mem, Network_Addr *addrs);
/** @brief Functions wrapping POSIX network functions. /** @brief Functions wrapping POSIX network functions.
* *
@ -61,6 +62,7 @@ typedef struct Network_Funcs {
net_accept_cb *accept; net_accept_cb *accept;
net_bind_cb *bind; net_bind_cb *bind;
net_listen_cb *listen; net_listen_cb *listen;
net_connect_cb *connect;
net_recvbuf_cb *recvbuf; net_recvbuf_cb *recvbuf;
net_recv_cb *recv; net_recv_cb *recv;
net_recvfrom_cb *recvfrom; net_recvfrom_cb *recvfrom;
@ -396,21 +398,23 @@ non_null()
void ipport_copy(IP_Port *target, const IP_Port *source); void ipport_copy(IP_Port *target, const IP_Port *source);
/** /**
* Resolves string into an IP address * @brief Resolves string into an IP address.
* *
* @param address a hostname (or something parseable to an IP address) * @param[in,out] ns Network object.
* @param to to.family MUST be initialized, either set to a specific IP version * @param[in] address a hostname (or something parseable to an IP address).
* @param[in,out] to to.family MUST be initialized, either set to a specific IP version
* (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both * (TOX_AF_INET/TOX_AF_INET6) or to the unspecified TOX_AF_UNSPEC (0), if both
* IP versions are acceptable * IP versions are acceptable.
* @param extra can be NULL and is only set in special circumstances, see returns * @param[out] extra can be NULL and is only set in special circumstances, see returns.
* @param[in] dns_enabled if false, DNS resolution is skipped.
* *
* Returns in `*to` a matching address (IPv6 or IPv4) * Returns in `*to` a matching address (IPv6 or IPv4).
* Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was TOX_AF_UNSPEC * Returns in `*extra`, if not NULL, an IPv4 address, if `to->family` was `TOX_AF_UNSPEC`.
* *
* @return true on success, false on failure * @return true on success, false on failure
*/ */
non_null(1, 2, 3) nullable(4) non_null(1, 2, 3, 4) nullable(5)
bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra); bool addr_resolve_or_parse_ip(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra, bool dns_enabled);
/** @brief Function to receive data, ip and port of sender is put into ip_port. /** @brief Function to receive data, ip and port of sender is put into ip_port.
* Packet data is put into data. * Packet data is put into data.
@ -501,7 +505,7 @@ void networking_poll(const Networking_Core *net, void *userdata);
* Return false on failure. * Return false on failure.
*/ */
non_null() non_null()
bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port); bool net_connect(const Network *ns, const Memory *mem, const Logger *log, Socket sock, const IP_Port *ip_port);
/** @brief High-level getaddrinfo implementation. /** @brief High-level getaddrinfo implementation.
* *
@ -510,14 +514,21 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por
* address that can be specified by calling `net_connect()`, the port is ignored. * address that can be specified by calling `net_connect()`, the port is ignored.
* *
* Skip all addresses with socktype != type (use type = -1 to get all addresses) * Skip all addresses with socktype != type (use type = -1 to get all addresses)
* To correctly deallocate array memory use `net_freeipport()` * To correctly deallocate array memory use `net_freeipport()`.
*
* @param ns Network object.
* @param mem Memory allocator.
* @param node The node parameter identifies the host or service on which to connect.
* @param[out] res An array of IP_Port structures will be allocated into this pointer.
* @param tox_type The type of socket to use (stream or datagram), only relevant for DNS lookups.
* @param dns_enabled If false, DNS resolution is skipped, when passed a hostname, this function will return an error.
* *
* @return number of elements in res array. * @return number of elements in res array.
* @retval 0 if res array empty. * @retval 0 if res array empty.
* @retval -1 on error. * @retval -1 on error.
*/ */
non_null() non_null()
int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int tox_type); int32_t net_getipport(const Network *ns, const Memory *mem, const char *node, IP_Port **res, int tox_type, bool dns_enabled);
/** Deallocates memory allocated by net_getipport */ /** Deallocates memory allocated by net_getipport */
non_null(1) nullable(2) non_null(1) nullable(2)

View File

@ -3,6 +3,7 @@
#include <iomanip> #include <iomanip>
#include "crypto_core.h" #include "crypto_core.h"
#include "mem.h"
#include "network.h" #include "network.h"
#include "test_util.hh" #include "test_util.hh"
@ -11,6 +12,7 @@ Network_Funcs const Network_Class::vtable = {
Method<net_accept_cb, Network_Class>::invoke<&Network_Class::accept>, Method<net_accept_cb, Network_Class>::invoke<&Network_Class::accept>,
Method<net_bind_cb, Network_Class>::invoke<&Network_Class::bind>, Method<net_bind_cb, Network_Class>::invoke<&Network_Class::bind>,
Method<net_listen_cb, Network_Class>::invoke<&Network_Class::listen>, Method<net_listen_cb, Network_Class>::invoke<&Network_Class::listen>,
Method<net_connect_cb, Network_Class>::invoke<&Network_Class::connect>,
Method<net_recvbuf_cb, Network_Class>::invoke<&Network_Class::recvbuf>, Method<net_recvbuf_cb, Network_Class>::invoke<&Network_Class::recvbuf>,
Method<net_recv_cb, Network_Class>::invoke<&Network_Class::recv>, Method<net_recv_cb, Network_Class>::invoke<&Network_Class::recv>,
Method<net_recvfrom_cb, Network_Class>::invoke<&Network_Class::recvfrom>, Method<net_recvfrom_cb, Network_Class>::invoke<&Network_Class::recvfrom>,
@ -34,6 +36,10 @@ int Test_Network::listen(void *obj, Socket sock, int backlog)
{ {
return net->funcs->listen(net->obj, sock, backlog); return net->funcs->listen(net->obj, sock, backlog);
} }
int Test_Network::connect(void *obj, Socket sock, const Network_Addr *addr)
{
return net->funcs->connect(net->obj, sock, addr);
}
int Test_Network::recvbuf(void *obj, Socket sock) { return net->funcs->recvbuf(net->obj, sock); } int Test_Network::recvbuf(void *obj, Socket sock) { return net->funcs->recvbuf(net->obj, sock); }
int Test_Network::recv(void *obj, Socket sock, uint8_t *buf, size_t len) int Test_Network::recv(void *obj, Socket sock, uint8_t *buf, size_t len)
{ {
@ -70,13 +76,14 @@ int Test_Network::setsockopt(
{ {
return net->funcs->setsockopt(net->obj, sock, level, optname, optval, optlen); return net->funcs->setsockopt(net->obj, sock, level, optname, optval, optlen);
} }
int Test_Network::getaddrinfo(void *obj, int family, Network_Addr **addrs) int Test_Network::getaddrinfo(void *obj, const Memory *mem, const char *address, int family,
int protocol, Network_Addr **addrs)
{ {
return net->funcs->getaddrinfo(net->obj, family, addrs); return net->funcs->getaddrinfo(net->obj, mem, address, family, protocol, addrs);
} }
int Test_Network::freeaddrinfo(void *obj, Network_Addr *addrs) int Test_Network::freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs)
{ {
return net->funcs->freeaddrinfo(net->obj, addrs); return net->funcs->freeaddrinfo(net->obj, mem, addrs);
} }
Network_Class::~Network_Class() = default; Network_Class::~Network_Class() = default;

View File

@ -4,6 +4,7 @@
#include <iosfwd> #include <iosfwd>
#include "crypto_core.h" #include "crypto_core.h"
#include "mem.h"
#include "network.h" #include "network.h"
#include "test_util.hh" #include "test_util.hh"
@ -24,6 +25,7 @@ struct Network_Class {
virtual net_accept_cb accept = 0; virtual net_accept_cb accept = 0;
virtual net_bind_cb bind = 0; virtual net_bind_cb bind = 0;
virtual net_listen_cb listen = 0; virtual net_listen_cb listen = 0;
virtual net_connect_cb connect = 0;
virtual net_recvbuf_cb recvbuf = 0; virtual net_recvbuf_cb recvbuf = 0;
virtual net_recv_cb recv = 0; virtual net_recv_cb recv = 0;
virtual net_recvfrom_cb recvfrom = 0; virtual net_recvfrom_cb recvfrom = 0;
@ -48,6 +50,7 @@ class Test_Network : public Network_Class {
Socket accept(void *obj, Socket sock) override; Socket accept(void *obj, Socket sock) override;
int bind(void *obj, Socket sock, const Network_Addr *addr) override; int bind(void *obj, Socket sock, const Network_Addr *addr) override;
int listen(void *obj, Socket sock, int backlog) override; int listen(void *obj, Socket sock, int backlog) override;
int connect(void *obj, Socket sock, const Network_Addr *addr) override;
int recvbuf(void *obj, Socket sock) override; int recvbuf(void *obj, Socket sock) override;
int recv(void *obj, Socket sock, uint8_t *buf, size_t len) override; int recv(void *obj, Socket sock, uint8_t *buf, size_t len) override;
int recvfrom(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr) override; int recvfrom(void *obj, Socket sock, uint8_t *buf, size_t len, Network_Addr *addr) override;
@ -60,8 +63,9 @@ class Test_Network : public Network_Class {
void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen) override; void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen) override;
int setsockopt( int setsockopt(
void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen) override; void *obj, Socket sock, int level, int optname, const void *optval, size_t optlen) override;
int getaddrinfo(void *obj, int family, Network_Addr **addrs) override; int getaddrinfo(void *obj, const Memory *mem, const char *address, int family, int protocol,
int freeaddrinfo(void *obj, Network_Addr *addrs) override; Network_Addr **addrs) override;
int freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs) override;
}; };
template <> template <>

View File

@ -180,7 +180,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_
* return -1 on failure. * return -1 on failure.
* return length of created packet on success. * return length of created packet on success.
*/ */
int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length, int create_onion_packet(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest, const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length) const uint8_t *data, uint16_t length)
{ {
@ -202,7 +202,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
ipport_pack(step2, &path->ip_port3); ipport_pack(step2, &path->ip_port3);
memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE); memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size, int len = encrypt_data_symmetric(mem, path->shared_key3, nonce, step1, step1_size,
step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) { if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
@ -213,7 +213,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
VLA(uint8_t, step3, step3_size); VLA(uint8_t, step3, step3_size);
ipport_pack(step3, &path->ip_port2); ipport_pack(step3, &path->ip_port2);
memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE); memcpy(step3 + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size, len = encrypt_data_symmetric(mem, path->shared_key2, nonce, step2, step2_size,
step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); step3 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) { if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
@ -224,7 +224,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE); memcpy(packet + 1, nonce, CRYPTO_NONCE_SIZE);
memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_NONCE_SIZE, path->public_key1, CRYPTO_PUBLIC_KEY_SIZE);
len = encrypt_data_symmetric(path->shared_key1, nonce, step3, step3_size, len = encrypt_data_symmetric(mem, path->shared_key1, nonce, step3, step3_size,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) { if (len != SIZE_IPPORT + SEND_BASE * 2 + length + CRYPTO_MAC_SIZE) {
@ -243,7 +243,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
* return -1 on failure. * return -1 on failure.
* return length of created packet on success. * return length of created packet on success.
*/ */
int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length, int create_onion_packet_tcp(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest, const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length) const uint8_t *data, uint16_t length)
{ {
@ -265,7 +265,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
ipport_pack(step2, &path->ip_port3); ipport_pack(step2, &path->ip_port3);
memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE); memcpy(step2 + SIZE_IPPORT, path->public_key3, CRYPTO_PUBLIC_KEY_SIZE);
int len = encrypt_data_symmetric(path->shared_key3, nonce, step1, step1_size, int len = encrypt_data_symmetric(mem, path->shared_key3, nonce, step1, step1_size,
step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); step2 + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) { if (len != SIZE_IPPORT + length + CRYPTO_MAC_SIZE) {
@ -274,7 +274,7 @@ int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_pac
ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2); ipport_pack(packet + CRYPTO_NONCE_SIZE, &path->ip_port2);
memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT, path->public_key2, CRYPTO_PUBLIC_KEY_SIZE);
len = encrypt_data_symmetric(path->shared_key2, nonce, step2, step2_size, len = encrypt_data_symmetric(mem, path->shared_key2, nonce, step2, step2_size,
packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE); packet + CRYPTO_NONCE_SIZE + SIZE_IPPORT + CRYPTO_PUBLIC_KEY_SIZE);
if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) { if (len != SIZE_IPPORT + SEND_BASE + length + CRYPTO_MAC_SIZE) {
@ -355,7 +355,7 @@ static int handle_send_initial(void *object, const IP_Port *source, const uint8_
} }
const int len = decrypt_data_symmetric( const int len = decrypt_data_symmetric(
shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain); onion->mem, shared_key, &packet[nonce_start], &packet[ciphertext_start], ciphertext_length, plain);
if (len != plaintext_length) { if (len != plaintext_length) {
LOGGER_TRACE(onion->log, "decrypt failed: %d != %d", len, plaintext_length); LOGGER_TRACE(onion->log, "decrypt failed: %d != %d", len, plaintext_length);
@ -393,7 +393,7 @@ int onion_send_1(const Onion *onion, const uint8_t *plain, uint16_t len, const I
uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT); uint16_t data_len = 1 + CRYPTO_NONCE_SIZE + (len - SIZE_IPPORT);
uint8_t *ret_part = data + data_len; uint8_t *ret_part = data + data_len;
random_nonce(onion->rng, ret_part); random_nonce(onion->rng, ret_part);
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT, len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ip_port, SIZE_IPPORT,
ret_part + CRYPTO_NONCE_SIZE); ret_part + CRYPTO_NONCE_SIZE);
if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) { if (len != SIZE_IPPORT + CRYPTO_MAC_SIZE) {
@ -436,7 +436,7 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac
return 1; return 1;
} }
int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, int len = decrypt_data_symmetric(onion->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain); length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1), plain);
if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) { if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_1 + CRYPTO_MAC_SIZE)) {
@ -459,7 +459,7 @@ static int handle_send_1(void *object, const IP_Port *source, const uint8_t *pac
uint8_t ret_data[RETURN_1 + SIZE_IPPORT]; uint8_t ret_data[RETURN_1 + SIZE_IPPORT];
ipport_pack(ret_data, source); ipport_pack(ret_data, source);
memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1); memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_1), RETURN_1);
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
ret_part + CRYPTO_NONCE_SIZE); ret_part + CRYPTO_NONCE_SIZE);
if (len != RETURN_2 - CRYPTO_NONCE_SIZE) { if (len != RETURN_2 - CRYPTO_NONCE_SIZE) {
@ -502,7 +502,7 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac
return 1; return 1;
} }
int len = decrypt_data_symmetric(shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, int len = decrypt_data_symmetric(onion->mem, shared_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain); length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2), plain);
if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) { if (len != length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + RETURN_2 + CRYPTO_MAC_SIZE)) {
@ -532,7 +532,7 @@ static int handle_send_2(void *object, const IP_Port *source, const uint8_t *pac
uint8_t ret_data[RETURN_2 + SIZE_IPPORT]; uint8_t ret_data[RETURN_2 + SIZE_IPPORT];
ipport_pack(ret_data, source); ipport_pack(ret_data, source);
memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2); memcpy(ret_data + SIZE_IPPORT, packet + (length - RETURN_2), RETURN_2);
len = encrypt_data_symmetric(onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data), len = encrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, ret_part, ret_data, sizeof(ret_data),
ret_part + CRYPTO_NONCE_SIZE); ret_part + CRYPTO_NONCE_SIZE);
if (len != RETURN_3 - CRYPTO_NONCE_SIZE) { if (len != RETURN_3 - CRYPTO_NONCE_SIZE) {
@ -574,7 +574,7 @@ static int handle_recv_3(void *object, const IP_Port *source, const uint8_t *pac
change_symmetric_key(onion); change_symmetric_key(onion);
uint8_t plain[SIZE_IPPORT + RETURN_2]; uint8_t plain[SIZE_IPPORT + RETURN_2];
const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain); SIZE_IPPORT + RETURN_2 + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != sizeof(plain)) { if ((uint32_t)len != sizeof(plain)) {
@ -627,7 +627,7 @@ static int handle_recv_2(void *object, const IP_Port *source, const uint8_t *pac
change_symmetric_key(onion); change_symmetric_key(onion);
uint8_t plain[SIZE_IPPORT + RETURN_1]; uint8_t plain[SIZE_IPPORT + RETURN_1];
const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain); SIZE_IPPORT + RETURN_1 + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != sizeof(plain)) { if ((uint32_t)len != sizeof(plain)) {
@ -679,7 +679,7 @@ static int handle_recv_1(void *object, const IP_Port *source, const uint8_t *pac
change_symmetric_key(onion); change_symmetric_key(onion);
uint8_t plain[SIZE_IPPORT]; uint8_t plain[SIZE_IPPORT];
const int len = decrypt_data_symmetric(onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE, const int len = decrypt_data_symmetric(onion->mem, onion->secret_symmetric_key, packet + 1, packet + 1 + CRYPTO_NONCE_SIZE,
SIZE_IPPORT + CRYPTO_MAC_SIZE, plain); SIZE_IPPORT + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)len != SIZE_IPPORT) { if ((uint32_t)len != SIZE_IPPORT) {

View File

@ -105,7 +105,7 @@ int onion_path_to_nodes(Node_format *nodes, unsigned int num_nodes, const Onion_
* return length of created packet on success. * return length of created packet on success.
*/ */
non_null() non_null()
int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_length, int create_onion_packet(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest, const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length); const uint8_t *data, uint16_t length);
@ -119,7 +119,7 @@ int create_onion_packet(const Random *rng, uint8_t *packet, uint16_t max_packet_
* return length of created packet on success. * return length of created packet on success.
*/ */
non_null() non_null()
int create_onion_packet_tcp(const Random *rng, uint8_t *packet, uint16_t max_packet_length, int create_onion_packet_tcp(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length,
const Onion_Path *path, const IP_Port *dest, const Onion_Path *path, const IP_Port *dest,
const uint8_t *data, uint16_t length); const uint8_t *data, uint16_t length);

View File

@ -9,7 +9,6 @@
#include "onion_announce.h" #include "onion_announce.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "DHT.h" #include "DHT.h"
@ -23,6 +22,7 @@
#include "network.h" #include "network.h"
#include "onion.h" #include "onion.h"
#include "shared_key_cache.h" #include "shared_key_cache.h"
#include "sort.h"
#include "timed_auth.h" #include "timed_auth.h"
#define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT #define PING_ID_TIMEOUT ONION_ANNOUNCE_TIMEOUT
@ -103,7 +103,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint
* return -1 on failure. * return -1 on failure.
* return packet length on success. * return packet length on success.
*/ */
int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, int create_announce_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
const uint8_t *data_public_key, uint64_t sendback_data) const uint8_t *data_public_key, uint64_t sendback_data)
{ {
@ -122,7 +122,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac
packet[0] = NET_PACKET_ANNOUNCE_REQUEST_OLD; packet[0] = NET_PACKET_ANNOUNCE_REQUEST_OLD;
random_nonce(rng, packet + 1); random_nonce(rng, packet + 1);
const int len = encrypt_data(dest_client_id, secret_key, packet + 1, plain, sizeof(plain), const int len = encrypt_data(mem, dest_client_id, secret_key, packet + 1, plain, sizeof(plain),
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_MIN_SIZE) { if ((uint32_t)len + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE != ONION_ANNOUNCE_REQUEST_MIN_SIZE) {
@ -146,7 +146,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac
* return -1 on failure. * return -1 on failure.
* return 0 on success. * return 0 on success.
*/ */
int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, int create_data_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length) const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length)
{ {
if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) { if (DATA_REQUEST_MIN_SIZE + length > max_packet_length) {
@ -167,7 +167,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, random_public_key, CRYPTO_PUBLIC_KEY_SIZE);
const int len = encrypt_data(encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length, const int len = encrypt_data(mem, encrypt_public_key, random_secret_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE); packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE);
if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE + if (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + len != DATA_REQUEST_MIN_SIZE +
@ -193,14 +193,14 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
* return 0 on success. * return 0 on success.
*/ */
int send_announce_request( int send_announce_request(
const Logger *log, const Networking_Core *net, const Random *rng, const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng,
const Onion_Path *path, const Node_format *dest, const Onion_Path *path, const Node_format *dest,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *public_key, const uint8_t *secret_key,
const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *ping_id, const uint8_t *client_id,
const uint8_t *data_public_key, uint64_t sendback_data) const uint8_t *data_public_key, uint64_t sendback_data)
{ {
uint8_t request[ONION_ANNOUNCE_REQUEST_MIN_SIZE]; uint8_t request[ONION_ANNOUNCE_REQUEST_MIN_SIZE];
int len = create_announce_request(rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id, int len = create_announce_request(mem, rng, request, sizeof(request), dest->public_key, public_key, secret_key, ping_id,
client_id, data_public_key, sendback_data); client_id, data_public_key, sendback_data);
if (len != sizeof(request)) { if (len != sizeof(request)) {
@ -208,7 +208,7 @@ int send_announce_request(
} }
uint8_t packet[ONION_MAX_PACKET_SIZE]; uint8_t packet[ONION_MAX_PACKET_SIZE];
len = create_onion_packet(rng, packet, sizeof(packet), path, &dest->ip_port, request, sizeof(request)); len = create_onion_packet(mem, rng, packet, sizeof(packet), path, &dest->ip_port, request, sizeof(request));
if (len == -1) { if (len == -1) {
return -1; return -1;
@ -238,19 +238,19 @@ int send_announce_request(
* return 0 on success. * return 0 on success.
*/ */
int send_data_request( int send_data_request(
const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
const uint8_t *data, uint16_t length) const uint8_t *data, uint16_t length)
{ {
uint8_t request[ONION_MAX_DATA_SIZE]; uint8_t request[ONION_MAX_DATA_SIZE];
int len = create_data_request(rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length); int len = create_data_request(mem, rng, request, sizeof(request), public_key, encrypt_public_key, nonce, data, length);
if (len == -1) { if (len == -1) {
return -1; return -1;
} }
uint8_t packet[ONION_MAX_PACKET_SIZE]; uint8_t packet[ONION_MAX_PACKET_SIZE];
len = create_onion_packet(rng, packet, sizeof(packet), path, dest, request, len); len = create_onion_packet(mem, rng, packet, sizeof(packet), path, dest, request, len);
if (len == -1) { if (len == -1) {
return -1; return -1;
@ -281,23 +281,17 @@ static int in_entries(const Onion_Announce *onion_a, const uint8_t *public_key)
return -1; return -1;
} }
typedef struct Cmp_Data { typedef struct Onion_Announce_Entry_Cmp {
const Memory *mem;
const Mono_Time *mono_time; const Mono_Time *mono_time;
const uint8_t *base_public_key; const uint8_t *comp_public_key;
Onion_Announce_Entry entry; } Onion_Announce_Entry_Cmp;
} Cmp_Data;
non_null() non_null()
static int cmp_entry(const void *a, const void *b) static int onion_announce_entry_cmp(const Onion_Announce_Entry_Cmp *cmp, const Onion_Announce_Entry *entry1, const Onion_Announce_Entry *entry2)
{ {
const Cmp_Data *cmp1 = (const Cmp_Data *)a; const bool t1 = mono_time_is_timeout(cmp->mono_time, entry1->announce_time, ONION_ANNOUNCE_TIMEOUT);
const Cmp_Data *cmp2 = (const Cmp_Data *)b; const bool t2 = mono_time_is_timeout(cmp->mono_time, entry2->announce_time, ONION_ANNOUNCE_TIMEOUT);
const Onion_Announce_Entry entry1 = cmp1->entry;
const Onion_Announce_Entry entry2 = cmp2->entry;
const uint8_t *cmp_public_key = cmp1->base_public_key;
const bool t1 = mono_time_is_timeout(cmp1->mono_time, entry1.announce_time, ONION_ANNOUNCE_TIMEOUT);
const bool t2 = mono_time_is_timeout(cmp1->mono_time, entry2.announce_time, ONION_ANNOUNCE_TIMEOUT);
if (t1 && t2) { if (t1 && t2) {
return 0; return 0;
@ -311,7 +305,7 @@ static int cmp_entry(const void *a, const void *b)
return 1; return 1;
} }
const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
if (closest == 1) { if (closest == 1) {
return 1; return 1;
@ -324,32 +318,81 @@ static int cmp_entry(const void *a, const void *b)
return 0; return 0;
} }
non_null()
static bool onion_announce_entry_less_handler(const void *object, const void *a, const void *b)
{
const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object;
const Onion_Announce_Entry *entry1 = (const Onion_Announce_Entry *)a;
const Onion_Announce_Entry *entry2 = (const Onion_Announce_Entry *)b;
return onion_announce_entry_cmp(cmp, entry1, entry2) < 0;
}
non_null()
static const void *onion_announce_entry_get_handler(const void *arr, uint32_t index)
{
const Onion_Announce_Entry *entries = (const Onion_Announce_Entry *)arr;
return &entries[index];
}
non_null()
static void onion_announce_entry_set_handler(void *arr, uint32_t index, const void *val)
{
Onion_Announce_Entry *entries = (Onion_Announce_Entry *)arr;
const Onion_Announce_Entry *entry = (const Onion_Announce_Entry *)val;
entries[index] = *entry;
}
non_null()
static void *onion_announce_entry_subarr_handler(void *arr, uint32_t index, uint32_t size)
{
Onion_Announce_Entry *entries = (Onion_Announce_Entry *)arr;
return &entries[index];
}
non_null()
static void *onion_announce_entry_alloc_handler(const void *object, uint32_t size)
{
const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object;
Onion_Announce_Entry *tmp = (Onion_Announce_Entry *)mem_valloc(cmp->mem, size, sizeof(Onion_Announce_Entry));
if (tmp == nullptr) {
return nullptr;
}
return tmp;
}
non_null()
static void onion_announce_entry_delete_handler(const void *object, void *arr, uint32_t size)
{
const Onion_Announce_Entry_Cmp *cmp = (const Onion_Announce_Entry_Cmp *)object;
mem_delete(cmp->mem, arr);
}
static const Sort_Funcs onion_announce_entry_cmp_funcs = {
onion_announce_entry_less_handler,
onion_announce_entry_get_handler,
onion_announce_entry_set_handler,
onion_announce_entry_subarr_handler,
onion_announce_entry_alloc_handler,
onion_announce_entry_delete_handler,
};
non_null() non_null()
static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time, static void sort_onion_announce_list(const Memory *mem, const Mono_Time *mono_time,
Onion_Announce_Entry *list, unsigned int length, Onion_Announce_Entry *list, unsigned int length,
const uint8_t *comp_public_key) const uint8_t *comp_public_key)
{ {
// Pass comp_public_key to qsort with each Client_data entry, so the // Pass comp_public_key to sort with each Onion_Announce_Entry entry, so the
// comparison function can use it as the base of comparison. // comparison function can use it as the base of comparison.
Cmp_Data *cmp_list = (Cmp_Data *)mem_valloc(mem, length, sizeof(Cmp_Data)); const Onion_Announce_Entry_Cmp cmp = {
mem,
mono_time,
comp_public_key,
};
if (cmp_list == nullptr) { merge_sort(list, length, &cmp, &onion_announce_entry_cmp_funcs);
return;
}
for (uint32_t i = 0; i < length; ++i) {
cmp_list[i].mono_time = mono_time;
cmp_list[i].base_public_key = comp_public_key;
cmp_list[i].entry = list[i];
}
qsort(cmp_list, length, sizeof(Cmp_Data), cmp_entry);
for (uint32_t i = 0; i < length; ++i) {
list[i] = cmp_list[i].entry;
}
mem_delete(mem, cmp_list);
} }
/** @brief add entry to entries list /** @brief add entry to entries list
@ -455,7 +498,7 @@ static int handle_announce_request_common(
return 1; return 1;
} }
const int decrypted_len = decrypt_data_symmetric(shared_key, packet + 1, const int decrypted_len = decrypt_data_symmetric(onion_a->mem, shared_key, packet + 1,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, plain_size + CRYPTO_MAC_SIZE, plain); packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, plain_size + CRYPTO_MAC_SIZE, plain);
if ((uint32_t)decrypted_len != plain_size) { if ((uint32_t)decrypted_len != plain_size) {
@ -542,7 +585,7 @@ static int handle_announce_request_common(
offset += extra_size; offset += extra_size;
uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE]; uint8_t data[ONION_ANNOUNCE_RESPONSE_MAX_SIZE];
const int len = encrypt_data_symmetric(shared_key, nonce, response, offset, const int len = encrypt_data_symmetric(onion_a->mem, shared_key, nonce, response, offset,
data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE); data + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE);
if (len != offset + CRYPTO_MAC_SIZE) { if (len != offset + CRYPTO_MAC_SIZE) {

View File

@ -65,7 +65,7 @@ void onion_announce_entry_set_time(Onion_Announce *onion_a, uint32_t entry, uint
* return packet length on success. * return packet length on success.
*/ */
non_null() non_null()
int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id, int create_announce_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *dest_client_id,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *ping_id, const uint8_t *client_id,
const uint8_t *data_public_key, uint64_t sendback_data); const uint8_t *data_public_key, uint64_t sendback_data);
@ -82,7 +82,7 @@ int create_announce_request(const Random *rng, uint8_t *packet, uint16_t max_pac
* return 0 on success. * return 0 on success.
*/ */
non_null() non_null()
int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key, int create_data_request(const Memory *mem, const Random *rng, uint8_t *packet, uint16_t max_packet_length, const uint8_t *public_key,
const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length); const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *data, uint16_t length);
/** @brief Create and send an onion announce request packet. /** @brief Create and send an onion announce request packet.
@ -101,7 +101,7 @@ int create_data_request(const Random *rng, uint8_t *packet, uint16_t max_packet_
*/ */
non_null() non_null()
int send_announce_request( int send_announce_request(
const Logger *log, const Networking_Core *net, const Random *rng, const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng,
const Onion_Path *path, const Node_format *dest, const Onion_Path *path, const Node_format *dest,
const uint8_t *public_key, const uint8_t *secret_key, const uint8_t *public_key, const uint8_t *secret_key,
const uint8_t *ping_id, const uint8_t *client_id, const uint8_t *ping_id, const uint8_t *client_id,
@ -125,7 +125,7 @@ int send_announce_request(
*/ */
non_null() non_null()
int send_data_request( int send_data_request(
const Logger *log, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest, const Logger *log, const Memory *mem, const Networking_Core *net, const Random *rng, const Onion_Path *path, const IP_Port *dest,
const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce, const uint8_t *public_key, const uint8_t *encrypt_public_key, const uint8_t *nonce,
const uint8_t *data, uint16_t length); const uint8_t *data, uint16_t length);

View File

@ -10,7 +10,6 @@
#include "onion_client.h" #include "onion_client.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "DHT.h" #include "DHT.h"
@ -29,6 +28,7 @@
#include "onion.h" #include "onion.h"
#include "onion_announce.h" #include "onion_announce.h"
#include "ping_array.h" #include "ping_array.h"
#include "sort.h"
#include "timed_auth.h" #include "timed_auth.h"
#include "util.h" #include "util.h"
@ -528,7 +528,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa
{ {
if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) { if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) {
uint8_t packet[ONION_MAX_PACKET_SIZE]; uint8_t packet[ONION_MAX_PACKET_SIZE];
const int len = create_onion_packet(onion_c->rng, packet, sizeof(packet), path, dest, data, length); const int len = create_onion_packet(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length);
if (len == -1) { if (len == -1) {
return -1; return -1;
@ -545,7 +545,7 @@ static int send_onion_packet_tcp_udp(const Onion_Client *onion_c, const Onion_Pa
if (ip_port_to_tcp_connections_number(&path->ip_port1, &tcp_connections_number)) { if (ip_port_to_tcp_connections_number(&path->ip_port1, &tcp_connections_number)) {
uint8_t packet[ONION_MAX_PACKET_SIZE]; uint8_t packet[ONION_MAX_PACKET_SIZE];
const int len = create_onion_packet_tcp(onion_c->rng, packet, sizeof(packet), path, dest, data, length); const int len = create_onion_packet_tcp(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length);
if (len == -1) { if (len == -1) {
return -1; return -1;
@ -661,7 +661,7 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
if (num == 0) { if (num == 0) {
len = create_announce_request( len = create_announce_request(
onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c), onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c),
nc_get_self_secret_key(onion_c->c), ping_id, nc_get_self_public_key(onion_c->c), nc_get_self_secret_key(onion_c->c), ping_id, nc_get_self_public_key(onion_c->c),
onion_c->temp_public_key, sendback); onion_c->temp_public_key, sendback);
} else { } else {
@ -669,14 +669,14 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
if (onion_friend->gc_data_length == 0) { // contact is a friend if (onion_friend->gc_data_length == 0) { // contact is a friend
len = create_announce_request( len = create_announce_request(
onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key, onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key, onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
zero_ping_id, sendback); zero_ping_id, sendback);
} else { // contact is a gc } else { // contact is a gc
onion_friend->is_groupchat = true; onion_friend->is_groupchat = true;
len = create_gca_announce_request( len = create_gca_announce_request(
onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key, onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key, onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
zero_ping_id, sendback, onion_friend->gc_data, zero_ping_id, sendback, onion_friend->gc_data,
onion_friend->gc_data_length); onion_friend->gc_data_length);
@ -694,23 +694,17 @@ static int client_send_announce_request(Onion_Client *onion_c, uint32_t num, con
return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len); return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
} }
typedef struct Onion_Client_Cmp_Data { typedef struct Onion_Node_Cmp {
const Memory *mem;
const Mono_Time *mono_time; const Mono_Time *mono_time;
const uint8_t *base_public_key; const uint8_t *comp_public_key;
Onion_Node entry; } Onion_Node_Cmp;
} Onion_Client_Cmp_Data;
non_null() non_null()
static int onion_client_cmp_entry(const void *a, const void *b) static int onion_node_cmp(const Onion_Node_Cmp *cmp, const Onion_Node *entry1, const Onion_Node *entry2)
{ {
const Onion_Client_Cmp_Data *cmp1 = (const Onion_Client_Cmp_Data *)a; const bool t1 = onion_node_timed_out(entry1, cmp->mono_time);
const Onion_Client_Cmp_Data *cmp2 = (const Onion_Client_Cmp_Data *)b; const bool t2 = onion_node_timed_out(entry2, cmp->mono_time);
const Onion_Node entry1 = cmp1->entry;
const Onion_Node entry2 = cmp2->entry;
const uint8_t *cmp_public_key = cmp1->base_public_key;
const bool t1 = onion_node_timed_out(&entry1, cmp1->mono_time);
const bool t2 = onion_node_timed_out(&entry2, cmp2->mono_time);
if (t1 && t2) { if (t1 && t2) {
return 0; return 0;
@ -724,7 +718,7 @@ static int onion_client_cmp_entry(const void *a, const void *b)
return 1; return 1;
} }
const int closest = id_closest(cmp_public_key, entry1.public_key, entry2.public_key); const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
if (closest == 1) { if (closest == 1) {
return 1; return 1;
@ -737,31 +731,80 @@ static int onion_client_cmp_entry(const void *a, const void *b)
return 0; return 0;
} }
non_null()
static bool onion_node_less_handler(const void *object, const void *a, const void *b)
{
const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
const Onion_Node *entry1 = (const Onion_Node *)a;
const Onion_Node *entry2 = (const Onion_Node *)b;
return onion_node_cmp(cmp, entry1, entry2) < 0;
}
non_null()
static const void *onion_node_get_handler(const void *arr, uint32_t index)
{
const Onion_Node *entries = (const Onion_Node *)arr;
return &entries[index];
}
non_null()
static void onion_node_set_handler(void *arr, uint32_t index, const void *val)
{
Onion_Node *entries = (Onion_Node *)arr;
const Onion_Node *entry = (const Onion_Node *)val;
entries[index] = *entry;
}
non_null()
static void *onion_node_subarr_handler(void *arr, uint32_t index, uint32_t size)
{
Onion_Node *entries = (Onion_Node *)arr;
return &entries[index];
}
non_null()
static void *onion_node_alloc_handler(const void *object, uint32_t size)
{
const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
Onion_Node *tmp = (Onion_Node *)mem_valloc(cmp->mem, size, sizeof(Onion_Node));
if (tmp == nullptr) {
return nullptr;
}
return tmp;
}
non_null()
static void onion_node_delete_handler(const void *object, void *arr, uint32_t size)
{
const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
mem_delete(cmp->mem, arr);
}
static const Sort_Funcs onion_node_cmp_funcs = {
onion_node_less_handler,
onion_node_get_handler,
onion_node_set_handler,
onion_node_subarr_handler,
onion_node_alloc_handler,
onion_node_delete_handler,
};
non_null() non_null()
static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time, static void sort_onion_node_list(const Memory *mem, const Mono_Time *mono_time,
Onion_Node *list, unsigned int length, const uint8_t *comp_public_key) Onion_Node *list, unsigned int length, const uint8_t *comp_public_key)
{ {
// Pass comp_public_key to qsort with each Client_data entry, so the // Pass comp_public_key to sort with each Onion_Node entry, so the
// comparison function can use it as the base of comparison. // comparison function can use it as the base of comparison.
Onion_Client_Cmp_Data *cmp_list = (Onion_Client_Cmp_Data *)mem_valloc(mem, length, sizeof(Onion_Client_Cmp_Data)); const Onion_Node_Cmp cmp = {
mem,
mono_time,
comp_public_key,
};
if (cmp_list == nullptr) { merge_sort(list, length, &cmp, &onion_node_cmp_funcs);
return;
}
for (uint32_t i = 0; i < length; ++i) {
cmp_list[i].mono_time = mono_time;
cmp_list[i].base_public_key = comp_public_key;
cmp_list[i].entry = list[i];
}
qsort(cmp_list, length, sizeof(Onion_Client_Cmp_Data), onion_client_cmp_entry);
for (uint32_t i = 0; i < length; ++i) {
list[i] = cmp_list[i].entry;
}
mem_delete(mem, cmp_list);
} }
non_null() non_null()
@ -962,7 +1005,7 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
const uint16_t ciphertext_size = length - ciphertext_start; const uint16_t ciphertext_size = length - ciphertext_start;
if (num == 0) { if (num == 0) {
len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c), len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c),
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
} else { } else {
if (!onion_c->friends_list[num - 1].is_valid) { if (!onion_c->friends_list[num - 1].is_valid) {
@ -970,7 +1013,7 @@ static int handle_announce_response(void *object, const IP_Port *source, const u
return 1; return 1;
} }
len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key,
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
} }
@ -1066,7 +1109,7 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
const uint16_t ciphertext_size = length - ciphertext_start; const uint16_t ciphertext_size = length - ciphertext_start;
if (num == 0) { if (num == 0) {
len = decrypt_data(public_key, nc_get_self_secret_key(onion_c->c), len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c),
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
} else { } else {
if (!onion_c->friends_list[num - 1].is_valid) { if (!onion_c->friends_list[num - 1].is_valid) {
@ -1074,7 +1117,7 @@ static int handle_announce_response_old(void *object, const IP_Port *source, con
return 1; return 1;
} }
len = decrypt_data(public_key, onion_c->friends_list[num - 1].temp_secret_key, len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key,
&packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain); &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
} }
@ -1136,7 +1179,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8
const uint16_t temp_plain_size = length - ONION_DATA_RESPONSE_MIN_SIZE; const uint16_t temp_plain_size = length - ONION_DATA_RESPONSE_MIN_SIZE;
VLA(uint8_t, temp_plain, temp_plain_size); VLA(uint8_t, temp_plain, temp_plain_size);
int len = decrypt_data(packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1, int len = decrypt_data(onion_c->mem, packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain); length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
@ -1146,7 +1189,7 @@ static int handle_data_response(void *object, const IP_Port *source, const uint8
const uint16_t plain_size = temp_plain_size - DATA_IN_RESPONSE_MIN_SIZE; const uint16_t plain_size = temp_plain_size - DATA_IN_RESPONSE_MIN_SIZE;
VLA(uint8_t, plain, plain_size); VLA(uint8_t, plain, plain_size);
len = decrypt_data(temp_plain, nc_get_self_secret_key(onion_c->c), len = decrypt_data(onion_c->mem, temp_plain, nc_get_self_secret_key(onion_c->c),
packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE, packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
temp_plain_size - CRYPTO_PUBLIC_KEY_SIZE, plain); temp_plain_size - CRYPTO_PUBLIC_KEY_SIZE, plain);
@ -1305,7 +1348,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
const uint16_t packet_size = DATA_IN_RESPONSE_MIN_SIZE + length; const uint16_t packet_size = DATA_IN_RESPONSE_MIN_SIZE + length;
VLA(uint8_t, packet, packet_size); VLA(uint8_t, packet, packet_size);
memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE); memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key,
nc_get_self_secret_key(onion_c->c), nonce, data, nc_get_self_secret_key(onion_c->c), nonce, data,
length, packet + CRYPTO_PUBLIC_KEY_SIZE); length, packet + CRYPTO_PUBLIC_KEY_SIZE);
@ -1324,7 +1367,7 @@ int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data,
uint8_t o_packet[ONION_MAX_PACKET_SIZE]; uint8_t o_packet[ONION_MAX_PACKET_SIZE];
len = create_data_request( len = create_data_request(
onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key, onion_c->mem, onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
node_list[good_nodes[i]].data_public_key, nonce, packet, packet_size); node_list[good_nodes[i]].data_public_key, nonce, packet, packet_size);
if (len == -1) { if (len == -1) {
@ -1364,7 +1407,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin
VLA(uint8_t, temp, temp_size); VLA(uint8_t, temp, temp_size);
memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE); memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
int len = encrypt_data(onion_c->friends_list[friend_num].real_public_key, int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key,
nc_get_self_secret_key(onion_c->c), nonce, data, nc_get_self_secret_key(onion_c->c), nonce, data,
length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
@ -1374,7 +1417,7 @@ static int send_dht_dhtpk(const Onion_Client *onion_c, int friend_num, const uin
uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE]; uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];
len = create_request( len = create_request(
onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data, onion_c->mem, onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data,
onion_c->friends_list[friend_num].dht_public_key, temp, temp_size, CRYPTO_PACKET_DHTPK); onion_c->friends_list[friend_num].dht_public_key, temp, temp_size, CRYPTO_PACKET_DHTPK);
assert(len <= UINT16_MAX); assert(len <= UINT16_MAX);
const Packet packet = {packet_data, (uint16_t)len}; const Packet packet = {packet_data, (uint16_t)len};
@ -1401,7 +1444,7 @@ static int handle_dht_dhtpk(void *object, const IP_Port *source, const uint8_t *
} }
uint8_t plain[DHTPK_DATA_MAX_LENGTH]; uint8_t plain[DHTPK_DATA_MAX_LENGTH];
const int len = decrypt_data(packet, nc_get_self_secret_key(onion_c->c), const int len = decrypt_data(onion_c->mem, packet, nc_get_self_secret_key(onion_c->c),
packet + CRYPTO_PUBLIC_KEY_SIZE, packet + CRYPTO_PUBLIC_KEY_SIZE,
packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain); length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain);

View File

@ -183,6 +183,8 @@ non_null()
unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key); unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key);
#define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE) #define ONION_DATA_IN_RESPONSE_MIN_SIZE (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_MAC_SIZE)
// TODO(Jfreegman): This is not the correct value; data this large will be dropped by the onion client.
#define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE) #define ONION_CLIENT_MAX_DATA_SIZE (MAX_DATA_REQUEST_SIZE - ONION_DATA_IN_RESPONSE_MIN_SIZE)
/** @brief Send data of length length to friendnum. /** @brief Send data of length length to friendnum.

View File

@ -31,6 +31,7 @@
struct Ping { struct Ping {
const Mono_Time *mono_time; const Mono_Time *mono_time;
const Random *rng; const Random *rng;
const Memory *mem;
DHT *dht; DHT *dht;
Ping_Array *ping_array; Ping_Array *ping_array;
@ -72,7 +73,7 @@ void ping_send_request(Ping *ping, const IP_Port *ipp, const uint8_t *public_key
pk_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey pk_copy(pk + 1, dht_get_self_public_key(ping->dht)); // Our pubkey
random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
rc = encrypt_data_symmetric(shared_key, rc = encrypt_data_symmetric(ping->mem, shared_key,
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
ping_plain, sizeof(ping_plain), ping_plain, sizeof(ping_plain),
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
@ -104,7 +105,7 @@ static int ping_send_response(const Ping *ping, const IP_Port *ipp, const uint8_
random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce random_nonce(ping->rng, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE); // Generate new nonce
// Encrypt ping_id using recipient privkey // Encrypt ping_id using recipient privkey
const int rc = encrypt_data_symmetric(shared_encryption_key, const int rc = encrypt_data_symmetric(ping->mem, shared_encryption_key,
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE, pk + 1 + CRYPTO_PUBLIC_KEY_SIZE,
ping_plain, sizeof(ping_plain), ping_plain, sizeof(ping_plain),
pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE); pk + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
@ -137,7 +138,7 @@ static int handle_ping_request(void *object, const IP_Port *source, const uint8_
uint8_t ping_plain[PING_PLAIN_SIZE]; uint8_t ping_plain[PING_PLAIN_SIZE];
// Decrypt ping_id // Decrypt ping_id
const int rc = decrypt_data_symmetric(shared_key, const int rc = decrypt_data_symmetric(ping->mem, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
@ -182,7 +183,7 @@ static int handle_ping_response(void *object, const IP_Port *source, const uint8
uint8_t ping_plain[PING_PLAIN_SIZE]; uint8_t ping_plain[PING_PLAIN_SIZE];
// Decrypt ping_id // Decrypt ping_id
rc = decrypt_data_symmetric(shared_key, rc = decrypt_data_symmetric(ping->mem, shared_key,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
PING_PLAIN_SIZE + CRYPTO_MAC_SIZE, PING_PLAIN_SIZE + CRYPTO_MAC_SIZE,
@ -348,6 +349,7 @@ Ping *ping_new(const Memory *mem, const Mono_Time *mono_time, const Random *rng,
ping->mono_time = mono_time; ping->mono_time = mono_time;
ping->rng = rng; ping->rng = rng;
ping->mem = mem;
ping->dht = dht; ping->dht = dht;
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht); networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_REQUEST, &handle_ping_request, dht);
networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht); networking_registerhandler(dht_get_net(ping->dht), NET_PACKET_PING_RESPONSE, &handle_ping_response, dht);

View File

@ -0,0 +1,182 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2023-2024 The TokTok team.
*/
#include "sort.h"
#include <assert.h>
#include "attributes.h"
#include "ccompat.h"
#include "util.h"
/**
* @brief Threshold for when to switch to insertion sort.
*
* This is a trade-off between the complexity of insertion sort and the
* overhead of merge sort. The threshold is chosen to be the smallest value
* that gives a measurable speedup for insertion sort over merge sort. This is
* based on measurements done in sort_bench.cc. Starting from 32 elements,
* merge sort is faster than insertion sort in all our tests (both unsorted
* and mostly-sorted).
*
* Toxcore has a lot of small arrays it wants to sort, so this optimisation
* makes sense.
*/
#define SMALL_ARRAY_THRESHOLD 16
non_null()
static void merge_sort_merge_back(
void *arr,
const void *l_arr, uint32_t l_arr_size,
const void *r_arr, uint32_t r_arr_size,
uint32_t left_start,
const void *object, const Sort_Funcs *funcs)
{
uint32_t li = 0;
uint32_t ri = 0;
uint32_t k = left_start;
while (li < l_arr_size && ri < r_arr_size) {
const void *l = funcs->get_callback(l_arr, li);
const void *r = funcs->get_callback(r_arr, ri);
// !(r < l) <=> (r >= l) <=> (l <= r)
if (!funcs->less_callback(object, r, l)) {
funcs->set_callback(arr, k, l);
++li;
} else {
funcs->set_callback(arr, k, r);
++ri;
}
++k;
}
/* Copy the remaining elements of `l_arr[]`, if there are any. */
while (li < l_arr_size) {
funcs->set_callback(arr, k, funcs->get_callback(l_arr, li));
++li;
++k;
}
/* Copy the remaining elements of `r_arr[]`, if there are any. */
while (ri < r_arr_size) {
funcs->set_callback(arr, k, funcs->get_callback(r_arr, ri));
++ri;
++k;
}
}
/** Function to merge the two haves `arr[left_start..mid]` and `arr[mid+1..right_end]` of array `arr[]`. */
non_null()
static void merge_sort_merge(
void *arr, uint32_t left_start, uint32_t mid, uint32_t right_end, void *tmp,
const void *object, const Sort_Funcs *funcs)
{
const uint32_t l_arr_size = mid - left_start + 1;
const uint32_t r_arr_size = right_end - mid;
/* Temporary arrays, using the tmp buffer created in `merge_sort` below. */
void *l_arr = funcs->subarr_callback(tmp, 0, l_arr_size);
void *r_arr = funcs->subarr_callback(tmp, l_arr_size, r_arr_size);
/* Copy data to temp arrays `l_arr[]` and `r_arr[]`.
*
* This is iterating and repeatedly calling `get` and `set`, which sounds
* slow, but is only marginally slower than having a `copy` callback. With
* a `copy` callback, we'd save 3-4% in time.
*/
for (uint32_t i = 0; i < l_arr_size; ++i) {
funcs->set_callback(l_arr, i, funcs->get_callback(arr, left_start + i));
}
for (uint32_t i = 0; i < r_arr_size; ++i) {
funcs->set_callback(r_arr, i, funcs->get_callback(arr, mid + 1 + i));
}
/* Merge the temp arrays back into `arr[left_start..right_end]`. */
merge_sort_merge_back(arr, l_arr, l_arr_size, r_arr, r_arr_size, left_start, object, funcs);
}
non_null()
static void insertion_sort_step(void *arr, void *tmp, uint32_t i, const void *object, const Sort_Funcs *funcs)
{
funcs->set_callback(tmp, 0, funcs->get_callback(arr, i));
uint32_t j = i;
while (j > 0) {
if (!funcs->less_callback(object, tmp, funcs->get_callback(arr, j - 1))) {
break;
}
funcs->set_callback(arr, j, funcs->get_callback(arr, j - 1));
--j;
}
funcs->set_callback(arr, j, tmp);
}
non_null()
static void insertion_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs)
{
for (uint32_t i = 1; i < arr_size; ++i) {
insertion_sort_step(arr, tmp, i, object, funcs);
}
}
non_null()
static bool insertion_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs)
{
void *tmp = funcs->alloc_callback(object, 1);
if (tmp == nullptr) {
return false;
}
insertion_sort_with_buf(arr, arr_size, tmp, 1, object, funcs);
funcs->delete_callback(object, tmp, 1);
return true;
}
void merge_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs)
{
assert(tmp_size >= arr_size);
if (arr_size <= SMALL_ARRAY_THRESHOLD) {
assert(tmp_size >= 1);
insertion_sort_with_buf(arr, arr_size, tmp, tmp_size, object, funcs);
return;
}
// Merge subarrays in bottom up manner. First merge subarrays of
// size 1 to create sorted subarrays of size 2, then merge subarrays
// of size 2 to create sorted subarrays of size 4, and so on.
for (uint32_t curr_size = 1; curr_size <= arr_size - 1; curr_size = 2 * curr_size) {
// Pick starting point of different subarrays of current size
for (uint32_t left_start = 0; left_start < arr_size - 1; left_start += 2 * curr_size) {
// Find ending point of left subarray. mid+1 is starting
// point of right
const uint32_t mid = min_u32(left_start + curr_size - 1, arr_size - 1);
const uint32_t right_end = min_u32(left_start + 2 * curr_size - 1, arr_size - 1);
// Merge Subarrays arr[left_start...mid] & arr[mid+1...right_end]
merge_sort_merge(arr, left_start, mid, right_end, tmp, object, funcs);
}
}
}
bool merge_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs)
{
if (arr_size <= SMALL_ARRAY_THRESHOLD) {
return insertion_sort(arr, arr_size, object, funcs);
}
void *tmp = funcs->alloc_callback(object, arr_size);
if (tmp == nullptr) {
return false;
}
merge_sort_with_buf(arr, arr_size, tmp, arr_size, object, funcs);
funcs->delete_callback(object, tmp, arr_size);
return true;
}

View File

@ -0,0 +1,116 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2023-2024 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_SORT_H
#define C_TOXCORE_TOXCORE_SORT_H
#include <stdbool.h>
#include <stdint.h>
#include "attributes.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @brief Compare elements with a less-than ordering: `a < b`. */
typedef bool sort_less_cb(const void *object, const void *a, const void *b);
/** @brief Get element from array at index. */
typedef const void *sort_get_cb(const void *arr, uint32_t index);
/** @brief Set element in array at index to new value (perform copy). */
typedef void sort_set_cb(void *arr, uint32_t index, const void *val);
/** @brief Get a sub-array at an index of a given size (mutable pointer).
*
* Used to index in the temporary array allocated by `sort_alloc_cb` and get
* a sub-array for working memory.
*/
typedef void *sort_subarr_cb(void *arr, uint32_t index, uint32_t size);
/** @brief Allocate a new array of the element type.
*
* @param size The array size in elements of type T (not byte size). This value
* is always exactly the input array size as passed to `merge_sort`.
*/
typedef void *sort_alloc_cb(const void *object, uint32_t size);
/** @brief Free the element type array. */
typedef void sort_delete_cb(const void *object, void *arr, uint32_t size);
/** @brief Virtual function table for getting/setting elements in an array and
* comparing them.
*
* Only the `less`, `alloc`, and `delete` functions get a `this`-pointer. We
* assume that indexing in an array doesn't need any other information than the
* array itself.
*
* For now, the `this`-pointer is const, because we assume sorting doesn't need
* to mutate any state, but if necessary that can be changed in the future.
*/
typedef struct Sort_Funcs {
sort_less_cb *less_callback;
sort_get_cb *get_callback;
sort_set_cb *set_callback;
sort_subarr_cb *subarr_callback;
sort_alloc_cb *alloc_callback;
sort_delete_cb *delete_callback;
} Sort_Funcs;
/** @brief Non-recursive merge sort function to sort `arr[0...arr_size-1]`.
*
* Avoids `memcpy` and avoids treating elements as byte arrays. Instead, uses
* callbacks to index in arrays and copy elements. This makes it quite a bit
* slower than `qsort`, but works with elements that require special care when
* being copied (e.g. if they are part of a graph or other data structure that
* with pointers or other invariants).
*
* This function actually uses insertion sort for small arrays (up to 16
* elements), which is faster than merge sort for small arrays, especially
* when mostly sorted (a common use case in toxcore).
*
* Allocates a single temporary array with the provided alloc callback, and
* frees it at the end. This is significantly faster than an in-place
* implementation.
*
* Complexity:
* - Space: `O(n) where n = array_size`.
* - Time: `O(n * log n) where n = array_size`.
*
* Compared to `qsort`, this is about 60-70% slower for large arrays. For small
* arrays (up to 16 elements), it's about 50% faster than `qsort`.
*
* @param[in,out] arr An array of type T.
* @param arr_size Number of elements in @p arr (count, not byte size).
* @param[in] object Comparator object.
* @param[in] funcs Callback struct for elements of type T.
*/
non_null()
bool merge_sort(void *arr, uint32_t arr_size, const void *object, const Sort_Funcs *funcs);
/**
* @brief Merge sort like above but with a pre-allocated buffer.
*
* This function is the same as `merge_sort` but uses a pre-allocated buffer
* for temporary storage. This can be useful if the caller wants to avoid
* dynamic memory allocation.
*
* This function is 1-2% faster than `merge_sort` for small arrays up to 1000
* elements, and about 5-10% faster for large arrays (2000+ elements).
*
* The main upside is that `alloc` and `delete` callbacks don't need to be
* implemented, and the caller can use a stack-allocated buffer.
*
* @param[in,out] arr An array of type T.
* @param arr_size Number of elements in @p arr (count, not byte size).
* @param[in,out] tmp A buffer of size `tmp_size` for temporary storage.
* @param tmp_size Number of elements in @p tmp (count, not byte size). Must be
* at least as large as `arr_size`.
* @param[in] object Comparator object.
* @param[in] funcs Callback struct for elements of type T.
*/
non_null()
void merge_sort_with_buf(void *arr, uint32_t arr_size, void *tmp, uint32_t tmp_size, const void *object, const Sort_Funcs *funcs);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* C_TOXCORE_TOXCORE_SORT_H */

View File

@ -0,0 +1,140 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2023-2024 The TokTok team.
*/
#include <benchmark/benchmark.h>
#include <algorithm>
#include <array>
#include <cstdint>
#include <random>
#include "mem.h"
#include "sort.h"
#include "sort_test_util.hh"
namespace {
std::pair<std::vector<Some_Type>, std::mt19937> random_vec(benchmark::State &state)
{
std::mt19937 rng;
// INT_MAX-1 so later we have room to add 1 larger element if needed.
std::uniform_int_distribution<uint32_t> dist{
std::numeric_limits<uint32_t>::min(), std::numeric_limits<uint32_t>::max() - 1};
std::vector<Some_Type> vec(state.range(0));
std::generate(std::begin(vec), std::end(vec), [&]() {
std::array<uint32_t, 8> compare_value;
std::generate(
std::begin(compare_value), std::end(compare_value), [&]() { return dist(rng); });
return Some_Type{nullptr, compare_value, "hello there"};
});
return {vec, rng};
}
std::vector<Some_Type> mostly_sorted_vec(benchmark::State &state)
{
auto [vec, rng] = random_vec(state);
std::sort(vec.begin(), vec.end());
// Randomly swap 5% of the vector.
std::uniform_int_distribution<std::size_t> dist{0, vec.size() - 1};
for (std::size_t i = 0; i < vec.size() / 20; ++i) {
const auto a = dist(rng);
const auto b = dist(rng);
std::swap(vec[a], vec[b]);
}
return vec;
}
void BM_merge_sort(benchmark::State &state)
{
const auto vec = random_vec(state).first;
for (auto _ : state) {
auto unsorted = vec;
merge_sort(unsorted.data(), unsorted.size(), &state, &Some_Type::funcs);
}
}
BENCHMARK(BM_merge_sort)->RangeMultiplier(2)->Range(8, 8 << 8);
void BM_merge_sort_with_buf(benchmark::State &state)
{
const auto vec = random_vec(state).first;
std::vector<Some_Type> buf(vec.size());
for (auto _ : state) {
auto unsorted = vec;
merge_sort_with_buf(
unsorted.data(), unsorted.size(), buf.data(), buf.size(), &state, &Some_Type::funcs);
}
}
BENCHMARK(BM_merge_sort_with_buf)->RangeMultiplier(2)->Range(8, 8 << 8);
void BM_merge_sort_mostly_sorted(benchmark::State &state)
{
auto vec = mostly_sorted_vec(state);
for (auto _ : state) {
auto unsorted = vec;
merge_sort(unsorted.data(), unsorted.size(), &state, &Some_Type::funcs);
}
}
BENCHMARK(BM_merge_sort_mostly_sorted)->RangeMultiplier(2)->Range(8, 8 << 8);
void BM_qsort(benchmark::State &state)
{
const auto vec = random_vec(state).first;
for (auto _ : state) {
auto unsorted = vec;
qsort(unsorted.data(), unsorted.size(), sizeof(unsorted[0]), my_type_cmp);
}
}
BENCHMARK(BM_qsort)->RangeMultiplier(2)->Range(8, 8 << 8);
void BM_qsort_mostly_sorted(benchmark::State &state)
{
auto vec = mostly_sorted_vec(state);
for (auto _ : state) {
auto unsorted = vec;
qsort(unsorted.data(), unsorted.size(), sizeof(unsorted[0]), my_type_cmp);
}
}
BENCHMARK(BM_qsort_mostly_sorted)->RangeMultiplier(2)->Range(8, 8 << 8);
void BM_std_sort(benchmark::State &state)
{
const auto vec = random_vec(state).first;
for (auto _ : state) {
auto unsorted = vec;
std::sort(unsorted.begin(), unsorted.end());
}
}
BENCHMARK(BM_std_sort)->RangeMultiplier(2)->Range(8, 8 << 8);
void BM_std_sort_mostly_sorted(benchmark::State &state)
{
auto vec = mostly_sorted_vec(state);
for (auto _ : state) {
auto unsorted = vec;
std::sort(unsorted.begin(), unsorted.end());
}
}
BENCHMARK(BM_std_sort_mostly_sorted)->RangeMultiplier(2)->Range(8, 8 << 8);
}
BENCHMARK_MAIN();

View File

@ -0,0 +1,79 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2023-2024 The TokTok team.
*/
#include "sort.h"
#include <gtest/gtest.h>
#include <limits>
#include <random>
#include "sort_test_util.hh"
namespace {
TEST(MergeSort, BehavesLikeStdSort)
{
std::mt19937 rng;
// INT_MAX-1 so later we have room to add 1 larger element if needed.
std::uniform_int_distribution<int> dist{
std::numeric_limits<int>::min(), std::numeric_limits<int>::max() - 1};
constexpr auto int_funcs = sort_funcs<int>();
// Test with int arrays.
for (uint32_t i = 1; i < 500; ++i) {
std::vector<int> vec(i);
std::generate(std::begin(vec), std::end(vec), [&]() { return dist(rng); });
auto sorted = vec;
std::sort(sorted.begin(), sorted.end(), std::less<int>());
// If vec was accidentally sorted, add another larger element that almost definitely makes
// it not sorted.
if (vec == sorted) {
int const largest = *std::prev(sorted.end()) + 1;
sorted.push_back(largest);
vec.insert(vec.begin(), largest);
}
ASSERT_NE(vec, sorted);
// Just pass some arbitrary "self" to make sure the callbacks pass it through.
ASSERT_TRUE(merge_sort(vec.data(), vec.size(), &i, &int_funcs));
ASSERT_EQ(vec, sorted);
}
}
TEST(MergeSort, WorksWithNonTrivialTypes)
{
std::mt19937 rng;
std::uniform_int_distribution<int> dist{
std::numeric_limits<int>::min(), std::numeric_limits<int>::max()};
constexpr auto string_funcs = sort_funcs<std::string>();
// Test with std::string arrays.
for (uint32_t i = 1; i < 500; ++i) {
std::vector<std::string> vec(i);
std::generate(std::begin(vec), std::end(vec), [&]() { return std::to_string(dist(rng)); });
auto sorted = vec;
std::sort(sorted.begin(), sorted.end(), std::less<std::string>());
// If vec was accidentally sorted, add another larger element that almost definitely makes
// it not sorted.
if (vec == sorted) {
std::string const largest = "larger than largest int";
sorted.push_back(largest);
vec.insert(vec.begin(), largest);
}
ASSERT_NE(vec, sorted);
// Just pass some arbitrary "self" to make sure the callbacks pass it through.
ASSERT_TRUE(merge_sort(vec.data(), vec.size(), &i, &string_funcs));
ASSERT_EQ(vec, sorted);
}
}
} // namespace

View File

@ -0,0 +1,32 @@
#include "sort_test_util.hh"
#include <array>
#include <cstddef>
#include "sort.h"
#include "util.h"
namespace {
template <typename T, std::size_t N>
int cmp_uint_array(const std::array<T, N> &a, const std::array<T, N> &b)
{
for (std::size_t i = 0; i < a.size(); ++i) {
const int cmp = cmp_uint(a[i], b[i]);
if (cmp != 0) {
return cmp;
}
}
return 0;
}
}
const Sort_Funcs Some_Type::funcs = sort_funcs<Some_Type>();
int my_type_cmp(const void *va, const void *vb)
{
const auto *a = static_cast<const Some_Type *>(va);
const auto *b = static_cast<const Some_Type *>(vb);
return cmp_uint_array(a->compare_value, b->compare_value);
}
bool operator<(const Some_Type &a, const Some_Type &b) { return a.compare_value < b.compare_value; }

View File

@ -0,0 +1,54 @@
/* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2023-2024 The TokTok team.
*/
#ifndef C_TOXCORE_TOXCORE_SORT_TEST_UTIL_H
#define C_TOXCORE_TOXCORE_SORT_TEST_UTIL_H
#include <array>
#include "sort.h"
struct Memory;
template <typename T>
constexpr Sort_Funcs sort_funcs()
{
return {
[](const void *object, const void *va, const void *vb) {
const T *a = static_cast<const T *>(va);
const T *b = static_cast<const T *>(vb);
return *a < *b;
},
[](const void *arr, uint32_t index) -> const void * {
const T *vec = static_cast<const T *>(arr);
return &vec[index];
},
[](void *arr, uint32_t index, const void *val) {
T *vec = static_cast<T *>(arr);
const T *value = static_cast<const T *>(val);
vec[index] = *value;
},
[](void *arr, uint32_t index, uint32_t size) -> void * {
T *vec = static_cast<T *>(arr);
return &vec[index];
},
[](const void *object, uint32_t size) -> void * { return new T[size]; },
[](const void *object, void *arr, uint32_t size) { delete[] static_cast<T *>(arr); },
};
}
// A realistic test case where we have a struct with some stuff and an expensive value we compare.
struct Some_Type {
const Memory *mem;
std::array<uint32_t, 8> compare_value;
const char *name;
static const Sort_Funcs funcs;
};
int my_type_cmp(const void *va, const void *vb);
bool operator<(const Some_Type &a, const Some_Type &b);
#endif // C_TOXCORE_TOXCORE_SORT_TEST_UTIL_H

View File

@ -752,6 +752,8 @@ static Tox *tox_new_system(const struct Tox_Options *options, Tox_Err_New *error
Messenger_Options m_options = {false}; Messenger_Options m_options = {false};
m_options.dns_enabled = !tox_options_get_experimental_disable_dns(opts);
bool load_savedata_sk = false; bool load_savedata_sk = false;
bool load_savedata_tox = false; bool load_savedata_tox = false;
@ -855,9 +857,10 @@ static Tox *tox_new_system(const struct Tox_Options *options, Tox_Err_New *error
} }
const char *const proxy_host = tox_options_get_proxy_host(opts); const char *const proxy_host = tox_options_get_proxy_host(opts);
const bool dns_enabled = !tox_options_get_experimental_disable_dns(opts);
if (proxy_host == nullptr if (proxy_host == nullptr
|| !addr_resolve_or_parse_ip(tox->sys.ns, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr)) { || !addr_resolve_or_parse_ip(tox->sys.ns, tox->sys.mem, proxy_host, &m_options.proxy_info.ip_port.ip, nullptr, dns_enabled)) {
SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST); SET_ERROR_PARAMETER(error, TOX_ERR_NEW_PROXY_BAD_HOST);
// TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain. // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain.
mem_delete(sys->mem, tox); mem_delete(sys->mem, tox);
@ -1139,7 +1142,7 @@ static int32_t resolve_bootstrap_node(Tox *tox, const char *host, uint16_t port,
return -1; return -1;
} }
const int32_t count = net_getipport(tox->sys.mem, host, root, TOX_SOCK_DGRAM); const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, host, root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled);
if (count < 1) { if (count < 1) {
LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host); LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host);

View File

@ -148,7 +148,7 @@ uint32_t tox_version_minor(void);
* Incremented when bugfixes are applied without changing any functionality or * Incremented when bugfixes are applied without changing any functionality or
* API or ABI. * API or ABI.
*/ */
#define TOX_VERSION_PATCH 19 #define TOX_VERSION_PATCH 20
uint32_t tox_version_patch(void); uint32_t tox_version_patch(void);
@ -274,7 +274,7 @@ uint32_t tox_max_status_message_length(void);
* *
* @deprecated The macro will be removed in 0.3.0. Use the function instead. * @deprecated The macro will be removed in 0.3.0. Use the function instead.
*/ */
#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016 #define TOX_MAX_FRIEND_REQUEST_LENGTH 921
uint32_t tox_max_friend_request_length(void); uint32_t tox_max_friend_request_length(void);
@ -668,6 +668,24 @@ struct Tox_Options {
* Default: false. * Default: false.
*/ */
bool experimental_groups_persistence; bool experimental_groups_persistence;
/**
* @brief Disable DNS hostname resolution.
*
* Hostnames or IP addresses are passed to the bootstrap/add_tcp_relay
* function and proxy host options. If disabled (this flag is true), only
* IP addresses are allowed.
*
* If this is set to true, the library will not attempt to resolve
* hostnames. This is useful for clients that want to resolve hostnames
* themselves and pass the resolved IP addresses to the library (e.g. in
* case it wants to use Tor).
* Passing hostnames will result in a TOX_ERR_BOOTSTRAP_BAD_HOST error if
* this is set to true.
*
* Default: false. May become true in the future (0.3.0).
*/
bool experimental_disable_dns;
}; };
bool tox_options_get_ipv6_enabled(const Tox_Options *options); bool tox_options_get_ipv6_enabled(const Tox_Options *options);
@ -742,6 +760,10 @@ bool tox_options_get_experimental_groups_persistence(const Tox_Options *options)
void tox_options_set_experimental_groups_persistence(Tox_Options *options, bool experimental_groups_persistence); void tox_options_set_experimental_groups_persistence(Tox_Options *options, bool experimental_groups_persistence);
bool tox_options_get_experimental_disable_dns(const Tox_Options *options);
void tox_options_set_experimental_disable_dns(Tox_Options *options, bool experimental_disable_dns);
/** /**
* @brief Initialises a Tox_Options object with the default options. * @brief Initialises a Tox_Options object with the default options.
* *

View File

@ -274,6 +274,14 @@ void tox_options_set_experimental_groups_persistence(
{ {
options->experimental_groups_persistence = experimental_groups_persistence; options->experimental_groups_persistence = experimental_groups_persistence;
} }
bool tox_options_get_experimental_disable_dns(const Tox_Options *options)
{
return options->experimental_disable_dns;
}
void tox_options_set_experimental_disable_dns(Tox_Options *options, bool experimental_disable_dns)
{
options->experimental_disable_dns = experimental_disable_dns;
}
const uint8_t *tox_options_get_savedata_data(const Tox_Options *options) const uint8_t *tox_options_get_savedata_data(const Tox_Options *options)
{ {
@ -299,6 +307,7 @@ void tox_options_default(Tox_Options *options)
tox_options_set_dht_announcements_enabled(options, true); tox_options_set_dht_announcements_enabled(options, true);
tox_options_set_experimental_thread_safety(options, false); tox_options_set_experimental_thread_safety(options, false);
tox_options_set_experimental_groups_persistence(options, false); tox_options_set_experimental_groups_persistence(options, false);
tox_options_set_experimental_disable_dns(options, false);
} }
} }

View File

@ -124,7 +124,7 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip
IP_Port *root; IP_Port *root;
const int32_t count = net_getipport(tox->sys.mem, ip, &root, TOX_SOCK_DGRAM); const int32_t count = net_getipport(tox->sys.ns, tox->sys.mem, ip, &root, TOX_SOCK_DGRAM, tox->m->options.dns_enabled);
if (count < 1) { if (count < 1) {
SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_IP); SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_IP);

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-3.0-or-later /* SPDX-License-Identifier: GPL-3.0-or-later
* Copyright © 2016-2018 The TokTok team. * Copyright © 2016-2024 The TokTok team.
* Copyright © 2013 Tox project. * Copyright © 2013 Tox project.
* Copyright © 2013 plutooo * Copyright © 2013 plutooo
*/ */
@ -16,6 +16,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "attributes.h"
#include "ccompat.h" #include "ccompat.h"
#include "mem.h" #include "mem.h"

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