Coverage Report

Created: 2025-10-08 19:34

/work/auto_tests/onion_test.c
Line
Count
Source (jump to first uncovered line)
1
#include <stdlib.h>
2
#include <string.h>
3
4
#include "../testing/misc_tools.h"
5
#include "../toxcore/mono_time.h"
6
#include "../toxcore/onion.h"
7
#include "../toxcore/onion_announce.h"
8
#include "../toxcore/onion_client.h"
9
#include "../toxcore/os_memory.h"
10
#include "../toxcore/os_random.h"
11
#include "auto_test_support.h"
12
#include "check_compat.h"
13
14
#ifndef USE_IPV6
15
#define USE_IPV6 1
16
#endif
17
18
static inline IP get_loopback(void)
19
96
{
20
96
    IP ip;
21
#if USE_IPV6
22
    ip.family = net_family_ipv6();
23
    ip.ip.v6 = get_ip6_loopback();
24
#else
25
96
    ip.family = net_family_ipv4();
26
96
    ip.ip.v4 = get_ip4_loopback();
27
96
#endif
28
96
    return ip;
29
96
}
30
static void do_onion(Mono_Time *mono_time, Onion *onion)
31
28
{
32
28
    mono_time_update(mono_time);
33
34
28
    networking_poll(onion->net, nullptr);
35
28
    do_dht(onion->dht);
36
28
}
37
38
static int handled_test_1;
39
static int handle_test_1(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
40
1
{
41
1
    const Onion *onion = (const Onion *)object;
42
43
1
    const char req_message[] = "Install Gentoo";
44
1
    uint8_t req_packet[1 + sizeof(req_message)];
45
1
    req_packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
46
1
    memcpy(req_packet + 1, req_message, sizeof(req_message));
47
48
1
    if (memcmp(packet, req_packet, sizeof(req_packet)) != 0) {
49
0
        return 1;
50
0
    }
51
52
1
    const char res_message[] = "install gentoo";
53
1
    uint8_t res_packet[1 + sizeof(res_message)];
54
1
    res_packet[0] = NET_PACKET_ANNOUNCE_RESPONSE;
55
1
    memcpy(res_packet + 1, res_message, sizeof(res_message));
56
57
1
    if (send_onion_response(onion->log, onion->net, source, res_packet, sizeof(res_packet),
58
1
                            packet + sizeof(res_packet)) == -1) {
59
0
        return 1;
60
0
    }
61
62
1
    handled_test_1 = 1;
63
1
    return 0;
64
1
}
65
66
static int handled_test_2;
67
static int handle_test_2(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
68
1
{
69
1
    const char res_message[] = "install gentoo";
70
1
    uint8_t res_packet[1 + sizeof(res_message)];
71
1
    res_packet[0] = NET_PACKET_ANNOUNCE_RESPONSE;
72
1
    memcpy(res_packet + 1, res_message, sizeof(res_message));
73
74
1
    if (length != sizeof(res_packet)) {
75
0
        return 1;
76
0
    }
77
78
1
    if (memcmp(packet, res_packet, sizeof(res_packet)) != 0) {
79
0
        return 1;
80
0
    }
81
82
1
    handled_test_2 = 1;
83
1
    return 0;
84
1
}
85
#if 0
86
void print_client_id(uint8_t *client_id, uint32_t length)
87
{
88
    uint32_t j;
89
90
    for (j = 0; j < length; j++) {
91
        printf("%02X", client_id[j]);
92
    }
93
94
    printf("\n");
95
}
96
#endif
97
static uint8_t sb_data[ONION_ANNOUNCE_SENDBACK_DATA_LENGTH];
98
static int handled_test_3;
99
static uint8_t test_3_pub_key[CRYPTO_PUBLIC_KEY_SIZE];
100
static uint8_t test_3_ping_id[CRYPTO_SHA256_SIZE];
101
static int handle_test_3(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
102
0
{
103
0
    const Onion *onion = (const Onion *)object;
104
105
0
    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
106
0
        return 1;
107
0
    }
108
109
0
    uint8_t plain[2 + CRYPTO_SHA256_SIZE];
110
#if 0
111
    print_client_id(packet, length);
112
#endif
113
0
    int len = decrypt_data(onion->mem, test_3_pub_key, dht_get_self_secret_key(onion->dht),
114
0
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
115
0
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
116
0
                           2 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain);
117
118
0
    if (len == -1) {
119
0
        return 1;
120
0
    }
121
122
0
    if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
123
0
        return 1;
124
0
    }
125
126
0
    memcpy(test_3_ping_id, plain + 1, CRYPTO_SHA256_SIZE);
127
#if 0
128
    print_client_id(test_3_ping_id, sizeof(test_3_ping_id));
129
#endif
130
0
    handled_test_3 = 1;
131
0
    return 0;
132
0
}
133
134
/* TODO: DEPRECATE */
135
static int handle_test_3_old(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length,
136
                             void *userdata)
137
2
{
138
2
    const Onion *onion = (const Onion *)object;
139
140
2
    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
141
0
        return 1;
142
0
    }
143
144
2
    uint8_t plain[2 + CRYPTO_SHA256_SIZE];
145
#if 0
146
    print_client_id(packet, length);
147
#endif
148
2
    int len = decrypt_data(onion->mem, test_3_pub_key, dht_get_self_secret_key(onion->dht),
149
2
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH,
150
2
                           packet + 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH + CRYPTO_NONCE_SIZE,
151
2
                           1 + CRYPTO_SHA256_SIZE + CRYPTO_MAC_SIZE, plain);
152
153
2
    if (len == -1) {
154
0
        return 1;
155
0
    }
156
157
2
    if (memcmp(packet + 1, sb_data, ONION_ANNOUNCE_SENDBACK_DATA_LENGTH) != 0) {
158
0
        return 1;
159
0
    }
160
161
2
    memcpy(test_3_ping_id, plain + 1, CRYPTO_SHA256_SIZE);
162
#if 0
163
    print_client_id(test_3_ping_id, sizeof(test_3_ping_id));
164
#endif
165
2
    handled_test_3 = 1;
166
2
    return 0;
167
2
}
168
169
static uint8_t nonce[CRYPTO_NONCE_SIZE];
170
static int handled_test_4;
171
static int handle_test_4(void *object, const IP_Port *source, const uint8_t *packet, uint16_t length, void *userdata)
172
1
{
173
1
    const Onion *onion = (const Onion *)object;
174
175
1
    if (length != (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE + sizeof("Install gentoo") +
176
1
                   CRYPTO_MAC_SIZE)) {
177
0
        return 1;
178
0
    }
179
180
1
    uint8_t plain[sizeof("Install gentoo")] = {0};
181
182
1
    if (memcmp(nonce, packet + 1, CRYPTO_NONCE_SIZE) != 0) {
183
0
        return 1;
184
0
    }
185
186
1
    int len = decrypt_data(onion->mem, packet + 1 + CRYPTO_NONCE_SIZE, dht_get_self_secret_key(onion->dht), packet + 1,
187
1
                           packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE, sizeof("Install gentoo") + CRYPTO_MAC_SIZE, plain);
188
189
1
    if (len == -1) {
190
0
        return 1;
191
0
    }
192
193
1
    if (memcmp(plain, "Install gentoo", sizeof("Install gentoo")) != 0) {
194
0
        return 1;
195
0
    }
196
197
1
    handled_test_4 = 1;
198
1
    return 0;
199
1
}
200
201
/** Create and send a onion packet.
202
 *
203
 * Use Onion_Path path to send data of length to dest.
204
 * Maximum length of data is ONION_MAX_DATA_SIZE.
205
 */
206
static void send_onion_packet(const Networking_Core *net, const Memory *mem, const Random *rng, const Onion_Path *path, const IP_Port *dest, const uint8_t *data, uint16_t length)
207
1
{
208
1
    uint8_t packet[ONION_MAX_PACKET_SIZE];
209
1
    const int len = create_onion_packet(mem, rng, packet, sizeof(packet), path, dest, data, length);
210
1
    ck_assert_msg(len != -1, "failed to create onion packet");
211
1
    ck_assert_msg(sendpacket(net, &path->ip_port1, packet, len) == len, "failed to send onion packet");
212
1
}
213
214
/** Initialize networking.
215
 * Added for reverse compatibility with old new_networking calls.
216
 */
217
static Networking_Core *new_networking(const Logger *log, const Memory *mem, const Network *ns, const IP *ip, uint16_t port)
218
53
{
219
53
    return new_networking_ex(log, mem, ns, ip, port, port + (TOX_PORTRANGE_TO - TOX_PORTRANGE_FROM), nullptr);
220
53
}
221
222
static void test_basic(void)
223
1
{
224
1
    uint32_t index[] = { 1, 2, 3 };
225
1
    const Network *ns = os_network();
226
1
    ck_assert(ns != nullptr);
227
1
    const Memory *mem = os_memory();
228
1
    ck_assert(mem != nullptr);
229
1
    const Random *rng = os_random();
230
1
    ck_assert(rng != nullptr);
231
232
1
    Logger *log1 = logger_new(mem);
233
1
    logger_callback_log(log1, print_debug_logger, nullptr, &index[0]);
234
1
    Logger *log2 = logger_new(mem);
235
1
    logger_callback_log(log2, print_debug_logger, nullptr, &index[1]);
236
237
1
    Mono_Time *mono_time1 = mono_time_new(mem, nullptr, nullptr);
238
1
    Mono_Time *mono_time2 = mono_time_new(mem, nullptr, nullptr);
239
240
1
    IP ip = get_loopback();
241
1
    Onion *onion1 = new_onion(log1, mem, mono_time1, rng, new_dht(log1, mem, rng, ns, mono_time1, new_networking(log1, mem, ns, &ip, 36567), true, false));
242
1
    Onion *onion2 = new_onion(log2, mem, mono_time2, rng, new_dht(log2, mem, rng, ns, mono_time2, new_networking(log2, mem, ns, &ip, 36568), true, false));
243
1
    ck_assert_msg((onion1 != nullptr) && (onion2 != nullptr), "Onion failed initializing.");
244
1
    networking_registerhandler(onion2->net, NET_PACKET_ANNOUNCE_REQUEST, &handle_test_1, onion2);
245
246
1
    IP_Port on1 = {ip, net_port(onion1->net)};
247
1
    Node_format n1;
248
1
    memcpy(n1.public_key, dht_get_self_public_key(onion1->dht), CRYPTO_PUBLIC_KEY_SIZE);
249
1
    n1.ip_port = on1;
250
251
1
    IP_Port on2 = {ip, net_port(onion2->net)};
252
1
    Node_format n2;
253
1
    memcpy(n2.public_key, dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE);
254
1
    n2.ip_port = on2;
255
256
1
    const char req_message[] = "Install Gentoo";
257
1
    uint8_t req_packet[1 + sizeof(req_message)];
258
1
    req_packet[0] = NET_PACKET_ANNOUNCE_REQUEST;
259
1
    memcpy(req_packet + 1, req_message, sizeof(req_message));
260
261
1
    Node_format nodes[4];
262
1
    nodes[0] = n1;
263
1
    nodes[1] = n2;
264
1
    nodes[2] = n1;
265
1
    nodes[3] = n2;
266
1
    Onion_Path path;
267
1
    create_onion_path(rng, onion1->dht, &path, nodes);
268
1
    send_onion_packet(onion1->net, onion1->mem, rng, &path, &nodes[3].ip_port, req_packet, sizeof(req_packet));
269
270
1
    handled_test_1 = 0;
271
272
2
    do {
273
2
        do_onion(mono_time1, onion1);
274
2
        do_onion(mono_time2, onion2);
275
2
    } while (handled_test_1 == 0);
276
277
1
    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_2, onion1);
278
1
    handled_test_2 = 0;
279
280
2
    do {
281
2
        do_onion(mono_time1, onion1);
282
2
        do_onion(mono_time2, onion2);
283
2
    } while (handled_test_2 == 0);
284
285
1
    Onion_Announce *onion1_a = new_onion_announce(log1, mem, rng, mono_time1, onion1->dht);
286
1
    Onion_Announce *onion2_a = new_onion_announce(log2, mem, rng, mono_time2, onion2->dht);
287
1
    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_test_3, onion1);
288
1
    networking_registerhandler(onion1->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_test_3_old, onion1);
289
1
    ck_assert_msg((onion1_a != nullptr) && (onion2_a != nullptr), "Onion_Announce failed initializing.");
290
1
    const uint8_t zeroes[64] = {0};
291
1
    random_bytes(rng, sb_data, sizeof(sb_data));
292
1
    uint64_t s;
293
1
    memcpy(&s, sb_data, sizeof(uint64_t));
294
1
    memcpy(test_3_pub_key, nodes[3].public_key, CRYPTO_PUBLIC_KEY_SIZE);
295
1
    int ret = send_announce_request(log1, onion1->mem, onion1->net, rng, &path, &nodes[3],
296
1
                                    dht_get_self_public_key(onion1->dht),
297
1
                                    dht_get_self_secret_key(onion1->dht),
298
1
                                    zeroes,
299
1
                                    dht_get_self_public_key(onion1->dht),
300
1
                                    dht_get_self_public_key(onion1->dht), s);
301
1
    ck_assert_msg(ret == 0, "Failed to create/send onion announce_request packet.");
302
1
    handled_test_3 = 0;
303
304
4
    do {
305
4
        do_onion(mono_time1, onion1);
306
4
        do_onion(mono_time2, onion2);
307
4
        c_sleep(50);
308
4
    } while (handled_test_3 == 0);
309
310
1
    printf("test 3 complete\n");
311
312
1
    random_bytes(rng, sb_data, sizeof(sb_data));
313
1
    memcpy(&s, sb_data, sizeof(uint64_t));
314
1
    memcpy(onion_announce_entry_public_key(onion2_a, 1), dht_get_self_public_key(onion2->dht), CRYPTO_PUBLIC_KEY_SIZE);
315
1
    onion_announce_entry_set_time(onion2_a, 1, mono_time_get(mono_time2));
316
1
    networking_registerhandler(onion1->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_test_4, onion1);
317
1
    send_announce_request(log1, onion1->mem, onion1->net, rng, &path, &nodes[3],
318
1
                          dht_get_self_public_key(onion1->dht),
319
1
                          dht_get_self_secret_key(onion1->dht),
320
1
                          test_3_ping_id,
321
1
                          dht_get_self_public_key(onion1->dht),
322
1
                          dht_get_self_public_key(onion1->dht), s);
323
324
2
    do {
325
2
        do_onion(mono_time1, onion1);
326
2
        do_onion(mono_time2, onion2);
327
2
        c_sleep(50);
328
2
    } while (memcmp(onion_announce_entry_public_key(onion2_a, ONION_ANNOUNCE_MAX_ENTRIES - 2),
329
2
                    dht_get_self_public_key(onion1->dht),
330
2
                    CRYPTO_PUBLIC_KEY_SIZE) != 0);
331
332
1
    c_sleep(1000);
333
1
    Logger *log3 = logger_new(mem);
334
1
    logger_callback_log(log3, print_debug_logger, nullptr, &index[2]);
335
336
1
    Mono_Time *mono_time3 = mono_time_new(mem, nullptr, nullptr);
337
338
1
    Onion *onion3 = new_onion(log3, mem, mono_time3, rng, new_dht(log3, mem, rng, ns, mono_time3, new_networking(log3, mem, ns, &ip, 36569), true, false));
339
1
    ck_assert_msg((onion3 != nullptr), "Onion failed initializing.");
340
341
1
    random_nonce(rng, nonce);
342
1
    ret = send_data_request(log3, onion3->mem, onion3->net, rng, &path, &nodes[3].ip_port,
343
1
                            dht_get_self_public_key(onion1->dht),
344
1
                            dht_get_self_public_key(onion1->dht),
345
1
                            nonce, (const uint8_t *)"Install gentoo", sizeof("Install gentoo"));
346
1
    ck_assert_msg(ret == 0, "Failed to create/send onion data_request packet.");
347
1
    handled_test_4 = 0;
348
349
4
    do {
350
4
        do_onion(mono_time1, onion1);
351
4
        do_onion(mono_time2, onion2);
352
4
        c_sleep(50);
353
4
    } while (handled_test_4 == 0);
354
355
1
    printf("test 4 complete\n");
356
357
1
    kill_onion_announce(onion2_a);
358
1
    kill_onion_announce(onion1_a);
359
360
1
    {
361
1
        Onion *onion = onion3;
362
363
1
        Networking_Core *net = dht_get_net(onion->dht);
364
1
        DHT *dht = onion->dht;
365
1
        kill_onion(onion);
366
1
        kill_dht(dht);
367
1
        kill_networking(net);
368
1
        mono_time_free(mem, mono_time3);
369
1
        logger_kill(log3);
370
1
    }
371
372
1
    {
373
1
        Onion *onion = onion2;
374
375
1
        Networking_Core *net = dht_get_net(onion->dht);
376
1
        DHT *dht = onion->dht;
377
1
        kill_onion(onion);
378
1
        kill_dht(dht);
379
1
        kill_networking(net);
380
1
        mono_time_free(mem, mono_time2);
381
1
        logger_kill(log2);
382
1
    }
383
384
1
    {
385
1
        Onion *onion = onion1;
386
387
1
        Networking_Core *net = dht_get_net(onion->dht);
388
1
        DHT *dht = onion->dht;
389
1
        kill_onion(onion);
390
1
        kill_dht(dht);
391
1
        kill_networking(net);
392
1
        mono_time_free(mem, mono_time1);
393
1
        logger_kill(log1);
394
1
    }
395
1
}
396
397
typedef struct {
398
    Logger *log;
399
    Mono_Time *mono_time;
400
    Net_Profile *tcp_np;
401
    Onion *onion;
402
    Onion_Announce *onion_a;
403
    Onion_Client *onion_c;
404
} Onions;
405
406
static Onions *new_onions(const Memory *mem, const Random *rng, uint16_t port, uint32_t *index)
407
50
{
408
50
    IP ip = get_loopback();
409
50
    ip.ip.v6.uint8[15] = 1;
410
50
    const Network *ns = os_network();
411
50
    Onions *on = (Onions *)malloc(sizeof(Onions));
412
413
50
    if (!on) {
414
0
        return nullptr;
415
0
    }
416
417
50
    on->log = logger_new(mem);
418
419
50
    if (!on->log) {
420
0
        free(on);
421
0
        return nullptr;
422
0
    }
423
424
50
    logger_callback_log(on->log, print_debug_logger, nullptr, index);
425
426
50
    on->mono_time = mono_time_new(mem, nullptr, nullptr);
427
428
50
    if (!on->mono_time) {
429
0
        logger_kill(on->log);
430
0
        free(on);
431
0
        return nullptr;
432
0
    }
433
434
50
    Networking_Core *net = new_networking(on->log, mem, ns, &ip, port);
435
436
50
    if (!net) {
437
0
        mono_time_free(mem, on->mono_time);
438
0
        logger_kill(on->log);
439
0
        free(on);
440
0
        return nullptr;
441
0
    }
442
443
50
    DHT *dht = new_dht(on->log, mem, rng, ns, on->mono_time, net, true, false);
444
445
50
    if (!dht) {
446
0
        kill_networking(net);
447
0
        mono_time_free(mem, on->mono_time);
448
0
        logger_kill(on->log);
449
0
        free(on);
450
0
        return nullptr;
451
0
    }
452
453
50
    on->onion = new_onion(on->log, mem, on->mono_time, rng, dht);
454
455
50
    if (!on->onion) {
456
0
        kill_dht(dht);
457
0
        kill_networking(net);
458
0
        mono_time_free(mem, on->mono_time);
459
0
        logger_kill(on->log);
460
0
        free(on);
461
0
        return nullptr;
462
0
    }
463
464
50
    on->onion_a = new_onion_announce(on->log, mem, rng, on->mono_time, dht);
465
466
50
    if (!on->onion_a) {
467
0
        kill_onion(on->onion);
468
0
        kill_dht(dht);
469
0
        kill_networking(net);
470
0
        mono_time_free(mem, on->mono_time);
471
0
        logger_kill(on->log);
472
0
        free(on);
473
0
        return nullptr;
474
0
    }
475
476
50
    on->tcp_np = netprof_new(on->log, mem);
477
478
50
    if (!on->tcp_np) {
479
0
        kill_onion_announce(on->onion_a);
480
0
        kill_onion(on->onion);
481
0
        kill_dht(dht);
482
0
        kill_networking(net);
483
0
        mono_time_free(mem, on->mono_time);
484
0
        logger_kill(on->log);
485
0
        free(on);
486
0
        return nullptr;
487
0
    }
488
489
50
    TCP_Proxy_Info inf = {{{{0}}}};
490
50
    on->onion_c = new_onion_client(on->log, mem, rng, on->mono_time, new_net_crypto(on->log, mem, rng, ns, on->mono_time, dht, &inf, on->tcp_np));
491
492
50
    if (!on->onion_c) {
493
0
        netprof_kill(mem, on->tcp_np);
494
0
        kill_onion_announce(on->onion_a);
495
0
        kill_onion(on->onion);
496
0
        kill_dht(dht);
497
0
        kill_networking(net);
498
0
        mono_time_free(mem, on->mono_time);
499
0
        logger_kill(on->log);
500
0
        free(on);
501
0
        return nullptr;
502
0
    }
503
504
50
    return on;
505
50
}
506
507
static void do_onions(Onions *on)
508
7.00k
{
509
7.00k
    mono_time_update(on->mono_time);
510
511
7.00k
    networking_poll(on->onion->net, nullptr);
512
7.00k
    do_dht(on->onion->dht);
513
7.00k
    do_onion_client(on->onion_c);
514
7.00k
}
515
516
static void kill_onions(const Memory *mem, Onions *on)
517
50
{
518
50
    Networking_Core *net = dht_get_net(on->onion->dht);
519
50
    DHT *dht = on->onion->dht;
520
50
    Net_Crypto *c = onion_get_net_crypto(on->onion_c);
521
50
    kill_onion_client(on->onion_c);
522
50
    kill_onion_announce(on->onion_a);
523
50
    kill_onion(on->onion);
524
50
    kill_net_crypto(c);
525
50
    netprof_kill(mem, on->tcp_np);
526
50
    kill_dht(dht);
527
50
    kill_networking(net);
528
50
    mono_time_free(mem, on->mono_time);
529
50
    logger_kill(on->log);
530
50
    free(on);
531
50
}
532
533
7.30k
#define NUM_ONIONS 50
534
13
#define NUM_FIRST 7
535
11
#define NUM_LAST 37
536
537
static bool first_ip, last_ip;
538
static void dht_ip_callback(void *object, int32_t number, const IP_Port *ip_port)
539
2
{
540
2
    if (NUM_FIRST == number) {
541
1
        first_ip = 1;
542
1
        return;
543
1
    }
544
545
1
    if (NUM_LAST == number) {
546
1
        last_ip = 1;
547
1
        return;
548
1
    }
549
550
0
    ck_abort_msg("Error.");
551
0
}
552
553
static bool first, last;
554
static uint8_t first_dht_pk[CRYPTO_PUBLIC_KEY_SIZE];
555
static uint8_t last_dht_pk[CRYPTO_PUBLIC_KEY_SIZE];
556
557
static void dht_pk_callback(void *object, int32_t number, const uint8_t *dht_public_key, void *userdata)
558
3
{
559
3
    if ((NUM_FIRST == number && !first) || (NUM_LAST == number && !last)) {
560
2
        Onions *on = (Onions *)object;
561
2
        uint32_t token = 0;
562
2
        int ret = dht_addfriend(on->onion->dht, dht_public_key, &dht_ip_callback, object, number, &token);
563
2
        ck_assert_msg(ret == 0, "dht_addfriend() did not return 0");
564
2
        ck_assert_msg(token == 1, "Count not 1, count is %u", token);
565
566
2
        if (NUM_FIRST == number && !first) {
567
1
            first = 1;
568
569
1
            if (memcmp(dht_public_key, last_dht_pk, CRYPTO_PUBLIC_KEY_SIZE) != 0) {
570
0
                ck_abort_msg("Error wrong dht key.");
571
0
            }
572
573
1
            return;
574
1
        }
575
576
1
        if (NUM_LAST == number && !last) {
577
1
            last = 1;
578
579
1
            if (memcmp(dht_public_key, first_dht_pk, CRYPTO_PUBLIC_KEY_SIZE) != 0) {
580
0
                ck_abort_msg("Error wrong dht key.");
581
0
            }
582
583
1
            return;
584
1
        }
585
586
0
        ck_abort_msg("Error.");
587
0
    }
588
3
}
589
590
static void test_announce(void)
591
1
{
592
1
    uint32_t index[NUM_ONIONS];
593
1
    Onions *onions[NUM_ONIONS];
594
1
    const Random *rng = os_random();
595
1
    ck_assert(rng != nullptr);
596
1
    const Memory *mem = os_memory();
597
1
    ck_assert(mem != nullptr);
598
599
51
    for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
600
50
        index[i] = i + 1;
601
50
        onions[i] = new_onions(mem, rng, i + 36655, &index[i]);
602
50
        ck_assert_msg(onions[i] != nullptr, "Failed to create onions. %u", i);
603
50
    }
604
605
1
    IP ip = get_loopback();
606
607
48
    for (uint32_t i = 3; i < NUM_ONIONS; ++i) {
608
47
        IP_Port ip_port = {ip, net_port(onions[i - 1]->onion->net)};
609
47
        dht_bootstrap(onions[i]->onion->dht, &ip_port, dht_get_self_public_key(onions[i - 1]->onion->dht));
610
47
        IP_Port ip_port1 = {ip, net_port(onions[i - 2]->onion->net)};
611
47
        dht_bootstrap(onions[i]->onion->dht, &ip_port1, dht_get_self_public_key(onions[i - 2]->onion->dht));
612
47
        IP_Port ip_port2 = {ip, net_port(onions[i - 3]->onion->net)};
613
47
        dht_bootstrap(onions[i]->onion->dht, &ip_port2, dht_get_self_public_key(onions[i - 3]->onion->dht));
614
47
    }
615
616
1
    uint32_t connected = 0;
617
618
14
    do {
619
14
        connected = 0;
620
621
714
        for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
622
700
            do_onions(onions[i]);
623
700
            connected += dht_isconnected(onions[i]->onion->dht);
624
700
        }
625
626
14
        c_sleep(50);
627
14
    } while (connected != NUM_ONIONS);
628
629
1
    printf("connected\n");
630
631
51
    for (uint32_t i = 0; i < 25 * 2; ++i) {
632
2.55k
        for (uint32_t j = 0; j < NUM_ONIONS; ++j) {
633
2.50k
            do_onions(onions[j]);
634
2.50k
        }
635
636
50
        c_sleep(50);
637
50
    }
638
639
1
    memcpy(first_dht_pk, dht_get_self_public_key(onions[NUM_FIRST]->onion->dht), CRYPTO_PUBLIC_KEY_SIZE);
640
1
    memcpy(last_dht_pk, dht_get_self_public_key(onions[NUM_LAST]->onion->dht), CRYPTO_PUBLIC_KEY_SIZE);
641
642
1
    printf("adding friend\n");
643
1
    int frnum_f = onion_addfriend(onions[NUM_FIRST]->onion_c,
644
1
                                  nc_get_self_public_key(onion_get_net_crypto(onions[NUM_LAST]->onion_c)));
645
1
    int frnum = onion_addfriend(onions[NUM_LAST]->onion_c,
646
1
                                nc_get_self_public_key(onion_get_net_crypto(onions[NUM_FIRST]->onion_c)));
647
648
1
    onion_dht_pk_callback(onions[NUM_FIRST]->onion_c, frnum_f, &dht_pk_callback, onions[NUM_FIRST], NUM_FIRST);
649
1
    onion_dht_pk_callback(onions[NUM_LAST]->onion_c, frnum, &dht_pk_callback, onions[NUM_LAST], NUM_LAST);
650
651
1
    IP_Port ip_port;
652
653
59
    do {
654
3.00k
        for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
655
2.95k
            do_onions(onions[i]);
656
2.95k
        }
657
658
59
        c_sleep(50);
659
59
    } while (!first || !last);
660
661
1
    printf("Waiting for ips\n");
662
663
17
    do {
664
867
        for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
665
850
            do_onions(onions[i]);
666
850
        }
667
668
17
        c_sleep(50);
669
17
    } while (!first_ip || !last_ip);
670
671
1
    onion_getfriendip(onions[NUM_LAST]->onion_c, frnum, &ip_port);
672
1
    ck_assert_msg(ip_port.port == net_port(onions[NUM_FIRST]->onion->net), "Port in returned ip not correct.");
673
674
51
    for (uint32_t i = 0; i < NUM_ONIONS; ++i) {
675
50
        kill_onions(mem, onions[i]);
676
50
    }
677
1
}
678
679
int main(void)
680
545
{
681
545
    setvbuf(stdout, nullptr, _IONBF, 0);
682
683
545
    test_basic();
684
545
    test_announce();
685
686
545
    return 0;
687
545
}