diff --git a/.circleci/config.yml b/.circleci/config.yml index 69811f4..3fae7ff 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -4,14 +4,15 @@ version: 2 workflows: version: 2 program-analysis: + # TODO(iphydf): Re-enable tsan when it's fixed. jobs: # Dynamic analysis in the Bazel build - bazel-asan - bazel-msan - - bazel-tsan + # - bazel-tsan # Dynamic analysis with CMake - asan - - tsan + # - tsan - ubsan # Static analysis - clang-analyze diff --git a/.cirrus.yml b/.cirrus.yml index 5f7bf44..cd54173 100644 --- a/.cirrus.yml +++ b/.cirrus.yml @@ -9,7 +9,9 @@ bazel-opt_task: - git submodule update --init --recursive - /src/workspace/tools/inject-repo c-toxcore 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 --build_tag_filters=-haskell --test_tag_filters=-haskell @@ -27,7 +29,9 @@ bazel-dbg_task: - git submodule update --init --recursive - /src/workspace/tools/inject-repo c-toxcore 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 --build_tag_filters=-haskell --test_tag_filters=-haskell @@ -45,7 +49,9 @@ cimple_task: - git submodule update --init --recursive - /src/workspace/tools/inject-repo c-toxcore 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 --build_tag_filters=haskell --test_tag_filters=haskell diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml new file mode 100644 index 0000000..f618b9e --- /dev/null +++ b/.github/workflows/checks.yml @@ -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 diff --git a/.gitignore b/.gitignore index 33b7971..33d31c0 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ testing/data # Vim *.swp +*.nvimlog # Object files *.o diff --git a/CHANGELOG.md b/CHANGELOG.md index 8bb93bc..36bfb39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 ### Merged PRs: @@ -30,6 +60,7 @@ - [#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 - [#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. - [#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 @@ -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 - [#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 +- [#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 - [#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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 5aebd17..2394bc0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,7 +44,7 @@ set_source_files_properties( # versions in a synchronised way. set(PROJECT_VERSION_MAJOR "0") 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 .so library version / following libtool scheme @@ -309,6 +309,8 @@ set(toxcore_SOURCES toxcore/mono_time.h toxcore/net_crypto.c toxcore/net_crypto.h + toxcore/net_profile.c + toxcore/net_profile.h toxcore/network.c toxcore/network.h toxcore/onion_announce.c @@ -352,7 +354,9 @@ set(toxcore_SOURCES toxcore/tox_unpack.h toxcore/util.c 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) else() set(toxcore_LINK_LIBRARIES ${toxcore_LINK_LIBRARIES} ${LIBSODIUM_LIBRARIES}) @@ -399,7 +403,9 @@ if(BUILD_TOXAV) set(toxcore_API_HEADERS ${toxcore_API_HEADERS} ${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) else() 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) 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) elseif(TARGET 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 - toxcore/DHT_test_util.cc - toxcore/DHT_test_util.hh - toxcore/crypto_core_test_util.cc - toxcore/crypto_core_test_util.hh - toxcore/mem_test_util.cc - toxcore/mem_test_util.hh - toxcore/network_test_util.cc - toxcore/network_test_util.hh - toxcore/test_util.cc - toxcore/test_util.hh) +if(UNITTEST) + add_library(test_util STATIC + toxcore/DHT_test_util.cc + toxcore/DHT_test_util.hh + toxcore/crypto_core_test_util.cc + toxcore/crypto_core_test_util.hh + toxcore/mem_test_util.cc + toxcore/mem_test_util.hh + toxcore/network_test_util.cc + toxcore/network_test_util.hh + toxcore/test_util.cc + toxcore/test_util.hh) +endif() function(unit_test subdir target) add_executable(unit_${target}_test ${subdir}/${target}_test.cc) @@ -530,6 +540,13 @@ function(unit_test subdir target) else() target_link_libraries(unit_${target}_test PRIVATE toxcore_shared) 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) set_target_properties(unit_${target}_test PROPERTIES COMPILE_FLAGS "${TEST_CXX_FLAGS}") 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) endif() 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) 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) elseif(TARGET Threads::Threads) target_link_libraries(DHT_bootstrap PRIVATE Threads::Threads) diff --git a/CMakePresets.json b/CMakePresets.json index 45caa10..2a8ebf9 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -7,6 +7,7 @@ "cacheVariables": { "ENABLE_SHARED": true, "ENABLE_STATIC": true, + "FLAT_OUTPUT_STRUCTURE": true, "AUTOTEST": true, "BUILD_MISC_TESTS": true, "BOOTSTRAP_DAEMON": false, @@ -17,5 +18,19 @@ "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" + } ] } diff --git a/auto_tests/CMakeLists.txt b/auto_tests/CMakeLists.txt index d891ba1..996846b 100644 --- a/auto_tests/CMakeLists.txt +++ b/auto_tests/CMakeLists.txt @@ -9,7 +9,9 @@ if(TARGET toxcore_static) else() target_link_libraries(auto_test_support PRIVATE toxcore_shared) 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) elseif(TARGET Threads::Threads) target_link_libraries(auto_test_support PRIVATE Threads::Threads) @@ -23,7 +25,9 @@ function(auto_test target) else() target_link_libraries(auto_${target}_test PRIVATE toxcore_shared) 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) elseif(TARGET Threads::Threads) target_link_libraries(auto_${target}_test PRIVATE Threads::Threads) @@ -67,6 +71,7 @@ auto_test(invalid_udp_proxy) auto_test(lan_discovery) auto_test(lossless_packet) auto_test(lossy_packet) +auto_test(netprof) auto_test(network) auto_test(onion) auto_test(overflow_recvq) @@ -98,7 +103,10 @@ if(BUILD_TOXAV) auto_test(toxav_basic) 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_many_test PRIVATE PkgConfig::VPX) else() diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c index c4ea79b..94a0608 100644 --- a/auto_tests/TCP_test.c +++ b/auto_tests/TCP_test.c @@ -53,7 +53,7 @@ static void test_basic(void) ck_assert(mem != 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); // 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++) { sock = net_socket(ns, net_family_ipv6(), TOX_SOCK_STREAM, TOX_PROTO_TCP); 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); // Leave open one connection for the next test. @@ -111,12 +111,12 @@ static void test_basic(void) // Sending the handshake ck_assert_msg(net_send(ns, logger, sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, - &localhost) == TCP_CLIENT_HANDSHAKE_SIZE - 1, + &localhost, nullptr) == TCP_CLIENT_HANDSHAKE_SIZE - 1, "An attempt to send the initial handshake minus last byte failed."); do_tcp_server_delay(tcp_s, mono_time, 50); - ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost) == 1, + ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost, nullptr) == 1, "The attempt to send the last byte of handshake failed."); free(handshake); @@ -155,7 +155,7 @@ static void test_basic(void) msg_length = sizeof(r_req) - i; } - ck_assert_msg(net_send(ns, logger, sock, r_req + i, msg_length, &localhost) == msg_length, + ck_assert_msg(net_send(ns, logger, sock, r_req + i, msg_length, &localhost, nullptr) == msg_length, "Failed to send request after completing the handshake."); i += msg_length; @@ -213,7 +213,7 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem, localhost.ip = get_loopback(); 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."); uint8_t f_secret_key[CRYPTO_SECRET_KEY_SIZE]; @@ -234,12 +234,12 @@ static struct sec_TCP_con *new_tcp_con(const Logger *logger, const Memory *mem, "Failed to encrypt the outgoing handshake."); ck_assert_msg(net_send(ns, logger, sock, handshake, TCP_CLIENT_HANDSHAKE_SIZE - 1, - &localhost) == TCP_CLIENT_HANDSHAKE_SIZE - 1, + &localhost, nullptr) == TCP_CLIENT_HANDSHAKE_SIZE - 1, "Failed to send the first portion of the handshake to the TCP relay server."); do_tcp_server_delay(tcp_s, mono_time, 50); - ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost) == 1, + ck_assert_msg(net_send(ns, logger, sock, handshake + (TCP_CLIENT_HANDSHAKE_SIZE - 1), 1, &localhost, nullptr) == 1, "Failed to send last byte of handshake."); do_tcp_server_delay(tcp_s, mono_time, 50); @@ -283,7 +283,7 @@ static int write_packet_tcp_test_connection(const Logger *logger, struct sec_TCP localhost.ip = get_loopback(); localhost.port = 0; - ck_assert_msg(net_send(con->ns, logger, con->sock, packet, packet_size, &localhost) == packet_size, + ck_assert_msg(net_send(con->ns, logger, con->sock, packet, packet_size, &localhost, nullptr) == packet_size, "Failed to send a packet."); return 0; } @@ -312,7 +312,7 @@ static void test_some(void) ck_assert(mem != 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_secret_key[CRYPTO_SECRET_KEY_SIZE]; @@ -506,7 +506,7 @@ static void test_client(void) const Memory *mem = os_memory(); ck_assert(mem != nullptr); - Logger *logger = logger_new(); + Logger *logger = logger_new(mem); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; @@ -524,7 +524,7 @@ static void test_client(void) ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); ip_port_tcp_s.ip = get_loopback(); - TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr); + TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f_public_key, f_secret_key, nullptr, nullptr); // TCP sockets might need a moment before they can be written to. c_sleep(50); do_tcp_connection(logger, mono_time, conn, nullptr); @@ -560,7 +560,7 @@ static void test_client(void) crypto_new_keypair(rng, f2_public_key, f2_secret_key); ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); TCP_Client_Connection *conn2 = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, self_public_key, f2_public_key, - f2_secret_key, nullptr); + f2_secret_key, nullptr, nullptr); c_sleep(50); // The client should call this function (defined earlier) during the routing process. @@ -643,7 +643,7 @@ static void test_client_invalid(void) ck_assert(mem != 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_secret_key[CRYPTO_SECRET_KEY_SIZE]; @@ -657,7 +657,7 @@ static void test_client_invalid(void) ip_port_tcp_s.port = net_htons(ports[random_u32(rng) % NUM_PORTS]); ip_port_tcp_s.ip = get_loopback(); TCP_Client_Connection *conn = new_tcp_connection(logger, mem, mono_time, rng, ns, &ip_port_tcp_s, - self_public_key, f_public_key, f_secret_key, nullptr); + self_public_key, f_public_key, f_secret_key, nullptr, nullptr); // Run the client's main loop but not the server. mono_time_update(mono_time); @@ -721,7 +721,7 @@ static void test_tcp_connection(void) ck_assert(mem != 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; uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; @@ -834,7 +834,7 @@ static void test_tcp_connection2(void) ck_assert(mem != 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_data_callback_called = 0; diff --git a/auto_tests/announce_test.c b/auto_tests/announce_test.c index c4f080d..ef93095 100644 --- a/auto_tests/announce_test.c +++ b/auto_tests/announce_test.c @@ -57,7 +57,7 @@ static void test_store_data(void) const Memory *mem = os_memory(); ck_assert(mem != nullptr); - Logger *log = logger_new(); + Logger *log = logger_new(mem); ck_assert(log != nullptr); logger_callback_log(log, print_debug_logger, nullptr, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); diff --git a/auto_tests/encryptsave_test.c b/auto_tests/encryptsave_test.c index e433e41..3573337 100644 --- a/auto_tests/encryptsave_test.c +++ b/auto_tests/encryptsave_test.c @@ -3,8 +3,6 @@ #include #include -#include - #include "../testing/misc_tools.h" #include "../toxcore/ccompat.h" #include "../toxcore/crypto_core.h" @@ -14,13 +12,10 @@ #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 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 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 */ 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) { 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); ck_assert_msg(key != nullptr, "pass key allocation failure"); 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; uint8_t *encdata2 = (uint8_t *)malloc(size2); ck_assert(encdata2 != nullptr); @@ -224,7 +205,6 @@ static void test_keys(void) int main(void) { setvbuf(stdout, nullptr, _IONBF, 0); - test_known_kdf(); test_save_friend(); test_keys(); diff --git a/auto_tests/forwarding_test.c b/auto_tests/forwarding_test.c index 75e330a..3ba85ed 100644 --- a/auto_tests/forwarding_test.c +++ b/auto_tests/forwarding_test.c @@ -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)); ck_assert(subtox != nullptr); - subtox->log = logger_new(); + subtox->log = logger_new(mem); ck_assert(subtox->log != nullptr); logger_callback_log(subtox->log, print_debug_logger, nullptr, index); subtox->mono_time = mono_time_new(mem, nullptr, nullptr); diff --git a/auto_tests/friend_request_test.c b/auto_tests/friend_request_test.c index 7dfc5bf..18bc5d6 100644 --- a/auto_tests/friend_request_test.c +++ b/auto_tests/friend_request_test.c @@ -10,44 +10,57 @@ #include "../toxcore/tox.h" #include "../toxcore/util.h" #include "../testing/misc_tools.h" + #include "auto_test_support.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, - void *userdata) +typedef struct Callback_Data { + 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 *data = tox_event_friend_request_get_message(event); const size_t length = tox_event_friend_request_get_message_length(event); - ck_assert_msg(length == sizeof(FR_MESSAGE) && memcmp(FR_MESSAGE, data, sizeof(FR_MESSAGE)) == 0, + ck_assert_msg(length == cb_data->length && memcmp(cb_data->message, data, cb_data->length) == 0, "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_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); - tox_dispatch_invoke(dispatch, events, tox1); + tox_dispatch_invoke(dispatch, events, cb_data); 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); - tox_dispatch_invoke(dispatch, events, tox2); + tox_dispatch_invoke(dispatch, events, cb_data); tox_events_free(events); 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"); uint32_t index[] = { 1, 2 }; @@ -60,7 +73,7 @@ static void test_friend_request(void) tox_events_init(tox1); tox_events_init(tox2); - printf("Bootstrapping tox2 off tox1.\n"); + printf("Bootstrapping Tox2 off Tox1.\n"); uint8_t dht_key[TOX_PUBLIC_KEY_SIZE]; tox_self_get_dht_id(tox1, dht_key); 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); 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 { - iterate2_wait(dispatch, tox1, tox2); + iterate2_wait(dispatch, &cb_data); } while (tox_self_get_connection_status(tox1) == 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)); 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); uint8_t address[TOX_ADDRESS_SIZE]; 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); do { - iterate2_wait(dispatch, tox1, tox2); + iterate2_wait(dispatch, &cb_data); } while (tox_friend_get_connection_status(tox1, 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); - 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; } diff --git a/auto_tests/netprof_test.c b/auto_tests/netprof_test.c new file mode 100644 index 0000000..029b003 --- /dev/null +++ b/auto_tests/netprof_test.c @@ -0,0 +1,121 @@ +/** Auto Tests: basic network profile functionality test (UDP only) + * TODO(JFreegman): test TCP packets as well + */ + +#include +#include +#include + +#include "../toxcore/tox_private.h" +#include "../toxcore/util.h" + +#include "auto_test_support.h" +#include "check_compat.h" + +#define NUM_TOXES 2 + +static void test_netprof(AutoTox *autotoxes) +{ + // Send some messages to create fake traffic + for (size_t i = 0; i < 256; ++i) { + for (uint32_t j = 0; j < NUM_TOXES; ++j) { + tox_friend_send_message(autotoxes[j].tox, 0, TOX_MESSAGE_TYPE_NORMAL, (const uint8_t *)"test", 4, nullptr); + } + + iterate_all_wait(autotoxes, NUM_TOXES, ITERATION_INTERVAL); + } + + // idle traffic for a while + for (size_t i = 0; i < 100; ++i) { + iterate_all_wait(autotoxes, NUM_TOXES, ITERATION_INTERVAL); + } + + const Tox *tox1 = autotoxes[0].tox; + + const uint64_t UDP_count_sent1 = tox_netprof_get_packet_total_count(tox1, TOX_NETPROF_PACKET_TYPE_UDP, + TOX_NETPROF_DIRECTION_SENT); + const uint64_t UDP_count_recv1 = tox_netprof_get_packet_total_count(tox1, TOX_NETPROF_PACKET_TYPE_UDP, + TOX_NETPROF_DIRECTION_RECV); + const uint64_t TCP_count_sent1 = tox_netprof_get_packet_total_count(tox1, TOX_NETPROF_PACKET_TYPE_TCP, + TOX_NETPROF_DIRECTION_SENT); + const uint64_t TCP_count_recv1 = tox_netprof_get_packet_total_count(tox1, TOX_NETPROF_PACKET_TYPE_TCP, + TOX_NETPROF_DIRECTION_RECV); + + const uint64_t UDP_bytes_sent1 = tox_netprof_get_packet_total_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, + TOX_NETPROF_DIRECTION_SENT); + const uint64_t UDP_bytes_recv1 = tox_netprof_get_packet_total_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, + TOX_NETPROF_DIRECTION_RECV); + const uint64_t TCP_bytes_sent1 = tox_netprof_get_packet_total_bytes(tox1, TOX_NETPROF_PACKET_TYPE_TCP, + TOX_NETPROF_DIRECTION_SENT); + const uint64_t TCP_bytes_recv1 = tox_netprof_get_packet_total_bytes(tox1, TOX_NETPROF_PACKET_TYPE_TCP, + TOX_NETPROF_DIRECTION_RECV); + + ck_assert(UDP_count_recv1 > 0 && UDP_count_sent1 > 0); + ck_assert(UDP_bytes_recv1 > 0 && UDP_bytes_sent1 > 0); + + (void)TCP_count_sent1; + (void)TCP_bytes_sent1; + (void)TCP_bytes_recv1; + (void)TCP_count_recv1; + + uint64_t total_sent_count = 0; + uint64_t total_recv_count = 0; + uint64_t total_sent_bytes = 0; + uint64_t total_recv_bytes = 0; + + // tox1 makes sure the sum value of all packet ID's is equal to the totals + for (size_t i = 0; i < 256; ++i) { + // this id isn't valid for UDP packets but we still want to call the + // functions and make sure they return some non-zero value + if (i == TOX_NETPROF_PACKET_ID_TCP_DATA) { + ck_assert(tox_netprof_get_packet_id_count(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_SENT) > 0); + ck_assert(tox_netprof_get_packet_id_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_SENT) > 0); + ck_assert(tox_netprof_get_packet_id_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_SENT) > 0); + ck_assert(tox_netprof_get_packet_id_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_RECV) > 0); + continue; + } + + total_sent_count += tox_netprof_get_packet_id_count(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_SENT); + total_recv_count += tox_netprof_get_packet_id_count(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_RECV); + + total_sent_bytes += tox_netprof_get_packet_id_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_SENT); + total_recv_bytes += tox_netprof_get_packet_id_bytes(tox1, TOX_NETPROF_PACKET_TYPE_UDP, i, + TOX_NETPROF_DIRECTION_RECV); + } + + const uint64_t total_packets = total_sent_count + total_recv_count; + ck_assert_msg(total_packets == UDP_count_sent1 + UDP_count_recv1, + "%" PRIu64 "does not match %" PRIu64 "\n", total_packets, UDP_count_sent1 + UDP_count_recv1); + + ck_assert_msg(total_sent_count == UDP_count_sent1, "%" PRIu64 " does not match %" PRIu64 "\n", total_sent_count, UDP_count_sent1); + ck_assert_msg(total_recv_count == UDP_count_recv1, "%" PRIu64 " does not match %" PRIu64"\n", total_recv_count, UDP_count_recv1); + + + const uint64_t total_bytes = total_sent_bytes + total_recv_bytes; + ck_assert_msg(total_bytes == UDP_bytes_sent1 + UDP_bytes_recv1, + "%" PRIu64 "does not match %" PRIu64 "\n", total_bytes, UDP_bytes_sent1 + UDP_bytes_recv1); + + ck_assert_msg(total_sent_bytes == UDP_bytes_sent1, "%" PRIu64 " does not match %" PRIu64 "\n", total_sent_bytes, UDP_bytes_sent1); + ck_assert_msg(total_recv_bytes == UDP_bytes_recv1, "%" PRIu64 " does not match %" PRIu64 "\n", total_recv_bytes, UDP_bytes_recv1); +} + +int main(void) +{ + setvbuf(stdout, nullptr, _IONBF, 0); + + Run_Auto_Options autotox_opts = default_run_auto_options(); + autotox_opts.graph = GRAPH_COMPLETE; + + run_auto_test(nullptr, NUM_TOXES, test_netprof, 0, &autotox_opts); + + return 0; +} + +#undef NUM_TOXES diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c index 76cb94a..a2bc301 100644 --- a/auto_tests/network_test.c +++ b/auto_tests/network_test.c @@ -23,12 +23,15 @@ static void test_addr_resolv_localhost(void) const Network *ns = os_network(); ck_assert(ns != nullptr); + const Memory *mem = os_memory(); + ck_assert(mem != nullptr); + const char localhost[] = "localhost"; IP ip; 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(); char *strerror = net_new_strerror(error); @@ -42,14 +45,14 @@ static void test_addr_resolv_localhost(void) net_ip_ntoa(&ip, &ip_str)); 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 int localhost_split = 0; 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; } @@ -75,7 +78,7 @@ static void test_addr_resolv_localhost(void) ip.family = net_family_unspec(); IP 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(); strerror = net_new_strerror(error); ck_assert_msg(res, "Resolver failed: %d, %s", error, strerror); diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c index 3a81df4..7a32306 100644 --- a/auto_tests/onion_test.c +++ b/auto_tests/onion_test.c @@ -228,9 +228,9 @@ static void test_basic(void) const Random *rng = os_random(); ck_assert(rng != nullptr); - Logger *log1 = logger_new(); + Logger *log1 = logger_new(mem); 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]); Mono_Time *mono_time1 = mono_time_new(mem, nullptr, nullptr); @@ -329,7 +329,7 @@ static void test_basic(void) CRYPTO_PUBLIC_KEY_SIZE) != 0); c_sleep(1000); - Logger *log3 = logger_new(); + Logger *log3 = logger_new(mem); logger_callback_log(log3, print_debug_logger, nullptr, &index[2]); Mono_Time *mono_time3 = mono_time_new(mem, nullptr, nullptr); @@ -412,7 +412,7 @@ static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, u return nullptr; } - on->log = logger_new(); + on->log = logger_new(mem); if (!on->log) { free(on); diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 941bc33..9313566 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,15 +1,25 @@ pool: vmImage: "windows-2019" jobs: - - job: "windows_msvc_conan" + - job: "vcpkg" strategy: matrix: static: - conan.shared: "False" + ENABLE_STATIC: "ON" + ENABLE_SHARED: "OFF" shared: - conan.shared: "True" + ENABLE_STATIC: "OFF" + ENABLE_SHARED: "ON" 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: conan install -if _build -o with_tests=True -o shared=$(conan.shared) . - - bash: CONAN_CPU_COUNT=50 CTEST_OUTPUT_ON_FAILURE=1 conan build -bf _build -if _build . || true + - bash: cmake --preset windows-default -DENABLE_STATIC=$(ENABLE_STATIC) -DENABLE_SHARED=$(ENABLE_SHARED) + 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 diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake index 900e9b1..fb30fdc 100644 --- a/cmake/Dependencies.cmake +++ b/cmake/Dependencies.cmake @@ -12,14 +12,20 @@ find_library(SOCKET_LIBRARIES socket) find_package(pthreads QUIET) if(NOT TARGET PThreads4W::PThreads4W) + find_package(pthreads4w QUIET) +endif() +if(NOT TARGET pthreads4w::pthreads4w) set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) endif() # For toxcore. -pkg_search_module(LIBSODIUM libsodium IMPORTED_TARGET REQUIRED) +pkg_search_module(LIBSODIUM libsodium IMPORTED_TARGET) if(MSVC) - find_package(unofficial-sodium REQUIRED) + find_package(libsodium) + if(NOT TARGET libsodium::libsodium) + find_package(unofficial-sodium REQUIRED) + endif() endif() # For toxav. @@ -27,10 +33,23 @@ pkg_search_module(OPUS opus IMPORTED_TARGET) if(NOT OPUS_FOUND) pkg_search_module(OPUS Opus IMPORTED_TARGET) 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) if(NOT VPX_FOUND) pkg_search_module(VPX libvpx IMPORTED_TARGET) endif() +if(NOT VPX_FOUND) + find_package(libvpx) + if(TARGET libvpx::libvpx) + set(VPX_FOUND TRUE) + endif() +endif() # For tox-bootstrapd. pkg_search_module(LIBCONFIG libconfig IMPORTED_TARGET) diff --git a/conanfile.py b/conanfile.py deleted file mode 100644 index e9af70b..0000000 --- a/conanfile.py +++ /dev/null @@ -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"] diff --git a/configure.ac b/configure.ac index 76eca6b..b2869a9 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.65]) -AC_INIT([tox], [0.2.19]) +AC_INIT([tox], [0.2.20]) AC_CONFIG_AUX_DIR(configure_aux) AC_CONFIG_SRCDIR([toxcore/net_crypto.c]) AM_INIT_AUTOMAKE([foreign 1.10 -Wall -Werror subdir-objects tar-ustar]) diff --git a/other/DHT_bootstrap.c b/other/DHT_bootstrap.c index 8a15fb5..c4511aa 100644 --- a/other/DHT_bootstrap.c +++ b/other/DHT_bootstrap.c @@ -144,16 +144,16 @@ int main(int argc, char *argv[]) IP ip; 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) { 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); const uint16_t start_port = PORT; 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); + // 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]); const bool res = dht_bootstrap_from_address(dht, argv[argvoffset + 1], - ipv6enabled, port, bootstrap_key); + ipv6enabled, dns_enabled, port, bootstrap_key); free(bootstrap_key); if (!res) { diff --git a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 index c726f00..33ace21 100644 --- a/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 +++ b/other/bootstrap_daemon/docker/tox-bootstrapd.sha256 @@ -1 +1 @@ -e96f03a89051c5df12c28d0d6941184da2b92742d248bd4c57d31189a0052844 /usr/local/bin/tox-bootstrapd +9ec2993a28988bd147bf8f4f21a824c2fc5dbf7255e391b3ce517d337ebce5c1 /usr/local/bin/tox-bootstrapd diff --git a/other/bootstrap_daemon/src/config.c b/other/bootstrap_daemon/src/config.c index ba9efa2..19779c5 100644 --- a/other/bootstrap_daemon/src/config.c +++ b/other/bootstrap_daemon/src/config.c @@ -390,6 +390,9 @@ bool bootstrap_from_config(const char *cfg_file_path, DHT *dht, bool enable_ipv6 bool address_resolved; 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); 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); - 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); free(bs_public_key_bin); diff --git a/other/bootstrap_daemon/src/tox-bootstrapd.c b/other/bootstrap_daemon/src/tox-bootstrapd.c index 60e14c0..e29afe5 100644 --- a/other/bootstrap_daemon/src/tox-bootstrapd.c +++ b/other/bootstrap_daemon/src/tox-bootstrapd.c @@ -283,16 +283,17 @@ int main(int argc, char *argv[]) IP ip; 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) { logger_callback_log(logger, toxcore_logger_callback, nullptr, nullptr); } 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); if (net == nullptr) { diff --git a/other/docker/pkgsrc/pkgsrc.Dockerfile b/other/docker/pkgsrc/pkgsrc.Dockerfile index c27ed7c..3483bdf 100644 --- a/other/docker/pkgsrc/pkgsrc.Dockerfile +++ b/other/docker/pkgsrc/pkgsrc.Dockerfile @@ -5,7 +5,7 @@ COPY . /work/c-toxcore-0.2.18 RUN ["tar", "zcf", "c-toxcore.tar.gz", "c-toxcore-0.2.18"] 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", "DISTFILES=c-toxcore.tar.gz", "DISTDIR=/work", "NO_CHECKSUM=yes"] RUN ["bmake", "install"] diff --git a/so.version b/so.version index 26514bc..3415d97 100644 --- a/so.version +++ b/so.version @@ -11,6 +11,6 @@ # For a full reference see: # https://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info -CURRENT=21 +CURRENT=22 REVISION=0 -AGE=19 +AGE=20 diff --git a/testing/BUILD.bazel b/testing/BUILD.bazel index 4427347..d907be3 100644 --- a/testing/BUILD.bazel +++ b/testing/BUILD.bazel @@ -75,7 +75,6 @@ cc_library( deps = [ "//c-toxcore/toxcore:ccompat", "//c-toxcore/toxcore:tox", - "@libsodium", ], ) diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index d664c0f..3c2bea1 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -8,15 +8,9 @@ if(TARGET toxcore_static) else() target_link_libraries(misc_tools PRIVATE toxcore_shared) endif() -if(TARGET unofficial-sodium::sodium) - target_link_libraries(misc_tools PRIVATE unofficial-sodium::sodium) -else() - 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) +if(TARGET pthreads4w::pthreads4w) + target_link_libraries(misc_tools PRIVATE pthreads4w::pthreads4w) +elseif(TARGET PThreads4W::PThreads4W) target_link_libraries(misc_tools PRIVATE PThreads4W::PThreads4W) elseif(TARGET Threads::Threads) target_link_libraries(misc_tools PRIVATE Threads::Threads) @@ -36,7 +30,9 @@ if(BUILD_MISC_TESTS) else() target_link_libraries(Messenger_test PRIVATE toxcore_shared) 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) elseif(TARGET Threads::Threads) target_link_libraries(Messenger_test PRIVATE Threads::Threads) diff --git a/testing/Makefile.inc b/testing/Makefile.inc index 223ebdc..7d5f24b 100644 --- a/testing/Makefile.inc +++ b/testing/Makefile.inc @@ -8,10 +8,6 @@ endif noinst_LTLIBRARIES += libmisc_tools.la 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 noinst_PROGRAMS += Messenger_test diff --git a/testing/Messenger_test.c b/testing/Messenger_test.c index 65ea8a9..18d7347 100644 --- a/testing/Messenger_test.c +++ b/testing/Messenger_test.c @@ -118,10 +118,13 @@ int main(int argc, char *argv[]) exit(1); } + // TODO(iphydf): Maybe disable. + const bool dns_enabled = true; + const uint16_t port = net_htons((uint16_t)port_conv); uint8_t *bootstrap_key = hex_string_to_bin(argv[argvoffset + 3]); bool res = dht_bootstrap_from_address(m->dht, argv[argvoffset + 1], - ipv6enabled, port, bootstrap_key); + ipv6enabled, dns_enabled, port, bootstrap_key); free(bootstrap_key); if (!res) { diff --git a/testing/fuzzing/fuzz_support.cc b/testing/fuzzing/fuzz_support.cc index fe760f9..5cbdb7d 100644 --- a/testing/fuzzing/fuzz_support.cc +++ b/testing/fuzzing/fuzz_support.cc @@ -111,6 +111,7 @@ static constexpr Network_Funcs fuzz_network_funcs = { /* .accept = */ ![](Fuzz_System *self, Socket sock) { return Socket{1337}; }, /* .bind = */ ![](Fuzz_System *self, Socket sock, const Network_Addr *addr) { 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 = */ ![](Fuzz_System *self, Socket sock) { assert(sock.value == 42 || sock.value == 1337); @@ -225,6 +226,7 @@ static constexpr Network_Funcs null_network_funcs = { /* .accept = */ ![](Null_System *self, Socket sock) { return Socket{1337}; }, /* .bind = */ ![](Null_System *self, Socket sock, const Network_Addr *addr) { 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; }, /* .recv = */ ![](Null_System *self, Socket sock, uint8_t *buf, size_t len) { @@ -341,6 +343,7 @@ static constexpr Network_Funcs record_network_funcs = { 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; }, /* .recv = */ ![](Record_System *self, Socket sock, uint8_t *buf, size_t len) { diff --git a/testing/misc_tools.c b/testing/misc_tools.c index a2b950c..6352f47 100644 --- a/testing/misc_tools.c +++ b/testing/misc_tools.c @@ -20,8 +20,6 @@ #include #include -#include - #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) #include #else @@ -137,60 +135,3 @@ int cmdline_parsefor_ipv46(int argc, char **argv, bool *ipv6enabled) 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); -} diff --git a/third_party/cmp b/third_party/cmp index 2ac6bca..52bfcfa 160000 --- a/third_party/cmp +++ b/third_party/cmp @@ -1 +1 @@ -Subproject commit 2ac6bca152987c805c04423ebbba4b750585337f +Subproject commit 52bfcfa17d2eb4322da2037ad625f5575129cece diff --git a/toxcore/BUILD.bazel b/toxcore/BUILD.bazel index 916c622..0ba23b3 100644 --- a/toxcore/BUILD.bazel +++ b/toxcore/BUILD.bazel @@ -121,6 +121,7 @@ cc_library( deps = [ ":attributes", ":ccompat", + ":mem", ], ) @@ -299,6 +300,18 @@ cc_library( ], ) +cc_library( + name = "net_profile", + srcs = ["net_profile.c"], + hdrs = ["net_profile.h"], + deps = [ + ":attributes", + ":ccompat", + ":logger", + ":mem", + ], +) + cc_library( name = "network", srcs = ["network.c"], @@ -318,6 +331,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":util", "@libsodium", "@psocket", @@ -332,6 +346,7 @@ cc_library( hdrs = ["network_test_util.hh"], deps = [ ":crypto_core", + ":mem", ":network", ":test_util", ], @@ -570,6 +585,7 @@ cc_library( ":crypto_core", ":logger", ":mem", + ":net_profile", ":network", ], ) @@ -597,6 +613,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":network", ":onion", ":util", @@ -618,6 +635,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":network", ":util", ], @@ -640,6 +658,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":network", ":onion", ":util", @@ -677,6 +696,7 @@ cc_library( ":logger", ":mem", ":mono_time", + ":net_profile", ":network", ":util", "@pthread", @@ -996,6 +1016,7 @@ cc_library( ":DHT", ":Messenger", ":TCP_client", + ":TCP_server", ":attributes", ":ccompat", ":crypto_core", @@ -1006,6 +1027,7 @@ cc_library( ":mem", ":mono_time", ":net_crypto", + ":net_profile", ":network", ":onion_client", ":state", diff --git a/toxcore/DHT.c b/toxcore/DHT.c index 89c85c3..ec51286 100644 --- a/toxcore/DHT.c +++ b/toxcore/DHT.c @@ -1840,7 +1840,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); } -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) { IP_Port ip_port_v64; @@ -1855,7 +1855,7 @@ bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, 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; dht_bootstrap(dht, &ip_port_v64, public_key); diff --git a/toxcore/DHT.h b/toxcore/DHT.h index 19a9e1d..38e98ba 100644 --- a/toxcore/DHT.h +++ b/toxcore/DHT.h @@ -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 ipv6enabled if false, the resolving sticks STRICTLY to 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 false otherwise */ 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); /** @brief Start sending packets after DHT loaded_friends_list and loaded_clients_list are set. diff --git a/toxcore/DHT_fuzz_test.cc b/toxcore/DHT_fuzz_test.cc index 868aede..5b1b635 100644 --- a/toxcore/DHT_fuzz_test.cc +++ b/toxcore/DHT_fuzz_test.cc @@ -31,7 +31,8 @@ void TestUnpackNodes(Fuzz_Data &input) const int packed_count = unpack_nodes( nodes, node_count, &processed_data_len, input.data(), input.size(), tcp_enabled); if (packed_count > 0) { - Logger *logger = logger_new(); + const Memory *mem = os_memory(); + Logger *logger = logger_new(mem); std::vector packed(packed_count * PACKED_NODE_SIZE_IP6); const int packed_size = pack_nodes(logger, packed.data(), packed.size(), nodes, packed_count); diff --git a/toxcore/DHT_test.cc b/toxcore/DHT_test.cc index 1028fc7..45f886e 100644 --- a/toxcore/DHT_test.cc +++ b/toxcore/DHT_test.cc @@ -334,7 +334,7 @@ TEST(AnnounceNodes, SetAndTest) Test_Memory mem; Test_Network ns; - Logger *log = logger_new(); + Logger *log = logger_new(mem); ASSERT_NE(log, nullptr); Mono_Time *mono_time = mono_time_new(mem, nullptr, nullptr); ASSERT_NE(mono_time, nullptr); diff --git a/toxcore/Makefile.inc b/toxcore/Makefile.inc index db3e193..e22e59d 100644 --- a/toxcore/Makefile.inc +++ b/toxcore/Makefile.inc @@ -74,6 +74,8 @@ libtoxcore_la_SOURCES = ../third_party/cmp/cmp.c \ ../toxcore/ping_array.c \ ../toxcore/net_crypto.h \ ../toxcore/net_crypto.c \ + ../toxcore/net_profile.c \ + ../toxcore/net_profile.h \ ../toxcore/friend_requests.h \ ../toxcore/friend_requests.c \ ../toxcore/LAN_discovery.h \ diff --git a/toxcore/Messenger.c b/toxcore/Messenger.c index 7c9730b..d2a8449 100644 --- a/toxcore/Messenger.c +++ b/toxcore/Messenger.c @@ -3482,7 +3482,7 @@ Messenger *new_messenger(Mono_Time *mono_time, const Memory *mem, const Random * return nullptr; } - m->log = logger_new(); + m->log = logger_new(mem); if (m->log == nullptr) { friendreq_kill(m->fr); diff --git a/toxcore/Messenger.h b/toxcore/Messenger.h index 998a009..be6fb5f 100644 --- a/toxcore/Messenger.h +++ b/toxcore/Messenger.h @@ -86,6 +86,8 @@ typedef struct Messenger_Options { Messenger_State_Plugin *state_plugins; uint8_t state_plugins_length; + + bool dns_enabled; } Messenger_Options; struct Receipts { diff --git a/toxcore/TCP_client.c b/toxcore/TCP_client.c index 2b8c6e4..4b90cdd 100644 --- a/toxcore/TCP_client.c +++ b/toxcore/TCP_client.c @@ -20,6 +20,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "util.h" @@ -107,12 +108,12 @@ void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value) * @retval false on failure */ 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) { - return net_connect(mem, logger, sock, &proxy_info->ip_port); + return net_connect(ns, mem, logger, sock, &proxy_info->ip_port); } else { - return net_connect(mem, logger, sock, ip_port); + return net_connect(ns, mem, logger, sock, ip_port); } } @@ -582,7 +583,7 @@ void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwa TCP_Client_Connection *new_tcp_connection( const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, - const TCP_Proxy_Info *proxy_info) + const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile) { assert(logger != nullptr); assert(mem != nullptr); @@ -617,7 +618,7 @@ TCP_Client_Connection *new_tcp_connection( 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); return nullptr; } @@ -634,6 +635,7 @@ TCP_Client_Connection *new_tcp_connection( temp->con.rng = rng; temp->con.sock = sock; temp->con.ip_port = *ip_port; + temp->con.net_profile = net_profile; memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE); memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE); encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key); @@ -819,6 +821,8 @@ static int handle_tcp_client_packet(const Logger *logger, TCP_Client_Connection return -1; } + netprof_record_packet(conn->con.net_profile, data[0], length, PACKET_DIRECTION_RECV); + switch (data[0]) { case TCP_PACKET_ROUTING_RESPONSE: return handle_tcp_client_routing_response(conn, data, length); diff --git a/toxcore/TCP_client.h b/toxcore/TCP_client.h index ea2654b..b103baa 100644 --- a/toxcore/TCP_client.h +++ b/toxcore/TCP_client.h @@ -15,6 +15,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #define TCP_CONNECTION_TIMEOUT 10 @@ -60,11 +61,11 @@ non_null() void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value); /** Create new TCP connection to ip_port/public_key */ -non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10) +non_null(1, 2, 3, 4, 5, 6, 7, 8, 9) nullable(10, 11) TCP_Client_Connection *new_tcp_connection( const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key, - const TCP_Proxy_Info *proxy_info); + const TCP_Proxy_Info *proxy_info, Net_Profile *net_profile); /** Run the TCP connection */ non_null(1, 2, 3) nullable(4) diff --git a/toxcore/TCP_common.c b/toxcore/TCP_common.c index bd3b7ca..919f09f 100644 --- a/toxcore/TCP_common.c +++ b/toxcore/TCP_common.c @@ -35,7 +35,8 @@ int send_pending_data_nonpriority(const Logger *logger, TCP_Connection *con) } const uint16_t left = con->last_packet_length - con->last_packet_sent; - const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port); + const int len = net_send(con->ns, logger, con->sock, con->last_packet + con->last_packet_sent, left, &con->ip_port, + con->net_profile); if (len <= 0) { return -1; @@ -66,7 +67,7 @@ int send_pending_data(const Logger *logger, TCP_Connection *con) while (p != nullptr) { const uint16_t left = p->size - p->sent; - const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port); + const int len = net_send(con->ns, logger, con->sock, p->data + p->sent, left, &con->ip_port, con->net_profile); if (len != left) { if (len > 0) { @@ -164,7 +165,8 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con } if (priority) { - len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port) : 0; + len = sendpriority ? net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port, + con->net_profile) : 0; if (len <= 0) { len = 0; @@ -179,7 +181,7 @@ int write_packet_tcp_secure_connection(const Logger *logger, TCP_Connection *con return add_priority(con, packet, packet_size, len) ? 1 : 0; } - len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port); + len = net_send(con->ns, logger, con->sock, packet, packet_size, &con->ip_port, con->net_profile); if (len <= 0) { return 0; diff --git a/toxcore/TCP_common.h b/toxcore/TCP_common.h index 9fa1366..3b6a548 100644 --- a/toxcore/TCP_common.h +++ b/toxcore/TCP_common.h @@ -10,6 +10,7 @@ #include "crypto_core.h" #include "logger.h" #include "mem.h" +#include "net_profile.h" #include "network.h" typedef struct TCP_Priority_List TCP_Priority_List; @@ -66,6 +67,10 @@ typedef struct TCP_Connection { TCP_Priority_List *priority_queue_start; TCP_Priority_List *priority_queue_end; + + // This is a shared pointer to the parent's respective Net_Profile object + // (either TCP_Server for TCP server packets or TCP_Connections for TCP client packets). + Net_Profile *net_profile; } TCP_Connection; /** diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c index c7161a9..a5294d5 100644 --- a/toxcore/TCP_connection.c +++ b/toxcore/TCP_connection.c @@ -20,6 +20,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "util.h" @@ -56,6 +57,9 @@ struct TCP_Connections { bool onion_status; uint16_t onion_num_conns; + + /* Network profile for all TCP client packets. */ + Net_Profile *net_profile; }; static const TCP_Connection_to empty_tcp_connection_to = {0}; @@ -928,7 +932,8 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE]; memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE); kill_tcp_connection(tcp_con->connection); - tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, + tcp_c->net_profile); if (tcp_con->connection == nullptr) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -1017,7 +1022,7 @@ static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connecti tcp_con->connection = new_tcp_connection( tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port, - tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, tcp_c->net_profile); if (tcp_con->connection == nullptr) { kill_tcp_relay_connection(tcp_c, tcp_connections_number); @@ -1315,7 +1320,7 @@ static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port tcp_con->connection = new_tcp_connection( tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy, - relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info); + relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info, tcp_c->net_profile); if (tcp_con->connection == nullptr) { return -1; @@ -1609,6 +1614,14 @@ TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, co return nullptr; } + Net_Profile *np = netprof_new(logger, mem); + + if (np == nullptr) { + mem_delete(mem, temp); + return nullptr; + } + + temp->net_profile = np; temp->logger = logger; temp->mem = mem; temp->rng = rng; @@ -1723,7 +1736,17 @@ void kill_tcp_connections(TCP_Connections *tcp_c) crypto_memzero(tcp_c->self_secret_key, sizeof(tcp_c->self_secret_key)); + netprof_kill(tcp_c->mem, tcp_c->net_profile); mem_delete(tcp_c->mem, tcp_c->tcp_connections); mem_delete(tcp_c->mem, tcp_c->connections); mem_delete(tcp_c->mem, tcp_c); } + +const Net_Profile *tcp_connection_get_client_net_profile(const TCP_Connections *tcp_c) +{ + if (tcp_c == nullptr) { + return nullptr; + } + + return tcp_c->net_profile; +} diff --git a/toxcore/TCP_connection.h b/toxcore/TCP_connection.h index 2d35919..8d0de32 100644 --- a/toxcore/TCP_connection.h +++ b/toxcore/TCP_connection.h @@ -21,6 +21,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #define TCP_CONN_NONE 0 @@ -317,4 +318,11 @@ void do_tcp_connections(const Logger *logger, TCP_Connections *tcp_c, void *user nullable(1) void kill_tcp_connections(TCP_Connections *tcp_c); +/** @brief a pointer to the tcp client net profile associated with tcp_c. + * + * @retval null if tcp_c is null. + */ +non_null() +const Net_Profile *tcp_connection_get_client_net_profile(const TCP_Connections *tcp_c); + #endif /* C_TOXCORE_TOXCORE_TCP_CONNECTION_H */ diff --git a/toxcore/TCP_server.c b/toxcore/TCP_server.c index 1363d90..e8b24f9 100644 --- a/toxcore/TCP_server.c +++ b/toxcore/TCP_server.c @@ -27,6 +27,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "onion.h" @@ -91,6 +92,9 @@ struct TCP_Server { uint64_t counter; BS_List accepted_key_list; + + /* Network profile for all TCP server packets. */ + Net_Profile *net_profile; }; static_assert(sizeof(TCP_Server) < 7 * 1024 * 1024, @@ -236,6 +240,7 @@ static int add_accepted(TCP_Server *tcp_server, const Mono_Time *mono_time, TCP_ tcp_server->accepted_connection_array[index].identifier = ++tcp_server->counter; tcp_server->accepted_connection_array[index].last_pinged = mono_time_get(mono_time); tcp_server->accepted_connection_array[index].ping_id = 0; + tcp_server->accepted_connection_array[index].con.net_profile = tcp_server->net_profile; return index; } @@ -357,7 +362,7 @@ static int handle_tcp_handshake(const Logger *logger, TCP_Secure_Connection *con const IP_Port ipp = {{{0}}}; - if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp)) { + if (TCP_SERVER_HANDSHAKE_SIZE != net_send(con->con.ns, logger, con->con.sock, response, TCP_SERVER_HANDSHAKE_SIZE, &ipp, con->con.net_profile)) { crypto_memzero(shared_key, sizeof(shared_key)); return -1; } @@ -680,6 +685,7 @@ static int handle_tcp_packet(TCP_Server *tcp_server, uint32_t con_id, const uint } TCP_Secure_Connection *const con = &tcp_server->accepted_connection_array[con_id]; + netprof_record_packet(con->con.net_profile, data[0], length, PACKET_DIRECTION_RECV); switch (data[0]) { case TCP_PACKET_ROUTING_REQUEST: { @@ -969,6 +975,14 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random return nullptr; } + Net_Profile *np = netprof_new(logger, mem); + + if (np == nullptr) { + mem_delete(mem, temp); + return nullptr; + } + + temp->net_profile = np; temp->logger = logger; temp->mem = mem; temp->ns = ns; @@ -978,6 +992,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random if (socks_listening == nullptr) { LOGGER_ERROR(logger, "socket allocation failed"); + netprof_kill(mem, temp->net_profile); mem_delete(mem, temp); return nullptr; } @@ -989,6 +1004,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random if (temp->efd == -1) { LOGGER_ERROR(logger, "epoll initialisation failed"); + netprof_kill(mem, temp->net_profile); mem_delete(mem, socks_listening); mem_delete(mem, temp); return nullptr; @@ -1022,6 +1038,7 @@ TCP_Server *new_tcp_server(const Logger *logger, const Memory *mem, const Random } if (temp->num_listening_socks == 0) { + netprof_kill(mem, temp->net_profile); mem_delete(mem, temp->socks_listening); mem_delete(mem, temp); return nullptr; @@ -1422,6 +1439,16 @@ void kill_tcp_server(TCP_Server *tcp_server) crypto_memzero(tcp_server->secret_key, sizeof(tcp_server->secret_key)); + netprof_kill(tcp_server->mem, tcp_server->net_profile); mem_delete(tcp_server->mem, tcp_server->socks_listening); mem_delete(tcp_server->mem, tcp_server); } + +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server) +{ + if (tcp_server == nullptr) { + return nullptr; + } + + return tcp_server->net_profile; +} diff --git a/toxcore/TCP_server.h b/toxcore/TCP_server.h index 1d3933a..b20c5e1 100644 --- a/toxcore/TCP_server.h +++ b/toxcore/TCP_server.h @@ -15,6 +15,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "onion.h" @@ -52,4 +53,11 @@ void do_tcp_server(TCP_Server *tcp_server, const Mono_Time *mono_time); nullable(1) void kill_tcp_server(TCP_Server *tcp_server); +/** @brief Returns a pointer to the net profile associated with `tcp_server`. + * + * Returns null if `tcp_server` is null. + */ +nullable(1) +const Net_Profile *tcp_server_get_net_profile(const TCP_Server *tcp_server); + #endif /* C_TOXCORE_TOXCORE_TCP_SERVER_H */ diff --git a/toxcore/events/dht_get_nodes_response.c b/toxcore/events/dht_get_nodes_response.c index 6e03b73..f637b9c 100644 --- a/toxcore/events/dht_get_nodes_response.c +++ b/toxcore/events/dht_get_nodes_response.c @@ -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.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; } diff --git a/toxcore/forwarding_fuzz_test.cc b/toxcore/forwarding_fuzz_test.cc index da772a1..4b8521a 100644 --- a/toxcore/forwarding_fuzz_test.cc +++ b/toxcore/forwarding_fuzz_test.cc @@ -46,7 +46,10 @@ void TestSendForwardRequest(Fuzz_Data &input) // rest of the fuzz data is input for malloc and network Fuzz_System sys(input); - Ptr logger(logger_new(), logger_kill); + Ptr logger(logger_new(sys.mem.get()), logger_kill); + if (logger == nullptr) { + return; + } Ptr net(new_networking_ex(logger.get(), sys.mem.get(), sys.ns.get(), &ipp.ip, 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 Fuzz_System sys(input); - Ptr logger(logger_new(), logger_kill); + Ptr logger(logger_new(sys.mem.get()), logger_kill); + if (logger == nullptr) { + return; + } Ptr net(new_networking_ex(logger.get(), sys.mem.get(), sys.ns.get(), &ipp.ip, ipp.port, ipp.port + 100, nullptr), diff --git a/toxcore/friend_connection.c b/toxcore/friend_connection.c index f017b08..9c44288 100644 --- a/toxcore/friend_connection.c +++ b/toxcore/friend_connection.c @@ -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, 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) { return -1; } diff --git a/toxcore/friend_requests.h b/toxcore/friend_requests.h index a78a570..4f3ed0a 100644 --- a/toxcore/friend_requests.h +++ b/toxcore/friend_requests.h @@ -14,7 +14,8 @@ #include "attributes.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; diff --git a/toxcore/group_announce_fuzz_test.cc b/toxcore/group_announce_fuzz_test.cc index eb0dfb6..9f5655a 100644 --- a/toxcore/group_announce_fuzz_test.cc +++ b/toxcore/group_announce_fuzz_test.cc @@ -19,7 +19,8 @@ void TestUnpackAnnouncesList(Fuzz_Data &input) // TODO(iphydf): How do we know the packed size? 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) != -1) { // 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? 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) { // Always allocate at least something to avoid passing nullptr to functions below. std::vector packed(packed_size + 1); @@ -50,7 +52,7 @@ void TestUnpackPublicAnnounce(Fuzz_Data &input) void TestDoGca(Fuzz_Data &input) { Test_Memory mem; - std::unique_ptr logger(logger_new(), logger_kill); + std::unique_ptr logger(logger_new(mem), logger_kill); uint64_t clock = 1; std::unique_ptr> mono_time( diff --git a/toxcore/group_announce_test.cc b/toxcore/group_announce_test.cc index 2918dc7..f1027f3 100644 --- a/toxcore/group_announce_test.cc +++ b/toxcore/group_announce_test.cc @@ -118,11 +118,12 @@ TEST_F(Announces, AnnouncesGetAndCleanup) struct AnnouncesPack : ::testing::Test { protected: std::vector announces_; + Test_Memory mem_; Logger *logger_ = nullptr; void SetUp() override { - logger_ = logger_new(); + logger_ = logger_new(mem_); ASSERT_NE(logger_, nullptr); // Add an announce without TCP relay. diff --git a/toxcore/group_moderation_test.cc b/toxcore/group_moderation_test.cc index ea72023..89555b9 100644 --- a/toxcore/group_moderation_test.cc +++ b/toxcore/group_moderation_test.cc @@ -191,9 +191,9 @@ struct SanctionsListMod : ::testing::Test { protected: Extended_Public_Key pk; Extended_Secret_Key sk; - Logger *log = logger_new(); Test_Random rng; Test_Memory mem; + Logger *log = logger_new(mem); Moderation mod{mem}; Mod_Sanction sanctions[2] = {}; diff --git a/toxcore/logger.c b/toxcore/logger.c index 67fa523..69d7f50 100644 --- a/toxcore/logger.c +++ b/toxcore/logger.c @@ -13,69 +13,41 @@ #include #include -#include "attributes.h" #include "ccompat.h" +#include "mem.h" struct Logger { + const Memory *mem; + logger_cb *callback; void *context; 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 ""; -} -#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 */ -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) { - free(log); + if (log == nullptr) { + return; + } + + mem_delete(log->mem, log); } 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, ...) { if (log == nullptr) { - log = &logger_stderr; + return; } if (log->callback == nullptr) { diff --git a/toxcore/logger.h b/toxcore/logger.h index 830db88..1c7c007 100644 --- a/toxcore/logger.h +++ b/toxcore/logger.h @@ -12,6 +12,7 @@ #include #include "attributes.h" +#include "mem.h" #ifdef __cplusplus 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. */ -Logger *logger_new(void); +non_null() +Logger *logger_new(const Memory *mem); /** * Frees all resources associated with the logger. diff --git a/toxcore/net_crypto.c b/toxcore/net_crypto.c index 5aafe8a..b78c68b 100644 --- a/toxcore/net_crypto.c +++ b/toxcore/net_crypto.c @@ -23,6 +23,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" #include "util.h" @@ -3096,3 +3097,18 @@ void kill_net_crypto(Net_Crypto *c) crypto_memzero(c, sizeof(Net_Crypto)); mem_delete(mem, c); } + +const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c) +{ + if (c == nullptr) { + return nullptr; + } + + const TCP_Connections *tcp_c = nc_get_tcp_c(c); + + if (tcp_c == nullptr) { + return nullptr; + } + + return tcp_connection_get_client_net_profile(tcp_c); +} diff --git a/toxcore/net_crypto.h b/toxcore/net_crypto.h index 8368d46..3456000 100644 --- a/toxcore/net_crypto.h +++ b/toxcore/net_crypto.h @@ -20,6 +20,7 @@ #include "logger.h" #include "mem.h" #include "mono_time.h" +#include "net_profile.h" #include "network.h" /*** Crypto payloads. */ @@ -417,4 +418,11 @@ void do_net_crypto(Net_Crypto *c, void *userdata); nullable(1) void kill_net_crypto(Net_Crypto *c); +/** + * Returns a pointer to the net profile object for the TCP client associated with `c`. + * Returns null if `c` is null or the TCP_Connections associated with `c` is null. + */ +non_null() +const Net_Profile *nc_get_tcp_client_net_profile(const Net_Crypto *c); + #endif /* C_TOXCORE_TOXCORE_NET_CRYPTO_H */ diff --git a/toxcore/net_profile.c b/toxcore/net_profile.c new file mode 100644 index 0000000..bbff79c --- /dev/null +++ b/toxcore/net_profile.c @@ -0,0 +1,157 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2023-2024 The TokTok team. + */ + +/** + * Functions for the network profile. + */ + +#include "net_profile.h" + +#include + +#include "attributes.h" +#include "logger.h" +#include "mem.h" + +#include "ccompat.h" + +#define NETPROF_TCP_DATA_PACKET_ID 0x10 + +typedef struct Net_Profile { + uint64_t packets_recv[NET_PROF_MAX_PACKET_IDS]; + uint64_t packets_sent[NET_PROF_MAX_PACKET_IDS]; + + uint64_t total_packets_recv; + uint64_t total_packets_sent; + + uint64_t bytes_recv[NET_PROF_MAX_PACKET_IDS]; + uint64_t bytes_sent[NET_PROF_MAX_PACKET_IDS]; + + uint64_t total_bytes_recv; + uint64_t total_bytes_sent; +} Net_Profile; + +/** Returns the number of sent or received packets for all ID's between `start_id` and `end_id`. */ +nullable(1) +static uint64_t netprof_get_packet_count_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, + Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->packets_sent : profile->packets_recv; + uint64_t count = 0; + + for (size_t i = start_id; i <= end_id; ++i) { + count += arr[i]; + } + + return count; +} + +/** Returns the number of sent or received bytes for all ID's between `start_id` and `end_id`. */ +nullable(1) +static uint64_t netprof_get_bytes_id_range(const Net_Profile *profile, uint8_t start_id, uint8_t end_id, + Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + const uint64_t *arr = dir == PACKET_DIRECTION_SEND ? profile->bytes_sent : profile->bytes_recv; + uint64_t bytes = 0; + + for (size_t i = start_id; i <= end_id; ++i) { + bytes += arr[i]; + } + + return bytes; +} + +void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir) +{ + if (profile == nullptr) { + return; + } + + if (dir == PACKET_DIRECTION_SEND) { + ++profile->total_packets_sent; + ++profile->packets_sent[id]; + + profile->total_bytes_sent += length; + profile->bytes_sent[id] += length; + } else { + ++profile->total_packets_recv; + ++profile->packets_recv[id]; + + profile->total_bytes_recv += length; + profile->bytes_recv[id] += length; + } +} + +uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + // Special case - TCP data packets can have any ID between 0x10 and 0xff + if (id == NETPROF_TCP_DATA_PACKET_ID) { + return netprof_get_packet_count_id_range(profile, id, UINT8_MAX, dir); + } + + return dir == PACKET_DIRECTION_SEND ? profile->packets_sent[id] : profile->packets_recv[id]; +} + +uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + return dir == PACKET_DIRECTION_SEND ? profile->total_packets_sent : profile->total_packets_recv; +} + +uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + // Special case - TCP data packets can have any ID between 0x10 and 0xff + if (id == NETPROF_TCP_DATA_PACKET_ID) { + return netprof_get_bytes_id_range(profile, id, 0xff, dir); + } + + return dir == PACKET_DIRECTION_SEND ? profile->bytes_sent[id] : profile->bytes_recv[id]; +} + +uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir) +{ + if (profile == nullptr) { + return 0; + } + + return dir == PACKET_DIRECTION_SEND ? profile->total_bytes_sent : profile->total_bytes_recv; +} + +Net_Profile *netprof_new(const Logger *log, const Memory *mem) +{ + Net_Profile *np = (Net_Profile *)mem_alloc(mem, sizeof(Net_Profile)); + + if (np == nullptr) { + LOGGER_ERROR(log, "failed to allocate memory for net profiler"); + return nullptr; + } + + return np; +} + +void netprof_kill(const Memory *mem, Net_Profile *net_profile) +{ + if (net_profile != nullptr) { + mem_delete(mem, net_profile); + } +} diff --git a/toxcore/net_profile.h b/toxcore/net_profile.h new file mode 100644 index 0000000..a2f66a1 --- /dev/null +++ b/toxcore/net_profile.h @@ -0,0 +1,73 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later + * Copyright © 2023-2024 The TokTok team. + */ + +/** + * Functions for the network profile. + */ +#ifndef C_TOXCORE_TOXCORE_NET_PROFILE_H +#define C_TOXCORE_TOXCORE_NET_PROFILE_H + +#include +#include + +#include "attributes.h" +#include "logger.h" +#include "mem.h" + +/* The max number of packet ID's (must fit inside one byte) */ +#define NET_PROF_MAX_PACKET_IDS 256 + +/* If passed to a netprof function as a nullptr the function will have no effect. */ +typedef struct Net_Profile Net_Profile; + +/** Specifies whether the query is for sent or received packets. */ +typedef enum Packet_Direction { + PACKET_DIRECTION_SEND, + PACKET_DIRECTION_RECV, +} Packet_Direction; + +/** + * Records a sent or received packet of type `id` and size `length` to the given profile. + */ +nullable(1) +void netprof_record_packet(Net_Profile *profile, uint8_t id, size_t length, Packet_Direction dir); + +/** + * Returns the number of sent or received packets of type `id` for the given profile. + */ +nullable(1) +uint64_t netprof_get_packet_count_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir); + +/** + * Returns the total number of sent or received packets for the given profile. + */ +nullable(1) +uint64_t netprof_get_packet_count_total(const Net_Profile *profile, Packet_Direction dir); + +/** + * Returns the number of bytes sent or received of packet type `id` for the given profile. + */ +nullable(1) +uint64_t netprof_get_bytes_id(const Net_Profile *profile, uint8_t id, Packet_Direction dir); + +/** + * Returns the total number of bytes sent or received for the given profile. + */ +nullable(1) +uint64_t netprof_get_bytes_total(const Net_Profile *profile, Packet_Direction dir); + +/** + * Returns a new net_profile object. The caller is responsible for freeing the + * returned memory via `netprof_kill`. + */ +non_null() +Net_Profile *netprof_new(const Logger *log, const Memory *mem); + +/** + * Kills a net_profile object and frees all associated memory. + */ +non_null(1) nullable(2) +void netprof_kill(const Memory *mem, Net_Profile *net_profile); + +#endif /* C_TOXCORE_TOXCORE_NET_PROFILE_H */ diff --git a/toxcore/network.c b/toxcore/network.c index 55aa4e2..2f6c6a2 100644 --- a/toxcore/network.c +++ b/toxcore/network.c @@ -86,6 +86,7 @@ #include "ccompat.h" #include "logger.h" #include "mem.h" +#include "net_profile.h" #include "util.h" // Disable MSG_NOSIGNAL on systems not supporting it, e.g. Windows, FreeBSD @@ -513,6 +514,12 @@ static int sys_listen(void *obj, Socket sock, int 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() static int sys_recvbuf(void *obj, Socket sock) { @@ -586,11 +593,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); } +// 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 = { sys_close, sys_accept, sys_bind, sys_listen, + sys_connect, sys_recvbuf, sys_recv, sys_recvfrom, @@ -600,8 +694,10 @@ static const Network_Funcs os_network_funcs = { sys_socket_nonblock, sys_getsockopt, 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) { @@ -812,9 +908,14 @@ static void loglogdata(const Logger *log, const char *message, const uint8_t *bu } int net_send(const Network *ns, const Logger *log, - Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port) + Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, Net_Profile *net_profile) { const int res = ns->funcs->send(ns->obj, sock, buf, len); + + if (res > 0) { + netprof_record_packet(net_profile, buf[0], res, PACKET_DIRECTION_SEND); + } + loglogdata(log, "T=>", buf, len, ip_port, res); return res; } @@ -882,7 +983,11 @@ bool set_socket_nosigpipe(const Network *ns, Socket sock) bool set_socket_reuseaddr(const Network *ns, Socket sock) { 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; +#endif /* OS_WIN32 */ } bool set_socket_dualstack(const Network *ns, Socket sock) @@ -914,6 +1019,8 @@ struct Networking_Core { uint16_t port; /* Our UDP socket. */ Socket sock; + + Net_Profile *udp_net_profile; }; Family net_family(const Networking_Core *net) @@ -999,6 +1106,11 @@ int send_packet(const Networking_Core *net, const IP_Port *ip_port, Packet packe loglogdata(net->log, "O=>", packet.data, packet.length, ip_port, res); assert(res <= INT_MAX); + + if (res == packet.length && packet.data != nullptr) { + netprof_record_packet(net->udp_net_profile, packet.data[0], packet.length, PACKET_DIRECTION_SEND); + } + return (int)res; } @@ -1103,6 +1215,8 @@ void networking_poll(const Networking_Core *net, void *userdata) continue; } + netprof_record_packet(net->udp_net_profile, data[0], length, PACKET_DIRECTION_RECV); + const Packet_Handler *const handler = &net->packethandlers[data[0]]; if (handler->function == nullptr) { @@ -1163,6 +1277,14 @@ Networking_Core *new_networking_ex( return nullptr; } + Net_Profile *np = netprof_new(log, mem); + + if (np == nullptr) { + free(temp); + return nullptr; + } + + temp->udp_net_profile = np; temp->ns = ns; temp->log = log; temp->mem = mem; @@ -1179,6 +1301,7 @@ Networking_Core *new_networking_ex( char *strerror = net_new_strerror(neterror); LOGGER_ERROR(log, "failed to get a socket?! %d, %s", neterror, strerror); net_kill_strerror(strerror); + netprof_kill(mem, temp->udp_net_profile); mem_delete(mem, temp); if (error != nullptr) { @@ -1386,6 +1509,7 @@ void kill_networking(Networking_Core *net) kill_sock(net->ns, net->sock); } + netprof_kill(net->mem, net->udp_net_profile); mem_delete(net->mem, net); } @@ -1815,37 +1939,34 @@ bool addr_parse_ip(const char *address, IP *to) * 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 * - * @return 0 on failure, `TOX_ADDR_RESOLVE_*` on success. + * @return false on failure, true on success. */ -non_null(1, 2, 3) nullable(4) -static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extra) +non_null(1, 2, 3, 4) nullable(5) +static bool addr_resolve(const Network *ns, const Memory *mem, const char *address, IP *to, IP *extra) { #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if ((true)) { - return 0; + return false; } #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ if (address == nullptr || to == nullptr) { - return 0; + return false; } const Family tox_family = to->family; const int family = make_family(tox_family); - struct addrinfo hints = {0}; - hints.ai_family = family; - hints.ai_socktype = SOCK_DGRAM; // type of socket Tox uses. + Network_Addr *addrs = nullptr; + const int rc = ns->funcs->getaddrinfo(ns->obj, mem, address, family, 0, &addrs); - struct addrinfo *server = nullptr; - - const int rc = getaddrinfo(address, nullptr, &hints, &server); - - // Lookup failed. - if (rc != 0) { - return 0; + // Lookup failed / empty. + if (rc <= 0) { + return false; } + assert(addrs != nullptr); + IP ip4; ip_init(&ip4, false); // ipv6enabled = false IP ip6; @@ -1854,16 +1975,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr int result = 0; bool done = false; - for (struct addrinfo *walker = server; walker != nullptr && !done; walker = walker->ai_next) { - switch (walker->ai_family) { + for (int i = 0; i < rc && !done; ++i) { + switch (addrs[i].addr.ss_family) { case AF_INET: { - if (walker->ai_family == family) { /* AF_INET requested, done */ - const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)walker->ai_addr; + if (addrs[i].addr.ss_family == family) { /* AF_INET requested, done */ + const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr; get_ip4(&to->ip.v4, &addr->sin_addr); result = TOX_ADDR_RESOLVE_INET; done = true; } 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); result |= TOX_ADDR_RESOLVE_INET; } @@ -1872,16 +1993,16 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr } case AF_INET6: { - if (walker->ai_family == family) { /* AF_INET6 requested, done */ - if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { - const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr; + if (addrs[i].addr.ss_family == family) { /* AF_INET6 requested, done */ + if (addrs[i].size == sizeof(struct sockaddr_in6)) { + const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr; get_ip6(&to->ip.v6, &addr->sin6_addr); result = TOX_ADDR_RESOLVE_INET6; done = true; } } else if ((result & TOX_ADDR_RESOLVE_INET6) == 0) { /* AF_UNSPEC requested, store away */ - if (walker->ai_addrlen == sizeof(struct sockaddr_in6)) { - const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)walker->ai_addr; + if (addrs[i].size == sizeof(struct sockaddr_in6)) { + const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(void *)&addrs[i].addr; get_ip6(&ip6.ip.v6, &addr->sin6_addr); result |= TOX_ADDR_RESOLVE_INET6; } @@ -1906,37 +2027,34 @@ static int addr_resolve(const Network *ns, const char *address, IP *to, IP *extr } } - freeaddrinfo(server); - return result; + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); + 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 (!addr_parse_ip(address, to)) { - return false; - } + if (dns_enabled && addr_resolve(ns, mem, address, to, extra)) { + return true; } - 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}; - size_t addrsize; + Network_Addr addr = {{0}}; 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; fill_addr4(&ip_port->ip.ip.v4, &addr4->sin_addr); addr4->sin_port = ip_port->port; } 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; fill_addr6(&ip_port->ip.ip.v6, &addr6->sin6_addr); addr6->sin6_port = ip_port->port; @@ -1958,7 +2076,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)); 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(); // Non-blocking socket: "Operation in progress" means it's connecting. @@ -1974,7 +2092,7 @@ bool net_connect(const Memory *mem, const Logger *log, Socket sock, const IP_Por 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); @@ -1996,6 +2114,10 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to return 1; } + if (!dns_enabled) { + return -1; + } + #ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION if ((true)) { IP_Port *ip_port = (IP_Port *)mem_alloc(mem, sizeof(IP_Port)); @@ -2010,25 +2132,29 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to } #endif /* FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION */ - // It's not an IP address, so now we try doing a DNS lookup. - struct addrinfo *infos; - const int ret = getaddrinfo(node, nullptr, nullptr, &infos); + int type = make_socktype(tox_type); + // ugly + 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; } + assert(addrs != nullptr); + // Used to avoid calloc parameter overflow 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; - for (struct addrinfo *cur = infos; count < max_count && cur != nullptr; cur = cur->ai_next) { - if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) { - continue; - } - - if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) { + for (int i = 0; i < rc && count < max_count; ++i) { + if (addrs[i].addr.ss_family != AF_INET && addrs[i].addr.ss_family != AF_INET6) { continue; } @@ -2038,40 +2164,36 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to assert(count <= max_count); if (count == 0) { - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); return 0; } IP_Port *ip_port = (IP_Port *)mem_valloc(mem, count, sizeof(IP_Port)); if (ip_port == nullptr) { - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); *res = nullptr; return -1; } *res = ip_port; - for (struct addrinfo *cur = infos; cur != nullptr; cur = cur->ai_next) { - if (cur->ai_socktype != 0 && type > 0 && cur->ai_socktype != type) { - continue; - } - - if (cur->ai_family == AF_INET) { - const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)cur->ai_addr; + for (int i = 0; i < rc && count < max_count; ++i) { + if (addrs[i].addr.ss_family == AF_INET) { + const struct sockaddr_in *addr = (const struct sockaddr_in *)(const void *)&addrs[i].addr; ip_port->ip.ip.v4.uint32 = addr->sin_addr.s_addr; - } else if (cur->ai_family == AF_INET6) { - const struct sockaddr_in6 *addr = (const struct sockaddr_in6 *)(const void *)cur->ai_addr; + } else if (addrs[i].addr.ss_family == AF_INET6) { + 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)); } else { 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); if (family == nullptr) { - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); return -1; } @@ -2080,7 +2202,7 @@ int32_t net_getipport(const Memory *mem, const char *node, IP_Port **res, int to ++ip_port; } - freeaddrinfo(infos); + ns->funcs->freeaddrinfo(ns->obj, mem, addrs); return count; } @@ -2296,3 +2418,12 @@ void net_kill_strerror(char *strerror) free(strerror); #endif /* OS_WIN32 */ } + +const Net_Profile *net_get_net_profile(const Networking_Core *net) +{ + if (net == nullptr) { + return nullptr; + } + + return net->udp_net_profile; +} diff --git a/toxcore/network.h b/toxcore/network.h index 06857b8..6547375 100644 --- a/toxcore/network.h +++ b/toxcore/network.h @@ -17,6 +17,7 @@ #include "bin_pack.h" #include "logger.h" #include "mem.h" +#include "net_profile.h" #ifdef __cplusplus extern "C" { @@ -39,6 +40,7 @@ typedef int net_close_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_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_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); @@ -48,8 +50,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_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_getaddrinfo_cb(void *obj, int family, Network_Addr **addrs); -typedef int net_freeaddrinfo_cb(void *obj, 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, const Memory *mem, Network_Addr *addrs); /** @brief Functions wrapping POSIX network functions. * @@ -61,6 +63,7 @@ typedef struct Network_Funcs { net_accept_cb *accept; net_bind_cb *bind; net_listen_cb *listen; + net_connect_cb *connect; net_recvbuf_cb *recvbuf; net_recv_cb *recv; net_recvfrom_cb *recvfrom; @@ -234,8 +237,9 @@ Socket net_invalid_socket(void); /** * Calls send(sockfd, buf, len, MSG_NOSIGNAL). */ -non_null() -int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port); +non_null(1, 2, 4, 6) nullable(7) +int net_send(const Network *ns, const Logger *log, Socket sock, const uint8_t *buf, size_t len, const IP_Port *ip_port, + Net_Profile *net_profile); /** * Calls recv(sockfd, buf, len, MSG_NOSIGNAL). */ @@ -396,21 +400,23 @@ non_null() 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 to to.family MUST be initialized, either set to a specific IP version + * @param[in,out] ns Network object. + * @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 - * IP versions are acceptable - * @param extra can be NULL and is only set in special circumstances, see returns + * IP versions are acceptable. + * @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 `*extra`, if not NULL, an IPv4 address, if `to->family` was TOX_AF_UNSPEC + * 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`. * * @return true on success, false on failure */ -non_null(1, 2, 3) nullable(4) -bool addr_resolve_or_parse_ip(const Network *ns, const char *address, IP *to, IP *extra); +non_null(1, 2, 3, 4) nullable(5) +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. * Packet data is put into data. @@ -501,7 +507,7 @@ void networking_poll(const Networking_Core *net, void *userdata); * Return false on failure. */ 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. * @@ -510,14 +516,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. * * 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. * @retval 0 if res array empty. * @retval -1 on error. */ 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 */ non_null(1) nullable(2) @@ -603,6 +616,13 @@ Networking_Core *new_networking_no_udp(const Logger *log, const Memory *mem, con nullable(1) void kill_networking(Networking_Core *net); +/** @brief Returns a pointer to the network net_profile object associated with `net`. + * + * Returns null if `net` is null. + */ +non_null() +const Net_Profile *net_get_net_profile(const Networking_Core *net); + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/toxcore/network_test_util.cc b/toxcore/network_test_util.cc index 758e495..c8d2ff3 100644 --- a/toxcore/network_test_util.cc +++ b/toxcore/network_test_util.cc @@ -3,6 +3,7 @@ #include #include "crypto_core.h" +#include "mem.h" #include "network.h" #include "test_util.hh" @@ -11,6 +12,7 @@ Network_Funcs const Network_Class::vtable = { Method::invoke<&Network_Class::accept>, Method::invoke<&Network_Class::bind>, Method::invoke<&Network_Class::listen>, + Method::invoke<&Network_Class::connect>, Method::invoke<&Network_Class::recvbuf>, Method::invoke<&Network_Class::recv>, Method::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); } +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::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); } -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; diff --git a/toxcore/network_test_util.hh b/toxcore/network_test_util.hh index 70f238a..be967d3 100644 --- a/toxcore/network_test_util.hh +++ b/toxcore/network_test_util.hh @@ -4,6 +4,7 @@ #include #include "crypto_core.h" +#include "mem.h" #include "network.h" #include "test_util.hh" @@ -24,6 +25,7 @@ struct Network_Class { virtual net_accept_cb accept = 0; virtual net_bind_cb bind = 0; virtual net_listen_cb listen = 0; + virtual net_connect_cb connect = 0; virtual net_recvbuf_cb recvbuf = 0; virtual net_recv_cb recv = 0; virtual net_recvfrom_cb recvfrom = 0; @@ -48,6 +50,7 @@ class Test_Network : public Network_Class { Socket accept(void *obj, Socket sock) override; int bind(void *obj, Socket sock, const Network_Addr *addr) 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 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; @@ -60,8 +63,9 @@ class Test_Network : public Network_Class { void *obj, Socket sock, int level, int optname, void *optval, size_t *optlen) override; int setsockopt( 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 freeaddrinfo(void *obj, Network_Addr *addrs) override; + int getaddrinfo(void *obj, const Memory *mem, const char *address, int family, int protocol, + Network_Addr **addrs) override; + int freeaddrinfo(void *obj, const Memory *mem, Network_Addr *addrs) override; }; template <> diff --git a/toxcore/onion_client.h b/toxcore/onion_client.h index 61e4e6f..92be110 100644 --- a/toxcore/onion_client.h +++ b/toxcore/onion_client.h @@ -183,6 +183,8 @@ non_null() 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) + +// 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) /** @brief Send data of length length to friendnum. diff --git a/toxcore/tox.c b/toxcore/tox.c index b02eb4e..5d703a2 100644 --- a/toxcore/tox.c +++ b/toxcore/tox.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2018 The TokTok team. + * Copyright © 2016-2024 The TokTok team. * Copyright © 2013 Tox project. */ @@ -752,6 +752,8 @@ static Tox *tox_new_system(const struct Tox_Options *options, Tox_Err_New *error Messenger_Options m_options = {false}; + m_options.dns_enabled = !tox_options_get_experimental_disable_dns(opts); + bool load_savedata_sk = 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 bool dns_enabled = !tox_options_get_experimental_disable_dns(opts); 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); // TODO(irungentoo): TOX_ERR_NEW_PROXY_NOT_FOUND if domain. 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; } - 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) { LOGGER_DEBUG(tox->m->log, "could not resolve bootstrap node '%s'", host); diff --git a/toxcore/tox.h b/toxcore/tox.h index 075f250..101437b 100644 --- a/toxcore/tox.h +++ b/toxcore/tox.h @@ -148,7 +148,7 @@ uint32_t tox_version_minor(void); * Incremented when bugfixes are applied without changing any functionality or * API or ABI. */ -#define TOX_VERSION_PATCH 19 +#define TOX_VERSION_PATCH 20 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. */ -#define TOX_MAX_FRIEND_REQUEST_LENGTH 1016 +#define TOX_MAX_FRIEND_REQUEST_LENGTH 921 uint32_t tox_max_friend_request_length(void); @@ -668,6 +668,24 @@ struct Tox_Options { * Default: false. */ 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); @@ -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); +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. * diff --git a/toxcore/tox_api.c b/toxcore/tox_api.c index 18d861c..19b46ef 100644 --- a/toxcore/tox_api.c +++ b/toxcore/tox_api.c @@ -274,6 +274,14 @@ void tox_options_set_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) { @@ -299,6 +307,7 @@ void tox_options_default(Tox_Options *options) tox_options_set_dht_announcements_enabled(options, true); tox_options_set_experimental_thread_safety(options, false); tox_options_set_experimental_groups_persistence(options, false); + tox_options_set_experimental_disable_dns(options, false); } } @@ -1713,3 +1722,120 @@ const char *tox_group_mod_event_to_string(Tox_Group_Mod_Event value) return ""; } +const char *tox_netprof_packet_id_to_string(Tox_Netprof_Packet_Id value) +{ + switch (value) { + case TOX_NETPROF_PACKET_ID_ZERO: + return "TOX_NETPROF_PACKET_ID_ZERO"; + case TOX_NETPROF_PACKET_ID_ONE: + return "TOX_NETPROF_PACKET_ID_ONE"; + case TOX_NETPROF_PACKET_ID_TWO: + return "TOX_NETPROF_PACKET_ID_TWO"; + case TOX_NETPROF_PACKET_ID_TCP_DISCONNECT: + return "TOX_NETPROF_PACKET_ID_TCP_DISCONNECT"; + case TOX_NETPROF_PACKET_ID_FOUR: + return "TOX_NETPROF_PACKET_ID_FOUR"; + case TOX_NETPROF_PACKET_ID_TCP_PONG: + return "TOX_NETPROF_PACKET_ID_TCP_PONG"; + case TOX_NETPROF_PACKET_ID_TCP_OOB_SEND: + return "TOX_NETPROF_PACKET_ID_TCP_OOB_SEND"; + case TOX_NETPROF_PACKET_ID_TCP_OOB_RECV: + return "TOX_NETPROF_PACKET_ID_TCP_OOB_RECV"; + case TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST: + return "TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST"; + case TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE: + return "TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE"; + case TOX_NETPROF_PACKET_ID_TCP_DATA: + return "TOX_NETPROF_PACKET_ID_TCP_DATA"; + case TOX_NETPROF_PACKET_ID_COOKIE_REQUEST: + return "TOX_NETPROF_PACKET_ID_COOKIE_REQUEST"; + case TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_CRYPTO_HS: + return "TOX_NETPROF_PACKET_ID_CRYPTO_HS"; + case TOX_NETPROF_PACKET_ID_CRYPTO_DATA: + return "TOX_NETPROF_PACKET_ID_CRYPTO_DATA"; + case TOX_NETPROF_PACKET_ID_CRYPTO: + return "TOX_NETPROF_PACKET_ID_CRYPTO"; + case TOX_NETPROF_PACKET_ID_LAN_DISCOVERY: + return "TOX_NETPROF_PACKET_ID_LAN_DISCOVERY"; + case TOX_NETPROF_PACKET_ID_GC_HANDSHAKE: + return "TOX_NETPROF_PACKET_ID_GC_HANDSHAKE"; + case TOX_NETPROF_PACKET_ID_GC_LOSSLESS: + return "TOX_NETPROF_PACKET_ID_GC_LOSSLESS"; + case TOX_NETPROF_PACKET_ID_GC_LOSSY: + return "TOX_NETPROF_PACKET_ID_GC_LOSSY"; + case TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL: + return "TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL"; + case TOX_NETPROF_PACKET_ID_ONION_SEND_1: + return "TOX_NETPROF_PACKET_ID_ONION_SEND_1"; + case TOX_NETPROF_PACKET_ID_ONION_SEND_2: + return "TOX_NETPROF_PACKET_ID_ONION_SEND_2"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD"; + case TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST: + return "TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST"; + case TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE: + return "TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST"; + case TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_ONION_RECV_3: + return "TOX_NETPROF_PACKET_ID_ONION_RECV_3"; + case TOX_NETPROF_PACKET_ID_ONION_RECV_2: + return "TOX_NETPROF_PACKET_ID_ONION_RECV_2"; + case TOX_NETPROF_PACKET_ID_ONION_RECV_1: + return "TOX_NETPROF_PACKET_ID_ONION_RECV_1"; + case TOX_NETPROF_PACKET_ID_FORWARD_REQUEST: + return "TOX_NETPROF_PACKET_ID_FORWARD_REQUEST"; + case TOX_NETPROF_PACKET_ID_FORWARDING: + return "TOX_NETPROF_PACKET_ID_FORWARDING"; + case TOX_NETPROF_PACKET_ID_FORWARD_REPLY: + return "TOX_NETPROF_PACKET_ID_FORWARD_REPLY"; + case TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST: + return "TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST"; + case TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE: + return "TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE"; + case TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST: + return "TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST"; + case TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST: + return "TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST"; + case TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE: + return "TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE"; + case TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO: + return "TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO"; + } + + return ""; +} +const char *tox_netprof_packet_type_to_string(Tox_Netprof_Packet_Type value) +{ + switch (value) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: + return "TOX_NETPROF_PACKET_TYPE_TCP_CLIENT"; + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: + return "TOX_NETPROF_PACKET_TYPE_TCP_SERVER"; + case TOX_NETPROF_PACKET_TYPE_TCP: + return "TOX_NETPROF_PACKET_TYPE_TCP"; + case TOX_NETPROF_PACKET_TYPE_UDP: + return "TOX_NETPROF_PACKET_TYPE_UDP"; + } + + return ""; +} +const char *tox_netprof_direction_to_string(Tox_Netprof_Direction value) +{ + switch (value) { + case TOX_NETPROF_DIRECTION_SENT: + return "TOX_NETPROF_DIRECTION_SENT"; + case TOX_NETPROF_DIRECTION_RECV: + return "TOX_NETPROF_DIRECTION_RECV"; + } + + return ""; +} diff --git a/toxcore/tox_private.c b/toxcore/tox_private.c index 7b6050a..9d34837 100644 --- a/toxcore/tox_private.c +++ b/toxcore/tox_private.c @@ -1,5 +1,5 @@ /* SPDX-License-Identifier: GPL-3.0-or-later - * Copyright © 2016-2022 The TokTok team. + * Copyright © 2016-2024 The TokTok team. * Copyright © 2013 Tox project. */ @@ -11,13 +11,16 @@ #include #include "DHT.h" +#include "TCP_server.h" #include "attributes.h" #include "ccompat.h" #include "crypto_core.h" #include "group_chats.h" #include "group_common.h" +#include "logger.h" #include "mem.h" #include "net_crypto.h" +#include "net_profile.h" #include "network.h" #include "tox.h" #include "tox_struct.h" @@ -124,7 +127,7 @@ bool tox_dht_get_nodes(const Tox *tox, const uint8_t *public_key, const char *ip 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) { SET_ERROR_PARAMETER(error, TOX_ERR_DHT_GET_NODES_BAD_IP); @@ -226,3 +229,199 @@ bool tox_group_peer_get_ip_address(const Tox *tox, uint32_t group_number, uint32 SET_ERROR_PARAMETER(error, TOX_ERR_GROUP_PEER_QUERY_OK); return true; } + +uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t count = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + count = netprof_get_packet_count_id(tcp_c_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + count = netprof_get_packet_count_id(tcp_s_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_count = netprof_get_packet_count_id(tcp_c_profile, id, dir); + const uint64_t tcp_s_count = netprof_get_packet_count_id(tcp_s_profile, id, dir); + count = tcp_c_count + tcp_s_count; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + count = netprof_get_packet_count_id(udp_profile, id, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return count; +} + +uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t count = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + count = netprof_get_packet_count_total(tcp_c_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + count = netprof_get_packet_count_total(tcp_s_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_count = netprof_get_packet_count_total(tcp_c_profile, dir); + const uint64_t tcp_s_count = netprof_get_packet_count_total(tcp_s_profile, dir); + count = tcp_c_count + tcp_s_count; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + count = netprof_get_packet_count_total(udp_profile, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return count; +} + +uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t bytes = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + bytes = netprof_get_bytes_id(tcp_c_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + bytes = netprof_get_bytes_id(tcp_s_profile, id, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_bytes = netprof_get_bytes_id(tcp_c_profile, id, dir); + const uint64_t tcp_s_bytes = netprof_get_bytes_id(tcp_s_profile, id, dir); + bytes = tcp_c_bytes + tcp_s_bytes; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + bytes = netprof_get_bytes_id(udp_profile, id, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return bytes; +} + +uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction) +{ + assert(tox != nullptr); + + tox_lock(tox); + + const Net_Profile *tcp_c_profile = nc_get_tcp_client_net_profile(tox->m->net_crypto); + const Net_Profile *tcp_s_profile = tcp_server_get_net_profile(tox->m->tcp_server); + + const Packet_Direction dir = (Packet_Direction) direction; + + uint64_t bytes = 0; + + switch (type) { + case TOX_NETPROF_PACKET_TYPE_TCP_CLIENT: { + bytes = netprof_get_bytes_total(tcp_c_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP_SERVER: { + bytes = netprof_get_bytes_total(tcp_s_profile, dir); + break; + } + + case TOX_NETPROF_PACKET_TYPE_TCP: { + const uint64_t tcp_c_bytes = netprof_get_bytes_total(tcp_c_profile, dir); + const uint64_t tcp_s_bytes = netprof_get_bytes_total(tcp_s_profile, dir); + bytes = tcp_c_bytes + tcp_s_bytes; + break; + } + + case TOX_NETPROF_PACKET_TYPE_UDP: { + const Net_Profile *udp_profile = net_get_net_profile(tox->m->net); + bytes = netprof_get_bytes_total(udp_profile, dir); + break; + } + + default: { + LOGGER_ERROR(tox->m->log, "invalid packet type: %d", type); + break; + } + } + + tox_unlock(tox); + + return bytes; +} diff --git a/toxcore/tox_private.h b/toxcore/tox_private.h index c872bfe..2c53c75 100644 --- a/toxcore/tox_private.h +++ b/toxcore/tox_private.h @@ -169,6 +169,267 @@ uint16_t tox_dht_get_num_closelist(const Tox *tox); */ uint16_t tox_dht_get_num_closelist_announce_capable(const Tox *tox); +/******************************************************************************* + * + * :: Network profiler + * + ******************************************************************************/ + + +/** + * Represents all of the network packet identifiers that Toxcore uses. + * + * Notes: + * - Some packet ID's have different purposes depending on the + * packet type. These ID's are given numeral names. + * + * - Queries for invalid packet ID's return undefined results. For example, + * querying a TCP-exclusive packet ID for UDP, or querying an ID that + * doesn't exist in this enum. + */ +typedef enum Tox_Netprof_Packet_Id { + /** + * Ping request packet (UDP). + * Routing request (TCP). + */ + TOX_NETPROF_PACKET_ID_ZERO = 0x00, + + /** + * Ping response packet (UDP). + * Routing response (TCP). + */ + TOX_NETPROF_PACKET_ID_ONE = 0x01, + + /** + * Get nodes request packet (UDP). + * Connection notification (TCP). + */ + TOX_NETPROF_PACKET_ID_TWO = 0x02, + + /** + * TCP disconnect notification. + */ + TOX_NETPROF_PACKET_ID_TCP_DISCONNECT = 0x03, + + /** + * Send nodes response packet (UDP). + * Ping packet (TCP). + */ + TOX_NETPROF_PACKET_ID_FOUR = 0x04, + + /** + * TCP pong packet. + */ + TOX_NETPROF_PACKET_ID_TCP_PONG = 0x05, + + /** + * TCP out-of-band send packet. + */ + TOX_NETPROF_PACKET_ID_TCP_OOB_SEND = 0x06, + + /** + * TCP out-of-band receive packet. + */ + TOX_NETPROF_PACKET_ID_TCP_OOB_RECV = 0x07, + + /** + * TCP onion request packet. + */ + TOX_NETPROF_PACKET_ID_TCP_ONION_REQUEST = 0x08, + + /** + * TCP onion response packet. + */ + TOX_NETPROF_PACKET_ID_TCP_ONION_RESPONSE = 0x09, + + /** + * TCP data packet. + */ + TOX_NETPROF_PACKET_ID_TCP_DATA = 0x10, + + /** + * Cookie request packet. + */ + TOX_NETPROF_PACKET_ID_COOKIE_REQUEST = 0x18, + + /** + * Cookie response packet. + */ + TOX_NETPROF_PACKET_ID_COOKIE_RESPONSE = 0x19, + + /** + * Crypto handshake packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO_HS = 0x1a, + + /** + * Crypto data packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO_DATA = 0x1b, + + /** + * Encrypted data packet. + */ + TOX_NETPROF_PACKET_ID_CRYPTO = 0x20, + + /** + * LAN discovery packet. + */ + TOX_NETPROF_PACKET_ID_LAN_DISCOVERY = 0x21, + + /** + * DHT groupchat packets. + */ + TOX_NETPROF_PACKET_ID_GC_HANDSHAKE = 0x5a, + TOX_NETPROF_PACKET_ID_GC_LOSSLESS = 0x5b, + TOX_NETPROF_PACKET_ID_GC_LOSSY = 0x5c, + + /** + * Onion send packets. + */ + TOX_NETPROF_PACKET_ID_ONION_SEND_INITIAL = 0x80, + TOX_NETPROF_PACKET_ID_ONION_SEND_1 = 0x81, + TOX_NETPROF_PACKET_ID_ONION_SEND_2 = 0x82, + + /** + * DHT announce request packet (deprecated). + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST_OLD = 0x83, + + /** + * DHT announce response packet (deprecated). + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE_OLD = 0x84, + + /** + * Onion data request packet. + */ + TOX_NETPROF_PACKET_ID_ONION_DATA_REQUEST = 0x85, + + /** + * Onion data response packet. + */ + TOX_NETPROF_PACKET_ID_ONION_DATA_RESPONSE = 0x86, + + /** + * DHT announce request packet. + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_REQUEST = 0x87, + + /** + * DHT announce response packet. + */ + TOX_NETPROF_PACKET_ID_ANNOUNCE_RESPONSE = 0x88, + + /** + * Onion receive packets. + */ + TOX_NETPROF_PACKET_ID_ONION_RECV_3 = 0x8c, + TOX_NETPROF_PACKET_ID_ONION_RECV_2 = 0x8d, + TOX_NETPROF_PACKET_ID_ONION_RECV_1 = 0x8e, + + TOX_NETPROF_PACKET_ID_FORWARD_REQUEST = 0x90, + TOX_NETPROF_PACKET_ID_FORWARDING = 0x91, + TOX_NETPROF_PACKET_ID_FORWARD_REPLY = 0x92, + + TOX_NETPROF_PACKET_ID_DATA_SEARCH_REQUEST = 0x93, + TOX_NETPROF_PACKET_ID_DATA_SEARCH_RESPONSE = 0x94, + TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_REQUEST = 0x95, + TOX_NETPROF_PACKET_ID_DATA_RETRIEVE_RESPONSE = 0x96, + TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_REQUEST = 0x97, + TOX_NETPROF_PACKET_ID_STORE_ANNOUNCE_RESPONSE = 0x98, + + /** + * Bootstrap info packet. + */ + TOX_NETPROF_PACKET_ID_BOOTSTRAP_INFO = 0xf0, +} Tox_Netprof_Packet_Id; + +const char *tox_netprof_packet_id_to_string(Tox_Netprof_Packet_Id value); + +/** + * Specifies the packet type for a given query. + */ +typedef enum Tox_Netprof_Packet_Type { + /** + * TCP client packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP_CLIENT, + + /** + * TCP server packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP_SERVER, + + /** + * Combined TCP server and TCP client packets. + */ + TOX_NETPROF_PACKET_TYPE_TCP, + + /** + * UDP packets. + */ + TOX_NETPROF_PACKET_TYPE_UDP, +} Tox_Netprof_Packet_Type; + +const char *tox_netprof_packet_type_to_string(Tox_Netprof_Packet_Type value); + +/** + * Specifies the packet direction for a given query. + */ +typedef enum Tox_Netprof_Direction { + /** + * Outbound packets. + */ + TOX_NETPROF_DIRECTION_SENT, + + /** + * Inbound packets. + */ + TOX_NETPROF_DIRECTION_RECV, +} Tox_Netprof_Direction; + +const char *tox_netprof_direction_to_string(Tox_Netprof_Direction value); + +/** + * Return the number of packets sent or received for a specific packet ID. + * + * @param type The types of packets being queried. + * @param id The packet ID being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_id_count(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction); + +/** + * Return the total number of packets sent or received. + * + * @param type The types of packets being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_total_count(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction); + +/** + * Return the number of bytes sent or received for a specific packet ID. + * + * @param type The types of packets being queried. + * @param id The packet ID being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_id_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, uint8_t id, + Tox_Netprof_Direction direction); + +/** + * Return the total number of bytes sent or received. + * + * @param type The types of packets being queried. + * @param direction The packet direction. + */ +uint64_t tox_netprof_get_packet_total_bytes(const Tox *tox, Tox_Netprof_Packet_Type type, + Tox_Netprof_Direction direction); + + /******************************************************************************* * * :: DHT groupchat queries.