Skip to content

Commit e49a477

Browse files
committed
feat: add forwarding and announce request handling
This is the "server-side" part of the new friend finding system, allowing DHT nodes to store small amounts of data and permit searching for it. A forwarding (proxying) mechanism allows this to be used by TCP clients, and deals with non-transitivity in the network.
1 parent 97acb39 commit e49a477

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+2523
-68
lines changed

.github/scripts/flags-clang.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ add_flag -Wno-unused-function
5050
add_flag -Wno-used-but-marked-unused
5151
# We use variable length arrays a lot.
5252
add_flag -Wno-vla
53-
# Disable warning about Doxygen retval tag
54-
add_flag -fcomment-block-commands=retval
53+
# Disable warnings about unknown Doxygen commands
54+
add_flag -Wno-documentation-unknown-command
5555

5656
# Disable specific warning flags for C++.
5757

CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,8 @@ set(toxcore_PKGCONFIG_REQUIRES)
197197
set(toxcore_SOURCES
198198
third_party/cmp/cmp.c
199199
third_party/cmp/cmp.h
200+
toxcore/announce.c
201+
toxcore/announce.h
200202
toxcore/bin_pack.c
201203
toxcore/bin_pack.h
202204
toxcore/bin_unpack.c
@@ -230,6 +232,8 @@ set(toxcore_SOURCES
230232
toxcore/events/friend_status_message.c
231233
toxcore/events/friend_typing.c
232234
toxcore/events/self_connection_status.c
235+
toxcore/forwarding.c
236+
toxcore/forwarding.h
233237
toxcore/friend_connection.c
234238
toxcore/friend_connection.h
235239
toxcore/friend_requests.c

auto_tests/BUILD.bazel

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ flaky_tests = {
4848
"//c-toxcore/toxcore:TCP_common",
4949
"//c-toxcore/toxcore:TCP_connection",
5050
"//c-toxcore/toxcore:TCP_server",
51+
"//c-toxcore/toxcore:announce",
5152
"//c-toxcore/toxcore:ccompat",
5253
"//c-toxcore/toxcore:crypto_core",
54+
"//c-toxcore/toxcore:forwarding",
5355
"//c-toxcore/toxcore:friend_connection",
5456
"//c-toxcore/toxcore:logger",
5557
"//c-toxcore/toxcore:mono_time",

auto_tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ function(auto_test target)
1919
endfunction()
2020

2121
auto_test(TCP)
22+
auto_test(announce)
2223
auto_test(conference)
2324
auto_test(conference_double_invite)
2425
auto_test(conference_invite_merge)
@@ -31,6 +32,7 @@ auto_test(dht_getnodes_api)
3132
auto_test(encryptsave)
3233
auto_test(file_transfer)
3334
auto_test(file_saving)
35+
auto_test(forwarding)
3436
auto_test(friend_connection)
3537
auto_test(friend_request)
3638
auto_test(friend_request_spam)

auto_tests/Makefile.inc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ libauto_test_support_la_SOURCES = ../auto_tests/auto_test_support.c ../auto_test
55
libauto_test_support_la_LIBADD = libmisc_tools.la libtoxcore.la
66

77
TESTS = \
8+
announce_test \
89
conference_double_invite_test \
910
conference_invite_merge_test \
1011
conference_peer_nick_test \
@@ -13,6 +14,7 @@ TESTS = \
1314
conference_two_test \
1415
crypto_test \
1516
file_transfer_test \
17+
forwarding_test \
1618
friend_connection_test \
1719
friend_request_test \
1820
invalid_tcp_proxy_test \
@@ -68,6 +70,10 @@ endif
6870

6971
check_PROGRAMS = $(TESTS)
7072

73+
announce_test_SOURCES = ../auto_tests/announce_test.c
74+
announce_test_CFLAGS = $(AUTOTEST_CFLAGS)
75+
announce_test_LDADD = $(AUTOTEST_LDADD)
76+
7177
conference_double_invite_test_SOURCES = ../auto_tests/conference_double_invite_test.c
7278
conference_double_invite_test_CFLAGS = $(AUTOTEST_CFLAGS)
7379
conference_double_invite_test_LDADD = $(AUTOTEST_LDADD)
@@ -108,6 +114,10 @@ file_transfer_test_SOURCES = ../auto_tests/file_transfer_test.c
108114
file_transfer_test_CFLAGS = $(AUTOTEST_CFLAGS)
109115
file_transfer_test_LDADD = $(AUTOTEST_LDADD)
110116

117+
forwarding_test_SOURCES = ../auto_tests/forwarding_test.c
118+
forwarding_test_CFLAGS = $(AUTOTEST_CFLAGS)
119+
forwarding_test_LDADD = $(AUTOTEST_LDADD)
120+
111121
friend_connection_test_SOURCES = ../auto_tests/friend_connection_test.c
112122
friend_connection_test_CFLAGS = $(AUTOTEST_CFLAGS)
113123
friend_connection_test_LDADD = $(AUTOTEST_LDADD)

auto_tests/TCP_test.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ static void test_basic(void)
5656
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
5757
crypto_new_keypair(rng, self_public_key, self_secret_key);
5858
const Network *ns = system_network();
59-
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr);
59+
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
6060
ck_assert_msg(tcp_s != nullptr, "Failed to create a TCP relay server.");
6161
ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS,
6262
"Failed to bind a TCP relay server to all %d attempted ports.", NUM_PORTS);
@@ -306,7 +306,7 @@ static void test_some(void)
306306
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
307307
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
308308
crypto_new_keypair(rng, self_public_key, self_secret_key);
309-
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr);
309+
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
310310
ck_assert_msg(tcp_s != nullptr, "Failed to create TCP relay server");
311311
ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind to all ports.");
312312

@@ -497,7 +497,7 @@ static void test_client(void)
497497
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
498498
crypto_new_keypair(rng, self_public_key, self_secret_key);
499499
const Network *ns = system_network();
500-
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr);
500+
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
501501
ck_assert_msg(tcp_s != nullptr, "Failed to create a TCP relay server.");
502502
ck_assert_msg(tcp_server_listen_count(tcp_s) == NUM_PORTS, "Failed to bind the relay server to all ports.");
503503

@@ -704,7 +704,7 @@ static void test_tcp_connection(void)
704704
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
705705
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
706706
crypto_new_keypair(rng, self_public_key, self_secret_key);
707-
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr);
707+
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
708708
ck_assert_msg(pk_equal(tcp_server_public_key(tcp_s), self_public_key), "Wrong public key");
709709

710710
TCP_Proxy_Info proxy_info;
@@ -815,7 +815,7 @@ static void test_tcp_connection2(void)
815815
uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
816816
uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
817817
crypto_new_keypair(rng, self_public_key, self_secret_key);
818-
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr);
818+
TCP_Server *tcp_s = new_TCP_server(logger, rng, ns, USE_IPV6, NUM_PORTS, ports, self_secret_key, nullptr, nullptr);
819819
ck_assert_msg(pk_equal(tcp_server_public_key(tcp_s), self_public_key), "Wrong public key");
820820

821821
TCP_Proxy_Info proxy_info;

auto_tests/announce_test.c

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#include <stdint.h>
2+
#include <string.h>
3+
4+
#include "../toxcore/announce.h"
5+
#include "../toxcore/tox.h"
6+
#include "../testing/misc_tools.h"
7+
#include "../toxcore/mono_time.h"
8+
#include "../toxcore/forwarding.h"
9+
#include "../toxcore/net_crypto.h"
10+
#include "../toxcore/util.h"
11+
#include "auto_test_support.h"
12+
#include "check_compat.h"
13+
14+
static void test_bucketnum(void)
15+
{
16+
const Random *rng = system_random();
17+
ck_assert(rng != nullptr);
18+
uint8_t key1[CRYPTO_PUBLIC_KEY_SIZE], key2[CRYPTO_PUBLIC_KEY_SIZE];
19+
random_bytes(rng, key1, sizeof(key1));
20+
memcpy(key2, key1, CRYPTO_PUBLIC_KEY_SIZE);
21+
22+
ck_assert_msg(get_bucketnum(key1, key2) == 0, "Bad bucketnum");
23+
24+
key2[4] ^= 0x09;
25+
key2[5] ^= 0xc5;
26+
27+
ck_assert_msg(get_bucketnum(key1, key2) == 7, "Bad bucketnum");
28+
29+
key2[4] ^= 0x09;
30+
31+
ck_assert_msg(get_bucketnum(key1, key2) == 17, "Bad bucketnum");
32+
33+
key2[5] ^= 0xc5;
34+
key2[31] ^= 0x09;
35+
36+
ck_assert_msg(get_bucketnum(key1, key2) == 4, "Bad bucketnum");
37+
}
38+
39+
typedef struct Announce_Test_Data {
40+
uint8_t data[MAX_ANNOUNCEMENT_SIZE];
41+
uint16_t length;
42+
bool passed;
43+
} Announce_Test_Data;
44+
45+
static void test_announce_data(void *object, const uint8_t *data, uint16_t length)
46+
{
47+
Announce_Test_Data *test_data = (Announce_Test_Data *) object;
48+
test_data->passed = test_data->length == length && memcmp(test_data->data, data, length) == 0;
49+
}
50+
51+
static void test_store_data(void)
52+
{
53+
const Random *rng = system_random();
54+
ck_assert(rng != nullptr);
55+
const Network *ns = system_network();
56+
ck_assert(ns != nullptr);
57+
Logger *log = logger_new();
58+
ck_assert(log != nullptr);
59+
logger_callback_log(log, (logger_cb *)print_debug_log, nullptr, nullptr);
60+
Mono_Time *mono_time = mono_time_new();
61+
Networking_Core *net = new_networking_no_udp(log, ns);
62+
DHT *dht = new_dht(log, rng, ns, mono_time, net, true, true);
63+
Forwarding *forwarding = new_forwarding(log, rng, mono_time, dht);
64+
Announcements *announce = new_announcements(log, rng, mono_time, forwarding);
65+
ck_assert(announce != nullptr);
66+
67+
/* Just to prevent CI from complaining that set_synch_offset is unused: */
68+
set_synch_offset(announce, 0);
69+
70+
Announce_Test_Data test_data;
71+
random_bytes(rng, test_data.data, sizeof(test_data.data));
72+
test_data.length = sizeof(test_data.data);
73+
74+
uint8_t key[CRYPTO_PUBLIC_KEY_SIZE];
75+
random_bytes(rng, key, sizeof(key));
76+
77+
ck_assert_msg(!on_stored(announce, key, nullptr, nullptr), "Unstored announcement exists");
78+
79+
ck_assert_msg(store_data(announce, key, test_data.data, sizeof(test_data.data),
80+
MAX_MAX_ANNOUNCEMENT_TIMEOUT), "Failed to store announcement");
81+
82+
ck_assert_msg(on_stored(announce, key, test_announce_data, &test_data), "Failed to get stored announcement");
83+
84+
ck_assert_msg(test_data.passed, "Bad stored announcement data");
85+
86+
const uint8_t *const base = dht_get_self_public_key(dht);
87+
ck_assert_msg(store_data(announce, base, test_data.data, sizeof(test_data.data), 1), "failed to store base");
88+
89+
uint8_t test_keys[ANNOUNCE_BUCKET_SIZE + 1][CRYPTO_PUBLIC_KEY_SIZE];
90+
91+
for (uint8_t i = 0; i < ANNOUNCE_BUCKET_SIZE + 1; ++i) {
92+
memcpy(test_keys[i], base, CRYPTO_PUBLIC_KEY_SIZE);
93+
test_keys[i][i] ^= 1;
94+
ck_assert_msg(store_data(announce, test_keys[i], test_data.data, sizeof(test_data.data), 1),
95+
"Failed to store announcement %d", i);
96+
}
97+
98+
ck_assert_msg(on_stored(announce, base, nullptr, nullptr), "base was evicted");
99+
ck_assert_msg(!on_stored(announce, test_keys[0], nullptr, nullptr), "furthest was not evicted");
100+
ck_assert_msg(!store_data(announce, test_keys[0], nullptr, 0, 1), "furthest evicted closer");
101+
102+
kill_announcements(announce);
103+
kill_forwarding(forwarding);
104+
kill_dht(dht);
105+
kill_networking(net);
106+
mono_time_free(mono_time);
107+
logger_kill(log);
108+
}
109+
110+
static void basic_announce_tests(void)
111+
{
112+
test_bucketnum();
113+
test_store_data();
114+
}
115+
116+
117+
int main(void)
118+
{
119+
setvbuf(stdout, nullptr, _IONBF, 0);
120+
121+
basic_announce_tests();
122+
return 0;
123+
}

0 commit comments

Comments
 (0)