Coverage Report

Created: 2026-10-24 08:16

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