Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/DHT.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2026 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/**
7
 * An implementation of the DHT as seen in docs/updates/DHT.md
8
 */
9
#include "DHT.h"
10
11
#include <assert.h>
12
#include <string.h>
13
14
#include "LAN_discovery.h"
15
#include "attributes.h"
16
#include "bin_pack.h"
17
#include "ccompat.h"
18
#include "crypto_core.h"
19
#include "logger.h"
20
#include "mem.h"
21
#include "mono_time.h"
22
#include "network.h"
23
#include "ping.h"
24
#include "ping_array.h"
25
#include "shared_key_cache.h"
26
#include "sort.h"
27
#include "state.h"
28
29
/** The timeout after which a node is discarded completely. */
30
13.6M
#define KILL_NODE_TIMEOUT (BAD_NODE_TIMEOUT + PING_INTERVAL)
31
32
/** Ping interval in seconds for each random sending of a nodes request. */
33
20.5k
#define NODES_REQUEST_INTERVAL 20
34
35
0
#define MAX_PUNCHING_PORTS 48
36
37
/** Interval in seconds between punching attempts*/
38
118
#define PUNCH_INTERVAL 3
39
40
/** Time in seconds after which punching parameters will be reset */
41
0
#define PUNCH_RESET_TIME 40
42
43
0
#define MAX_NORMAL_PUNCHING_TRIES 5
44
45
783
#define NAT_PING_REQUEST    0
46
665
#define NAT_PING_RESPONSE   1
47
48
/** Number of node requests to send to quickly find close nodes. */
49
18.7k
#define MAX_BOOTSTRAP_TIMES 5
50
51
// TODO(sudden6): find out why we need multiple callbacks and if we really need 32
52
77.7k
#define DHT_FRIEND_MAX_LOCKS 32
53
54
/* Settings for the shared key cache */
55
4.09k
#define MAX_KEYS_PER_SLOT 4
56
4.09k
#define KEYS_TIMEOUT 600
57
58
typedef struct NAT {
59
    /* true if currently hole punching */
60
    bool        hole_punching;
61
    uint32_t    punching_index;
62
    uint32_t    tries;
63
    uint32_t    punching_index2;
64
65
    uint64_t    punching_timestamp;
66
    uint64_t    recv_nat_ping_timestamp;
67
    uint64_t    nat_ping_id;
68
    uint64_t    nat_ping_timestamp;
69
} NAT;
70
71
typedef struct DHT_Friend_Callback {
72
    dht_ip_cb *_Nullable ip_callback;
73
    void *_Nullable data;
74
    int32_t number;
75
} DHT_Friend_Callback;
76
77
struct DHT_Friend {
78
    uint8_t     public_key[CRYPTO_PUBLIC_KEY_SIZE];
79
    Client_data client_list[MAX_FRIEND_CLIENTS];
80
81
    /* Time at which the last nodes request was sent. */
82
    uint64_t    last_nodes_request;
83
    /* number of times nodes request packets were sent. */
84
    uint32_t    bootstrap_times;
85
86
    /* Symmetric NAT hole punching stuff. */
87
    NAT         nat;
88
89
    /* Each set bit represents one installed callback */
90
    uint32_t lock_flags;
91
    DHT_Friend_Callback callbacks[DHT_FRIEND_MAX_LOCKS];
92
93
    Node_format to_bootstrap[MAX_SENT_NODES];
94
    unsigned int num_to_bootstrap;
95
};
96
97
static const DHT_Friend empty_dht_friend = {{0}};
98
const Node_format empty_node_format = {{0}};
99
100
static_assert(sizeof(empty_dht_friend.lock_flags) * 8 == DHT_FRIEND_MAX_LOCKS, "Bitfield size and number of locks don't match");
101
102
typedef struct Cryptopacket_Handler {
103
    cryptopacket_handler_cb *_Nullable function;
104
    void *_Nullable object;
105
} Cryptopacket_Handler;
106
107
struct DHT {
108
    const Logger *_Nonnull log;
109
    const Network *_Nonnull ns;
110
    Mono_Time *_Nonnull mono_time;
111
    const Memory *_Nonnull mem;
112
    const Random *_Nonnull rng;
113
    Networking_Core *_Nonnull net;
114
115
    bool hole_punching_enabled;
116
    bool lan_discovery_enabled;
117
118
    Client_data    close_clientlist[LCLIENT_LIST];
119
    uint64_t       close_last_nodes_request;
120
    uint32_t       close_bootstrap_times;
121
122
    /* DHT keypair */
123
    uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
124
    uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
125
126
    DHT_Friend    *_Nullable friends_list;
127
    uint16_t       num_friends;
128
129
    Node_format   *_Nullable loaded_nodes_list;
130
    uint32_t       loaded_num_nodes;
131
    unsigned int   loaded_nodes_index;
132
133
    Shared_Key_Cache *_Nonnull shared_keys_recv;
134
    Shared_Key_Cache *_Nonnull shared_keys_sent;
135
136
    struct Ping   *_Nonnull ping;
137
    Ping_Array    *_Nonnull dht_ping_array;
138
    uint64_t       cur_time;
139
140
    Cryptopacket_Handler cryptopackethandlers[256];
141
142
    Node_format to_bootstrap[MAX_CLOSE_TO_BOOTSTRAP_NODES];
143
    unsigned int num_to_bootstrap;
144
145
    dht_nodes_response_cb *_Nullable nodes_response_callback;
146
};
147
148
const uint8_t *dht_friend_public_key(const DHT_Friend *dht_friend)
149
784
{
150
784
    return dht_friend->public_key;
151
784
}
152
153
const Client_data *dht_friend_client(const DHT_Friend *dht_friend, size_t index)
154
6.27k
{
155
6.27k
    return &dht_friend->client_list[index];
156
6.27k
}
157
158
const uint8_t *dht_get_self_public_key(const DHT *dht)
159
171k
{
160
171k
    return dht->self_public_key;
161
171k
}
162
const uint8_t *dht_get_self_secret_key(const DHT *dht)
163
16.9k
{
164
16.9k
    return dht->self_secret_key;
165
16.9k
}
166
167
void dht_set_self_public_key(DHT *dht, const uint8_t *key)
168
0
{
169
0
    memcpy(dht->self_public_key, key, CRYPTO_PUBLIC_KEY_SIZE);
170
0
}
171
void dht_set_self_secret_key(DHT *dht, const uint8_t *key)
172
0
{
173
0
    memcpy(dht->self_secret_key, key, CRYPTO_SECRET_KEY_SIZE);
174
0
}
175
176
struct Ping *dht_get_ping(const DHT *dht)
177
9.76k
{
178
9.76k
    return dht->ping;
179
9.76k
}
180
const Client_data *dht_get_close_clientlist(const DHT *dht)
181
49.9k
{
182
49.9k
    return dht->close_clientlist;
183
49.9k
}
184
const Client_data *dht_get_close_client(const DHT *dht, uint32_t client_num)
185
532k
{
186
532k
    assert(client_num < sizeof(dht->close_clientlist) / sizeof(dht->close_clientlist[0]));
187
532k
    return &dht->close_clientlist[client_num];
188
532k
}
189
uint16_t dht_get_num_friends(const DHT *dht)
190
1.87k
{
191
1.87k
    return dht->num_friends;
192
1.87k
}
193
194
DHT_Friend *dht_get_friend(DHT *dht, uint32_t friend_num)
195
784
{
196
784
    assert(friend_num < dht->num_friends);
197
784
    return &dht->friends_list[friend_num];
198
784
}
199
const uint8_t *dht_get_friend_public_key(const DHT *dht, uint32_t friend_num)
200
515
{
201
515
    assert(friend_num < dht->num_friends);
202
515
    return dht->friends_list[friend_num].public_key;
203
515
}
204
205
static bool assoc_timeout(uint64_t cur_time, const IPPTsPng *_Nonnull assoc)
206
147M
{
207
147M
    return (assoc->timestamp + BAD_NODE_TIMEOUT) <= cur_time;
208
147M
}
209
210
/** @brief Converts an IPv4-in-IPv6 to IPv4 and returns the new IP_Port.
211
 *
212
 * If the ip_port is already IPv4 this function returns a copy of the original ip_port.
213
 */
214
static IP_Port ip_port_normalize(const IP_Port *_Nonnull ip_port)
215
293k
{
216
293k
    IP_Port res = *ip_port;
217
218
293k
    if (net_family_is_ipv6(res.ip.family) && ipv6_ipv4_in_v6(&res.ip.ip.v6)) {
219
0
        res.ip.family = net_family_ipv4();
220
0
        res.ip.ip.v4.uint32 = res.ip.ip.v6.uint32[3];
221
0
    }
222
223
293k
    return res;
224
293k
}
225
226
int id_closest(const uint8_t *pk, const uint8_t *pk1, const uint8_t *pk2)
227
9.78M
{
228
10.7M
    for (size_t i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
229
10.7M
        const uint8_t distance1 = pk[i] ^ pk1[i];
230
10.7M
        const uint8_t distance2 = pk[i] ^ pk2[i];
231
232
10.7M
        if (distance1 < distance2) {
233
7.64M
            return 1;
234
7.64M
        }
235
236
3.10M
        if (distance1 > distance2) {
237
2.11M
            return 2;
238
2.11M
        }
239
3.10M
    }
240
241
23.0k
    return 0;
242
9.78M
}
243
244
/** Return index of first unequal bit number between public keys pk1 and pk2. */
245
unsigned int bit_by_bit_cmp(const uint8_t *pk1, const uint8_t *pk2)
246
568k
{
247
568k
    unsigned int i;
248
568k
    unsigned int j = 0;
249
250
1.88M
    for (i = 0; i < CRYPTO_PUBLIC_KEY_SIZE; ++i) {
251
1.84M
        if (pk1[i] == pk2[i]) {
252
1.31M
            continue;
253
1.31M
        }
254
255
1.22M
        for (j = 0; j < 8; ++j) {
256
1.22M
            const uint8_t mask = 1 << (7 - j);
257
258
1.22M
            if ((pk1[i] & mask) != (pk2[i] & mask)) {
259
527k
                break;
260
527k
            }
261
1.22M
        }
262
263
527k
        break;
264
1.84M
    }
265
266
568k
    return i * 8 + j;
267
568k
}
268
269
/**
270
 * Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
271
 * for packets that we receive.
272
 */
273
const uint8_t *dht_get_shared_key_recv(DHT *dht, const uint8_t *public_key)
274
80.1k
{
275
80.1k
    return shared_key_cache_lookup(dht->shared_keys_recv, public_key);
276
80.1k
}
277
278
/**
279
 * Copy shared_key to encrypt/decrypt DHT packet from public_key into shared_key
280
 * for packets that we send.
281
 */
282
const uint8_t *dht_get_shared_key_sent(DHT *dht, const uint8_t *public_key)
283
145k
{
284
145k
    return shared_key_cache_lookup(dht->shared_keys_sent, public_key);
285
145k
}
286
287
85.0k
#define CRYPTO_SIZE (1 + CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE)
288
289
int create_request(const Memory *mem, const Random *rng, const uint8_t *send_public_key, const uint8_t *send_secret_key,
290
                   uint8_t *packet, const uint8_t *recv_public_key,
291
                   const uint8_t *data, uint32_t data_length, uint8_t request_id)
292
4.92k
{
293
4.92k
    if (send_public_key == nullptr || packet == nullptr || recv_public_key == nullptr || data == nullptr) {
294
0
        return -1;
295
0
    }
296
297
4.92k
    if (MAX_CRYPTO_REQUEST_SIZE < data_length + CRYPTO_SIZE + 1 + CRYPTO_MAC_SIZE) {
298
1
        return -1;
299
1
    }
300
301
4.92k
    uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
302
4.92k
    random_nonce(rng, nonce);
303
4.92k
    uint8_t temp[MAX_CRYPTO_REQUEST_SIZE] = {0};
304
4.92k
    temp[0] = request_id;
305
4.92k
    memcpy(temp + 1, data, data_length);
306
4.92k
    const int len = encrypt_data(mem, recv_public_key, send_secret_key, nonce, temp, data_length + 1,
307
4.92k
                                 packet + CRYPTO_SIZE);
308
309
4.92k
    if (len == -1) {
310
0
        crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
311
0
        return -1;
312
0
    }
313
314
4.92k
    packet[0] = NET_PACKET_CRYPTO;
315
4.92k
    memcpy(packet + 1, recv_public_key, CRYPTO_PUBLIC_KEY_SIZE);
316
4.92k
    memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, send_public_key, CRYPTO_PUBLIC_KEY_SIZE);
317
318
4.92k
    crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
319
4.92k
    return len + CRYPTO_SIZE;
320
4.92k
}
321
322
int handle_request(const Memory *mem, const uint8_t *self_public_key, const uint8_t *self_secret_key, uint8_t *public_key, uint8_t *data,
323
                   uint8_t *request_id, const uint8_t *packet, uint16_t packet_length)
324
2.02k
{
325
2.02k
    if (self_public_key == nullptr || public_key == nullptr || data == nullptr || request_id == nullptr
326
2.02k
            || packet == nullptr) {
327
0
        return -1;
328
0
    }
329
330
2.02k
    if (packet_length <= CRYPTO_SIZE + CRYPTO_MAC_SIZE || packet_length > MAX_CRYPTO_REQUEST_SIZE) {
331
3
        return -1;
332
3
    }
333
334
2.01k
    if (!pk_equal(packet + 1, self_public_key)) {
335
1
        return -1;
336
1
    }
337
338
2.01k
    memcpy(public_key, packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_PUBLIC_KEY_SIZE);
339
2.01k
    const uint8_t *const nonce = packet + 1 + CRYPTO_PUBLIC_KEY_SIZE * 2;
340
2.01k
    uint8_t temp[MAX_CRYPTO_REQUEST_SIZE];
341
2.01k
    int32_t len1 = decrypt_data(mem, public_key, self_secret_key, nonce,
342
2.01k
                                packet + CRYPTO_SIZE, packet_length - CRYPTO_SIZE, temp);
343
344
2.01k
    if (len1 == -1 || len1 == 0) {
345
0
        crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
346
0
        return -1;
347
0
    }
348
349
2.01k
    assert(len1 == packet_length - CRYPTO_SIZE - CRYPTO_MAC_SIZE);
350
    // Because coverity can't figure out this equation:
351
2.01k
    assert(len1 <= MAX_CRYPTO_REQUEST_SIZE - CRYPTO_SIZE - CRYPTO_MAC_SIZE);
352
353
2.01k
    request_id[0] = temp[0];
354
2.01k
    --len1;
355
2.01k
    memcpy(data, temp + 1, len1);
356
2.01k
    crypto_memzero(temp, MAX_CRYPTO_REQUEST_SIZE);
357
2.01k
    return len1;
358
2.01k
}
359
360
int packed_node_size(Family ip_family)
361
11.9k
{
362
11.9k
    if (net_family_is_ipv4(ip_family) || net_family_is_tcp_ipv4(ip_family)) {
363
2.98k
        return PACKED_NODE_SIZE_IP4;
364
2.98k
    }
365
366
8.94k
    if (net_family_is_ipv6(ip_family) || net_family_is_tcp_ipv6(ip_family)) {
367
8.94k
        return PACKED_NODE_SIZE_IP6;
368
8.94k
    }
369
370
0
    return -1;
371
8.94k
}
372
373
int dht_create_packet(const Memory *mem, const Random *rng,
374
                      const uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE],
375
                      const uint8_t *shared_key, const uint8_t type,
376
                      const uint8_t *plain, size_t plain_length,
377
                      uint8_t *packet, size_t length)
378
141k
{
379
141k
    uint8_t nonce[CRYPTO_NONCE_SIZE];
380
141k
    uint8_t *encrypted = (uint8_t *)mem_balloc(mem, plain_length + CRYPTO_MAC_SIZE);
381
382
141k
    if (encrypted == nullptr) {
383
5
        return -1;
384
5
    }
385
386
141k
    random_nonce(rng, nonce);
387
388
141k
    const int encrypted_length = encrypt_data_symmetric(mem, shared_key, nonce, plain, plain_length, encrypted);
389
390
141k
    if (encrypted_length < 0) {
391
4
        mem_delete(mem, encrypted);
392
4
        return -1;
393
4
    }
394
395
141k
    if (length < 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + (size_t)encrypted_length) {
396
0
        mem_delete(mem, encrypted);
397
0
        return -1;
398
0
    }
399
400
141k
    packet[0] = type;
401
141k
    memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
402
141k
    memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
403
141k
    memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE, encrypted, encrypted_length);
404
405
141k
    mem_delete(mem, encrypted);
406
141k
    return 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + encrypted_length;
407
141k
}
408
409
/** @brief Pack a single node from a node array.
410
 *
411
 * @retval true on success.
412
 */
413
static bool bin_pack_node_handler(const void *_Nonnull arr, uint32_t index, const Logger *_Nonnull logger, Bin_Pack *_Nonnull bp)
414
876k
{
415
876k
    const Node_format *nodes = (const Node_format *)arr;
416
876k
    return bin_pack_ip_port(bp, logger, &nodes[index].ip_port)
417
876k
           && bin_pack_bin_b(bp, nodes[index].public_key, CRYPTO_PUBLIC_KEY_SIZE);
418
876k
}
419
420
int pack_nodes(const Logger *logger, uint8_t *data, uint16_t length, const Node_format *nodes, uint16_t number)
421
233k
{
422
233k
    const uint32_t size = bin_pack_obj_array_b_size(bin_pack_node_handler, nodes, number, logger);
423
233k
    if (!bin_pack_obj_array_b(bin_pack_node_handler, nodes, number, logger, data, length)) {
424
188
        return -1;
425
188
    }
426
232k
    return size;
427
233k
}
428
429
int unpack_nodes(Node_format *nodes, uint16_t max_num_nodes, uint16_t *processed_data_len, const uint8_t *data,
430
                 uint16_t length, bool tcp_enabled)
431
166k
{
432
166k
    if (nodes == nullptr && max_num_nodes > 0) {
433
0
        return -1;
434
0
    }
435
436
166k
    uint32_t num = 0;
437
166k
    uint32_t len_processed = 0;
438
439
571k
    while (num < max_num_nodes && len_processed < length) {
440
406k
        const int ipp_size = unpack_ip_port(&nodes[num].ip_port, data + len_processed, length - len_processed, tcp_enabled);
441
442
406k
        if (ipp_size == -1) {
443
852
            break;
444
852
        }
445
446
405k
        len_processed += ipp_size;
447
448
405k
        if (len_processed + CRYPTO_PUBLIC_KEY_SIZE > length) {
449
176
            return -1;
450
176
        }
451
452
405k
        memcpy(nodes[num].public_key, data + len_processed, CRYPTO_PUBLIC_KEY_SIZE);
453
405k
        len_processed += CRYPTO_PUBLIC_KEY_SIZE;
454
405k
        ++num;
455
456
405k
#ifndef NDEBUG
457
405k
        const uint32_t increment = ipp_size + CRYPTO_PUBLIC_KEY_SIZE;
458
405k
        assert(increment == PACKED_NODE_SIZE_IP4 || increment == PACKED_NODE_SIZE_IP6);
459
405k
#endif /* NDEBUG */
460
405k
    }
461
462
166k
    if (num == 0 && max_num_nodes > 0 && length > 0) {
463
379
        return -1;
464
379
    }
465
466
165k
    if (processed_data_len != nullptr) {
467
69.6k
        *processed_data_len = len_processed;
468
69.6k
    }
469
470
165k
    return num;
471
166k
}
472
473
/** @brief Find index in an array with public_key equal to pk.
474
 *
475
 * @return index or UINT32_MAX if not found.
476
 */
477
static uint32_t index_of_client_pk(const Client_data *_Nullable array, uint32_t size, const uint8_t *_Nonnull pk)
478
1.04M
{
479
1.04M
    assert(size == 0 || array != nullptr);
480
27.1M
    for (uint32_t i = 0; i < size; ++i) {
481
26.5M
        if (pk_equal(array[i].public_key, pk)) {
482
459k
            return i;
483
459k
        }
484
26.5M
    }
485
486
586k
    return UINT32_MAX;
487
1.04M
}
488
489
static uint32_t index_of_friend_pk(const DHT_Friend *_Nullable array, uint32_t size, const uint8_t *_Nonnull pk)
490
31.5k
{
491
31.5k
    assert(size == 0 || array != nullptr);
492
95.2k
    for (uint32_t i = 0; i < size; ++i) {
493
68.8k
        if (pk_equal(array[i].public_key, pk)) {
494
5.20k
            return i;
495
5.20k
        }
496
68.8k
    }
497
498
26.3k
    return UINT32_MAX;
499
31.5k
}
500
501
static uint32_t index_of_node_pk(const Node_format *_Nullable array, uint32_t size, const uint8_t *_Nonnull pk)
502
3.57M
{
503
3.57M
    assert(size == 0 || array != nullptr);
504
14.2M
    for (uint32_t i = 0; i < size; ++i) {
505
11.2M
        if (pk_equal(array[i].public_key, pk)) {
506
589k
            return i;
507
589k
        }
508
11.2M
    }
509
510
2.98M
    return UINT32_MAX;
511
3.57M
}
512
513
/** @brief Find index of Client_data with ip_port equal to param ip_port.
514
 *
515
 * @return index or UINT32_MAX if not found.
516
 */
517
static uint32_t index_of_client_ip_port(const Client_data *_Nullable array, uint32_t size, const IP_Port *_Nonnull ip_port)
518
100k
{
519
100k
    assert(size == 0 || array != nullptr);
520
19.1M
    for (uint32_t i = 0; i < size; ++i) {
521
19.0M
        if ((net_family_is_ipv4(ip_port->ip.family) && ipport_equal(&array[i].assoc4.ip_port, ip_port)) ||
522
19.0M
                (net_family_is_ipv6(ip_port->ip.family) && ipport_equal(&array[i].assoc6.ip_port, ip_port))) {
523
11
            return i;
524
11
        }
525
19.0M
    }
526
527
100k
    return UINT32_MAX;
528
100k
}
529
530
/** Update ip_port of client if it's needed. */
531
static void update_client(const Logger *_Nonnull log, const Mono_Time *_Nonnull mono_time, int index, Client_data *_Nonnull client, const IP_Port *_Nonnull ip_port)
532
125k
{
533
125k
    IPPTsPng *assoc;
534
125k
    int ip_version;
535
536
125k
    if (net_family_is_ipv4(ip_port->ip.family)) {
537
125k
        assoc = &client->assoc4;
538
125k
        ip_version = 4;
539
18.4E
    } else if (net_family_is_ipv6(ip_port->ip.family)) {
540
0
        assoc = &client->assoc6;
541
0
        ip_version = 6;
542
18.4E
    } else {
543
18.4E
        return;
544
18.4E
    }
545
546
125k
    if (!ipport_equal(&assoc->ip_port, ip_port)) {
547
6
        Ip_Ntoa ip_str_from;
548
6
        Ip_Ntoa ip_str_to;
549
6
        LOGGER_TRACE(log, "coipil[%u]: switching ipv%d from %s:%u to %s:%u",
550
6
                     (unsigned int)index, ip_version,
551
6
                     net_ip_ntoa(&assoc->ip_port.ip, &ip_str_from),
552
6
                     net_ntohs(assoc->ip_port.port),
553
6
                     net_ip_ntoa(&ip_port->ip, &ip_str_to),
554
6
                     net_ntohs(ip_port->port));
555
6
    }
556
557
125k
    if (!ip_is_lan(&assoc->ip_port.ip) && ip_is_lan(&ip_port->ip)) {
558
0
        return;
559
0
    }
560
561
125k
    assoc->ip_port = *ip_port;
562
125k
    assoc->timestamp = mono_time_get(mono_time);
563
125k
}
564
565
/** @brief Check if client with public_key is already in list of length length.
566
 *
567
 * If it is then set its corresponding timestamp to current time.
568
 * If the id is already in the list with a different ip_port, update it.
569
 * TODO(irungentoo): Maybe optimize this.
570
 */
571
static bool client_or_ip_port_in_list(const Logger *_Nonnull log, const Mono_Time *_Nonnull mono_time, Client_data *_Nonnull list, uint16_t length, const uint8_t *_Nonnull public_key,
572
                                      const IP_Port *_Nonnull ip_port)
573
225k
{
574
225k
    const uint64_t temp_time = mono_time_get(mono_time);
575
225k
    uint32_t index = index_of_client_pk(list, length, public_key);
576
577
    /* if public_key is in list, find it and maybe overwrite ip_port */
578
225k
    if (index != UINT32_MAX) {
579
125k
        update_client(log, mono_time, index, &list[index], ip_port);
580
125k
        return true;
581
125k
    }
582
583
    /* public_key not in list yet: see if we can find an identical ip_port, in
584
     * that case we kill the old public_key by overwriting it with the new one
585
     * TODO(irungentoo): maybe we SHOULDN'T do that if that public_key is in a friend_list
586
     * and the one who is the actual friend's public_key/address set?
587
     * MAYBE: check the other address, if valid, don't nuke? */
588
100k
    index = index_of_client_ip_port(list, length, ip_port);
589
590
100k
    if (index == UINT32_MAX) {
591
100k
        return false;
592
100k
    }
593
594
2
    IPPTsPng *assoc;
595
2
    int ip_version;
596
597
11
    if (net_family_is_ipv4(ip_port->ip.family)) {
598
11
        assoc = &list[index].assoc4;
599
11
        ip_version = 4;
600
18.4E
    } else {
601
18.4E
        assoc = &list[index].assoc6;
602
18.4E
        ip_version = 6;
603
18.4E
    }
604
605
    /* Initialize client timestamp. */
606
2
    assoc->timestamp = temp_time;
607
2
    memcpy(list[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
608
609
2
    LOGGER_DEBUG(log, "coipil[%u]: switching public_key (ipv%d)", index, ip_version);
610
611
    /* kill the other address, if it was set.
612
     * We just updated `assoc` (which is either assoc4 or assoc6) with the new public_key.
613
     * If there was an association for the other IP version, it's now invalid for this new identity.
614
     */
615
11
    if (ip_version == 4) {
616
11
        const IPPTsPng empty_ipptspng = {{{{0}}}};
617
11
        list[index].assoc6 = empty_ipptspng;
618
18.4E
    } else {
619
18.4E
        const IPPTsPng empty_ipptspng = {{{{0}}}};
620
18.4E
        list[index].assoc4 = empty_ipptspng;
621
18.4E
    }
622
623
2
    return true;
624
100k
}
625
626
bool add_to_list(
627
    Node_format *nodes_list, uint32_t length, const uint8_t pk[CRYPTO_PUBLIC_KEY_SIZE],
628
    const IP_Port *ip_port, const uint8_t cmp_pk[CRYPTO_PUBLIC_KEY_SIZE])
629
2.05M
{
630
2.05M
    uint8_t pk_cur[CRYPTO_PUBLIC_KEY_SIZE];
631
2.05M
    memcpy(pk_cur, pk, CRYPTO_PUBLIC_KEY_SIZE);
632
2.05M
    IP_Port ip_port_cur = *ip_port;
633
634
2.05M
    bool inserted = false;
635
636
10.3M
    for (uint32_t i = 0; i < length; ++i) {
637
8.26M
        Node_format *node = &nodes_list[i];
638
639
8.26M
        if (id_closest(cmp_pk, node->public_key, pk_cur) == 2) {
640
1.67M
            uint8_t pk_bak[CRYPTO_PUBLIC_KEY_SIZE];
641
1.67M
            memcpy(pk_bak, node->public_key, CRYPTO_PUBLIC_KEY_SIZE);
642
1.67M
            const IP_Port ip_port_bak = node->ip_port;
643
644
1.67M
            memcpy(node->public_key, pk_cur, CRYPTO_PUBLIC_KEY_SIZE);
645
1.67M
            node->ip_port = ip_port_cur;
646
647
1.67M
            memcpy(pk_cur, pk_bak, CRYPTO_PUBLIC_KEY_SIZE);
648
1.67M
            ip_port_cur = ip_port_bak;
649
1.67M
            inserted = true;
650
1.67M
        }
651
8.26M
    }
652
653
2.05M
    return inserted;
654
2.05M
}
655
656
/**
657
 * helper for `get_close_nodes()`. argument list is a monster :D
658
 */
659
static void get_close_nodes_inner(uint64_t cur_time, const uint8_t *_Nonnull public_key, Node_format *_Nonnull nodes_list, uint32_t *_Nonnull num_nodes_ptr, Family sa_family,
660
                                  const Client_data *_Nonnull client_list, uint32_t client_list_length, bool is_lan, bool want_announce)
661
351k
{
662
351k
    if (!net_family_is_ipv4(sa_family) && !net_family_is_ipv6(sa_family) && !net_family_is_unspec(sa_family)) {
663
0
        return;
664
0
    }
665
666
351k
    uint32_t num_nodes = *num_nodes_ptr;
667
668
112M
    for (uint32_t i = 0; i < client_list_length; ++i) {
669
112M
        const Client_data *const client = &client_list[i];
670
112M
        const IPPTsPng *ipptp;
671
672
112M
        if (net_family_is_ipv4(sa_family)) {
673
0
            ipptp = &client->assoc4;
674
112M
        } else if (net_family_is_ipv6(sa_family)) {
675
0
            ipptp = &client->assoc6;
676
112M
        } else if (client->assoc4.timestamp >= client->assoc6.timestamp) {
677
112M
            ipptp = &client->assoc4;
678
112M
        } else {
679
28.0k
            ipptp = &client->assoc6;
680
28.0k
        }
681
682
        /* node not in a good condition? */
683
112M
        if (assoc_timeout(cur_time, ipptp)) {
684
109M
            continue;
685
109M
        }
686
687
        /* don't send LAN ips to non LAN peers */
688
2.78M
        if (ip_is_lan(&ipptp->ip_port.ip) && !is_lan) {
689
0
            continue;
690
0
        }
691
692
2.78M
#ifdef CHECK_ANNOUNCE_NODE
693
694
2.78M
        if (want_announce && !client->announce_node) {
695
15.0k
            continue;
696
15.0k
        }
697
698
2.76M
#endif /* CHECK_ANNOUNCE_NODE */
699
700
        /* node already in list? */
701
2.76M
        if (index_of_node_pk(nodes_list, num_nodes, client->public_key) != UINT32_MAX) {
702
453k
            continue;
703
453k
        }
704
705
2.31M
        if (num_nodes < MAX_SENT_NODES) {
706
357k
            memcpy(nodes_list[num_nodes].public_key, client->public_key, CRYPTO_PUBLIC_KEY_SIZE);
707
357k
            nodes_list[num_nodes].ip_port = ipptp->ip_port;
708
357k
            ++num_nodes;
709
1.95M
        } else {
710
            // TODO(zugz): this could be made significantly more efficient by
711
            // using a version of add_to_list which works with a sorted list.
712
1.95M
            add_to_list(nodes_list, MAX_SENT_NODES, client->public_key, &ipptp->ip_port, public_key);
713
1.95M
        }
714
2.31M
    }
715
716
351k
    *num_nodes_ptr = num_nodes;
717
351k
}
718
719
/**
720
 * Find MAX_SENT_NODES nodes closest to the public_key for the nodes request:
721
 * put them in the nodes_list and return how many were found.
722
 *
723
 * want_announce: return only nodes which implement the dht announcements protocol.
724
 */
725
static int get_somewhat_close_nodes(uint64_t cur_time, const uint8_t *_Nonnull public_key, Node_format nodes_list[_Nonnull MAX_SENT_NODES], Family sa_family,
726
                                    const Client_data *_Nonnull close_clientlist, const DHT_Friend *_Nonnull friends_list, uint16_t friends_list_size, bool is_lan, bool want_announce)
727
108k
{
728
542k
    for (uint16_t i = 0; i < MAX_SENT_NODES; ++i) {
729
433k
        nodes_list[i] = empty_node_format;
730
433k
    }
731
732
108k
    uint32_t num_nodes = 0;
733
108k
    get_close_nodes_inner(
734
108k
        cur_time, public_key,
735
108k
        nodes_list, &num_nodes,
736
108k
        sa_family, close_clientlist, LCLIENT_LIST,
737
108k
        is_lan, want_announce);
738
739
351k
    for (uint16_t i = 0; i < friends_list_size; ++i) {
740
242k
        const DHT_Friend *dht_friend = &friends_list[i];
741
742
242k
        get_close_nodes_inner(
743
242k
            cur_time, public_key,
744
242k
            nodes_list, &num_nodes,
745
242k
            sa_family, dht_friend->client_list, MAX_FRIEND_CLIENTS,
746
242k
            is_lan, want_announce);
747
242k
    }
748
749
108k
    return num_nodes;
750
108k
}
751
752
int get_close_nodes(
753
    const DHT *dht, const uint8_t *public_key,
754
    Node_format nodes_list[MAX_SENT_NODES], Family sa_family,
755
    bool is_lan, bool want_announce)
756
108k
{
757
108k
    return get_somewhat_close_nodes(
758
108k
               dht->cur_time, public_key, nodes_list,
759
108k
               sa_family, dht->close_clientlist,
760
108k
               dht->friends_list, dht->num_friends,
761
108k
               is_lan, want_announce);
762
108k
}
763
764
#ifdef CHECK_ANNOUNCE_NODE
765
static void set_announce_node_in_list(Client_data *_Nonnull list, uint32_t list_len, const uint8_t *_Nonnull public_key)
766
16.5k
{
767
16.5k
    const uint32_t index = index_of_client_pk(list, list_len, public_key);
768
769
16.5k
    if (index != UINT32_MAX) {
770
11.0k
        list[index].announce_node = true;
771
11.0k
    }
772
16.5k
}
773
774
void set_announce_node(DHT *dht, const uint8_t *public_key)
775
5.51k
{
776
5.51k
    unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
777
778
5.51k
    if (index >= LCLIENT_LENGTH) {
779
2
        index = LCLIENT_LENGTH - 1;
780
2
    }
781
782
5.51k
    set_announce_node_in_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, public_key);
783
784
16.5k
    for (int32_t i = 0; i < dht->num_friends; ++i) {
785
11.0k
        set_announce_node_in_list(dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key);
786
11.0k
    }
787
5.51k
}
788
789
/** @brief Send data search request, searching for a random key. */
790
static bool send_announce_ping(DHT *_Nonnull dht, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port)
791
7.36k
{
792
7.36k
    uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t)];
793
794
7.36k
    uint8_t unused_secret_key[CRYPTO_SECRET_KEY_SIZE];
795
7.36k
    crypto_new_keypair(dht->rng, plain, unused_secret_key);
796
797
7.36k
    const uint64_t ping_id = ping_array_add(dht->dht_ping_array,
798
7.36k
                                            dht->mono_time,
799
7.36k
                                            dht->rng,
800
7.36k
                                            public_key, CRYPTO_PUBLIC_KEY_SIZE);
801
7.36k
    memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, &ping_id, sizeof(ping_id));
802
803
7.36k
    const uint8_t *shared_key = dht_get_shared_key_sent(dht, public_key);
804
805
7.36k
    uint8_t request[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
806
807
7.36k
    if (dht_create_packet(dht->mem, dht->rng,
808
7.36k
                          dht->self_public_key, shared_key, NET_PACKET_DATA_SEARCH_REQUEST,
809
7.36k
                          plain, sizeof(plain), request, sizeof(request)) != sizeof(request)) {
810
8
        return false;
811
8
    }
812
813
7.35k
    return sendpacket(dht->net, ip_port, request, sizeof(request)) == sizeof(request);
814
7.36k
}
815
816
/** @brief If the response is valid, set the sender as an announce node. */
817
static int handle_data_search_response(void *_Nonnull object, const IP_Port *_Nonnull source,
818
                                       const uint8_t *_Nonnull packet, uint16_t length,
819
                                       void *_Nullable userdata)
820
5.51k
{
821
5.51k
    DHT *dht = (DHT *) object;
822
5.51k
    const int32_t plain_len = (int32_t)length - (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
823
824
5.51k
    if (plain_len < (int32_t)(CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))) {
825
0
        return 1;
826
0
    }
827
828
5.51k
    VLA(uint8_t, plain, plain_len);
829
5.51k
    const uint8_t *public_key = packet + 1;
830
5.51k
    const uint8_t *shared_key = dht_get_shared_key_recv(dht, public_key);
831
832
5.51k
    if (decrypt_data_symmetric(dht->mem, shared_key,
833
5.51k
                               packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
834
5.51k
                               packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
835
5.51k
                               plain_len + CRYPTO_MAC_SIZE,
836
5.51k
                               plain) != plain_len) {
837
0
        return 1;
838
0
    }
839
840
5.51k
    uint64_t ping_id;
841
5.51k
    memcpy(&ping_id, plain + (plain_len - sizeof(uint64_t)), sizeof(ping_id));
842
843
5.51k
    uint8_t ping_data[CRYPTO_PUBLIC_KEY_SIZE];
844
845
5.51k
    if (ping_array_check(dht->dht_ping_array,
846
5.51k
                         dht->mono_time, ping_data,
847
5.51k
                         sizeof(ping_data), ping_id) != sizeof(ping_data)) {
848
11
        return 1;
849
11
    }
850
851
5.50k
    if (!pk_equal(ping_data, public_key)) {
852
0
        return 1;
853
0
    }
854
855
5.50k
    set_announce_node(dht, public_key);
856
857
5.50k
    return 0;
858
859
5.50k
}
860
#endif /* CHECK_ANNOUNCE_NODE */
861
862
/** @brief Is it ok to store node with public_key in client.
863
 *
864
 * return false if node can't be stored.
865
 * return true if it can.
866
 */
867
static bool store_node_ok(const Client_data *_Nonnull client, uint64_t cur_time, const uint8_t *_Nonnull public_key, const uint8_t *_Nonnull comp_public_key)
868
1.25M
{
869
1.25M
    return (assoc_timeout(cur_time, &client->assoc4)
870
1.25M
            && assoc_timeout(cur_time, &client->assoc6))
871
1.25M
           || id_closest(comp_public_key, client->public_key, public_key) == 2;
872
1.25M
}
873
874
typedef struct Client_data_Cmp {
875
    const Memory *_Nonnull mem;
876
    uint64_t cur_time;
877
    const uint8_t *_Nonnull comp_public_key;
878
} Client_data_Cmp;
879
880
static int client_data_cmp(const Client_data_Cmp *_Nonnull cmp, const Client_data *_Nonnull entry1, const Client_data *_Nonnull entry2)
881
210k
{
882
210k
    const bool t1 = assoc_timeout(cmp->cur_time, &entry1->assoc4) && assoc_timeout(cmp->cur_time, &entry1->assoc6);
883
210k
    const bool t2 = assoc_timeout(cmp->cur_time, &entry2->assoc4) && assoc_timeout(cmp->cur_time, &entry2->assoc6);
884
885
210k
    if (t1 && t2) {
886
71.5k
        return 0;
887
71.5k
    }
888
889
138k
    if (t1) {
890
27.3k
        return -1;
891
27.3k
    }
892
893
111k
    if (t2) {
894
11.7k
        return 1;
895
11.7k
    }
896
897
99.4k
    const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
898
899
99.4k
    if (closest == 1) {
900
68.7k
        return 1;
901
68.7k
    }
902
903
30.7k
    if (closest == 2) {
904
30.7k
        return -1;
905
30.7k
    }
906
907
18.4E
    return 0;
908
30.7k
}
909
910
static bool client_data_less_handler(const void *_Nonnull object, const void *_Nonnull a, const void *_Nonnull b)
911
210k
{
912
210k
    const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
913
210k
    const Client_data *entry1 = (const Client_data *)a;
914
210k
    const Client_data *entry2 = (const Client_data *)b;
915
916
210k
    return client_data_cmp(cmp, entry1, entry2) < 0;
917
210k
}
918
919
static const void *_Nonnull client_data_get_handler(const void *_Nonnull arr, uint32_t index)
920
432k
{
921
432k
    const Client_data *entries = (const Client_data *)arr;
922
432k
    return &entries[index];
923
432k
}
924
925
static void client_data_set_handler(void *_Nonnull arr, uint32_t index, const void *_Nonnull val)
926
386k
{
927
386k
    Client_data *entries = (Client_data *)arr;
928
386k
    const Client_data *entry = (const Client_data *)val;
929
386k
    entries[index] = *entry;
930
386k
}
931
932
static void *_Nonnull client_data_subarr_handler(void *_Nonnull arr, uint32_t index, uint32_t size)
933
0
{
934
0
    Client_data *entries = (Client_data *)arr;
935
0
    return &entries[index];
936
0
}
937
938
static void *_Nullable client_data_alloc_handler(const void *_Nonnull object, uint32_t size)
939
23.4k
{
940
23.4k
    const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
941
23.4k
    Client_data *tmp = (Client_data *)mem_valloc(cmp->mem, size, sizeof(Client_data));
942
943
23.4k
    if (tmp == nullptr) {
944
4
        return nullptr;
945
4
    }
946
947
23.4k
    return tmp;
948
23.4k
}
949
950
static void client_data_delete_handler(const void *_Nonnull object, void *_Nonnull arr, uint32_t size)
951
23.4k
{
952
23.4k
    const Client_data_Cmp *cmp = (const Client_data_Cmp *)object;
953
23.4k
    mem_delete(cmp->mem, arr);
954
23.4k
}
955
956
static const Sort_Funcs client_data_cmp_funcs = {
957
    client_data_less_handler,
958
    client_data_get_handler,
959
    client_data_set_handler,
960
    client_data_subarr_handler,
961
    client_data_alloc_handler,
962
    client_data_delete_handler,
963
};
964
965
static void sort_client_list(const Memory *_Nonnull mem, Client_data *_Nonnull list, uint64_t cur_time, unsigned int length, const uint8_t *_Nonnull comp_public_key)
966
23.4k
{
967
    // Pass comp_public_key to merge_sort with each Client_data entry, so the
968
    // comparison function can use it as the base of comparison.
969
23.4k
    const Client_data_Cmp cmp = {
970
23.4k
        mem,
971
23.4k
        cur_time,
972
23.4k
        comp_public_key,
973
23.4k
    };
974
975
23.4k
    merge_sort(list, length, &cmp, &client_data_cmp_funcs);
976
23.4k
}
977
978
static void update_client_with_reset(const Mono_Time *_Nonnull mono_time, Client_data *_Nonnull client, const IP_Port *_Nonnull ip_port)
979
21.0k
{
980
21.0k
    IPPTsPng *ipptp_write = nullptr;
981
21.0k
    IPPTsPng *ipptp_clear = nullptr;
982
983
21.0k
    if (net_family_is_ipv4(ip_port->ip.family)) {
984
21.0k
        ipptp_write = &client->assoc4;
985
21.0k
        ipptp_clear = &client->assoc6;
986
21.0k
    } else {
987
1
        ipptp_write = &client->assoc6;
988
1
        ipptp_clear = &client->assoc4;
989
1
    }
990
991
21.0k
    ipptp_write->ip_port = *ip_port;
992
21.0k
    ipptp_write->timestamp = mono_time_get(mono_time);
993
994
21.0k
    ip_reset(&ipptp_write->ret_ip_port.ip);
995
21.0k
    ipptp_write->ret_ip_port.port = 0;
996
21.0k
    ipptp_write->ret_timestamp = 0;
997
21.0k
    ipptp_write->ret_ip_self = false;
998
999
    /* zero out other address */
1000
21.0k
    const IPPTsPng empty_ipptp = {{{{0}}}};
1001
21.0k
    *ipptp_clear = empty_ipptp;
1002
21.0k
}
1003
1004
/**
1005
 * Replace a first bad (or empty) node with this one
1006
 * or replace a possibly bad node (tests failed or not done yet)
1007
 * that is further than any other in the list
1008
 * from the comp_public_key
1009
 * or replace a good node that is further
1010
 * than any other in the list from the comp_public_key
1011
 * and further than public_key.
1012
 *
1013
 * Do not replace any node if the list has no bad or possibly bad nodes
1014
 * and all nodes in the list are closer to comp_public_key
1015
 * than public_key.
1016
 *
1017
 * @return true when the item was stored, false otherwise
1018
 */
1019
static bool replace_all(const DHT *_Nonnull dht, Client_data *_Nonnull list, uint16_t length, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port,
1020
                        const uint8_t *_Nonnull comp_public_key)
1021
81.9k
{
1022
81.9k
    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {
1023
0
        return false;
1024
0
    }
1025
1026
81.9k
    if (!store_node_ok(&list[1], dht->cur_time, public_key, comp_public_key) &&
1027
81.9k
            !store_node_ok(&list[0], dht->cur_time, public_key, comp_public_key)) {
1028
68.2k
        return false;
1029
68.2k
    }
1030
1031
13.6k
    sort_client_list(dht->mem, list, dht->cur_time, length, comp_public_key);
1032
1033
13.6k
    Client_data *const client = &list[0];
1034
13.6k
    pk_copy(client->public_key, public_key);
1035
1036
13.6k
    update_client_with_reset(dht->mono_time, client, ip_port);
1037
13.6k
    return true;
1038
81.9k
}
1039
1040
/** @brief Add node to close list.
1041
 *
1042
 * simulate is set to 1 if we want to check if a node can be added to the list without adding it.
1043
 *
1044
 * return false on failure.
1045
 * return true on success.
1046
 */
1047
static bool add_to_close(DHT *_Nonnull dht, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port, bool simulate)
1048
319k
{
1049
319k
    unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
1050
1051
319k
    if (index >= LCLIENT_LENGTH) {
1052
20.4k
        index = LCLIENT_LENGTH - 1;
1053
20.4k
    }
1054
1055
1.67M
    for (uint32_t i = 0; i < LCLIENT_NODES; ++i) {
1056
        /* TODO(iphydf): write bounds checking test to catch the case that
1057
         * index is left as >= LCLIENT_LENGTH */
1058
1.57M
        Client_data *const client = &dht->close_clientlist[(index * LCLIENT_NODES) + i];
1059
1060
1.57M
        if (!assoc_timeout(dht->cur_time, &client->assoc4) ||
1061
1.57M
                !assoc_timeout(dht->cur_time, &client->assoc6)) {
1062
1.36M
            continue;
1063
1.36M
        }
1064
1065
219k
        if (simulate) {
1066
212k
            return true;
1067
212k
        }
1068
1069
7.06k
        pk_copy(client->public_key, public_key);
1070
7.06k
        update_client_with_reset(dht->mono_time, client, ip_port);
1071
7.06k
#ifdef CHECK_ANNOUNCE_NODE
1072
7.06k
        client->announce_node = false;
1073
7.06k
        send_announce_ping(dht, public_key, ip_port);
1074
7.06k
#endif /* CHECK_ANNOUNCE_NODE */
1075
7.06k
        return true;
1076
219k
    }
1077
1078
99.8k
    return false;
1079
319k
}
1080
1081
/** Return 1 if node can be added to close list, 0 if it can't. */
1082
bool node_addable_to_close_list(DHT *dht, const uint8_t *public_key, const IP_Port *ip_port)
1083
75.2k
{
1084
75.2k
    return add_to_close(dht, public_key, ip_port, true);
1085
75.2k
}
1086
1087
static bool is_pk_in_client_list(const Client_data *_Nonnull list, unsigned int client_list_length, uint64_t cur_time, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port)
1088
776k
{
1089
776k
    const uint32_t index = index_of_client_pk(list, client_list_length, public_key);
1090
1091
776k
    if (index == UINT32_MAX) {
1092
479k
        return false;
1093
479k
    }
1094
1095
296k
    const IPPTsPng *assoc = net_family_is_ipv4(ip_port->ip.family)
1096
296k
                            ? &list[index].assoc4
1097
18.4E
                            : &list[index].assoc6;
1098
1099
296k
    return !assoc_timeout(cur_time, assoc);
1100
776k
}
1101
1102
static bool is_pk_in_close_list(const DHT *_Nonnull dht, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port)
1103
226k
{
1104
226k
    unsigned int index = bit_by_bit_cmp(public_key, dht->self_public_key);
1105
1106
226k
    if (index >= LCLIENT_LENGTH) {
1107
20.4k
        index = LCLIENT_LENGTH - 1;
1108
20.4k
    }
1109
1110
226k
    return is_pk_in_client_list(dht->close_clientlist + index * LCLIENT_NODES, LCLIENT_NODES, dht->cur_time, public_key,
1111
226k
                                ip_port);
1112
226k
}
1113
1114
/** @brief Check if the node obtained from a nodes response with public_key should be pinged.
1115
 *
1116
 * NOTE: for best results call it after addto_lists.
1117
 *
1118
 * return false if the node should not be pinged.
1119
 * return true if it should.
1120
 */
1121
static bool ping_node_from_nodes_response_ok(DHT *_Nonnull dht, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port)
1122
226k
{
1123
226k
    bool ret = false;
1124
1125
226k
    if (add_to_close(dht, public_key, ip_port, true)) {
1126
157k
        ret = true;
1127
157k
    }
1128
1129
226k
    {
1130
226k
        unsigned int *const num = &dht->num_to_bootstrap;
1131
226k
        const uint32_t index = index_of_node_pk(dht->to_bootstrap, *num, public_key);
1132
226k
        const bool in_close_list = is_pk_in_close_list(dht, public_key, ip_port);
1133
1134
226k
        if (ret && index == UINT32_MAX && !in_close_list) {
1135
24.6k
            if (*num < MAX_CLOSE_TO_BOOTSTRAP_NODES) {
1136
8.84k
                memcpy(dht->to_bootstrap[*num].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1137
8.84k
                dht->to_bootstrap[*num].ip_port = *ip_port;
1138
8.84k
                ++*num;
1139
15.7k
            } else {
1140
                // TODO(irungentoo): ipv6 vs v4
1141
15.7k
                add_to_list(dht->to_bootstrap, MAX_CLOSE_TO_BOOTSTRAP_NODES, public_key, ip_port, dht->self_public_key);
1142
15.7k
            }
1143
24.6k
        }
1144
226k
    }
1145
1146
776k
    for (uint32_t i = 0; i < dht->num_friends; ++i) {
1147
550k
        DHT_Friend *dht_friend = &dht->friends_list[i];
1148
1149
550k
        bool store_ok = false;
1150
1151
550k
        if (store_node_ok(&dht_friend->client_list[1], dht->cur_time, public_key, dht_friend->public_key)) {
1152
275k
            store_ok = true;
1153
275k
        }
1154
1155
550k
        if (store_node_ok(&dht_friend->client_list[0], dht->cur_time, public_key, dht_friend->public_key)) {
1156
181k
            store_ok = true;
1157
181k
        }
1158
1159
550k
        unsigned int *const friend_num = &dht_friend->num_to_bootstrap;
1160
550k
        const uint32_t index = index_of_node_pk(dht_friend->to_bootstrap, *friend_num, public_key);
1161
550k
        const bool pk_in_list = is_pk_in_client_list(dht_friend->client_list, MAX_FRIEND_CLIENTS, dht->cur_time, public_key,
1162
550k
                                ip_port);
1163
1164
550k
        if (store_ok && index == UINT32_MAX && !pk_in_list) {
1165
60.2k
            if (*friend_num < MAX_SENT_NODES) {
1166
12.0k
                Node_format *const format = &dht_friend->to_bootstrap[*friend_num];
1167
12.0k
                memcpy(format->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1168
12.0k
                format->ip_port = *ip_port;
1169
12.0k
                ++*friend_num;
1170
48.2k
            } else {
1171
48.2k
                add_to_list(dht_friend->to_bootstrap, MAX_SENT_NODES, public_key, ip_port, dht_friend->public_key);
1172
48.2k
            }
1173
1174
60.2k
            ret = true;
1175
60.2k
        }
1176
550k
    }
1177
1178
226k
    return ret;
1179
226k
}
1180
1181
/** @brief Attempt to add client with ip_port and public_key to the friends client list
1182
 * and close_clientlist.
1183
 *
1184
 * @return 1+ if the item is used in any list, 0 else
1185
 */
1186
uint32_t addto_lists(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)
1187
67.0k
{
1188
67.0k
    const IP_Port ipp_copy = ip_port_normalize(ip_port);
1189
1190
67.0k
    uint32_t used = 0;
1191
1192
    /* NOTE: Current behavior if there are two clients with the same id is
1193
     * to replace the first ip by the second.
1194
     */
1195
67.0k
    const bool in_close_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->close_clientlist, LCLIENT_LIST,
1196
67.0k
                               public_key, &ipp_copy);
1197
1198
    /* add_to_close should be called only if !in_list (don't extract to variable) */
1199
67.0k
    if (in_close_list || !add_to_close(dht, public_key, &ipp_copy, false)) {
1200
59.6k
        ++used;
1201
59.6k
    }
1202
1203
67.0k
    const DHT_Friend *friend_foundip = nullptr;
1204
1205
225k
    for (uint32_t i = 0; i < dht->num_friends; ++i) {
1206
158k
        const bool in_list = client_or_ip_port_in_list(dht->log, dht->mono_time, dht->friends_list[i].client_list,
1207
158k
                             MAX_FRIEND_CLIENTS, public_key, &ipp_copy);
1208
1209
        /* replace_all should be called only if !in_list (don't extract to variable) */
1210
158k
        if (in_list
1211
158k
                || replace_all(dht, dht->friends_list[i].client_list, MAX_FRIEND_CLIENTS, public_key, &ipp_copy,
1212
90.5k
                               dht->friends_list[i].public_key)) {
1213
90.5k
            const DHT_Friend *dht_friend = &dht->friends_list[i];
1214
1215
90.5k
            if (pk_equal(public_key, dht_friend->public_key)) {
1216
2.04k
                friend_foundip = dht_friend;
1217
2.04k
            }
1218
1219
90.5k
            ++used;
1220
90.5k
        }
1221
158k
    }
1222
1223
67.0k
    if (friend_foundip == nullptr) {
1224
64.9k
        return used;
1225
64.9k
    }
1226
1227
67.4k
    for (uint32_t i = 0; i < DHT_FRIEND_MAX_LOCKS; ++i) {
1228
65.4k
        const bool has_lock = (friend_foundip->lock_flags & (UINT32_C(1) << i)) > 0;
1229
65.4k
        if (has_lock && friend_foundip->callbacks[i].ip_callback != nullptr) {
1230
2.04k
            friend_foundip->callbacks[i].ip_callback(friend_foundip->callbacks[i].data,
1231
2.04k
                    friend_foundip->callbacks[i].number, &ipp_copy);
1232
2.04k
        }
1233
65.4k
    }
1234
1235
2.04k
    return used;
1236
67.0k
}
1237
1238
static bool update_client_data(const Mono_Time *_Nonnull mono_time, Client_data *_Nonnull array, size_t size, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull pk, bool node_is_self)
1239
27.8k
{
1240
27.8k
    const uint64_t temp_time = mono_time_get(mono_time);
1241
27.8k
    const uint32_t index = index_of_client_pk(array, size, pk);
1242
1243
27.8k
    if (index == UINT32_MAX) {
1244
1.21k
        return false;
1245
1.21k
    }
1246
1247
26.6k
    Client_data *const data = &array[index];
1248
26.6k
    IPPTsPng *assoc;
1249
1250
26.6k
    if (net_family_is_ipv4(ip_port->ip.family)) {
1251
26.6k
        assoc = &data->assoc4;
1252
18.4E
    } else if (net_family_is_ipv6(ip_port->ip.family)) {
1253
0
        assoc = &data->assoc6;
1254
18.4E
    } else {
1255
18.4E
        return true;
1256
18.4E
    }
1257
1258
26.6k
    assoc->ret_ip_port = *ip_port;
1259
26.6k
    assoc->ret_timestamp = temp_time;
1260
26.6k
    assoc->ret_ip_self = node_is_self;
1261
1262
26.6k
    return true;
1263
26.6k
}
1264
1265
/**
1266
 * If public_key is a friend or us, update ret_ip_port
1267
 * nodepublic_key is the id of the node that sent us this info.
1268
 */
1269
static void returnedip_ports(DHT *_Nonnull dht, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key, const uint8_t *_Nonnull nodepublic_key)
1270
226k
{
1271
226k
    const IP_Port ipp_copy = ip_port_normalize(ip_port);
1272
1273
226k
    if (pk_equal(public_key, dht->self_public_key)) {
1274
20.4k
        update_client_data(dht->mono_time, dht->close_clientlist, LCLIENT_LIST, &ipp_copy, nodepublic_key, true);
1275
20.4k
        return;
1276
20.4k
    }
1277
1278
675k
    for (uint32_t i = 0; i < dht->num_friends; ++i) {
1279
476k
        if (pk_equal(public_key, dht->friends_list[i].public_key)) {
1280
7.44k
            Client_data *const client_list = dht->friends_list[i].client_list;
1281
1282
7.44k
            if (update_client_data(dht->mono_time, client_list, MAX_FRIEND_CLIENTS, &ipp_copy, nodepublic_key, false)) {
1283
7.18k
                return;
1284
7.18k
            }
1285
7.44k
        }
1286
476k
    }
1287
205k
}
1288
1289
bool dht_send_nodes_request(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *client_id)
1290
72.5k
{
1291
    /* Check if packet is going to be sent to ourself. */
1292
72.5k
    if (pk_equal(public_key, dht->self_public_key)) {
1293
7.52k
        return false;
1294
7.52k
    }
1295
1296
64.9k
    uint8_t plain_message[sizeof(Node_format) * 2] = {0};
1297
1298
64.9k
    Node_format receiver;
1299
64.9k
    memcpy(receiver.public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1300
64.9k
    receiver.ip_port = *ip_port;
1301
1302
    /* Avoid warning message when IPv6 is disabled and node address is IPv6. */
1303
64.9k
    if (!net_socket_family_compatible(dht->net, ip_port, false)) {
1304
566
        return false;
1305
566
    }
1306
1307
64.4k
    if (pack_nodes(dht->log, plain_message, sizeof(plain_message), &receiver, 1) == -1) {
1308
2
        return false;
1309
2
    }
1310
1311
64.4k
    uint64_t ping_id = 0;
1312
1313
64.4k
    ping_id = ping_array_add(dht->dht_ping_array, dht->mono_time, dht->rng, plain_message, sizeof(receiver));
1314
1315
64.4k
    if (ping_id == 0) {
1316
2
        LOGGER_ERROR(dht->log, "adding ping id failed");
1317
2
        return false;
1318
2
    }
1319
1320
64.4k
    uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + sizeof(ping_id)];
1321
64.4k
    uint8_t data[1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE];
1322
1323
64.4k
    memcpy(plain, client_id, CRYPTO_PUBLIC_KEY_SIZE);
1324
64.4k
    memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, &ping_id, sizeof(ping_id));
1325
1326
64.4k
    const uint8_t *shared_key = dht_get_shared_key_sent(dht, public_key);
1327
1328
64.4k
    const int len = dht_create_packet(dht->mem, dht->rng,
1329
64.4k
                                      dht->self_public_key, shared_key, NET_PACKET_NODES_REQUEST,
1330
64.4k
                                      plain, sizeof(plain), data, sizeof(data));
1331
1332
64.4k
    if (len != sizeof(data)) {
1333
1
        LOGGER_ERROR(dht->log, "nodes request packet encryption failed");
1334
1
        return false;
1335
1
    }
1336
1337
64.4k
    return sendpacket(dht->net, ip_port, data, len) > 0;
1338
64.4k
}
1339
1340
/** Send a nodes response */
1341
static int send_nodes_response(const DHT *_Nonnull dht, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key, const uint8_t *_Nonnull client_id,
1342
                               const uint8_t *_Nonnull sendback_data, uint16_t length, const uint8_t *_Nonnull shared_encryption_key)
1343
64.2k
{
1344
    /* Check if packet is going to be sent to ourself. */
1345
64.2k
    if (pk_equal(public_key, dht->self_public_key)) {
1346
0
        return -1;
1347
0
    }
1348
1349
64.2k
    if (length != sizeof(uint64_t)) {
1350
0
        return -1;
1351
0
    }
1352
1353
64.2k
    const size_t node_format_size = sizeof(Node_format);
1354
1355
64.2k
    Node_format nodes_list[MAX_SENT_NODES];
1356
64.2k
    const uint32_t num_nodes =
1357
64.2k
        get_close_nodes(dht, client_id, nodes_list, net_family_unspec(), ip_is_lan(&ip_port->ip), false);
1358
1359
64.2k
    VLA(uint8_t, plain, 1 + node_format_size * MAX_SENT_NODES + length);
1360
1361
64.2k
    int nodes_length = 0;
1362
1363
64.2k
    if (num_nodes > 0) {
1364
62.9k
        nodes_length = pack_nodes(dht->log, plain + 1, node_format_size * MAX_SENT_NODES, nodes_list, num_nodes);
1365
1366
62.9k
        if (nodes_length <= 0) {
1367
0
            return -1;
1368
0
        }
1369
62.9k
    }
1370
1371
64.2k
    plain[0] = num_nodes;
1372
64.2k
    memcpy(plain + 1 + nodes_length, sendback_data, length);
1373
1374
64.2k
    const uint16_t crypto_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE;
1375
64.2k
    const uint16_t data_size = 1 + nodes_length + length + crypto_size;
1376
64.2k
    VLA(uint8_t, data, data_size);
1377
1378
64.2k
    const int len = dht_create_packet(dht->mem, dht->rng,
1379
64.2k
                                      dht->self_public_key, shared_encryption_key, NET_PACKET_NODES_RESPONSE,
1380
64.2k
                                      plain, 1 + nodes_length + length, data, data_size);
1381
1382
64.2k
    if (len < 0 || (uint32_t)len != data_size) {
1383
0
        return -1;
1384
0
    }
1385
1386
64.2k
    return sendpacket(dht->net, ip_port, data, len);
1387
64.2k
}
1388
1389
128k
#define CRYPTO_NODE_SIZE (CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint64_t))
1390
1391
static int handle_nodes_request(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, void *_Nonnull userdata)
1392
64.2k
{
1393
64.2k
    DHT *const dht = (DHT *)object;
1394
1395
64.2k
    if (length != (CRYPTO_SIZE + CRYPTO_MAC_SIZE + sizeof(uint64_t))) {
1396
0
        return 1;
1397
0
    }
1398
1399
    /* Check if packet is from ourself. */
1400
64.2k
    if (pk_equal(packet + 1, dht->self_public_key)) {
1401
9
        return 1;
1402
9
    }
1403
1404
64.2k
    uint8_t plain[CRYPTO_NODE_SIZE];
1405
64.2k
    const uint8_t *shared_key = dht_get_shared_key_recv(dht, packet + 1);
1406
64.2k
    const int len = decrypt_data_symmetric(
1407
64.2k
                        dht->mem,
1408
64.2k
                        shared_key,
1409
64.2k
                        packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
1410
64.2k
                        packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1411
64.2k
                        CRYPTO_NODE_SIZE + CRYPTO_MAC_SIZE,
1412
64.2k
                        plain);
1413
1414
64.2k
    if (len != CRYPTO_NODE_SIZE) {
1415
39
        return 1;
1416
39
    }
1417
1418
64.1k
    send_nodes_response(dht, source, packet + 1, plain, plain + CRYPTO_PUBLIC_KEY_SIZE, sizeof(uint64_t), shared_key);
1419
1420
64.1k
    ping_add(dht->ping, packet + 1, source);
1421
1422
64.1k
    return 0;
1423
64.2k
}
1424
1425
/** Return true if we sent a nodes request packet to the peer associated with the supplied info. */
1426
static bool sent_nodes_request_to_node(DHT *_Nonnull dht, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull node_ip_port, uint64_t ping_id)
1427
62.9k
{
1428
62.9k
    uint8_t data[sizeof(Node_format) * 2];
1429
1430
62.9k
    if (ping_array_check(dht->dht_ping_array, dht->mono_time, data, sizeof(data), ping_id) != sizeof(Node_format)) {
1431
914
        return false;
1432
914
    }
1433
1434
62.0k
    Node_format test;
1435
1436
62.0k
    if (unpack_nodes(&test, 1, nullptr, data, sizeof(data), false) != 1) {
1437
0
        return false;
1438
0
    }
1439
1440
62.0k
    return ipport_equal(&test.ip_port, node_ip_port) && pk_equal(test.public_key, public_key);
1441
62.0k
}
1442
1443
static bool handle_nodes_response_core(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, Node_format *_Nonnull plain_nodes,
1444
                                       uint16_t size_plain_nodes, uint32_t *_Nonnull num_nodes_out)
1445
64.2k
{
1446
64.2k
    DHT *const dht = (DHT *)object;
1447
64.2k
    const uint32_t cid_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + 1 + sizeof(uint64_t) + CRYPTO_MAC_SIZE;
1448
1449
64.2k
    if (length < cid_size) { /* too short */
1450
0
        return false;
1451
0
    }
1452
1453
64.2k
    const uint32_t data_size = length - cid_size;
1454
1455
64.2k
    if (data_size == 0) {
1456
1.29k
        return false;
1457
1.29k
    }
1458
1459
62.9k
    if (data_size > sizeof(Node_format) * MAX_SENT_NODES) { /* invalid length */
1460
0
        return false;
1461
0
    }
1462
1463
62.9k
    const uint32_t plain_size = 1 + data_size + sizeof(uint64_t);
1464
62.9k
    VLA(uint8_t, plain, plain_size);
1465
62.9k
    const uint8_t *shared_key = dht_get_shared_key_sent(dht, packet + 1);
1466
62.9k
    const int len = decrypt_data_symmetric(
1467
62.9k
                        dht->mem,
1468
62.9k
                        shared_key,
1469
62.9k
                        packet + 1 + CRYPTO_PUBLIC_KEY_SIZE,
1470
62.9k
                        packet + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1471
62.9k
                        1 + data_size + sizeof(uint64_t) + CRYPTO_MAC_SIZE,
1472
62.9k
                        plain);
1473
1474
62.9k
    if ((uint32_t)len != plain_size) {
1475
0
        return false;
1476
0
    }
1477
1478
62.9k
    if (plain[0] > size_plain_nodes) {
1479
0
        return false;
1480
0
    }
1481
1482
62.9k
    uint64_t ping_id;
1483
62.9k
    memcpy(&ping_id, plain + 1 + data_size, sizeof(ping_id));
1484
1485
62.9k
    if (!sent_nodes_request_to_node(dht, packet + 1, source, ping_id)) {
1486
914
        return false;
1487
914
    }
1488
1489
62.0k
    uint16_t length_nodes = 0;
1490
62.0k
    const int num_nodes = unpack_nodes(plain_nodes, plain[0], &length_nodes, plain + 1, data_size, false);
1491
1492
62.0k
    if (length_nodes != data_size) {
1493
0
        return false;
1494
0
    }
1495
1496
62.0k
    if (num_nodes != plain[0]) {
1497
0
        return false;
1498
0
    }
1499
1500
62.0k
    if (num_nodes < 0) {
1501
0
        return false;
1502
0
    }
1503
1504
    /* store the address the *request* was sent to */
1505
62.0k
    addto_lists(dht, source, packet + 1);
1506
1507
62.0k
    *num_nodes_out = num_nodes;
1508
1509
62.0k
    return true;
1510
62.0k
}
1511
1512
static int handle_nodes_response(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, void *_Nonnull userdata)
1513
64.2k
{
1514
64.2k
    DHT *const dht = (DHT *)object;
1515
64.2k
    Node_format plain_nodes[MAX_SENT_NODES];
1516
64.2k
    uint32_t num_nodes;
1517
1518
64.2k
    if (!handle_nodes_response_core(object, source, packet, length, plain_nodes, MAX_SENT_NODES, &num_nodes)) {
1519
2.20k
        return 1;
1520
2.20k
    }
1521
1522
62.0k
    if (num_nodes == 0) {
1523
0
        return 0;
1524
0
    }
1525
1526
288k
    for (uint32_t i = 0; i < num_nodes; ++i) {
1527
226k
        if (ipport_isset(&plain_nodes[i].ip_port)) {
1528
226k
            ping_node_from_nodes_response_ok(dht, plain_nodes[i].public_key, &plain_nodes[i].ip_port);
1529
226k
            returnedip_ports(dht, &plain_nodes[i].ip_port, plain_nodes[i].public_key, packet + 1);
1530
1531
226k
            if (dht->nodes_response_callback != nullptr) {
1532
192k
                dht->nodes_response_callback(dht, &plain_nodes[i], userdata);
1533
192k
            }
1534
226k
        }
1535
226k
    }
1536
1537
62.0k
    return 0;
1538
62.0k
}
1539
1540
/*----------------------------------------------------------------------------------*/
1541
/*------------------------END of packet handling functions--------------------------*/
1542
1543
static uint32_t dht_friend_lock(DHT_Friend *_Nonnull dht_friend, dht_ip_cb *_Nullable ip_callback,
1544
                                void *_Nullable data, int32_t number)
1545
4.58k
{
1546
    // find first free slot
1547
4.58k
    uint8_t lock_num;
1548
4.58k
    uint32_t lock_token = 0;
1549
4.58k
    for (lock_num = 0; lock_num < DHT_FRIEND_MAX_LOCKS; ++lock_num) {
1550
4.58k
        lock_token = UINT32_C(1) << lock_num;
1551
4.58k
        if ((dht_friend->lock_flags & lock_token) == 0) {
1552
4.58k
            break;
1553
4.58k
        }
1554
4.58k
    }
1555
1556
    // One of the conditions would be enough, but static analyzers don't get that
1557
4.58k
    if (lock_token == 0 || lock_num == DHT_FRIEND_MAX_LOCKS) {
1558
0
        return 0;
1559
0
    }
1560
1561
    // Claim that slot
1562
4.58k
    dht_friend->lock_flags |= lock_token;
1563
1564
4.58k
    dht_friend->callbacks[lock_num].ip_callback = ip_callback;
1565
4.58k
    dht_friend->callbacks[lock_num].data = data;
1566
4.58k
    dht_friend->callbacks[lock_num].number = number;
1567
1568
4.58k
    return lock_token;
1569
4.58k
}
1570
1571
static void dht_friend_unlock(DHT_Friend *_Nonnull dht_friend, uint32_t lock_token)
1572
532
{
1573
    // If this triggers, there was a double free
1574
532
    assert((lock_token & dht_friend->lock_flags) > 0);
1575
1576
    // find used slot
1577
532
    uint8_t lock_num;
1578
532
    for (lock_num = 0; lock_num < DHT_FRIEND_MAX_LOCKS; ++lock_num) {
1579
532
        if (((UINT32_C(1) << lock_num) & lock_token) > 0) {
1580
532
            break;
1581
532
        }
1582
532
    }
1583
1584
532
    if (lock_num == DHT_FRIEND_MAX_LOCKS) {
1585
        // Gracefully handle double unlock
1586
0
        return;
1587
0
    }
1588
1589
    // Clear the slot
1590
532
    dht_friend->lock_flags &= ~lock_token;
1591
1592
532
    dht_friend->callbacks[lock_num].ip_callback = nullptr;
1593
532
    dht_friend->callbacks[lock_num].data = nullptr;
1594
532
    dht_friend->callbacks[lock_num].number = 0;
1595
532
}
1596
1597
int dht_addfriend(DHT *dht, const uint8_t *public_key, dht_ip_cb *ip_callback,
1598
                  void *data, int32_t number, uint32_t *lock_token)
1599
4.59k
{
1600
4.59k
    const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1601
1602
4.59k
    if (friend_num != UINT32_MAX) { /* Is friend already in DHT? */
1603
0
        DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1604
0
        const uint32_t tmp_lock_token = dht_friend_lock(dht_friend, ip_callback, data, number);
1605
1606
0
        if (tmp_lock_token == 0) {
1607
0
            return -1;
1608
0
        }
1609
1610
0
        return 0;
1611
0
    }
1612
1613
4.59k
    DHT_Friend *const temp = (DHT_Friend *)mem_vrealloc(dht->mem, dht->friends_list, dht->num_friends + 1, sizeof(DHT_Friend));
1614
1615
4.59k
    if (temp == nullptr) {
1616
8
        return -1;
1617
8
    }
1618
1619
4.58k
    dht->friends_list = temp;
1620
4.58k
    DHT_Friend *const dht_friend = &dht->friends_list[dht->num_friends];
1621
4.58k
    *dht_friend = empty_dht_friend;
1622
4.58k
    memcpy(dht_friend->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1623
1624
4.58k
    dht_friend->nat.nat_ping_id = random_u64(dht->rng);
1625
4.58k
    ++dht->num_friends;
1626
1627
4.58k
    *lock_token = dht_friend_lock(dht_friend, ip_callback, data, number);
1628
4.58k
    assert(*lock_token != 0); // Friend was newly allocated
1629
1630
4.58k
    dht_friend->num_to_bootstrap = get_close_nodes(dht, dht_friend->public_key, dht_friend->to_bootstrap, net_family_unspec(),
1631
4.58k
                                   true, false);
1632
1633
4.58k
    return 0;
1634
4.58k
}
1635
1636
int dht_delfriend(DHT *dht, const uint8_t *public_key, uint32_t lock_token)
1637
532
{
1638
532
    const uint32_t friend_num = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1639
1640
532
    if (friend_num == UINT32_MAX) {
1641
0
        return -1;
1642
0
    }
1643
1644
532
    DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1645
532
    dht_friend_unlock(dht_friend, lock_token);
1646
532
    if (dht_friend->lock_flags > 0) {
1647
        /* DHT friend is still in use.*/
1648
0
        return 0;
1649
0
    }
1650
1651
532
    --dht->num_friends;
1652
1653
532
    if (dht->num_friends != friend_num) {
1654
140
        dht->friends_list[friend_num] = dht->friends_list[dht->num_friends];
1655
140
    }
1656
1657
532
    if (dht->num_friends == 0) {
1658
0
        mem_delete(dht->mem, dht->friends_list);
1659
0
        dht->friends_list = nullptr;
1660
0
        return 0;
1661
0
    }
1662
1663
532
    DHT_Friend *const temp = (DHT_Friend *)mem_vrealloc(dht->mem, dht->friends_list, dht->num_friends, sizeof(DHT_Friend));
1664
1665
532
    if (temp == nullptr) {
1666
0
        return -1;
1667
0
    }
1668
1669
532
    dht->friends_list = temp;
1670
532
    return 0;
1671
532
}
1672
1673
/* TODO(irungentoo): Optimize this. */
1674
int dht_getfriendip(const DHT *dht, const uint8_t *public_key, IP_Port *ip_port)
1675
21.6k
{
1676
21.6k
    ip_reset(&ip_port->ip);
1677
21.6k
    ip_port->port = 0;
1678
1679
21.6k
    const uint32_t friend_index = index_of_friend_pk(dht->friends_list, dht->num_friends, public_key);
1680
1681
21.6k
    if (friend_index == UINT32_MAX) {
1682
21.6k
        return -1;
1683
21.6k
    }
1684
1685
7
    const DHT_Friend *const frnd = &dht->friends_list[friend_index];
1686
7
    const uint32_t client_index = index_of_client_pk(frnd->client_list, MAX_FRIEND_CLIENTS, public_key);
1687
1688
7
    if (client_index == UINT32_MAX) {
1689
1
        return 0;
1690
1
    }
1691
1692
6
    const Client_data *const client = &frnd->client_list[client_index];
1693
6
    const IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4, nullptr };
1694
1695
7
    for (const IPPTsPng * const *it = assocs; *it != nullptr; ++it) {
1696
2
        const IPPTsPng *const assoc = *it;
1697
1698
2
        if (!assoc_timeout(dht->cur_time, assoc)) {
1699
1
            *ip_port = assoc->ip_port;
1700
1
            return 1;
1701
1
        }
1702
2
    }
1703
1704
5
    return -1;
1705
6
}
1706
1707
/** returns number of nodes not in kill-timeout */
1708
static uint8_t do_ping_and_sendnode_requests(DHT *_Nonnull dht, uint64_t *_Nonnull lastgetnode, const uint8_t *_Nonnull public_key, Client_data *_Nonnull list, uint32_t list_count,
1709
        uint32_t *_Nonnull bootstrap_times, bool sortable)
1710
22.3k
{
1711
22.3k
    uint8_t not_kill = 0;
1712
22.3k
    const uint64_t temp_time = mono_time_get(dht->mono_time);
1713
1714
22.3k
    uint32_t num_nodes = 0;
1715
22.3k
    Client_data **client_list = (Client_data **)mem_valloc(dht->mem, list_count * 2, sizeof(Client_data *));
1716
22.3k
    IPPTsPng **assoc_list = (IPPTsPng **)mem_valloc(dht->mem, list_count * 2, sizeof(IPPTsPng *));
1717
22.3k
    unsigned int sort = 0;
1718
22.3k
    bool sort_ok = false;
1719
1720
22.3k
    if (client_list == nullptr || assoc_list == nullptr) {
1721
0
        mem_delete(dht->mem, assoc_list);
1722
0
        mem_delete(dht->mem, client_list);
1723
0
        return 0;
1724
0
    }
1725
1726
6.86M
    for (uint32_t i = 0; i < list_count; ++i) {
1727
        /* If node is not dead. */
1728
6.84M
        Client_data *client = &list[i];
1729
1730
6.84M
        IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4 };
1731
1732
20.5M
        for (uint32_t j = 0; j < sizeof(assocs) / sizeof(assocs[0]); ++j) {
1733
13.6M
            IPPTsPng *const assoc = assocs[j];
1734
1735
13.6M
            if (!mono_time_is_timeout(dht->mono_time, assoc->timestamp, KILL_NODE_TIMEOUT)) {
1736
145k
                sort = 0;
1737
145k
                ++not_kill;
1738
1739
145k
                if (mono_time_is_timeout(dht->mono_time, assoc->last_pinged, PING_INTERVAL)) {
1740
13.7k
                    const IP_Port *target = &assoc->ip_port;
1741
13.7k
                    const uint8_t *target_key = client->public_key;
1742
13.7k
                    dht_send_nodes_request(dht, target, target_key, public_key);
1743
13.7k
                    assoc->last_pinged = temp_time;
1744
13.7k
                }
1745
1746
                /* If node is good. */
1747
145k
                if (!assoc_timeout(dht->cur_time, assoc)) {
1748
145k
                    client_list[num_nodes] = client;
1749
145k
                    assoc_list[num_nodes] = assoc;
1750
145k
                    ++num_nodes;
1751
145k
                }
1752
13.5M
            } else {
1753
13.5M
                ++sort;
1754
1755
                /* Timed out should be at beginning, if they are not, sort the list. */
1756
13.5M
                if (sort > 1 && sort < (((j + 1) * 2) - 1)) {
1757
28.6k
                    sort_ok = true;
1758
28.6k
                }
1759
13.5M
            }
1760
13.6M
        }
1761
6.84M
    }
1762
1763
22.3k
    if (sortable && sort_ok) {
1764
9.76k
        sort_client_list(dht->mem, list, dht->cur_time, list_count, public_key);
1765
9.76k
    }
1766
1767
22.3k
    if (num_nodes > 0 && (mono_time_is_timeout(dht->mono_time, *lastgetnode, NODES_REQUEST_INTERVAL)
1768
20.5k
                          || *bootstrap_times < MAX_BOOTSTRAP_TIMES)) {
1769
7.07k
        uint32_t rand_node = random_range_u32(dht->rng, num_nodes);
1770
1771
7.07k
        if ((num_nodes - 1) != rand_node) {
1772
4.11k
            rand_node += random_range_u32(dht->rng, num_nodes - (rand_node + 1));
1773
4.11k
        }
1774
1775
7.07k
        const IP_Port *target = &assoc_list[rand_node]->ip_port;
1776
7.07k
        const uint8_t *target_key = client_list[rand_node]->public_key;
1777
7.07k
        dht_send_nodes_request(dht, target, target_key, public_key);
1778
1779
7.07k
        *lastgetnode = temp_time;
1780
7.07k
        ++*bootstrap_times;
1781
7.07k
    }
1782
1783
22.3k
    mem_delete(dht->mem, assoc_list);
1784
22.3k
    mem_delete(dht->mem, client_list);
1785
22.3k
    return not_kill;
1786
22.3k
}
1787
1788
/** @brief Ping each client in the "friends" list every PING_INTERVAL seconds.
1789
 *
1790
 * Send a nodes request  every NODES_REQUEST_INTERVAL seconds to a random good
1791
 * node for each "friend" in our "friends" list.
1792
 */
1793
static void do_dht_friends(DHT *_Nonnull dht)
1794
6.56k
{
1795
22.3k
    for (size_t i = 0; i < dht->num_friends; ++i) {
1796
15.7k
        DHT_Friend *const dht_friend = &dht->friends_list[i];
1797
1798
28.2k
        for (size_t j = 0; j < dht_friend->num_to_bootstrap; ++j) {
1799
12.4k
            dht_send_nodes_request(dht, &dht_friend->to_bootstrap[j].ip_port, dht_friend->to_bootstrap[j].public_key, dht_friend->public_key);
1800
12.4k
        }
1801
1802
15.7k
        dht_friend->num_to_bootstrap = 0;
1803
1804
15.7k
        do_ping_and_sendnode_requests(dht, &dht_friend->last_nodes_request, dht_friend->public_key, dht_friend->client_list,
1805
15.7k
                                      MAX_FRIEND_CLIENTS, &dht_friend->bootstrap_times, true);
1806
15.7k
    }
1807
6.56k
}
1808
1809
/** @brief Ping each client in the close nodes list every PING_INTERVAL seconds.
1810
 *
1811
 * Send a nodes request every NODES_REQUEST_INTERVAL seconds to a random good node in the list.
1812
 */
1813
static void do_close(DHT *_Nonnull dht)
1814
6.56k
{
1815
15.2k
    for (size_t i = 0; i < dht->num_to_bootstrap; ++i) {
1816
8.71k
        dht_send_nodes_request(dht, &dht->to_bootstrap[i].ip_port, dht->to_bootstrap[i].public_key, dht->self_public_key);
1817
8.71k
    }
1818
1819
6.56k
    dht->num_to_bootstrap = 0;
1820
1821
6.56k
    const uint8_t not_killed = do_ping_and_sendnode_requests(
1822
6.56k
                                   dht, &dht->close_last_nodes_request, dht->self_public_key, dht->close_clientlist, LCLIENT_LIST, &dht->close_bootstrap_times,
1823
6.56k
                                   false);
1824
1825
6.56k
    if (not_killed != 0) {
1826
6.02k
        return;
1827
6.02k
    }
1828
1829
    /* all existing nodes are at least KILL_NODE_TIMEOUT,
1830
     * which means we are mute, as we only send packets to
1831
     * nodes NOT in KILL_NODE_TIMEOUT
1832
     *
1833
     * so: reset all nodes to be BAD_NODE_TIMEOUT, but not
1834
     * KILL_NODE_TIMEOUT, so we at least keep trying pings */
1835
535
    const uint64_t badonly = mono_time_get(dht->mono_time) - BAD_NODE_TIMEOUT;
1836
1837
547k
    for (size_t i = 0; i < LCLIENT_LIST; ++i) {
1838
547k
        Client_data *const client = &dht->close_clientlist[i];
1839
1840
547k
        if (client->assoc4.timestamp != 0) {
1841
0
            client->assoc4.timestamp = badonly;
1842
0
        }
1843
547k
        if (client->assoc6.timestamp != 0) {
1844
0
            client->assoc6.timestamp = badonly;
1845
0
        }
1846
547k
    }
1847
535
}
1848
1849
bool dht_bootstrap(DHT *dht, const IP_Port *ip_port, const uint8_t *public_key)
1850
1.55k
{
1851
1.55k
    if (pk_equal(public_key, dht->self_public_key)) {
1852
        // Bootstrapping off ourselves is ok (onion paths are still set up).
1853
18
        return true;
1854
18
    }
1855
1856
1.53k
    return dht_send_nodes_request(dht, ip_port, public_key, dht->self_public_key);
1857
1.55k
}
1858
1859
bool dht_bootstrap_from_address(DHT *dht, const char *address, bool ipv6enabled, bool dns_enabled,
1860
                                uint16_t port, const uint8_t *public_key)
1861
0
{
1862
0
    IP_Port ip_port_v64;
1863
0
    IP *ip_extra = nullptr;
1864
0
    IP_Port ip_port_v4;
1865
0
    ip_init(&ip_port_v64.ip, ipv6enabled);
1866
1867
0
    if (ipv6enabled) {
1868
        /* setup for getting BOTH: an IPv6 AND an IPv4 address */
1869
0
        ip_port_v64.ip.family = net_family_unspec();
1870
0
        ip_reset(&ip_port_v4.ip);
1871
0
        ip_extra = &ip_port_v4.ip;
1872
0
    }
1873
1874
0
    if (addr_resolve_or_parse_ip(dht->ns, dht->mem, address, &ip_port_v64.ip, ip_extra, dns_enabled)) {
1875
0
        ip_port_v64.port = port;
1876
0
        dht_bootstrap(dht, &ip_port_v64, public_key);
1877
1878
0
        if ((ip_extra != nullptr) && ip_isset(ip_extra)) {
1879
0
            ip_port_v4.port = port;
1880
0
            dht_bootstrap(dht, &ip_port_v4, public_key);
1881
0
        }
1882
1883
0
        return true;
1884
0
    }
1885
1886
0
    return false;
1887
0
}
1888
1889
int route_packet(const DHT *dht, const uint8_t *public_key, const uint8_t *packet, uint16_t length)
1890
1.15k
{
1891
41.6k
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
1892
41.6k
        if (pk_equal(public_key, dht->close_clientlist[i].public_key)) {
1893
1.15k
            const Client_data *const client = &dht->close_clientlist[i];
1894
1.15k
            const IPPTsPng *const assocs[] = { &client->assoc6, &client->assoc4, nullptr };
1895
1896
2.30k
            for (const IPPTsPng * const *it = assocs; *it != nullptr; ++it) {
1897
2.30k
                const IPPTsPng *const assoc = *it;
1898
1899
2.30k
                if (ip_isset(&assoc->ip_port.ip)) {
1900
1.15k
                    return sendpacket(dht->net, &assoc->ip_port, packet, length);
1901
1.15k
                }
1902
2.30k
            }
1903
1904
0
            break;
1905
1.15k
        }
1906
41.6k
    }
1907
1908
0
    return -1;
1909
1.15k
}
1910
1911
/** @brief Puts all the different ips returned by the nodes for a friend_num into array ip_portlist.
1912
 *
1913
 * @param ip_portlist must be at least MAX_FRIEND_CLIENTS big.
1914
 *
1915
 * @return the number of ips returned.
1916
 * @retval 0 if we are connected to friend or if no ips were found.
1917
 * @retval -1 if no such friend.
1918
 */
1919
static int friend_iplist(const DHT *_Nonnull dht, IP_Port *_Nonnull ip_portlist, uint16_t friend_num)
1920
19.4k
{
1921
19.4k
    if (friend_num >= dht->num_friends) {
1922
0
        return -1;
1923
0
    }
1924
1925
19.4k
    const DHT_Friend *const dht_friend = &dht->friends_list[friend_num];
1926
19.4k
    IP_Port ipv4s[MAX_FRIEND_CLIENTS];
1927
19.4k
    int num_ipv4s = 0;
1928
19.4k
    IP_Port ipv6s[MAX_FRIEND_CLIENTS];
1929
19.4k
    int num_ipv6s = 0;
1930
1931
172k
    for (size_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
1932
155k
        const Client_data *const client = &dht_friend->client_list[i];
1933
1934
        /* If ip is not zero and node is good. */
1935
155k
        if (ip_isset(&client->assoc4.ret_ip_port.ip)
1936
155k
                && !mono_time_is_timeout(dht->mono_time, client->assoc4.ret_timestamp, BAD_NODE_TIMEOUT)) {
1937
7.72k
            ipv4s[num_ipv4s] = client->assoc4.ret_ip_port;
1938
7.72k
            ++num_ipv4s;
1939
7.72k
        }
1940
1941
155k
        if (ip_isset(&client->assoc6.ret_ip_port.ip)
1942
155k
                && !mono_time_is_timeout(dht->mono_time, client->assoc6.ret_timestamp, BAD_NODE_TIMEOUT)) {
1943
0
            ipv6s[num_ipv6s] = client->assoc6.ret_ip_port;
1944
0
            ++num_ipv6s;
1945
0
        }
1946
1947
155k
        if (pk_equal(client->public_key, dht_friend->public_key)) {
1948
2.32k
            if (!assoc_timeout(dht->cur_time, &client->assoc6)
1949
2.32k
                    || !assoc_timeout(dht->cur_time, &client->assoc4)) {
1950
2.32k
                return 0; /* direct connectivity */
1951
2.32k
            }
1952
2.32k
        }
1953
155k
    }
1954
1955
#ifdef FRIEND_IPLIST_PAD
1956
    memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1957
1958
    if (num_ipv6s == MAX_FRIEND_CLIENTS) {
1959
        return MAX_FRIEND_CLIENTS;
1960
    }
1961
1962
    int num_ipv4s_used = MAX_FRIEND_CLIENTS - num_ipv6s;
1963
1964
    if (num_ipv4s_used > num_ipv4s) {
1965
        num_ipv4s_used = num_ipv4s;
1966
    }
1967
1968
    memcpy(&ip_portlist[num_ipv6s], ipv4s, num_ipv4s_used * sizeof(IP_Port));
1969
    return num_ipv6s + num_ipv4s_used;
1970
1971
#else /* !FRIEND_IPLIST_PAD */
1972
1973
    /* there must be some secret reason why we can't pad the longer list
1974
     * with the shorter one...
1975
     */
1976
17.0k
    if (num_ipv6s >= num_ipv4s) {
1977
16.5k
        memcpy(ip_portlist, ipv6s, num_ipv6s * sizeof(IP_Port));
1978
16.5k
        return num_ipv6s;
1979
16.5k
    }
1980
1981
500
    memcpy(ip_portlist, ipv4s, num_ipv4s * sizeof(IP_Port));
1982
500
    return num_ipv4s;
1983
1984
17.0k
#endif /* !FRIEND_IPLIST_PAD */
1985
17.0k
}
1986
1987
/**
1988
 * Callback invoked for each IP/port of each client of a friend.
1989
 *
1990
 * For each client, the callback is invoked twice: once for IPv4 and once for
1991
 * IPv6. If the callback returns `false` after the IPv4 invocation, it will not
1992
 * be invoked for IPv6.
1993
 *
1994
 * @param dht The main DHT instance.
1995
 * @param ip_port The currently processed IP/port.
1996
 * @param n A pointer to the number that will be returned from `foreach_ip_port`.
1997
 * @param userdata The `userdata` pointer passed to `foreach_ip_port`.
1998
 */
1999
typedef bool foreach_ip_port_cb(const DHT *_Nonnull dht, const IP_Port *_Nonnull ip_port, uint32_t *_Nonnull n, void *_Nonnull userdata);
2000
2001
/**
2002
 * Runs a callback on every active connection for a given DHT friend.
2003
 *
2004
 * This iterates over the client list of a DHT friend and invokes a callback for
2005
 * every non-zero IP/port (IPv4 and IPv6) that's not timed out.
2006
 *
2007
 * @param dht The main DHT instance, passed to the callback.
2008
 * @param dht_friend The friend over whose connections we should iterate.
2009
 * @param callback The callback to invoke for each IP/port.
2010
 * @param userdata Extra pointer passed to the callback.
2011
 */
2012
static uint32_t foreach_ip_port(const DHT *_Nonnull dht, const DHT_Friend *_Nonnull dht_friend, foreach_ip_port_cb *_Nonnull callback, void *_Nonnull userdata)
2013
588
{
2014
588
    uint32_t n = 0;
2015
2016
    /* extra legwork, because having the outside allocating the space for us
2017
     * is *usually* good(tm) (bites us in the behind in this case though) */
2018
5.29k
    for (uint32_t i = 0; i < MAX_FRIEND_CLIENTS; ++i) {
2019
4.70k
        const Client_data *const client = &dht_friend->client_list[i];
2020
4.70k
        const IPPTsPng *const assocs[] = { &client->assoc4, &client->assoc6, nullptr };
2021
2022
12.4k
        for (const IPPTsPng * const *it = assocs; *it != nullptr; ++it) {
2023
8.58k
            const IPPTsPng *const assoc = *it;
2024
2025
            /* If ip is not zero and node is good. */
2026
8.58k
            if (!ip_isset(&assoc->ret_ip_port.ip)
2027
8.58k
                    || mono_time_is_timeout(dht->mono_time, assoc->ret_timestamp, BAD_NODE_TIMEOUT)) {
2028
6.58k
                continue;
2029
6.58k
            }
2030
2031
2.00k
            if (!callback(dht, &assoc->ip_port, &n, userdata)) {
2032
                /* If the callback is happy with just one of the assocs, we
2033
                 * don't give it the second one. */
2034
820
                break;
2035
820
            }
2036
2.00k
        }
2037
4.70k
    }
2038
2039
588
    return n;
2040
588
}
2041
2042
static bool send_packet_to_friend(const DHT *_Nonnull dht, const IP_Port *_Nonnull ip_port, uint32_t *_Nonnull n, void *_Nonnull userdata)
2043
820
{
2044
820
    const Net_Packet *packet = (const Net_Packet *)userdata;
2045
820
    const int retval = net_send_packet(dht->net, ip_port, *packet);
2046
2047
821
    if ((uint32_t)retval == packet->length) {
2048
821
        ++*n;
2049
        /* Send one packet per friend: stop the foreach on the first success. */
2050
821
        return false;
2051
821
    }
2052
2053
18.4E
    return true;
2054
820
}
2055
2056
/**
2057
 * Send the following packet to everyone who tells us they are connected to friend_id.
2058
 * Only works if more than (MAX_FRIEND_CLIENTS / 4) return an ip for friend.
2059
 *
2060
 * @return number of nodes the packet was sent to.
2061
 */
2062
uint32_t route_to_friend(const DHT *dht, const uint8_t *friend_id, const Net_Packet *packet)
2063
3.62k
{
2064
3.62k
    const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
2065
2066
3.62k
    if (num == UINT32_MAX) {
2067
0
        return 0;
2068
0
    }
2069
2070
3.62k
    IP_Port ip_list[MAX_FRIEND_CLIENTS];
2071
3.62k
    const int ip_num = friend_iplist(dht, ip_list, num);
2072
2073
3.62k
    if (ip_num < MAX_FRIEND_CLIENTS / 4) {
2074
3.41k
        return 0; /* Reason for that? */
2075
3.41k
    }
2076
2077
208
    const DHT_Friend *const dht_friend = &dht->friends_list[num];
2078
208
    Net_Packet packet_userdata = *packet;  // Copy because it needs to be non-const.
2079
2080
208
    return foreach_ip_port(dht, dht_friend, send_packet_to_friend, &packet_userdata);
2081
3.62k
}
2082
2083
static bool get_ip_port(const DHT *_Nonnull dht, const IP_Port *_Nonnull ip_port, uint32_t *_Nonnull n, void *_Nonnull userdata)
2084
1.18k
{
2085
1.18k
    IP_Port *ip_list = (IP_Port *)userdata;
2086
1.18k
    ip_list[*n] = *ip_port;
2087
1.18k
    ++*n;
2088
1.18k
    return true;
2089
1.18k
}
2090
2091
/** @brief Send the following packet to one random person who tells us they are connected to friend_id.
2092
 *
2093
 * @return number of nodes the packet was sent to.
2094
 */
2095
static uint32_t routeone_to_friend(const DHT *_Nonnull dht, const uint8_t *_Nonnull friend_id, const Net_Packet *_Nonnull packet)
2096
380
{
2097
380
    const uint32_t num = index_of_friend_pk(dht->friends_list, dht->num_friends, friend_id);
2098
2099
380
    if (num == UINT32_MAX) {
2100
0
        return 0;
2101
0
    }
2102
2103
380
    const DHT_Friend *const dht_friend = &dht->friends_list[num];
2104
2105
380
    IP_Port ip_list[MAX_FRIEND_CLIENTS * 2];
2106
2107
380
    const int n = foreach_ip_port(dht, dht_friend, get_ip_port, ip_list);
2108
2109
380
    if (n < 1) {
2110
95
        return 0;
2111
95
    }
2112
2113
285
    const uint32_t rand_idx = random_range_u32(dht->rng, n);
2114
285
    const int retval = net_send_packet(dht->net, &ip_list[rand_idx], *packet);
2115
2116
285
    if ((unsigned int)retval == packet->length) {
2117
285
        return 1;
2118
285
    }
2119
2120
0
    return 0;
2121
285
}
2122
2123
/*----------------------------------------------------------------------------------*/
2124
/*---------------------BEGINNING OF NAT PUNCHING FUNCTIONS--------------------------*/
2125
2126
static int send_nat_ping(const DHT *_Nonnull dht, const uint8_t *_Nonnull public_key, uint64_t ping_id, uint8_t type)
2127
498
{
2128
498
    uint8_t data[sizeof(uint64_t) + 1];
2129
498
    uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];
2130
2131
498
    data[0] = type;
2132
498
    memcpy(data + 1, &ping_id, sizeof(uint64_t));
2133
    /* 254 is NAT ping request packet id */
2134
498
    const int len = create_request(
2135
498
                        dht->mem, dht->rng, dht->self_public_key, dht->self_secret_key, packet_data, public_key,
2136
498
                        data, sizeof(uint64_t) + 1, CRYPTO_PACKET_NAT_PING);
2137
2138
498
    if (len == -1) {
2139
0
        return -1;
2140
0
    }
2141
2142
498
    assert(len <= UINT16_MAX);
2143
498
    uint32_t num = 0;
2144
498
    const Net_Packet packet = {packet_data, (uint16_t)len};
2145
2146
498
    if (type == 0) { /* If packet is request use many people to route it. */
2147
118
        num = route_to_friend(dht, public_key, &packet);
2148
380
    } else if (type == 1) { /* If packet is response use only one person to route it */
2149
380
        num = routeone_to_friend(dht, public_key, &packet);
2150
380
    }
2151
2152
498
    if (num == 0) {
2153
95
        return -1;
2154
95
    }
2155
2156
403
    return num;
2157
498
}
2158
2159
/** Handle a received ping request for. */
2160
static int handle_nat_ping(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull source_pubkey, const uint8_t *_Nonnull packet, uint16_t length,
2161
                           void *_Nonnull userdata)
2162
752
{
2163
752
    DHT *const dht = (DHT *)object;
2164
2165
752
    if (length != sizeof(uint64_t) + 1) {
2166
0
        return 1;
2167
0
    }
2168
2169
752
    uint64_t ping_id;
2170
752
    memcpy(&ping_id, packet + 1, sizeof(uint64_t));
2171
2172
752
    const uint32_t friendnumber = index_of_friend_pk(dht->friends_list, dht->num_friends, source_pubkey);
2173
2174
752
    if (friendnumber == UINT32_MAX) {
2175
87
        return 1;
2176
87
    }
2177
2178
665
    DHT_Friend *const dht_friend = &dht->friends_list[friendnumber];
2179
2180
665
    if (packet[0] == NAT_PING_REQUEST) {
2181
        /* 1 is reply */
2182
380
        send_nat_ping(dht, source_pubkey, ping_id, NAT_PING_RESPONSE);
2183
380
        dht_friend->nat.recv_nat_ping_timestamp = mono_time_get(dht->mono_time);
2184
380
        return 0;
2185
380
    }
2186
2187
285
    if (packet[0] == NAT_PING_RESPONSE) {
2188
285
        if (dht_friend->nat.nat_ping_id == ping_id) {
2189
86
            dht_friend->nat.nat_ping_id = random_u64(dht->rng);
2190
86
            dht_friend->nat.hole_punching = true;
2191
86
            return 0;
2192
86
        }
2193
285
    }
2194
2195
199
    return 1;
2196
285
}
2197
2198
/** @brief Get the most common ip in the ip_portlist.
2199
 * Only return ip if it appears in list min_num or more.
2200
 * len must not be bigger than MAX_FRIEND_CLIENTS.
2201
 *
2202
 * @return ip of 0 if failure.
2203
 */
2204
static IP nat_commonip(const IP_Port *_Nonnull ip_portlist, uint16_t len, uint16_t min_num)
2205
0
{
2206
0
    IP zero;
2207
0
    ip_reset(&zero);
2208
2209
0
    if (len > MAX_FRIEND_CLIENTS) {
2210
0
        return zero;
2211
0
    }
2212
2213
0
    uint16_t numbers[MAX_FRIEND_CLIENTS] = {0};
2214
2215
0
    for (uint32_t i = 0; i < len; ++i) {
2216
0
        for (uint32_t j = 0; j < len; ++j) {
2217
0
            if (ip_equal(&ip_portlist[i].ip, &ip_portlist[j].ip)) {
2218
0
                ++numbers[i];
2219
0
            }
2220
0
        }
2221
2222
0
        if (numbers[i] >= min_num) {
2223
0
            return ip_portlist[i].ip;
2224
0
        }
2225
0
    }
2226
2227
0
    return zero;
2228
0
}
2229
2230
/** @brief Return all the ports for one ip in a list.
2231
 * portlist must be at least len long,
2232
 * where len is the length of ip_portlist.
2233
 *
2234
 * @return number of ports and puts the list of ports in portlist.
2235
 */
2236
static uint16_t nat_getports(uint16_t *_Nonnull portlist, const IP_Port *_Nonnull ip_portlist, uint16_t len, const IP *_Nonnull ip)
2237
0
{
2238
0
    uint16_t num = 0;
2239
2240
0
    for (uint32_t i = 0; i < len; ++i) {
2241
0
        if (ip_equal(&ip_portlist[i].ip, ip)) {
2242
0
            portlist[num] = net_ntohs(ip_portlist[i].port);
2243
0
            ++num;
2244
0
        }
2245
0
    }
2246
2247
0
    return num;
2248
0
}
2249
2250
static void punch_holes(DHT *_Nonnull dht, const IP *_Nonnull ip, const uint16_t *_Nonnull port_list, uint16_t numports, uint16_t friend_num)
2251
0
{
2252
0
    if (!dht->hole_punching_enabled) {
2253
0
        return;
2254
0
    }
2255
2256
0
    if (numports > MAX_FRIEND_CLIENTS || numports == 0) {
2257
0
        return;
2258
0
    }
2259
2260
0
    const uint16_t first_port = port_list[0];
2261
0
    uint16_t port_candidate;
2262
2263
0
    for (port_candidate = 0; port_candidate < numports; ++port_candidate) {
2264
0
        if (first_port != port_list[port_candidate]) {
2265
0
            break;
2266
0
        }
2267
0
    }
2268
2269
0
    if (port_candidate == numports) { /* If all ports are the same, only try that one port. */
2270
0
        IP_Port pinging;
2271
0
        ip_copy(&pinging.ip, ip);
2272
0
        pinging.port = net_htons(first_port);
2273
0
        ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);
2274
0
    } else {
2275
0
        uint16_t i;
2276
0
        for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
2277
            /* TODO(irungentoo): Improve port guessing algorithm. */
2278
0
            const uint32_t it = i + dht->friends_list[friend_num].nat.punching_index;
2279
0
            const int8_t sign = (it % 2 != 0) ? -1 : 1;
2280
0
            const uint32_t delta = sign * (it / (2 * numports));
2281
0
            const uint32_t index = (it / 2) % numports;
2282
0
            const uint16_t port = port_list[index] + delta;
2283
0
            IP_Port pinging;
2284
0
            ip_copy(&pinging.ip, ip);
2285
0
            pinging.port = net_htons(port);
2286
0
            ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);
2287
0
        }
2288
2289
0
        dht->friends_list[friend_num].nat.punching_index += i;
2290
0
    }
2291
2292
0
    if (dht->friends_list[friend_num].nat.tries > MAX_NORMAL_PUNCHING_TRIES) {
2293
0
        IP_Port pinging;
2294
0
        ip_copy(&pinging.ip, ip);
2295
2296
0
        uint16_t i;
2297
0
        for (i = 0; i < MAX_PUNCHING_PORTS; ++i) {
2298
0
            const uint32_t it = i + dht->friends_list[friend_num].nat.punching_index2;
2299
0
            const uint16_t port = 1024;
2300
0
            pinging.port = net_htons(port + it);
2301
0
            ping_send_request(dht->ping, &pinging, dht->friends_list[friend_num].public_key);
2302
0
        }
2303
2304
0
        dht->friends_list[friend_num].nat.punching_index2 += i - (MAX_PUNCHING_PORTS / 2);
2305
0
    }
2306
2307
0
    ++dht->friends_list[friend_num].nat.tries;
2308
0
}
2309
2310
static void do_nat(DHT *_Nonnull dht)
2311
6.56k
{
2312
6.56k
    const uint64_t temp_time = mono_time_get(dht->mono_time);
2313
2314
22.3k
    for (uint32_t i = 0; i < dht->num_friends; ++i) {
2315
15.7k
        IP_Port ip_list[MAX_FRIEND_CLIENTS];
2316
15.7k
        const int num = friend_iplist(dht, ip_list, i);
2317
2318
        /* If already connected or friend is not online don't try to hole punch. */
2319
15.7k
        if (num < MAX_FRIEND_CLIENTS / 2) {
2320
15.6k
            continue;
2321
15.6k
        }
2322
2323
118
        if (dht->friends_list[i].nat.nat_ping_timestamp + PUNCH_INTERVAL < temp_time) {
2324
118
            send_nat_ping(dht, dht->friends_list[i].public_key, dht->friends_list[i].nat.nat_ping_id, NAT_PING_REQUEST);
2325
118
            dht->friends_list[i].nat.nat_ping_timestamp = temp_time;
2326
118
        }
2327
2328
118
        if (dht->friends_list[i].nat.hole_punching &&
2329
118
                dht->friends_list[i].nat.punching_timestamp + PUNCH_INTERVAL < temp_time &&
2330
118
                dht->friends_list[i].nat.recv_nat_ping_timestamp + PUNCH_INTERVAL * 2 >= temp_time) {
2331
2332
0
            const IP ip = nat_commonip(ip_list, num, MAX_FRIEND_CLIENTS / 2);
2333
2334
0
            if (!ip_isset(&ip)) {
2335
0
                continue;
2336
0
            }
2337
2338
0
            if (dht->friends_list[i].nat.punching_timestamp + PUNCH_RESET_TIME < temp_time) {
2339
0
                dht->friends_list[i].nat.tries = 0;
2340
0
                dht->friends_list[i].nat.punching_index = 0;
2341
0
                dht->friends_list[i].nat.punching_index2 = 0;
2342
0
            }
2343
2344
0
            uint16_t port_list[MAX_FRIEND_CLIENTS];
2345
0
            const uint16_t numports = nat_getports(port_list, ip_list, num, &ip);
2346
0
            punch_holes(dht, &ip, port_list, numports, i);
2347
2348
0
            dht->friends_list[i].nat.punching_timestamp = temp_time;
2349
0
            dht->friends_list[i].nat.hole_punching = false;
2350
0
        }
2351
118
    }
2352
6.56k
}
2353
2354
/*----------------------------------------------------------------------------------*/
2355
/*-----------------------END OF NAT PUNCHING FUNCTIONS------------------------------*/
2356
2357
/** @brief Put up to max_num nodes in nodes from the closelist.
2358
 *
2359
 * @return the number of nodes.
2360
 */
2361
static uint16_t list_nodes(const Random *_Nonnull rng, const Client_data *_Nonnull list, size_t length, uint64_t cur_time, Node_format *_Nonnull nodes, uint16_t max_num)
2362
18.6k
{
2363
18.6k
    if (max_num == 0) {
2364
0
        return 0;
2365
0
    }
2366
2367
18.6k
    uint16_t count = 0;
2368
2369
6.71M
    for (size_t i = length; i != 0; --i) {
2370
6.70M
        const IPPTsPng *assoc = nullptr;
2371
2372
6.70M
        if (!assoc_timeout(cur_time, &list[i - 1].assoc4)) {
2373
44.2k
            assoc = &list[i - 1].assoc4;
2374
44.2k
        }
2375
2376
6.70M
        if (!assoc_timeout(cur_time, &list[i - 1].assoc6)) {
2377
0
            if (assoc == nullptr || (random_u08(rng) % 2) != 0) {
2378
0
                assoc = &list[i - 1].assoc6;
2379
0
            }
2380
0
        }
2381
2382
6.70M
        if (assoc != nullptr) {
2383
44.2k
            memcpy(nodes[count].public_key, list[i - 1].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2384
44.2k
            nodes[count].ip_port = assoc->ip_port;
2385
44.2k
            ++count;
2386
2387
44.2k
            if (count >= max_num) {
2388
5.77k
                return count;
2389
5.77k
            }
2390
44.2k
        }
2391
6.70M
    }
2392
2393
12.8k
    return count;
2394
18.6k
}
2395
2396
/** @brief Put up to max_num nodes in nodes from the random friends.
2397
 *
2398
 * Important: this function relies on the first two DHT friends *not* being real
2399
 * friends to avoid leaking information about real friends into the onion paths.
2400
 *
2401
 * @return the number of nodes.
2402
 */
2403
uint16_t randfriends_nodes(const DHT *dht, Node_format *nodes, uint16_t max_num)
2404
7.48k
{
2405
7.48k
    if (max_num == 0) {
2406
0
        return 0;
2407
0
    }
2408
2409
7.48k
    uint16_t count = 0;
2410
7.48k
    const uint32_t r = random_u32(dht->rng);
2411
2412
7.48k
    assert(DHT_FAKE_FRIEND_NUMBER <= dht->num_friends);
2413
2414
    // Only gather nodes from the initial 2 fake friends.
2415
15.7k
    for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2416
12.1k
        count += list_nodes(dht->rng, dht->friends_list[(i + r) % DHT_FAKE_FRIEND_NUMBER].client_list,
2417
12.1k
                            MAX_FRIEND_CLIENTS, dht->cur_time,
2418
12.1k
                            nodes + count, max_num - count);
2419
2420
12.1k
        if (count >= max_num) {
2421
3.85k
            break;
2422
3.85k
        }
2423
12.1k
    }
2424
2425
7.48k
    return count;
2426
7.48k
}
2427
2428
/** @brief Put up to max_num nodes in nodes from the closelist.
2429
 *
2430
 * @return the number of nodes.
2431
 */
2432
uint16_t closelist_nodes(const DHT *dht, Node_format *nodes, uint16_t max_num)
2433
6.49k
{
2434
6.49k
    return list_nodes(dht->rng, dht->close_clientlist, LCLIENT_LIST, dht->cur_time, nodes, max_num);
2435
6.49k
}
2436
2437
/*----------------------------------------------------------------------------------*/
2438
2439
void cryptopacket_registerhandler(DHT *dht, uint8_t byte, cryptopacket_handler_cb *cb, void *object)
2440
7.94k
{
2441
7.94k
    dht->cryptopackethandlers[byte].function = cb;
2442
7.94k
    dht->cryptopackethandlers[byte].object = object;
2443
7.94k
}
2444
2445
static int cryptopacket_handle(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, void *_Nonnull userdata)
2446
2.19k
{
2447
2.19k
    DHT *const dht = (DHT *)object;
2448
2449
2.19k
    assert(packet[0] == NET_PACKET_CRYPTO);
2450
2451
2.19k
    if (length <= CRYPTO_PUBLIC_KEY_SIZE * 2 + CRYPTO_NONCE_SIZE + 1 + CRYPTO_MAC_SIZE ||
2452
2.19k
            length > MAX_CRYPTO_REQUEST_SIZE + CRYPTO_MAC_SIZE) {
2453
0
        return 1;
2454
0
    }
2455
2456
    // Check if request is for us.
2457
2.19k
    if (pk_equal(packet + 1, dht->self_public_key)) {
2458
1.09k
        uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
2459
1.09k
        uint8_t data[MAX_CRYPTO_REQUEST_SIZE];
2460
1.09k
        uint8_t number;
2461
1.09k
        const int len = handle_request(dht->mem, dht->self_public_key, dht->self_secret_key, public_key,
2462
1.09k
                                       data, &number, packet, length);
2463
2464
1.09k
        if (len == -1 || len == 0) {
2465
0
            return 1;
2466
0
        }
2467
2468
1.09k
        if (dht->cryptopackethandlers[number].function == nullptr) {
2469
0
            return 1;
2470
0
        }
2471
2472
1.09k
        return dht->cryptopackethandlers[number].function(
2473
1.09k
                   dht->cryptopackethandlers[number].object, source, public_key,
2474
1.09k
                   data, len, userdata);
2475
1.09k
    }
2476
2477
    /* If request is not for us, try routing it. */
2478
1.10k
    const int retval = route_packet(dht, packet + 1, packet, length);
2479
2480
1.10k
    if ((unsigned int)retval == length) {
2481
1.10k
        return 0;
2482
1.10k
    }
2483
2484
18.4E
    return 1;
2485
1.10k
}
2486
2487
void dht_callback_nodes_response(DHT *dht, dht_nodes_response_cb *function)
2488
1.40k
{
2489
1.40k
    dht->nodes_response_callback = function;
2490
1.40k
}
2491
2492
static int handle_lan_discovery(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length,
2493
                                void *_Nullable userdata)
2494
297
{
2495
297
    DHT *dht = (DHT *)object;
2496
297
    if (!dht->lan_discovery_enabled) {
2497
267
        return 1;
2498
267
    }
2499
2500
30
    if (!ip_is_lan(&source->ip)) {
2501
0
        return 1;
2502
0
    }
2503
2504
30
    if (length != CRYPTO_PUBLIC_KEY_SIZE + 1) {
2505
0
        return 1;
2506
0
    }
2507
2508
30
    dht_bootstrap(dht, source, packet + 1);
2509
30
    return 0;
2510
30
}
2511
2512
/*----------------------------------------------------------------------------------*/
2513
2514
DHT *new_dht(const Logger *log, const Memory *mem, const Random *rng, const Network *ns,
2515
             Mono_Time *mono_time, Networking_Core *net,
2516
             bool hole_punching_enabled, bool lan_discovery_enabled)
2517
2.07k
{
2518
2.07k
    if (net == nullptr) {
2519
0
        return nullptr;
2520
0
    }
2521
2522
2.07k
    DHT *const dht = (DHT *)mem_alloc(mem, sizeof(DHT));
2523
2524
2.07k
    if (dht == nullptr) {
2525
5
        LOGGER_ERROR(log, "failed to allocate DHT struct (%lu bytes)", (unsigned long)sizeof(DHT));
2526
5
        return nullptr;
2527
5
    }
2528
2529
2.06k
    dht->ns = ns;
2530
2.06k
    dht->mono_time = mono_time;
2531
2.06k
    dht->cur_time = mono_time_get(mono_time);
2532
2.06k
    dht->log = log;
2533
2.06k
    dht->net = net;
2534
2.06k
    dht->rng = rng;
2535
2.06k
    dht->mem = mem;
2536
2537
2.06k
    dht->hole_punching_enabled = hole_punching_enabled;
2538
2.06k
    dht->lan_discovery_enabled = lan_discovery_enabled;
2539
2540
2.06k
    struct Ping *temp_ping = ping_new(mem, mono_time, rng, dht, net);
2541
2542
2.06k
    if (temp_ping == nullptr) {
2543
12
        LOGGER_ERROR(log, "failed to initialise ping");
2544
12
        kill_dht(dht);
2545
12
        return nullptr;
2546
12
    }
2547
2548
2.05k
    dht->ping = temp_ping;
2549
2550
2.05k
    networking_registerhandler(dht->net, NET_PACKET_NODES_REQUEST, &handle_nodes_request, dht);
2551
2.05k
    networking_registerhandler(dht->net, NET_PACKET_NODES_RESPONSE, &handle_nodes_response, dht);
2552
2.05k
    networking_registerhandler(dht->net, NET_PACKET_CRYPTO, &cryptopacket_handle, dht);
2553
2.05k
    networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, &handle_lan_discovery, dht);
2554
2.05k
    cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, &handle_nat_ping, dht);
2555
2556
2.05k
#ifdef CHECK_ANNOUNCE_NODE
2557
2.05k
    networking_registerhandler(dht->net, NET_PACKET_DATA_SEARCH_RESPONSE, &handle_data_search_response, dht);
2558
2.05k
#endif /* CHECK_ANNOUNCE_NODE */
2559
2560
2.05k
    crypto_new_keypair(rng, dht->self_public_key, dht->self_secret_key);
2561
2562
2.05k
    Shared_Key_Cache *const temp_shared_keys_recv = shared_key_cache_new(log, mono_time, mem, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
2563
2564
2.05k
    if (temp_shared_keys_recv == nullptr) {
2565
8
        LOGGER_ERROR(log, "failed to initialise shared key cache");
2566
8
        kill_dht(dht);
2567
8
        return nullptr;
2568
8
    }
2569
2570
2.04k
    dht->shared_keys_recv = temp_shared_keys_recv;
2571
2572
2.04k
    Shared_Key_Cache *const temp_shared_keys_sent = shared_key_cache_new(log, mono_time, mem, dht->self_secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
2573
2574
2.04k
    if (temp_shared_keys_sent == nullptr) {
2575
8
        LOGGER_ERROR(log, "failed to initialise shared key cache");
2576
8
        kill_dht(dht);
2577
8
        return nullptr;
2578
8
    }
2579
2580
2.03k
    dht->shared_keys_sent = temp_shared_keys_sent;
2581
2582
2.03k
    Ping_Array *const temp_ping_array = ping_array_new(mem, DHT_PING_ARRAY_SIZE, PING_TIMEOUT);
2583
2584
2.03k
    if (temp_ping_array == nullptr) {
2585
6
        LOGGER_ERROR(log, "failed to initialise ping array");
2586
6
        kill_dht(dht);
2587
6
        return nullptr;
2588
6
    }
2589
2590
2.03k
    dht->dht_ping_array = temp_ping_array;
2591
2592
6.08k
    for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER; ++i) {
2593
4.05k
        uint8_t random_public_key_bytes[CRYPTO_PUBLIC_KEY_SIZE];
2594
4.05k
        uint8_t random_secret_key_bytes[CRYPTO_SECRET_KEY_SIZE];
2595
2596
4.05k
        crypto_new_keypair(rng, random_public_key_bytes, random_secret_key_bytes);
2597
2598
4.05k
        uint32_t token; // We don't intend to delete these ever, but need to pass the token
2599
4.05k
        if (dht_addfriend(dht, random_public_key_bytes, nullptr, nullptr, 0, &token) != 0) {
2600
8
            LOGGER_ERROR(log, "failed to add initial random seed DHT friends");
2601
8
            kill_dht(dht);
2602
8
            return nullptr;
2603
8
        }
2604
4.05k
    }
2605
2606
2.02k
    if (dht->num_friends != DHT_FAKE_FRIEND_NUMBER) {
2607
0
        LOGGER_ERROR(log, "the RNG provided seems to be broken: it generated the same keypair twice");
2608
0
        kill_dht(dht);
2609
0
        return nullptr;
2610
0
    }
2611
2612
2.02k
    return dht;
2613
2.02k
}
2614
2615
void do_dht(DHT *dht)
2616
100k
{
2617
100k
    const uint64_t cur_time = mono_time_get(dht->mono_time);
2618
2619
100k
    if (dht->cur_time == cur_time) {
2620
94.2k
        return;
2621
94.2k
    }
2622
2623
6.55k
    dht->cur_time = cur_time;
2624
2625
    // Load friends/clients if first call to do_dht
2626
6.55k
    if (dht->loaded_num_nodes > 0) {
2627
84
        dht_connect_after_load(dht);
2628
84
    }
2629
2630
6.55k
    do_close(dht);
2631
6.55k
    do_dht_friends(dht);
2632
6.55k
    do_nat(dht);
2633
6.55k
    ping_iterate(dht->ping);
2634
6.55k
}
2635
2636
void kill_dht(DHT *dht)
2637
2.04k
{
2638
2.04k
    if (dht == nullptr) {
2639
0
        return;
2640
0
    }
2641
2642
2.04k
    networking_registerhandler(dht->net, NET_PACKET_NODES_REQUEST, nullptr, nullptr);
2643
2.04k
    networking_registerhandler(dht->net, NET_PACKET_NODES_RESPONSE, nullptr, nullptr);
2644
2.04k
    networking_registerhandler(dht->net, NET_PACKET_CRYPTO, nullptr, nullptr);
2645
2.04k
    networking_registerhandler(dht->net, NET_PACKET_LAN_DISCOVERY, nullptr, nullptr);
2646
2.04k
    cryptopacket_registerhandler(dht, CRYPTO_PACKET_NAT_PING, nullptr, nullptr);
2647
2648
2.04k
    shared_key_cache_free(dht->shared_keys_recv);
2649
2.04k
    shared_key_cache_free(dht->shared_keys_sent);
2650
2.04k
    ping_array_kill(dht->dht_ping_array);
2651
2.04k
    ping_kill(dht->mem, dht->ping);
2652
2.04k
    mem_delete(dht->mem, dht->friends_list);
2653
2.04k
    mem_delete(dht->mem, dht->loaded_nodes_list);
2654
2.04k
    crypto_memzero(dht->self_secret_key, sizeof(dht->self_secret_key));
2655
2.04k
    mem_delete(dht->mem, dht);
2656
2.04k
}
2657
2658
/* new DHT format for load/save, more robust and forward compatible */
2659
// TODO(irungentoo): Move this closer to Messenger.
2660
1.64k
#define DHT_STATE_COOKIE_GLOBAL 0x159000d
2661
2662
2.61k
#define DHT_STATE_COOKIE_TYPE      0x11ce
2663
1.53k
#define DHT_STATE_TYPE_NODES       4
2664
2665
2.05k
#define MAX_SAVED_DHT_NODES (((DHT_FAKE_FRIEND_NUMBER * MAX_FRIEND_CLIENTS) + LCLIENT_LIST) * 2)
2666
2667
/** Get the size of the DHT (for saving). */
2668
uint32_t dht_size(const DHT *dht)
2669
2.98k
{
2670
2.98k
    uint32_t numv4 = 0;
2671
2.98k
    uint32_t numv6 = 0;
2672
2673
13.6k
    for (uint32_t i = 0; i < dht->loaded_num_nodes; ++i) {
2674
10.6k
        numv4 += net_family_is_ipv4(dht->loaded_nodes_list[i].ip_port.ip.family) ? 1 : 0;
2675
10.6k
        numv6 += net_family_is_ipv6(dht->loaded_nodes_list[i].ip_port.ip.family) ? 1 : 0;
2676
10.6k
    }
2677
2678
3.05M
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2679
3.05M
        numv4 += dht->close_clientlist[i].assoc4.timestamp != 0 ? 1 : 0;
2680
3.05M
        numv6 += dht->close_clientlist[i].assoc6.timestamp != 0 ? 1 : 0;
2681
3.05M
    }
2682
2683
8.94k
    for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2684
5.96k
        const DHT_Friend *const fr = &dht->friends_list[i];
2685
2686
53.6k
        for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2687
47.7k
            numv4 += fr->client_list[j].assoc4.timestamp != 0 ? 1 : 0;
2688
47.7k
            numv6 += fr->client_list[j].assoc6.timestamp != 0 ? 1 : 0;
2689
47.7k
        }
2690
5.96k
    }
2691
2692
2.98k
    const uint32_t size32 = sizeof(uint32_t);
2693
2.98k
    const uint32_t sizesubhead = size32 * 2;
2694
2695
2.98k
    return size32 + sizesubhead + packed_node_size(net_family_ipv4()) * numv4 + packed_node_size(net_family_ipv6()) * numv6;
2696
2.98k
}
2697
2698
/** Save the DHT in data where data is an array of size `dht_size()`. */
2699
void dht_save(const DHT *dht, uint8_t *data)
2700
994
{
2701
994
    host_to_lendian_bytes32(data, DHT_STATE_COOKIE_GLOBAL);
2702
994
    data += sizeof(uint32_t);
2703
2704
994
    uint8_t *const old_data = data;
2705
2706
    /* get right offset. we write the actual header later. */
2707
994
    data = state_write_section_header(data, DHT_STATE_COOKIE_TYPE, 0, 0);
2708
2709
994
    Node_format *clients = (Node_format *)mem_valloc(dht->mem, MAX_SAVED_DHT_NODES, sizeof(Node_format));
2710
2711
994
    if (clients == nullptr) {
2712
0
        LOGGER_ERROR(dht->log, "could not allocate %u nodes", (unsigned int)MAX_SAVED_DHT_NODES);
2713
0
        return;
2714
0
    }
2715
2716
994
    uint32_t num = 0;
2717
2718
994
    if (dht->loaded_num_nodes > 0) {
2719
164
        memcpy(clients, dht->loaded_nodes_list, sizeof(Node_format) * dht->loaded_num_nodes);
2720
164
        num += dht->loaded_num_nodes;
2721
164
    }
2722
2723
1.01M
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2724
1.01M
        if (dht->close_clientlist[i].assoc4.timestamp != 0) {
2725
7
            memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2726
7
            clients[num].ip_port = dht->close_clientlist[i].assoc4.ip_port;
2727
7
            ++num;
2728
7
        }
2729
2730
1.01M
        if (dht->close_clientlist[i].assoc6.timestamp != 0) {
2731
0
            memcpy(clients[num].public_key, dht->close_clientlist[i].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2732
0
            clients[num].ip_port = dht->close_clientlist[i].assoc6.ip_port;
2733
0
            ++num;
2734
0
        }
2735
1.01M
    }
2736
2737
2.98k
    for (uint32_t i = 0; i < DHT_FAKE_FRIEND_NUMBER && i < dht->num_friends; ++i) {
2738
1.98k
        const DHT_Friend *const fr = &dht->friends_list[i];
2739
2740
17.8k
        for (uint32_t j = 0; j < MAX_FRIEND_CLIENTS; ++j) {
2741
15.9k
            if (fr->client_list[j].assoc4.timestamp != 0) {
2742
14
                memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2743
14
                clients[num].ip_port = fr->client_list[j].assoc4.ip_port;
2744
14
                ++num;
2745
14
            }
2746
2747
15.9k
            if (fr->client_list[j].assoc6.timestamp != 0) {
2748
0
                memcpy(clients[num].public_key, fr->client_list[j].public_key, CRYPTO_PUBLIC_KEY_SIZE);
2749
0
                clients[num].ip_port = fr->client_list[j].assoc6.ip_port;
2750
0
                ++num;
2751
0
            }
2752
15.9k
        }
2753
1.98k
    }
2754
2755
994
    state_write_section_header(
2756
994
        old_data, DHT_STATE_COOKIE_TYPE, pack_nodes(dht->log, data, sizeof(Node_format) * num, clients, num),
2757
994
        DHT_STATE_TYPE_NODES);
2758
2759
994
    mem_delete(dht->mem, clients);
2760
994
}
2761
2762
/** Bootstrap from this number of nodes every time `dht_connect_after_load()` is called */
2763
402
#define SAVE_BOOTSTAP_FREQUENCY 8
2764
2765
int dht_connect_after_load(DHT *dht)
2766
84
{
2767
84
    if (dht == nullptr) {
2768
0
        return -1;
2769
0
    }
2770
2771
84
    if (dht->loaded_nodes_list == nullptr) {
2772
0
        return -1;
2773
0
    }
2774
2775
    /* DHT is connected, stop. */
2776
84
    if (dht_non_lan_connected(dht)) {
2777
0
        mem_delete(dht->mem, dht->loaded_nodes_list);
2778
0
        dht->loaded_nodes_list = nullptr;
2779
0
        dht->loaded_num_nodes = 0;
2780
0
        return 0;
2781
0
    }
2782
2783
486
    for (uint32_t i = 0; i < dht->loaded_num_nodes && i < SAVE_BOOTSTAP_FREQUENCY; ++i) {
2784
402
        const unsigned int index = dht->loaded_nodes_index % dht->loaded_num_nodes;
2785
402
        dht_bootstrap(dht, &dht->loaded_nodes_list[index].ip_port, dht->loaded_nodes_list[index].public_key);
2786
402
        ++dht->loaded_nodes_index;
2787
402
    }
2788
2789
84
    return 0;
2790
84
}
2791
2792
static State_Load_Status dht_load_state_callback(void *_Nonnull outer, const uint8_t *_Nonnull data, uint32_t length, uint16_t type)
2793
610
{
2794
610
    DHT *dht = (DHT *)outer;
2795
2796
610
    switch (type) {
2797
544
        case DHT_STATE_TYPE_NODES: {
2798
544
            if (length == 0) {
2799
14
                break;
2800
14
            }
2801
2802
            // TODO(Green-Sky): This allocates 130KiB, might be worth reducing or retrying with smaller, partial allocations.
2803
530
            Node_format *nodes = (Node_format *)mem_valloc(dht->mem, MAX_SAVED_DHT_NODES, sizeof(Node_format));
2804
2805
530
            if (nodes == nullptr) {
2806
0
                LOGGER_ERROR(dht->log, "could not allocate %u nodes", (unsigned int)MAX_SAVED_DHT_NODES);
2807
0
                break;
2808
0
            }
2809
2810
530
            const int num = unpack_nodes(nodes, MAX_SAVED_DHT_NODES, nullptr, data, length, false);
2811
2812
530
            if (num <= 0) {
2813
                // Unpack error happened or list was empty, we ignore it.
2814
36
                mem_delete(dht->mem, nodes);
2815
494
            } else {
2816
494
                mem_delete(dht->mem, dht->loaded_nodes_list);
2817
494
                dht->loaded_num_nodes = num;
2818
494
                dht->loaded_nodes_list = nodes;
2819
494
            }
2820
2821
530
            break;
2822
530
        }
2823
2824
66
        default: {
2825
66
            LOGGER_ERROR(dht->log, "Load state (DHT): contains unrecognized part (len %u, type %u)",
2826
66
                         length, type);
2827
66
            break;
2828
530
        }
2829
610
    }
2830
2831
610
    return STATE_LOAD_STATUS_CONTINUE;
2832
610
}
2833
2834
int dht_load(DHT *dht, const uint8_t *data, uint32_t length)
2835
712
{
2836
712
    const uint32_t cookie_len = sizeof(uint32_t);
2837
2838
712
    if (length > cookie_len) {
2839
646
        uint32_t data32;
2840
646
        lendian_bytes_to_host32(&data32, data);
2841
2842
646
        if (data32 == DHT_STATE_COOKIE_GLOBAL) {
2843
627
            return state_load(dht->log, dht_load_state_callback, dht, data + cookie_len,
2844
627
                              length - cookie_len, DHT_STATE_COOKIE_TYPE);
2845
627
        }
2846
646
    }
2847
2848
85
    return -1;
2849
712
}
2850
2851
/**
2852
 * @retval false if we are not connected to the DHT.
2853
 * @retval true if we are.
2854
 */
2855
bool dht_isconnected(const DHT *dht)
2856
7.81k
{
2857
1.29M
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2858
1.29M
        const Client_data *const client = &dht->close_clientlist[i];
2859
2860
1.29M
        if (!assoc_timeout(dht->cur_time, &client->assoc4) ||
2861
1.29M
                !assoc_timeout(dht->cur_time, &client->assoc6)) {
2862
6.57k
            return true;
2863
6.57k
        }
2864
1.29M
    }
2865
2866
1.24k
    return false;
2867
7.81k
}
2868
2869
/**
2870
 * @retval false if we are not connected or only connected to lan peers with the DHT.
2871
 * @retval true if we are.
2872
 */
2873
bool dht_non_lan_connected(const DHT *dht)
2874
8.44k
{
2875
7.56M
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2876
7.55M
        const Client_data *const client = &dht->close_clientlist[i];
2877
2878
7.55M
        if (!assoc_timeout(dht->cur_time, &client->assoc4)
2879
7.55M
                && !ip_is_lan(&client->assoc4.ip_port.ip)) {
2880
1.05k
            return true;
2881
1.05k
        }
2882
2883
7.55M
        if (!assoc_timeout(dht->cur_time, &client->assoc6)
2884
7.55M
                && !ip_is_lan(&client->assoc6.ip_port.ip)) {
2885
0
            return true;
2886
0
        }
2887
7.55M
    }
2888
2889
7.38k
    return false;
2890
8.44k
}
2891
2892
uint16_t dht_get_num_closelist(const DHT *dht)
2893
0
{
2894
0
    uint16_t num_valid_close_clients = 0;
2895
0
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2896
0
        const Client_data *const client = dht_get_close_client(dht, i);
2897
2898
        // check if client is valid
2899
0
        if (!(assoc_timeout(dht->cur_time, &client->assoc4) && assoc_timeout(dht->cur_time, &client->assoc6))) {
2900
0
            ++num_valid_close_clients;
2901
0
        }
2902
0
    }
2903
2904
0
    return num_valid_close_clients;
2905
0
}
2906
2907
uint16_t dht_get_num_closelist_announce_capable(const DHT *dht)
2908
0
{
2909
0
    uint16_t num_valid_close_clients_with_cap = 0;
2910
0
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2911
0
        const Client_data *const client = dht_get_close_client(dht, i);
2912
2913
        // check if client is valid
2914
0
        if (!(assoc_timeout(dht->cur_time, &client->assoc4) && assoc_timeout(dht->cur_time, &client->assoc6)) && client->announce_node) {
2915
0
            ++num_valid_close_clients_with_cap;
2916
0
        }
2917
0
    }
2918
2919
0
    return num_valid_close_clients_with_cap;
2920
0
}
2921
2922
unsigned int ipport_self_copy(const DHT *dht, IP_Port *dest)
2923
135
{
2924
135
    ipport_reset(dest);
2925
2926
135
    bool is_lan = false;
2927
2928
138k
    for (uint32_t i = 0; i < LCLIENT_LIST; ++i) {
2929
138k
        const Client_data *client = dht_get_close_client(dht, i);
2930
138k
        const IP_Port *ip_port4 = &client->assoc4.ret_ip_port;
2931
2932
138k
        if (client->assoc4.ret_ip_self && ipport_isset(ip_port4)) {
2933
432
            ipport_copy(dest, ip_port4);
2934
432
            is_lan = ip_is_lan(&dest->ip);
2935
2936
432
            if (!is_lan) {
2937
0
                break;
2938
0
            }
2939
432
        }
2940
2941
138k
        const IP_Port *ip_port6 = &client->assoc6.ret_ip_port;
2942
2943
138k
        if (client->assoc6.ret_ip_self && ipport_isset(ip_port6)) {
2944
0
            ipport_copy(dest, ip_port6);
2945
0
            is_lan = ip_is_lan(&dest->ip);
2946
2947
0
            if (!is_lan) {
2948
0
                break;
2949
0
            }
2950
0
        }
2951
138k
    }
2952
2953
135
    if (!ipport_isset(dest)) {
2954
17
        return 0;
2955
17
    }
2956
2957
118
    if (is_lan) {
2958
118
        return 2;
2959
118
    }
2960
2961
0
    return 1;
2962
118
}