Skip to content

Commit

Permalink
feat: Add back the tox_loop implementation for low latency.
Browse files Browse the repository at this point in the history
Copied code from #335.
  • Loading branch information
iphydf committed Nov 17, 2023
1 parent cd34b60 commit 1c9e801
Show file tree
Hide file tree
Showing 24 changed files with 711 additions and 9 deletions.
1 change: 1 addition & 0 deletions .circleci/cmake-tsan
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ cmake -B_build -H. -GNinja \
-DSTRICT_ABI=ON \
-DTEST_TIMEOUT_SECONDS=120 \
-DUSE_IPV6=OFF \
-DUSE_LIBEV=ON \
-DAUTOTEST=ON

cd _build
Expand Down
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ jobs:
cmake
git
libconfig-dev
libev-dev
libgtest-dev
libopus-dev
libsodium-dev
Expand Down Expand Up @@ -144,6 +145,8 @@ jobs:
- run: other/analysis/run-clang
- run: other/analysis/run-cppcheck
- run: other/analysis/run-gcc
- run: other/analysis/run-cppcheck
- run: other/analysis/run-clang-analyze

clang-analyze:
working_directory: ~/work
Expand Down
3 changes: 1 addition & 2 deletions .restyled.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
exclude:
- "**/*.api.h"
# shfmt doesn't support this file
# shfmt doesn't support this file
- "other/analysis/run-clang-tidy"

restylers:
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,12 @@ endif()
# We don't transfer floats over the network, so we disable this functionality.
add_definitions(-DCMP_NO_FLOAT=1)

# TODO(iphydf): Check whether this is actually true.
option(USE_LIBEV "Whether to use libev for tox_loop" OFF)
if(USE_LIBEV)
add_definitions(-DHAVE_LIBEV=1)
endif()

################################################################################
#
# :: Tox Core Library
Expand Down
1 change: 1 addition & 0 deletions auto_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ auto_test(set_name)
auto_test(set_status_message)
auto_test(tox_dispatch)
auto_test(tox_events)
auto_test(tox_loop)
auto_test(tox_many)
auto_test(tox_many_tcp)
auto_test(tox_strncasecmp)
Expand Down
5 changes: 4 additions & 1 deletion auto_tests/file_transfer_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
#include "auto_test_support.h"
#include "check_compat.h"

/* The Travis-CI container responds poorly to ::1 as a localhost address
/* The CI containers respond poorly to ::1 as a localhost address
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST

Check warning on line 19 in auto_tests/file_transfer_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/file_transfer_test.c#L19

MISRA 20.5 rule
#endif
#ifdef FORCE_TESTS_IPV6
#define TOX_LOCALHOST "::1"
#else
Expand Down
2 changes: 1 addition & 1 deletion auto_tests/save_load_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "auto_test_support.h"
#include "check_compat.h"

/* The Travis-CI container responds poorly to ::1 as a localhost address
/* The CI containers respond poorly to ::1 as a localhost address
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST
Expand Down
128 changes: 128 additions & 0 deletions auto_tests/tox_loop_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
#include <pthread.h>
#include <stdlib.h>
#include <time.h>

Check warning on line 3 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L3

MISRA 1.10 rule

#include "../toxcore/tox.h"

#include "check_compat.h"
#include "../testing/misc_tools.h"

/* The CI containers respond poorly to ::1 as a localhost address
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST

Check warning on line 13 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L13

MISRA 20.5 rule
#endif
#ifdef FORCE_TESTS_IPV6
#define TOX_LOCALHOST "::1"
#else
#define TOX_LOCALHOST "127.0.0.1"
#endif

#ifdef TCP_RELAY_PORT
#undef TCP_RELAY_PORT

Check warning on line 22 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L22

MISRA 20.5 rule
#endif
#define TCP_RELAY_PORT 33431

typedef struct Loop_Test {
int start_count;
int stop_count;
pthread_mutex_t mutex;
Tox *tox;
} Loop_Test;

static void tox_loop_cb_start(Tox *tox, void *data)
{
Loop_Test *userdata = (Loop_Test *)data;
pthread_mutex_lock(&userdata->mutex);
++userdata->start_count;
}

static void tox_loop_cb_stop(Tox *tox, void *data)
{
Loop_Test *userdata = (Loop_Test *)data;
++userdata->stop_count;
pthread_mutex_unlock(&userdata->mutex);
}

static void *tox_loop_worker(void *data)
{
Loop_Test *userdata = (Loop_Test *)data;
Tox_Err_Loop err;
tox_loop(userdata->tox, userdata, &err);
ck_assert_msg(err == TOX_ERR_LOOP_OK, "tox_loop error: %d", err);

Check warning on line 52 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L52

MISRA 21.8 rule
return nullptr;
}

static void test_tox_loop(void)
{
pthread_t worker, worker_tcp;

Check warning on line 58 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L58

MISRA 12.3 rule
Tox_Err_Options_New err_opts;
struct Tox_Options *opts = tox_options_new(&err_opts);
ck_assert_msg(err_opts == TOX_ERR_OPTIONS_NEW_OK, "tox_options_new: %d\n", err_opts);

Check warning on line 61 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L61

MISRA 21.8 rule
tox_options_set_experimental_thread_safety(opts, true);

Loop_Test *userdata = (Loop_Test *)calloc(1, sizeof(Loop_Test));

Check warning on line 64 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L64

MISRA 21.3 rule
ck_assert(userdata != nullptr);

Check warning on line 65 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L65

MISRA 21.8 rule
uint8_t dpk[TOX_PUBLIC_KEY_SIZE];

userdata->start_count = 0;
userdata->stop_count = 0;
pthread_mutex_init(&userdata->mutex, nullptr);

tox_options_set_tcp_port(opts, TCP_RELAY_PORT);
Tox_Err_New err_new;
userdata->tox = tox_new(opts, &err_new);
ck_assert_msg(err_new == TOX_ERR_NEW_OK, "tox_new: %d\n", err_new);

Check warning on line 75 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L75

MISRA 21.8 rule
tox_callback_loop_begin(userdata->tox, tox_loop_cb_start);
tox_callback_loop_end(userdata->tox, tox_loop_cb_stop);
pthread_create(&worker, nullptr, tox_loop_worker, userdata);

tox_self_get_dht_id(userdata->tox, dpk);

tox_options_default(opts);
tox_options_set_experimental_thread_safety(opts, true);
Loop_Test userdata_tcp;
userdata_tcp.start_count = 0;
userdata_tcp.stop_count = 0;
pthread_mutex_init(&userdata_tcp.mutex, nullptr);
userdata_tcp.tox = tox_new(opts, &err_new);
ck_assert_msg(err_new == TOX_ERR_NEW_OK, "tox_new: %d\n", err_new);
tox_callback_loop_begin(userdata_tcp.tox, tox_loop_cb_start);
tox_callback_loop_end(userdata_tcp.tox, tox_loop_cb_stop);
pthread_create(&worker_tcp, nullptr, tox_loop_worker, &userdata_tcp);

pthread_mutex_lock(&userdata_tcp.mutex);
Tox_Err_Bootstrap error;
ck_assert_msg(tox_add_tcp_relay(userdata_tcp.tox, TOX_LOCALHOST, TCP_RELAY_PORT, dpk, &error), "Add relay error, %i",

Check warning on line 96 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L96

MISRA 21.8 rule
error);
ck_assert_msg(tox_bootstrap(userdata_tcp.tox, TOX_LOCALHOST, 33445, dpk, &error), "Bootstrap error, %i", error);

Check warning on line 98 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L98

MISRA 21.8 rule
pthread_mutex_unlock(&userdata_tcp.mutex);

c_sleep(1000);

tox_loop_stop(userdata->tox);
void *retval = nullptr;
pthread_join(worker, &retval);
ck_assert_msg((uintptr_t)retval == 0, "tox_loop didn't return 0");

Check warning on line 106 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L106

MISRA 11.6 rule

Check warning on line 106 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L106

MISRA 21.8 rule

tox_kill(userdata->tox);
ck_assert_msg(userdata->start_count == userdata->stop_count, "start and stop must match (start = %d, stop = %d)",

Check warning on line 109 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L109

MISRA 21.8 rule
userdata->start_count, userdata->stop_count);

tox_loop_stop(userdata_tcp.tox);
pthread_join(worker_tcp, &retval);
ck_assert_msg((uintptr_t)retval == 0, "tox_loop didn't return 0");

tox_kill(userdata_tcp.tox);
ck_assert_msg(userdata_tcp.start_count == userdata_tcp.stop_count, "start and stop must match (start = %d, stop = %d)",

Check warning on line 117 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L117

MISRA 21.8 rule
userdata_tcp.start_count, userdata_tcp.stop_count);

tox_options_free(opts);
free(userdata);

Check warning on line 121 in auto_tests/tox_loop_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_loop_test.c#L121

MISRA 21.3 rule
}

int main(int argc, char *argv[])
{
test_tox_loop();
return 0;
}
5 changes: 4 additions & 1 deletion auto_tests/tox_many_tcp_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
#include "auto_test_support.h"
#include "check_compat.h"

/* The Travis-CI container responds poorly to ::1 as a localhost address
/* The CI containers respond poorly to ::1 as a localhost address
* You're encouraged to -D FORCE_TESTS_IPV6 on a local test */
#ifdef TOX_LOCALHOST
#undef TOX_LOCALHOST

Check warning on line 19 in auto_tests/tox_many_tcp_test.c

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

auto_tests/tox_many_tcp_test.c#L19

MISRA 20.5 rule
#endif
#ifdef FORCE_TESTS_IPV6
#define TOX_LOCALHOST "::1"
#else
Expand Down
2 changes: 1 addition & 1 deletion other/analysis/gen-file.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ CPPFLAGS+=("-Itoxav")
CPPFLAGS+=("-Itoxencryptsave")
CPPFLAGS+=("-Ithird_party/cmp")

LDFLAGS=("-lopus" "-lsodium" "-lvpx" "-lpthread" "-lconfig" "-lgtest")
LDFLAGS=("-lopus" "-lsodium" "-lvpx" "-lpthread" "-lconfig" "-lgtest" "-lev")
LDFLAGS+=("-fuse-ld=gold")
LDFLAGS+=("-Wl,--detect-odr-violations")
LDFLAGS+=("-Wl,--warn-common")
Expand Down
3 changes: 3 additions & 0 deletions other/analysis/run-clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ CHECKS="$CHECKS,-clang-diagnostic-tautological-pointer-compare"
# [unreadVariable]
CHECKS="$CHECKS,-cppcoreguidelines-init-variables"

# Used by libev.
CHECKS="$CHECKS,-hicpp-no-assembler"

# Short variable names are used quite a lot, and we don't consider them a
# readability issue.
CHECKS="$CHECKS,-readability-identifier-length"
Expand Down
4 changes: 3 additions & 1 deletion other/analysis/variants.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#!/bin/bash

run
run "$@"
#run -DVANILLA_NACL -I/usr/include/sodium "$@"
run -DHAVE_LIBEV "$@"
2 changes: 1 addition & 1 deletion other/bootstrap_daemon/docker/tox-bootstrapd.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
b2996d73cab7c7453dc10ccf7ad733622558de3b1ad0db824a379cf96f500379 /usr/local/bin/tox-bootstrapd
d9b7c12d7dca260ca9a3aa907d300954c6d888a026d3219138f1875dbc59297c /usr/local/bin/tox-bootstrapd
1 change: 1 addition & 0 deletions toxcore/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,7 @@ cc_library(
":logger",
":mem",
":mono_time",
":net_crypto",
":network",
"//c-toxcore/toxencryptsave:defines",
],
Expand Down
3 changes: 2 additions & 1 deletion toxcore/LAN_discovery.c
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ static Broadcast_Info *fetch_broadcast_info(const Network *ns)

#endif

/** @brief Send packet to all IPv4 broadcast addresses
/**
* @brief Send packet to all IPv4 broadcast addresses
*
* @retval true if sent to at least one broadcast target.
* @retval false on failure to find any valid broadcast target.
Expand Down
56 changes: 56 additions & 0 deletions toxcore/TCP_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include <stdlib.h>
#include <string.h>

#ifdef HAVE_LIBEV
#include <ev.h>
#endif

#include "TCP_common.h"
#include "ccompat.h"
#include "mono_time.h"
Expand All @@ -25,9 +29,19 @@ typedef struct TCP_Client_Conn {
uint32_t number;
} TCP_Client_Conn;

#ifdef HAVE_LIBEV
typedef struct TCP_Client_Socket_Listener {
ev_io listener;
struct ev_loop *dispatcher;
} TCP_Client_Socket_Listener;
#endif

struct TCP_Client_Connection {
TCP_Connection con;
TCP_Client_Status status;
#ifdef HAVE_LIBEV
TCP_Client_Socket_Listener sock_listener;
#endif
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
IP_Port ip_port; /* The ip and port of the server */
Expand Down Expand Up @@ -80,6 +94,43 @@ TCP_Client_Status tcp_con_status(const TCP_Client_Connection *con)
{
return con->status;
}

#ifdef HAVE_LIBEV
static bool tcp_con_ev_is_active(TCP_Client_Connection *con)
{
return ev_is_active(&con->sock_listener.listener)
|| ev_is_pending(&con->sock_listener.listener);
}

void tcp_con_ev_listen(TCP_Client_Connection *con, struct ev_loop *dispatcher, tcp_con_ev_listen_cb *callback,
void *data)
{
if (tcp_con_ev_is_active(con)) {
return;
}

con->sock_listener.dispatcher = dispatcher;
con->sock_listener.listener.data = data;

ev_io_init(&con->sock_listener.listener, callback, con->con.sock.sock, EV_READ);
ev_io_start(dispatcher, &con->sock_listener.listener);
}

void tcp_con_ev_stop(TCP_Client_Connection *con)
{
if (!tcp_con_ev_is_active(con)) {
return;
}

ev_io_stop(con->sock_listener.dispatcher, &con->sock_listener.listener);
}
#else
Socket tcp_con_sock(const TCP_Client_Connection *con)
{
return con->con.sock;
}
#endif

void *tcp_con_custom_object(const TCP_Client_Connection *con)
{
return con->custom_object;
Expand Down Expand Up @@ -1015,6 +1066,11 @@ void kill_tcp_connection(TCP_Client_Connection *tcp_connection)

wipe_priority_list(tcp_connection->con.mem, tcp_connection->con.priority_queue_start);
kill_sock(tcp_connection->con.ns, tcp_connection->con.sock);

#ifdef HAVE_LIBEV
ev_io_stop(tcp_connection->sock_listener.dispatcher, &tcp_connection->sock_listener.listener);
#endif

crypto_memzero(tcp_connection, sizeof(TCP_Client_Connection));
mem_delete(mem, tcp_connection);
}
18 changes: 18 additions & 0 deletions toxcore/TCP_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#ifndef C_TOXCORE_TOXCORE_TCP_CLIENT_H
#define C_TOXCORE_TOXCORE_TCP_CLIENT_H

#ifdef HAVE_LIBEV
#include <ev.h>
#endif

#include "crypto_core.h"
#include "forwarding.h"
#include "mono_time.h"
Expand Down Expand Up @@ -47,6 +51,20 @@ IP_Port tcp_con_ip_port(const TCP_Client_Connection *con);
non_null()
TCP_Client_Status tcp_con_status(const TCP_Client_Connection *con);

// TODO(iphydf): This is exactly the same as in network.h. It should be factored
// out and probably abstracted away from ev.h.
#ifdef HAVE_LIBEV
typedef void tcp_con_ev_listen_cb(struct ev_loop *dispatcher, ev_io *sock_listener, int events);
non_null()
void tcp_con_ev_listen(TCP_Client_Connection *con, struct ev_loop *dispatcher, tcp_con_ev_listen_cb *callback,
void *data);
non_null()
void tcp_con_ev_stop(TCP_Client_Connection *con);
#else
non_null()
Socket tcp_con_sock(const TCP_Client_Connection *con);
#endif

non_null()
void *tcp_con_custom_object(const TCP_Client_Connection *con);
non_null()
Expand Down
Loading

0 comments on commit 1c9e801

Please sign in to comment.