summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--auto_tests/Makefile.inc10
-rw-r--r--auto_tests/TCP_test.c10
-rw-r--r--auto_tests/assoc_test.c12
-rw-r--r--auto_tests/crypto_test.c12
-rw-r--r--auto_tests/dht_test.c362
-rw-r--r--auto_tests/helpers.h15
-rw-r--r--auto_tests/messenger_test.c7
-rw-r--r--auto_tests/network_test.c7
-rw-r--r--auto_tests/onion_test.c10
-rw-r--r--auto_tests/skeleton_test.c8
-rw-r--r--auto_tests/tox_test.c10
-rw-r--r--auto_tests/toxav_basic_test.c8
-rw-r--r--toxcore/DHT.c247
-rw-r--r--toxcore/onion_client.c2
14 files changed, 451 insertions, 269 deletions
diff --git a/auto_tests/Makefile.inc b/auto_tests/Makefile.inc
index ecf3f31f..c68f313b 100644
--- a/auto_tests/Makefile.inc
+++ b/auto_tests/Makefile.inc
@@ -1,7 +1,7 @@
1if BUILD_TESTS 1if BUILD_TESTS
2 2
3TESTS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test 3TESTS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test dht_autotest
4check_PROGRAMS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test 4check_PROGRAMS = messenger_autotest crypto_test network_test assoc_test onion_test TCP_test tox_test dht_autotest
5 5
6AUTOTEST_CFLAGS = \ 6AUTOTEST_CFLAGS = \
7 $(LIBSODIUM_CFLAGS) \ 7 $(LIBSODIUM_CFLAGS) \
@@ -74,6 +74,12 @@ tox_test_CFLAGS = $(AUTOTEST_CFLAGS)
74tox_test_LDADD = $(AUTOTEST_LDADD) 74tox_test_LDADD = $(AUTOTEST_LDADD)
75 75
76 76
77dht_autotest_SOURCES = ../auto_tests/dht_test.c
78
79dht_autotest_CFLAGS = $(AUTOTEST_CFLAGS)
80
81dht_autotest_LDADD = $(AUTOTEST_LDADD)
82
77 83
78if BUILD_AV 84if BUILD_AV
79toxav_basic_test_SOURCES = ../auto_tests/toxav_basic_test.c 85toxav_basic_test_SOURCES = ../auto_tests/toxav_basic_test.c
diff --git a/auto_tests/TCP_test.c b/auto_tests/TCP_test.c
index 8e75fae0..25827df3 100644
--- a/auto_tests/TCP_test.c
+++ b/auto_tests/TCP_test.c
@@ -14,6 +14,8 @@
14 14
15#include "../toxcore/util.h" 15#include "../toxcore/util.h"
16 16
17#include "helpers.h"
18
17#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 19#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
18#define c_sleep(x) Sleep(1*x) 20#define c_sleep(x) Sleep(1*x)
19#else 21#else
@@ -489,14 +491,6 @@ START_TEST(test_client_invalid)
489} 491}
490END_TEST 492END_TEST
491 493
492#define DEFTESTCASE(NAME) \
493 TCase *tc_##NAME = tcase_create(#NAME); \
494 tcase_add_test(tc_##NAME, test_##NAME); \
495 suite_add_tcase(s, tc_##NAME);
496
497#define DEFTESTCASE_SLOW(NAME, TIMEOUT) \
498 DEFTESTCASE(NAME) \
499 tcase_set_timeout(tc_##NAME, TIMEOUT);
500Suite *TCP_suite(void) 494Suite *TCP_suite(void)
501{ 495{
502 Suite *s = suite_create("TCP"); 496 Suite *s = suite_create("TCP");
diff --git a/auto_tests/assoc_test.c b/auto_tests/assoc_test.c
index 5f496ece..b377cadf 100644
--- a/auto_tests/assoc_test.c
+++ b/auto_tests/assoc_test.c
@@ -1,4 +1,3 @@
1
2#ifdef HAVE_CONFIG_H 1#ifdef HAVE_CONFIG_H
3#include "config.h" 2#include "config.h"
4#endif 3#endif
@@ -14,6 +13,8 @@
14 13
15#include <check.h> 14#include <check.h>
16 15
16#include "helpers.h"
17
17START_TEST(test_basics) 18START_TEST(test_basics)
18{ 19{
19 /* TODO: real test */ 20 /* TODO: real test */
@@ -132,15 +133,6 @@ START_TEST(test_fillup)
132} 133}
133END_TEST 134END_TEST
134 135
135#define DEFTESTCASE(NAME) \
136 TCase *tc_##NAME = tcase_create(#NAME); \
137 tcase_add_test(tc_##NAME, test_##NAME); \
138 suite_add_tcase(s, tc_##NAME);
139
140#define DEFTESTCASE_SLOW(NAME, TIMEOUT) \
141 DEFTESTCASE(NAME) \
142 tcase_set_timeout(tc_##NAME, TIMEOUT);
143
144Suite *Assoc_suite(void) 136Suite *Assoc_suite(void)
145{ 137{
146 Suite *s = suite_create("Assoc"); 138 Suite *s = suite_create("Assoc");
diff --git a/auto_tests/crypto_test.c b/auto_tests/crypto_test.c
index 252f7275..2fb08b8b 100644
--- a/auto_tests/crypto_test.c
+++ b/auto_tests/crypto_test.c
@@ -10,6 +10,8 @@
10#include <stdlib.h> 10#include <stdlib.h>
11#include <time.h> 11#include <time.h>
12 12
13#include "helpers.h"
14
13void rand_bytes(uint8_t *b, size_t blen) 15void rand_bytes(uint8_t *b, size_t blen)
14{ 16{
15 size_t i; 17 size_t i;
@@ -270,16 +272,6 @@ START_TEST(test_large_data_symmetric)
270} 272}
271END_TEST 273END_TEST
272 274
273
274#define DEFTESTCASE(NAME) \
275 TCase *NAME = tcase_create(#NAME); \
276 tcase_add_test(NAME, test_##NAME); \
277 suite_add_tcase(s, NAME);
278
279#define DEFTESTCASE_SLOW(NAME, TIMEOUT) \
280 DEFTESTCASE(NAME) \
281 tcase_set_timeout(NAME, TIMEOUT);
282
283Suite *crypto_suite(void) 275Suite *crypto_suite(void)
284{ 276{
285 Suite *s = suite_create("Crypto"); 277 Suite *s = suite_create("Crypto");
diff --git a/auto_tests/dht_test.c b/auto_tests/dht_test.c
new file mode 100644
index 00000000..6d7e70ad
--- /dev/null
+++ b/auto_tests/dht_test.c
@@ -0,0 +1,362 @@
1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif
4
5#include <sys/param.h>
6#include <time.h>
7
8#include "../toxcore/tox.h"
9#include "../toxcore/DHT.c"
10
11#include "helpers.h"
12
13#define swap(x,y) do \
14 { unsigned char swap_temp[sizeof(x) == sizeof(y) ? (signed)sizeof(x) : -1]; \
15 memcpy(swap_temp,&y,sizeof(x)); \
16 memcpy(&y,&x, sizeof(x)); \
17 memcpy(&x,swap_temp,sizeof(x)); \
18 } while(0)
19
20
21void mark_bad(IPPTsPng *ipptp)
22{
23 ipptp->timestamp = unix_time() - 2 * BAD_NODE_TIMEOUT;
24 ipptp->hardening.routes_requests_ok = 0;
25 ipptp->hardening.send_nodes_ok = 0;
26 ipptp->hardening.testing_requests = 0;
27}
28
29void mark_possible_bad(IPPTsPng *ipptp)
30{
31 ipptp->timestamp = unix_time();
32 ipptp->hardening.routes_requests_ok = 0;
33 ipptp->hardening.send_nodes_ok = 0;
34 ipptp->hardening.testing_requests = 0;
35}
36
37void mark_good(IPPTsPng *ipptp)
38{
39 ipptp->timestamp = unix_time();
40 ipptp->hardening.routes_requests_ok = (HARDENING_ALL_OK >> 0) & 1;
41 ipptp->hardening.send_nodes_ok = (HARDENING_ALL_OK >> 1) & 1;
42 ipptp->hardening.testing_requests = (HARDENING_ALL_OK >> 2) & 1;
43}
44
45void mark_all_good(Client_data *list, uint32_t length, uint8_t ipv6)
46{
47 uint32_t i;
48 for (i = 0; i < length; ++i) {
49 if (ipv6)
50 mark_good(&list[i].assoc6);
51 else
52 mark_good(&list[i].assoc4);
53 }
54}
55
56/* Returns 1 if client_id has a furthest distance to comp_client_id
57 than all client_id's in the list */
58uint8_t is_furthest(const uint8_t *comp_client_id, Client_data *list, uint32_t length, const uint8_t *client_id)
59{
60 uint32_t i;
61 for (i = 0; i < length; ++i)
62 if (id_closest(comp_client_id, client_id, list[i].client_id) == 1)
63 return 0;
64 return 1;
65}
66
67int client_in_list(Client_data *list, uint32_t length, const uint8_t *client_id)
68{
69 int i;
70 for (i = 0; i < (int)length; ++i)
71 if (id_equal(client_id, list[i].client_id))
72 return i;
73 return -1;
74}
75
76void test_addto_lists_update(DHT *dht,
77 Client_data *list,
78 uint32_t length,
79 IP_Port *ip_port)
80{
81 int used, test, test1, test2, found;
82 IP_Port test_ipp;
83 uint8_t test_id[CLIENT_ID_SIZE];
84 uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0;
85
86 // check id update for existing ip_port
87 test = rand() % length;
88 ipport_copy(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port);
89
90 randombytes(test_id, sizeof(test_id));
91 used = addto_lists(dht, test_ipp, test_id);
92 ck_assert_msg(used >= 1, "Wrong number of added clients");
93 // it is possible to have ip_port duplicates in the list, so ip_port @ found not always equal to ip_port @ test
94 found = client_in_list(list, length, test_id);
95 ck_assert_msg(found >= 0, "Client id is not in the list");
96 ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[found].assoc6.ip_port : &list[found].assoc4.ip_port), "Client IP_Port is incorrect");
97
98 // check ip_port update for existing id
99 test = rand() % length;
100 test_ipp.port = rand() % TOX_PORT_DEFAULT;
101 id_copy(test_id, list[test].client_id);
102
103 used = addto_lists(dht, test_ipp, test_id);
104 ck_assert_msg(used >= 1, "Wrong number of added clients");
105 // it is not possible to have id duplicates in the list, so id @ found must be equal id @ test
106 ck_assert_msg(client_in_list(list, length, test_id) == test, "Client id is not in the list");
107 ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test].assoc6.ip_port : &list[test].assoc4.ip_port), "Client IP_Port is incorrect");
108
109 // check ip_port update for existing id and ip_port (... port ... id ...)
110 test1 = rand() % (length / 2);
111 test2 = rand() % (length / 2) + length / 2;
112
113 ipport_copy(&test_ipp, ipv6 ? &list[test1].assoc6.ip_port : &list[test1].assoc4.ip_port);
114 id_copy(test_id, list[test2].client_id);
115 if (ipv6) list[test2].assoc6.ip_port.port = -1; else list[test2].assoc4.ip_port.port = -1;
116 used = addto_lists(dht, test_ipp, test_id);
117 ck_assert_msg(used >= 1, "Wrong number of added clients");
118 ck_assert_msg(client_in_list(list, length, test_id) == test2, "Client id is not in the list");
119 ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test2].assoc6.ip_port : &list[test2].assoc4.ip_port), "Client IP_Port is incorrect");
120
121 // check ip_port update for existing id and ip_port (... id ... port ...)
122 test1 = rand() % (length / 2);
123 test2 = rand() % (length / 2) + length / 2;
124
125 ipport_copy(&test_ipp, ipv6 ? &list[test2].assoc6.ip_port : &list[test2].assoc4.ip_port);
126 id_copy(test_id, list[test1].client_id);
127 if (ipv6) list[test1].assoc6.ip_port.port = -1; else list[test1].assoc4.ip_port.port = -1;
128 used = addto_lists(dht, test_ipp, test_id);
129 ck_assert_msg(used >= 1, "Wrong number of added clients");
130 ck_assert_msg(client_in_list(list, length, test_id) == test1, "Client id is not in the list");
131 ck_assert_msg(ipport_equal(&test_ipp, ipv6 ? &list[test1].assoc6.ip_port : &list[test1].assoc4.ip_port), "Client IP_Port is incorrect");
132}
133
134void test_addto_lists_bad(DHT *dht,
135 Client_data *list,
136 uint32_t length,
137 IP_Port *ip_port)
138{
139 // check "bad" clients replacement
140 int used, test1, test2, test3;
141 uint8_t client_id[CLIENT_ID_SIZE], test_id1[CLIENT_ID_SIZE], test_id2[CLIENT_ID_SIZE], test_id3[CLIENT_ID_SIZE];
142 uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0;
143
144 randombytes(client_id, sizeof(client_id));
145 mark_all_good(list, length, ipv6);
146
147 test1 = rand() % (length / 3);
148 test2 = rand() % (length / 3) + length / 3;
149 test3 = rand() % (length / 3) + 2 * length / 3;
150 ck_assert_msg(!(test1 == test2 || test1 == test3 || test2 == test3), "Wrong test indices are chosen");
151
152 id_copy((uint8_t*)&test_id1, list[test1].client_id);
153 id_copy((uint8_t*)&test_id2, list[test2].client_id);
154 id_copy((uint8_t*)&test_id3, list[test3].client_id);
155
156 // mark nodes as "bad"
157 if (ipv6) {
158 mark_bad(&list[test1].assoc6);
159 mark_bad(&list[test2].assoc6);
160 mark_bad(&list[test3].assoc6);
161 } else {
162 mark_bad(&list[test1].assoc4);
163 mark_bad(&list[test2].assoc4);
164 mark_bad(&list[test3].assoc4);
165 }
166
167 ip_port->port += 1;
168 used = addto_lists(dht, *ip_port, client_id);
169 ck_assert_msg(used >= 1, "Wrong number of added clients");
170
171 ck_assert_msg(client_in_list(list, length, client_id) >= 0, "Client id is not in the list");
172 ck_assert_msg(id_equal(client_id, list[test1].client_id), "Wrong bad client removed");
173 ck_assert_msg(id_equal(test_id2, list[test2].client_id), "Wrong bad client removed");
174 ck_assert_msg(id_equal(test_id3, list[test3].client_id), "Wrong bad client removed");
175}
176
177void test_addto_lists_possible_bad(DHT *dht,
178 Client_data *list,
179 uint32_t length,
180 IP_Port *ip_port,
181 const uint8_t *comp_client_id)
182{
183 // check "possibly bad" clients replacement
184 int used, test1, test2, test3;
185 uint8_t client_id[CLIENT_ID_SIZE], test_id1[CLIENT_ID_SIZE], test_id2[CLIENT_ID_SIZE], test_id3[CLIENT_ID_SIZE];
186 uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0;
187
188 randombytes(client_id, sizeof(client_id));
189 mark_all_good(list, length, ipv6);
190
191 test1 = rand() % (length / 3);
192 test2 = rand() % (length / 3) + length / 3;
193 test3 = rand() % (length / 3) + 2 * length / 3;
194 ck_assert_msg(!(test1 == test2 || test1 == test3 || test2 == test3), "Wrong test indices are chosen");
195
196 id_copy((uint8_t*)&test_id1, list[test1].client_id);
197 id_copy((uint8_t*)&test_id2, list[test2].client_id);
198 id_copy((uint8_t*)&test_id3, list[test3].client_id);
199
200 // mark nodes as "possibly bad"
201 if (ipv6) {
202 mark_possible_bad(&list[test1].assoc6);
203 mark_possible_bad(&list[test2].assoc6);
204 mark_possible_bad(&list[test3].assoc6);
205 } else {
206 mark_possible_bad(&list[test1].assoc4);
207 mark_possible_bad(&list[test2].assoc4);
208 mark_possible_bad(&list[test3].assoc4);
209 }
210
211 ip_port->port += 1;
212 used = addto_lists(dht, *ip_port, client_id);
213 ck_assert_msg(used >= 1, "Wrong number of added clients");
214
215 ck_assert_msg(client_in_list(list, length, client_id) >= 0, "Client id is not in the list");
216
217 int inlist_id1 = client_in_list(list, length, test_id1) >= 0;
218 int inlist_id2 = client_in_list(list, length, test_id2) >= 0;
219 int inlist_id3 = client_in_list(list, length, test_id3) >= 0;
220
221 ck_assert_msg(inlist_id1 + inlist_id2 + inlist_id3 == 2, "Wrong client removed");
222
223 if (!inlist_id1) {
224 ck_assert_msg(id_closest(comp_client_id, test_id2, test_id1) == 1, "Id has been removed but is closer to than another one");
225 ck_assert_msg(id_closest(comp_client_id, test_id3, test_id1) == 1, "Id has been removed but is closer to than another one");
226 } else if (!inlist_id2) {
227 ck_assert_msg(id_closest(comp_client_id, test_id1, test_id2) == 1, "Id has been removed but is closer to than another one");
228 ck_assert_msg(id_closest(comp_client_id, test_id3, test_id2) == 1, "Id has been removed but is closer to than another one");
229 } else if (!inlist_id3) {
230 ck_assert_msg(id_closest(comp_client_id, test_id1, test_id3) == 1, "Id has been removed but is closer to than another one");
231 ck_assert_msg(id_closest(comp_client_id, test_id2, test_id3) == 1, "Id has been removed but is closer to than another one");
232 }
233}
234
235void test_addto_lists_good(DHT *dht,
236 Client_data *list,
237 uint32_t length,
238 IP_Port *ip_port,
239 const uint8_t *comp_client_id)
240{
241 uint8_t client_id[CLIENT_ID_SIZE];
242 uint8_t ipv6 = ip_port->ip.family == AF_INET6 ? 1 : 0;
243
244 mark_all_good(list, length, ipv6);
245
246 // check "good" client id replacement
247 do {
248 randombytes(client_id, sizeof(client_id));
249 } while (is_furthest(comp_client_id, list, length, client_id));
250 ip_port->port += 1;
251 addto_lists(dht, *ip_port, client_id);
252 ck_assert_msg(client_in_list(list, length, client_id) >= 0, "Good client id is not in the list");
253
254 // check "good" client id skip
255 do {
256 randombytes(client_id, sizeof(client_id));
257 } while (!is_furthest(comp_client_id, list, length, client_id));
258
259 ip_port->port += 1;
260 addto_lists(dht, *ip_port, client_id);
261 ck_assert_msg(client_in_list(list, length, client_id) == -1, "Good client id is in the list");
262}
263
264void test_addto_lists(IP ip)
265{
266 Networking_Core* net = new_networking(ip, TOX_PORT_DEFAULT);
267 ck_assert_msg(net != 0, "Failed to create Networking_Core");
268
269 DHT* dht = new_DHT(net);
270 ck_assert_msg(dht != 0, "Failed to create DHT");
271
272 IP_Port ip_port = { .ip = ip, .port = TOX_PORT_DEFAULT };
273 uint8_t client_id[CLIENT_ID_SIZE];
274 int i, used;
275
276 // check lists filling
277 for (i = 0; i < MAX(LCLIENT_LIST, MAX_FRIEND_CLIENTS); ++i) {
278 randombytes(client_id, sizeof(client_id));
279 used = addto_lists(dht, ip_port, client_id);
280 ck_assert_msg(used == dht->num_friends + 1, "Wrong number of added clients with existing ip_port");
281 }
282
283 for (i = 0; i < MAX(LCLIENT_LIST, MAX_FRIEND_CLIENTS); ++i) {
284 ip_port.port += 1;
285 used = addto_lists(dht, ip_port, client_id);
286 ck_assert_msg(used == dht->num_friends + 1, "Wrong number of added clients with existing client_id");
287 }
288
289 for (i = 0; i < MAX(LCLIENT_LIST, MAX_FRIEND_CLIENTS); ++i) {
290 ip_port.port += 1;
291 randombytes(client_id, sizeof(client_id));
292 used = addto_lists(dht, ip_port, client_id);
293 ck_assert_msg(used >= 1, "Wrong number of added clients");
294 }
295
296 /*check: Current behavior if there are two clients with the same id is
297 * to replace the first ip by the second. */
298 test_addto_lists_update(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port);
299 for (i = 0; i < dht->num_friends; ++i)
300 test_addto_lists_update(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port);
301
302 // check "bad" entries
303 test_addto_lists_bad(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port);
304 for (i = 0; i < dht->num_friends; ++i)
305 test_addto_lists_bad(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port);
306
307 // check "possibly bad" entries
308 test_addto_lists_possible_bad(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port, dht->self_public_key);
309 for (i = 0; i < dht->num_friends; ++i)
310 test_addto_lists_possible_bad(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port, dht->friends_list[i].client_id);
311
312 // check "good" entries
313 test_addto_lists_good(dht, dht->close_clientlist, LCLIENT_LIST, &ip_port, dht->self_public_key);
314 for (i = 0; i < dht->num_friends; ++i)
315 test_addto_lists_good(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, &ip_port, dht->friends_list[i].client_id);
316
317 kill_DHT(dht);
318 kill_networking(net);
319}
320
321START_TEST(test_addto_lists_ipv4)
322{
323 IP ip;
324 ip_init(&ip, 0);
325 test_addto_lists(ip);
326
327}
328END_TEST
329
330START_TEST(test_addto_lists_ipv6)
331{
332 IP ip;
333 ip_init(&ip, 1);
334 test_addto_lists(ip);
335
336}
337END_TEST
338
339Suite *dht_suite(void)
340{
341 Suite *s = suite_create("DHT");
342
343 DEFTESTCASE(addto_lists_ipv4);
344 DEFTESTCASE(addto_lists_ipv6);
345 return s;
346}
347
348int main(int argc, char *argv[])
349{
350 srand((unsigned int) time(NULL));
351
352 Suite *dht = dht_suite();
353 SRunner *test_runner = srunner_create(dht);
354
355 int number_failed = 0;
356 srunner_run_all(test_runner, CK_NORMAL);
357 number_failed = srunner_ntests_failed(test_runner);
358
359 srunner_free(test_runner);
360
361 return number_failed;
362}
diff --git a/auto_tests/helpers.h b/auto_tests/helpers.h
new file mode 100644
index 00000000..9e8043db
--- /dev/null
+++ b/auto_tests/helpers.h
@@ -0,0 +1,15 @@
1#ifndef TOXCORE_TEST_HELPERS_H
2#define TOXCORE_TEST_HELPERS_H
3
4#include <check.h>
5
6#define DEFTESTCASE(NAME) \
7 TCase *tc_##NAME = tcase_create(#NAME); \
8 tcase_add_test(tc_##NAME, test_##NAME); \
9 suite_add_tcase(s, tc_##NAME);
10
11#define DEFTESTCASE_SLOW(NAME, TIMEOUT) \
12 DEFTESTCASE(NAME) \
13 tcase_set_timeout(tc_##NAME, TIMEOUT);
14
15#endif // TOXCORE_TEST_HELPERS_H
diff --git a/auto_tests/messenger_test.c b/auto_tests/messenger_test.c
index 7ab7d674..3024ed1a 100644
--- a/auto_tests/messenger_test.c
+++ b/auto_tests/messenger_test.c
@@ -21,6 +21,8 @@
21#include <string.h> 21#include <string.h>
22#include <check.h> 22#include <check.h>
23 23
24#include "helpers.h"
25
24#define REALLY_BIG_NUMBER ((1) << (sizeof(uint16_t) * 7)) 26#define REALLY_BIG_NUMBER ((1) << (sizeof(uint16_t) * 7))
25#define STRINGS_EQUAL(X, Y) (strcmp(X, Y) == 0) 27#define STRINGS_EQUAL(X, Y) (strcmp(X, Y) == 0)
26 28
@@ -298,11 +300,6 @@ START_TEST(test_messenger_state_saveloadsave)
298} 300}
299END_TEST 301END_TEST
300 302
301#define DEFTESTCASE(NAME) \
302 TCase *tc_##NAME = tcase_create(#NAME); \
303 tcase_add_test(tc_##NAME, test_##NAME); \
304 suite_add_tcase(s, tc_##NAME);
305
306Suite *messenger_suite(void) 303Suite *messenger_suite(void)
307{ 304{
308 Suite *s = suite_create("Messenger"); 305 Suite *s = suite_create("Messenger");
diff --git a/auto_tests/network_test.c b/auto_tests/network_test.c
index afd90e7a..9d07fbb4 100644
--- a/auto_tests/network_test.c
+++ b/auto_tests/network_test.c
@@ -11,6 +11,8 @@
11 11
12#include "../toxcore/network.h" 12#include "../toxcore/network.h"
13 13
14#include "helpers.h"
15
14START_TEST(test_addr_resolv_localhost) 16START_TEST(test_addr_resolv_localhost)
15{ 17{
16#ifdef __CYGWIN__ 18#ifdef __CYGWIN__
@@ -141,11 +143,6 @@ START_TEST(test_struct_sizes)
141} 143}
142END_TEST 144END_TEST
143 145
144#define DEFTESTCASE(NAME) \
145 TCase *tc_##NAME = tcase_create(#NAME); \
146 tcase_add_test(tc_##NAME, test_##NAME); \
147 suite_add_tcase(s, tc_##NAME);
148
149Suite *network_suite(void) 146Suite *network_suite(void)
150{ 147{
151 Suite *s = suite_create("Network"); 148 Suite *s = suite_create("Network");
diff --git a/auto_tests/onion_test.c b/auto_tests/onion_test.c
index 2394e03d..ed297022 100644
--- a/auto_tests/onion_test.c
+++ b/auto_tests/onion_test.c
@@ -14,6 +14,8 @@
14#include "../toxcore/onion_client.h" 14#include "../toxcore/onion_client.h"
15#include "../toxcore/util.h" 15#include "../toxcore/util.h"
16 16
17#include "helpers.h"
18
17#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 19#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
18#define c_sleep(x) Sleep(1*x) 20#define c_sleep(x) Sleep(1*x)
19#else 21#else
@@ -335,14 +337,6 @@ START_TEST(test_announce)
335} 337}
336END_TEST 338END_TEST
337 339
338#define DEFTESTCASE(NAME) \
339 TCase *tc_##NAME = tcase_create(#NAME); \
340 tcase_add_test(tc_##NAME, test_##NAME); \
341 suite_add_tcase(s, tc_##NAME);
342
343#define DEFTESTCASE_SLOW(NAME, TIMEOUT) \
344 DEFTESTCASE(NAME) \
345 tcase_set_timeout(tc_##NAME, TIMEOUT);
346Suite *onion_suite(void) 340Suite *onion_suite(void)
347{ 341{
348 Suite *s = suite_create("Onion"); 342 Suite *s = suite_create("Onion");
diff --git a/auto_tests/skeleton_test.c b/auto_tests/skeleton_test.c
index 89ef1b8b..27c9123a 100644
--- a/auto_tests/skeleton_test.c
+++ b/auto_tests/skeleton_test.c
@@ -9,6 +9,8 @@
9#include <stdlib.h> 9#include <stdlib.h>
10#include <time.h> 10#include <time.h>
11 11
12#include "helpers.h"
13
12/* 14/*
13#include "../<stuff to test>" 15#include "../<stuff to test>"
14*/ 16*/
@@ -20,12 +22,6 @@ START_TEST(test_creativetestnamegoeshere)
20} 22}
21END_TEST 23END_TEST
22 24
23
24#define DEFTESTCASE(NAME) \
25 TCase *tc_##NAME = tcase_create(#NAME); \
26 tcase_add_test(tc_##NAME, test_##NAME); \
27 suite_add_tcase(s, tc_##NAME);
28
29Suite *creativesuitenamegoeshere_suite(void) 25Suite *creativesuitenamegoeshere_suite(void)
30{ 26{
31 Suite *s = suite_create("creativesuitedescritptiongoeshere"); 27 Suite *s = suite_create("creativesuitedescritptiongoeshere");
diff --git a/auto_tests/tox_test.c b/auto_tests/tox_test.c
index 43fb7a1c..f765fcd3 100644
--- a/auto_tests/tox_test.c
+++ b/auto_tests/tox_test.c
@@ -12,6 +12,8 @@
12 12
13#include "../toxcore/tox.h" 13#include "../toxcore/tox.h"
14 14
15#include "helpers.h"
16
15#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 17#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
16#define c_sleep(x) Sleep(1*x) 18#define c_sleep(x) Sleep(1*x)
17#else 19#else
@@ -360,14 +362,6 @@ loop_top:
360} 362}
361END_TEST 363END_TEST
362 364
363#define DEFTESTCASE(NAME) \
364 TCase *tc_##NAME = tcase_create(#NAME); \
365 tcase_add_test(tc_##NAME, test_##NAME); \
366 suite_add_tcase(s, tc_##NAME);
367
368#define DEFTESTCASE_SLOW(NAME, TIMEOUT) \
369 DEFTESTCASE(NAME) \
370 tcase_set_timeout(tc_##NAME, TIMEOUT);
371Suite *tox_suite(void) 365Suite *tox_suite(void)
372{ 366{
373 Suite *s = suite_create("Tox"); 367 Suite *s = suite_create("Tox");
diff --git a/auto_tests/toxav_basic_test.c b/auto_tests/toxav_basic_test.c
index 57685bfc..c6481366 100644
--- a/auto_tests/toxav_basic_test.c
+++ b/auto_tests/toxav_basic_test.c
@@ -16,6 +16,8 @@
16#include "../toxcore/crypto_core.h" 16#include "../toxcore/crypto_core.h"
17#include "../toxav/toxav.h" 17#include "../toxav/toxav.h"
18 18
19#include "helpers.h"
20
19#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32) 21#if defined(_WIN32) || defined(__WIN32__) || defined (WIN32)
20#define c_sleep(x) Sleep(1*x) 22#define c_sleep(x) Sleep(1*x)
21#else 23#else
@@ -214,7 +216,6 @@ case 3: /* Wait for Both to have status ended */\
214if (status_control.Alice.status == Ended && status_control.Bob.status == Ended) running = 0; break; } c_sleep(20); } } printf("\n"); 216if (status_control.Alice.status == Ended && status_control.Bob.status == Ended) running = 0; break; } c_sleep(20); } } printf("\n");
215 217
216START_TEST(test_AV_flows) 218START_TEST(test_AV_flows)
217// int test_AV_flows()
218{ 219{
219 long long unsigned int cur_time = time(NULL); 220 long long unsigned int cur_time = time(NULL);
220 Tox *bootstrap_node = tox_new(0); 221 Tox *bootstrap_node = tox_new(0);
@@ -574,10 +575,7 @@ Suite *tox_suite(void)
574{ 575{
575 Suite *s = suite_create("ToxAV"); 576 Suite *s = suite_create("ToxAV");
576 577
577 TCase *tc_av_flows = tcase_create("AV_flows"); 578 DEFTESTCASE_SLOW(AV_flows, 200);
578 tcase_add_test(tc_av_flows, test_AV_flows);
579 tcase_set_timeout(tc_av_flows, 200);
580 suite_add_tcase(s, tc_av_flows);
581 579
582 return s; 580 return s;
583} 581}
diff --git a/toxcore/DHT.c b/toxcore/DHT.c
index 77d126c1..5658d757 100644
--- a/toxcore/DHT.c
+++ b/toxcore/DHT.c
@@ -65,17 +65,6 @@
65/* Number of get node requests to send to quickly find close nodes. */ 65/* Number of get node requests to send to quickly find close nodes. */
66#define MAX_BOOTSTRAP_TIMES 10 66#define MAX_BOOTSTRAP_TIMES 10
67 67
68/* Used in the comparison function for sorting lists of Client_data. */
69typedef struct {
70 Client_data c1;
71 Client_data c2;
72} ClientPair;
73
74/* Create the declaration for a quick sort for ClientPair structures. */
75declare_quick_sort(ClientPair);
76/* Create the quicksort function. See misc_tools.h for the definition. */
77make_quick_sort(ClientPair);
78
79Client_data *DHT_get_close_list(DHT *dht) 68Client_data *DHT_get_close_list(DHT *dht)
80{ 69{
81 return dht->close_clientlist; 70 return dht->close_clientlist;
@@ -107,19 +96,6 @@ int id_closest(const uint8_t *id, const uint8_t *id1, const uint8_t *id2)
107 return 0; 96 return 0;
108} 97}
109 98
110/* Turns the result of id_closest into something quick_sort can use.
111 * Assumes p1->c1 == p2->c1.
112 */
113static int client_id_cmp(const ClientPair p1, const ClientPair p2)
114{
115 int c = id_closest(p1.c1.client_id, p1.c2.client_id, p2.c2.client_id);
116
117 if (c == 2)
118 return -1;
119
120 return c;
121}
122
123/* Shared key generations are costly, it is therefor smart to store commonly used 99/* Shared key generations are costly, it is therefor smart to store commonly used
124 * ones so that they can re used later without being computed again. 100 * ones so that they can re used later without being computed again.
125 * 101 *
@@ -629,172 +605,61 @@ int get_close_nodes(const DHT *dht, const uint8_t *client_id, Node_format *nodes
629#endif 605#endif
630} 606}
631 607
632/* Replace first bad (or empty) node with this one. 608/* Replace a first bad (or empty) node with this one
609 * or replace a possibly bad node (tests failed or not done yet)
610 * that is further than any other in the list
611 * from the comp_client_id
612 * or replace a good node that is further
613 * than any other in the list from the comp_client_id
614 * and further than client_id.
633 * 615 *
634 * return 0 if successful. 616 * Do not replace any node if the list has no bad or possibly bad nodes
635 * return 1 if not (list contains no bad nodes). 617 * and all nodes in the list are closer to comp_client_id
636 */ 618 * than client_id.
637static int replace_bad( Client_data *list, 619 *
638 uint32_t length, 620 * returns True(1) when the item was stored, False(0) otherwise */
639 const uint8_t *client_id, 621static int replace_all( Client_data *list,
640 IP_Port ip_port ) 622 uint32_t length,
623 const uint8_t *client_id,
624 IP_Port ip_port,
625 const uint8_t *comp_client_id )
641{ 626{
642 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6)) 627 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
643 return 1; 628 return 1;
644 629
645 uint32_t i; 630 uint32_t i, replace = ~0, bad = ~0, possibly_bad = ~0, good = ~0;
646 631
647 for (i = 0; i < length; ++i) { 632 for (i = 0; i < length; ++i) {
648 /* If node is bad */ 633
649 Client_data *client = &list[i]; 634 Client_data *client = &list[i];
650 635
651 if (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) && 636 if (is_timeout(client->assoc4.timestamp, BAD_NODE_TIMEOUT) &&
652 is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) { 637 is_timeout(client->assoc6.timestamp, BAD_NODE_TIMEOUT)) {
653 638 // "bad" node
654 IPPTsPng *ipptp_write = NULL; 639 bad = i;
655 IPPTsPng *ipptp_clear = NULL; 640 break;
656 641 } else if (hardening_correct(&client->assoc4.hardening) != HARDENING_ALL_OK &&
657 if (ip_port.ip.family == AF_INET) { 642 hardening_correct(&client->assoc6.hardening) != HARDENING_ALL_OK) {
658 ipptp_write = &client->assoc4; 643 // "possibly bad" node
659 ipptp_clear = &client->assoc6; 644 if (possibly_bad == ~0 ||
660 } else { 645 id_closest(comp_client_id, list[possibly_bad].client_id, list[i].client_id) == 1)
661 ipptp_write = &client->assoc6; 646 possibly_bad = i;
662 ipptp_clear = &client->assoc4; 647 } else {
663 } 648 // "good" node
664 649 if (good == ~0 ||
665 memcpy(client->client_id, client_id, CLIENT_ID_SIZE); 650 id_closest(comp_client_id, list[good].client_id, list[i].client_id) == 1)
666 ipptp_write->ip_port = ip_port; 651 good = i;
667 ipptp_write->timestamp = unix_time();
668
669 ip_reset(&ipptp_write->ret_ip_port.ip);
670 ipptp_write->ret_ip_port.port = 0;
671 ipptp_write->ret_timestamp = 0;
672
673 /* zero out other address */
674 memset(ipptp_clear, 0, sizeof(*ipptp_clear));
675
676 return 0;
677 }
678 }
679
680 return 1;
681}
682
683
684/* Sort the list. It will be sorted from furthest to closest.
685 * Turns list into data that quick sort can use and reverts it back.
686 */
687static void sort_list(Client_data *list, uint32_t length, const uint8_t *comp_client_id)
688{
689 Client_data cd;
690 ClientPair pairs[length];
691 uint32_t i;
692
693 memcpy(cd.client_id, comp_client_id, CLIENT_ID_SIZE);
694
695 for (i = 0; i < length; ++i) {
696 pairs[i].c1 = cd;
697 pairs[i].c2 = list[i];
698 }
699
700 ClientPair_quick_sort(pairs, length, client_id_cmp);
701
702 for (i = 0; i < length; ++i)
703 list[i] = pairs[i].c2;
704}
705
706/* Replace first node that is possibly bad (tests failed or not done yet.) with this one.
707 *
708 * return 0 if successful.
709 * return 1 if not (list contains no bad nodes).
710 */
711static int replace_possible_bad( Client_data *list,
712 uint32_t length,
713 const uint8_t *client_id,
714 IP_Port ip_port,
715 const uint8_t *comp_client_id )
716{
717 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
718 return 1;
719
720 sort_list(list, length, comp_client_id);
721
722 /* TODO: decide if the following lines should stay commented or not.
723 if (id_closest(comp_client_id, list[0].client_id, client_id) == 1)
724 return 0;*/
725
726 uint32_t i;
727
728 for (i = 0; i < length; ++i) {
729 /* If node is bad */
730 Client_data *client = &list[i];
731
732 if (hardening_correct(&client->assoc4.hardening) != HARDENING_ALL_OK &&
733 hardening_correct(&client->assoc6.hardening) != HARDENING_ALL_OK) {
734
735 IPPTsPng *ipptp_write = NULL;
736 IPPTsPng *ipptp_clear = NULL;
737
738 if (ip_port.ip.family == AF_INET) {
739 ipptp_write = &client->assoc4;
740 ipptp_clear = &client->assoc6;
741 } else {
742 ipptp_write = &client->assoc6;
743 ipptp_clear = &client->assoc4;
744 }
745
746 memcpy(client->client_id, client_id, CLIENT_ID_SIZE);
747 ipptp_write->ip_port = ip_port;
748 ipptp_write->timestamp = unix_time();
749
750 ip_reset(&ipptp_write->ret_ip_port.ip);
751 ipptp_write->ret_ip_port.port = 0;
752 ipptp_write->ret_timestamp = 0;
753
754 /* zero out other address */
755 memset(ipptp_clear, 0, sizeof(*ipptp_clear));
756
757 return 0;
758 } 652 }
759 } 653 }
760 654
761 return 1; 655 if (bad != ~0)
762} 656 replace = bad;
657 else if (possibly_bad != ~0)
658 replace = possibly_bad;
659 else if (good != ~0 && id_closest(comp_client_id, list[good].client_id, client_id) == 2)
660 replace = good;
763 661
764/* Replace the first good node that is further to the comp_client_id than that of the client_id in the list 662 if (replace != ~0) {
765 *
766 * returns 0 when the item was stored, 1 otherwise */
767static int replace_good( Client_data *list,
768 uint32_t length,
769 const uint8_t *client_id,
770 IP_Port ip_port,
771 const uint8_t *comp_client_id )
772{
773 if ((ip_port.ip.family != AF_INET) && (ip_port.ip.family != AF_INET6))
774 return 1;
775
776 /* TODO: eventually remove this.*/
777 if (length != LCLIENT_LIST)
778 sort_list(list, length, comp_client_id);
779
780 int8_t replace = -1;
781
782 /* Because the list is sorted, we can simply check the client_id at the
783 * border, either it is closer, then every other one is as well, or it is
784 * further, then it gets pushed out in favor of the new address, which
785 * will with the next sort() move to its "rightful" position
786 *
787 * CAVEAT: weirdly enough, the list is sorted DESCENDING in distance
788 * so the furthest element is the first, NOT the last (at least that's
789 * what the comment above sort_list() claims)
790 */
791 if (id_closest(comp_client_id, list[0].client_id, client_id) == 2)
792 replace = 0;
793
794 if (replace != -1) {
795#ifdef DEBUG
796 assert(replace >= 0 && replace < length);
797#endif
798 Client_data *client = &list[replace]; 663 Client_data *client = &list[replace];
799 IPPTsPng *ipptp_write = NULL; 664 IPPTsPng *ipptp_write = NULL;
800 IPPTsPng *ipptp_clear = NULL; 665 IPPTsPng *ipptp_clear = NULL;
@@ -807,7 +672,7 @@ static int replace_good( Client_data *list,
807 ipptp_clear = &client->assoc4; 672 ipptp_clear = &client->assoc4;
808 } 673 }
809 674
810 memcpy(client->client_id, client_id, CLIENT_ID_SIZE); 675 id_copy(client->client_id, client_id);
811 ipptp_write->ip_port = ip_port; 676 ipptp_write->ip_port = ip_port;
812 ipptp_write->timestamp = unix_time(); 677 ipptp_write->timestamp = unix_time();
813 678
@@ -818,10 +683,10 @@ static int replace_good( Client_data *list,
818 /* zero out other address */ 683 /* zero out other address */
819 memset(ipptp_clear, 0, sizeof(*ipptp_clear)); 684 memset(ipptp_clear, 0, sizeof(*ipptp_clear));
820 685
821 return 0; 686 return 1;
822 } 687 }
823 688
824 return 1; 689 return 0;
825} 690}
826 691
827/* Attempt to add client with ip_port and client_id to the friends client list 692/* Attempt to add client with ip_port and client_id to the friends client list
@@ -843,16 +708,7 @@ int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *client_id)
843 * to replace the first ip by the second. 708 * to replace the first ip by the second.
844 */ 709 */
845 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 710 if (!client_or_ip_port_in_list(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) {
846 if (replace_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port)) { 711 if (replace_all(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port, dht->self_public_key))
847 if (replace_possible_bad(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
848 dht->self_public_key)) {
849 /* If we can't replace bad nodes we try replacing good ones. */
850 if (!replace_good(dht->close_clientlist, LCLIENT_LIST, client_id, ip_port,
851 dht->self_public_key))
852 used++;
853 } else
854 used++;
855 } else
856 used++; 712 used++;
857 } else 713 } else
858 used++; 714 used++;
@@ -860,19 +716,8 @@ int addto_lists(DHT *dht, IP_Port ip_port, const uint8_t *client_id)
860 for (i = 0; i < dht->num_friends; ++i) { 716 for (i = 0; i < dht->num_friends; ++i) {
861 if (!client_or_ip_port_in_list(dht->friends_list[i].client_list, 717 if (!client_or_ip_port_in_list(dht->friends_list[i].client_list,
862 MAX_FRIEND_CLIENTS, client_id, ip_port)) { 718 MAX_FRIEND_CLIENTS, client_id, ip_port)) {
863 719 if (replace_all(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
864 if (replace_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, 720 client_id, ip_port, dht->friends_list[i].client_id))
865 client_id, ip_port)) {
866 /*if (replace_possible_bad(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
867 client_id, ip_port, dht->friends_list[i].client_id)) {*/
868 /* If we can't replace bad nodes we try replacing good ones. */
869 if (!replace_good(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS,
870 client_id, ip_port, dht->friends_list[i].client_id))
871 used++;
872
873 /*} else
874 used++;*/
875 } else
876 used++; 721 used++;
877 } else 722 } else
878 used++; 723 used++;
diff --git a/toxcore/onion_client.c b/toxcore/onion_client.c
index fbabea6d..f296426f 100644
--- a/toxcore/onion_client.c
+++ b/toxcore/onion_client.c
@@ -67,7 +67,7 @@ static uint16_t random_nodes_path_onion(const Onion_Client *onion_c, Node_format
67 if (onion_c->path_nodes_index < 3) 67 if (onion_c->path_nodes_index < 3)
68 return random_nodes_path(onion_c->dht, nodes, max_num); 68 return random_nodes_path(onion_c->dht, nodes, max_num);
69 69
70 unsigned int i, num_nodes = onion_c->path_nodes_index < MAX_PATH_NODES ? onion_c->path_nodes_index : MAX_PATH_NODES; 70 unsigned int i, num_nodes = (onion_c->path_nodes_index < MAX_PATH_NODES) ? onion_c->path_nodes_index : MAX_PATH_NODES;
71 71
72 for (i = 0; i < max_num; ++i) { 72 for (i = 0; i < max_num; ++i) {
73 nodes[i] = onion_c->path_nodes[rand() % num_nodes]; 73 nodes[i] = onion_c->path_nodes[rand() % num_nodes];