Coverage Report

Created: 2024-01-26 01:52

/work/toxcore/TCP_connection.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2018 The TokTok team.
3
 * Copyright © 2015 Tox project.
4
 */
5
6
/**
7
 * Handles TCP relay connections between two Tox clients.
8
 */
9
#include "TCP_connection.h"
10
11
#include <assert.h>
12
#include <string.h>
13
14
#include "DHT.h"
15
#include "TCP_client.h"
16
#include "ccompat.h"
17
#include "crypto_core.h"
18
#include "forwarding.h"
19
#include "logger.h"
20
#include "mem.h"
21
#include "mono_time.h"
22
#include "network.h"
23
#include "util.h"
24
25
struct TCP_Connections {
26
    const Logger *logger;
27
    const Memory *mem;
28
    const Random *rng;
29
    Mono_Time *mono_time;
30
    const Network *ns;
31
    DHT *dht;
32
33
    uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE];
34
    uint8_t self_secret_key[CRYPTO_SECRET_KEY_SIZE];
35
36
    TCP_Connection_to *connections;
37
    uint32_t connections_length; /* Length of connections array. */
38
39
    TCP_con *tcp_connections;
40
    uint32_t tcp_connections_length; /* Length of tcp_connections array. */
41
42
    tcp_data_cb *tcp_data_callback;
43
    void *tcp_data_callback_object;
44
45
    tcp_oob_cb *tcp_oob_callback;
46
    void *tcp_oob_callback_object;
47
48
    tcp_onion_cb *tcp_onion_callback;
49
    void *tcp_onion_callback_object;
50
51
    forwarded_response_cb *tcp_forwarded_response_callback;
52
    void *tcp_forwarded_response_callback_object;
53
54
    TCP_Proxy_Info proxy_info;
55
56
    bool onion_status;
57
    uint16_t onion_num_conns;
58
};
59
60
61
static const TCP_Connection_to empty_tcp_connection_to = {0};
62
static const TCP_con empty_tcp_con = {0};
63
64
65
const uint8_t *tcp_connections_public_key(const TCP_Connections *tcp_c)
66
8
{
67
8
    return tcp_c->self_public_key;
68
8
}
69
70
71
uint32_t tcp_connections_count(const TCP_Connections *tcp_c)
72
10.2k
{
73
10.2k
    return tcp_c->tcp_connections_length;
74
10.2k
}
75
76
/** @brief Set the size of the array to num.
77
 *
78
 * @retval -1 if mem_vrealloc fails.
79
 * @retval 0 if it succeeds.
80
 */
81
non_null()
82
static int realloc_tcp_connection_to(const Memory *mem, TCP_Connection_to **array, size_t num)
83
3.07k
{
84
3.07k
    if (num == 0) {
85
606
        mem_delete(mem, *array);
86
606
        *array = nullptr;
87
606
        return 0;
88
606
    }
89
90
2.46k
    TCP_Connection_to *temp_pointer =
91
2.46k
        (TCP_Connection_to *)mem_vrealloc(mem, *array, num, sizeof(TCP_Connection_to));
92
93
2.46k
    if (temp_pointer == nullptr) {
94
19
        return -1;
95
19
    }
96
97
2.45k
    *array = temp_pointer;
98
99
2.45k
    return 0;
100
2.46k
}
101
102
non_null()
103
static int realloc_tcp_con(const Memory *mem, TCP_con **array, size_t num)
104
430
{
105
430
    if (num == 0) {
106
55
        mem_delete(mem, *array);
107
55
        *array = nullptr;
108
55
        return 0;
109
55
    }
110
111
375
    TCP_con *temp_pointer = (TCP_con *)mem_vrealloc(mem, *array, num, sizeof(TCP_con));
112
113
375
    if (temp_pointer == nullptr) {
114
36
        return -1;
115
36
    }
116
117
339
    *array = temp_pointer;
118
119
339
    return 0;
120
375
}
121
122
123
/**
124
 * Return true if the connections_number is valid.
125
 */
126
non_null()
127
static bool connections_number_is_valid(const TCP_Connections *tcp_c, int connections_number)
128
290k
{
129
290k
    if ((unsigned int)connections_number >= tcp_c->connections_length) {
130
263
        return false;
131
263
    }
132
133
290k
    if (tcp_c->connections == nullptr) {
134
0
        return false;
135
0
    }
136
137
290k
    return tcp_c->connections[connections_number].status != TCP_CONN_NONE;
138
290k
}
139
140
/**
141
 * Return true if the tcp_connections_number is valid.
142
 */
143
non_null()
144
static bool tcp_connections_number_is_valid(const TCP_Connections *tcp_c, int tcp_connections_number)
145
42.1k
{
146
42.1k
    if ((uint32_t)tcp_connections_number >= tcp_c->tcp_connections_length) {
147
0
        return false;
148
0
    }
149
150
42.1k
    if (tcp_c->tcp_connections == nullptr) {
151
0
        return false;
152
0
    }
153
154
42.1k
    return tcp_c->tcp_connections[tcp_connections_number].status != TCP_CONN_NONE;
155
42.1k
}
156
157
/** @brief Create a new empty connection.
158
 *
159
 * return -1 on failure.
160
 * return connections_number on success.
161
 */
162
non_null()
163
static int create_connection(TCP_Connections *tcp_c)
164
2.45k
{
165
5.75k
    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
166
3.67k
        if (tcp_c->connections[i].status == TCP_CONN_NONE) {
167
375
            return i;
168
375
        }
169
3.67k
    }
170
171
2.08k
    int id = -1;
172
173
2.08k
    if (realloc_tcp_connection_to(tcp_c->mem, &tcp_c->connections, tcp_c->connections_length + 1) == 0) {
174
2.06k
        id = tcp_c->connections_length;
175
2.06k
        ++tcp_c->connections_length;
176
2.06k
        tcp_c->connections[id] = empty_tcp_connection_to;
177
2.06k
    }
178
179
2.08k
    return id;
180
2.45k
}
181
182
/** @brief Create a new empty tcp connection.
183
 *
184
 * return -1 on failure.
185
 * return tcp_connections_number on success.
186
 */
187
non_null()
188
static int create_tcp_connection(TCP_Connections *tcp_c)
189
375
{
190
393
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
191
18
        if (tcp_c->tcp_connections[i].status == TCP_CONN_NONE) {
192
0
            return i;
193
0
        }
194
18
    }
195
196
375
    int id = -1;
197
198
375
    if (realloc_tcp_con(tcp_c->mem, &tcp_c->tcp_connections, tcp_c->tcp_connections_length + 1) == 0) {
199
339
        id = tcp_c->tcp_connections_length;
200
339
        ++tcp_c->tcp_connections_length;
201
339
        tcp_c->tcp_connections[id] = empty_tcp_con;
202
339
    }
203
204
375
    return id;
205
375
}
206
207
/** @brief Wipe a connection.
208
 *
209
 * return -1 on failure.
210
 * return 0 on success.
211
 */
212
non_null()
213
static int wipe_connection(TCP_Connections *tcp_c, int connections_number)
214
1.75k
{
215
1.75k
    if (!connections_number_is_valid(tcp_c, connections_number)) {
216
0
        return -1;
217
0
    }
218
219
1.75k
    uint32_t i;
220
1.75k
    tcp_c->connections[connections_number] = empty_tcp_connection_to;
221
222
3.11k
    for (i = tcp_c->connections_length; i != 0; --i) {
223
2.51k
        if (tcp_c->connections[i - 1].status != TCP_CONN_NONE) {
224
1.14k
            break;
225
1.14k
        }
226
2.51k
    }
227
228
1.75k
    if (tcp_c->connections_length != i) {
229
995
        tcp_c->connections_length = i;
230
995
        if (realloc_tcp_connection_to(tcp_c->mem, &tcp_c->connections, tcp_c->connections_length) != 0) {
231
0
            return -1;
232
0
        }
233
995
    }
234
235
1.75k
    return 0;
236
1.75k
}
237
238
/** @brief Wipe a connection.
239
 *
240
 * return -1 on failure.
241
 * return 0 on success.
242
 */
243
non_null()
244
static int wipe_tcp_connection(TCP_Connections *tcp_c, int tcp_connections_number)
245
61
{
246
61
    if (!tcp_connections_number_is_valid(tcp_c, tcp_connections_number)) {
247
0
        return -1;
248
0
    }
249
250
61
    tcp_c->tcp_connections[tcp_connections_number] = empty_tcp_con;
251
252
61
    uint32_t i;
253
254
122
    for (i = tcp_c->tcp_connections_length; i != 0; --i) {
255
67
        if (tcp_c->tcp_connections[i - 1].status != TCP_CONN_NONE) {
256
6
            break;
257
6
        }
258
67
    }
259
260
61
    if (tcp_c->tcp_connections_length != i) {
261
55
        tcp_c->tcp_connections_length = i;
262
55
        if (realloc_tcp_con(tcp_c->mem, &tcp_c->tcp_connections, tcp_c->tcp_connections_length) != 0) {
263
0
            return -1;
264
0
        }
265
55
    }
266
267
61
    return 0;
268
61
}
269
270
non_null()
271
static TCP_Connection_to *get_connection(const TCP_Connections *tcp_c, int connections_number)
272
288k
{
273
288k
    if (!connections_number_is_valid(tcp_c, connections_number)) {
274
821
        return nullptr;
275
821
    }
276
277
288k
    return &tcp_c->connections[connections_number];
278
288k
}
279
280
non_null()
281
static TCP_con *get_tcp_connection(const TCP_Connections *tcp_c, int tcp_connections_number)
282
42.0k
{
283
42.0k
    if (!tcp_connections_number_is_valid(tcp_c, tcp_connections_number)) {
284
1.85k
        return nullptr;
285
1.85k
    }
286
287
40.2k
    return &tcp_c->tcp_connections[tcp_connections_number];
288
42.0k
}
289
290
uint32_t tcp_connected_relays_count(const TCP_Connections *tcp_c)
291
9.85k
{
292
9.85k
    uint32_t count = 0;
293
9.85k
    const uint32_t size = tcp_connections_count(tcp_c);
294
295
9.96k
    for (uint32_t i = 0; i < size; ++i) {
296
108
        const TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
297
298
108
        if (tcp_con == nullptr) {
299
0
            continue;
300
0
        }
301
302
108
        if (tcp_con->status == TCP_CONN_CONNECTED) {
303
0
            ++count;
304
0
        }
305
108
    }
306
307
9.85k
    return count;
308
9.85k
}
309
310
/** @brief Send a packet to the TCP connection.
311
 *
312
 * return -1 on failure.
313
 * return 0 on success.
314
 */
315
int send_packet_tcp_connection(const TCP_Connections *tcp_c, int connections_number, const uint8_t *packet,
316
                               uint16_t length)
317
18.3k
{
318
18.3k
    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
319
320
18.3k
    if (con_to == nullptr) {
321
1
        return -1;
322
1
    }
323
324
    // TODO(irungentoo): detect and kill bad relays.
325
    // TODO(irungentoo): thread safety?
326
18.3k
    int ret = -1;
327
328
18.3k
    bool limit_reached = false;
329
330
121k
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
331
104k
        uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
332
104k
        const uint8_t status = con_to->connections[i].status;
333
104k
        const uint8_t connection_id = con_to->connections[i].connection_id;
334
335
104k
        if (tcp_con_num > 0 && status == TCP_CONNECTIONS_STATUS_ONLINE) {
336
1.06k
            tcp_con_num -= 1;
337
1.06k
            TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num);
338
339
1.06k
            if (tcp_con == nullptr) {
340
0
                continue;
341
0
            }
342
343
1.06k
            ret = send_data(tcp_c->logger, tcp_con->connection, connection_id, packet, length);
344
345
1.06k
            if (ret == 0) {
346
0
                limit_reached = true;
347
0
            }
348
349
1.06k
            if (ret == 1) {
350
1.06k
                break;
351
1.06k
            }
352
1.06k
        }
353
104k
    }
354
355
18.3k
    if (ret == 1) {
356
1.06k
        return 0;
357
1.06k
    }
358
359
17.2k
    if (limit_reached) {
360
0
        return -1;
361
0
    }
362
363
17.2k
    bool sent_any = false;
364
365
    /* Send oob packets to all relays tied to the connection. */
366
120k
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
367
103k
        uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
368
103k
        const uint8_t status = con_to->connections[i].status;
369
370
103k
        if (tcp_con_num > 0 && status == TCP_CONNECTIONS_STATUS_REGISTERED) {
371
120
            tcp_con_num -= 1;
372
120
            TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_con_num);
373
374
120
            if (tcp_con == nullptr) {
375
0
                continue;
376
0
            }
377
378
120
            if (send_oob_packet(tcp_c->logger, tcp_con->connection, con_to->public_key, packet, length) == 1) {
379
120
                sent_any = true;
380
120
            }
381
120
        }
382
103k
    }
383
384
17.2k
    return sent_any ? 0 : -1;
385
17.2k
}
386
387
/** @brief Return a TCP connection number for use in send_tcp_onion_request.
388
 *
389
 * TODO(irungentoo): This number is just the index of an array that the elements
390
 * can change without warning.
391
 *
392
 * return TCP connection number on success.
393
 * return -1 on failure.
394
 */
395
int get_random_tcp_onion_conn_number(const TCP_Connections *tcp_c)
396
2.27k
{
397
2.27k
    const uint32_t r = random_u32(tcp_c->rng);
398
399
2.37k
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
400
626
        const uint32_t index = (i + r) % tcp_c->tcp_connections_length;
401
402
626
        if (tcp_c->tcp_connections[index].onion && tcp_c->tcp_connections[index].status == TCP_CONN_CONNECTED) {
403
528
            return index;
404
528
        }
405
626
    }
406
407
1.74k
    return -1;
408
2.27k
}
409
410
/** @brief Return TCP connection number of active TCP connection with ip_port.
411
 *
412
 * return TCP connection number on success.
413
 * return -1 on failure.
414
 */
415
non_null()
416
static int get_conn_number_by_ip_port(const TCP_Connections *tcp_c, const IP_Port *ip_port)
417
9
{
418
9
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
419
9
        const IP_Port conn_ip_port = tcp_con_ip_port(tcp_c->tcp_connections[i].connection);
420
421
9
        if (ipport_equal(ip_port, &conn_ip_port) &&
422
9
                tcp_c->tcp_connections[i].status == TCP_CONN_CONNECTED) {
423
9
            return i;
424
9
        }
425
9
    }
426
427
0
    return -1;
428
9
}
429
430
/** @brief Put IP_Port of a random onion TCP connection in ip_port.
431
 *
432
 * return true on success.
433
 * return false on failure.
434
 */
435
bool tcp_get_random_conn_ip_port(const TCP_Connections *tcp_c, IP_Port *ip_port)
436
9
{
437
9
    const int index = get_random_tcp_onion_conn_number(tcp_c);
438
439
9
    if (index == -1) {
440
0
        return false;
441
0
    }
442
443
9
    *ip_port = tcp_con_ip_port(tcp_c->tcp_connections[index].connection);
444
9
    return true;
445
9
}
446
447
/** @brief Send an onion packet via the TCP relay corresponding to tcp_connections_number.
448
 *
449
 * return 0 on success.
450
 * return -1 on failure.
451
 */
452
int tcp_send_onion_request(TCP_Connections *tcp_c, uint32_t tcp_connections_number, const uint8_t *data,
453
                           uint16_t length)
454
1.02k
{
455
1.02k
    if (tcp_connections_number >= tcp_c->tcp_connections_length) {
456
0
        return -1;
457
0
    }
458
459
1.02k
    if (tcp_c->tcp_connections[tcp_connections_number].status == TCP_CONN_CONNECTED) {
460
1.02k
        const int ret = send_onion_request(tcp_c->logger, tcp_c->tcp_connections[tcp_connections_number].connection, data,
461
1.02k
                                           length);
462
463
1.02k
        if (ret == 1) {
464
1.02k
            return 0;
465
1.02k
        }
466
1.02k
    }
467
468
0
    return -1;
469
1.02k
}
470
471
/* Send a forward request to the TCP relay with IP_Port tcp_forwarder,
472
 * requesting to forward data via a chain of dht nodes starting with dht_node.
473
 * A chain_length of 0 means that dht_node is the final destination of data.
474
 *
475
 * return 0 on success.
476
 * return -1 on failure.
477
 */
478
int tcp_send_forward_request(const Logger *logger, TCP_Connections *tcp_c, const IP_Port *tcp_forwarder,
479
                             const IP_Port *dht_node,
480
                             const uint8_t *chain_keys, uint16_t chain_length,
481
                             const uint8_t *data, uint16_t data_length)
482
9
{
483
9
    const int index = get_conn_number_by_ip_port(tcp_c, tcp_forwarder);
484
485
9
    if (index == -1) {
486
0
        return -1;
487
0
    }
488
489
9
    if (chain_length == 0) {
490
1
        return send_forward_request_tcp(logger, tcp_c->tcp_connections[index].connection, dht_node, data,
491
1
                                        data_length) == 1 ? 0 : -1;
492
1
    }
493
494
8
    const uint16_t len = forward_chain_packet_size(chain_length, data_length);
495
8
    VLA(uint8_t, packet, len);
496
497
8
    return create_forward_chain_packet(chain_keys, chain_length, data, data_length, packet)
498
8
           && send_forward_request_tcp(logger, tcp_c->tcp_connections[index].connection, dht_node, packet, len) == 1 ? 0 : -1;
499
9
}
500
501
/** @brief Send an oob packet via the TCP relay corresponding to tcp_connections_number.
502
 *
503
 * return 0 on success.
504
 * return -1 on failure.
505
 */
506
int tcp_send_oob_packet(const TCP_Connections *tcp_c, unsigned int tcp_connections_number,
507
                        const uint8_t *public_key, const uint8_t *packet, uint16_t length)
508
52
{
509
52
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
510
511
52
    if (tcp_con == nullptr) {
512
0
        return -1;
513
0
    }
514
515
52
    if (tcp_con->status != TCP_CONN_CONNECTED) {
516
0
        return -1;
517
0
    }
518
519
52
    const int ret = send_oob_packet(tcp_c->logger, tcp_con->connection, public_key, packet, length);
520
521
52
    if (ret == 1) {
522
52
        return 0;
523
52
    }
524
525
0
    return -1;
526
52
}
527
528
non_null()
529
static int find_tcp_connection_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk);
530
531
/** @brief Send an oob packet via the TCP relay corresponding to relay_pk.
532
 *
533
 * return 0 on success.
534
 * return -1 on failure.
535
 */
536
int tcp_send_oob_packet_using_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk, const uint8_t *public_key,
537
                                    const uint8_t *packet, uint16_t length)
538
0
{
539
0
    const int tcp_con_number = find_tcp_connection_relay(tcp_c, relay_pk);
540
541
0
    if (tcp_con_number < 0) {
542
0
        return -1;
543
0
    }
544
545
0
    return tcp_send_oob_packet(tcp_c, tcp_con_number, public_key, packet, length);
546
0
}
547
548
/** @brief Set the callback for TCP data packets. */
549
void set_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_data_cb *tcp_data_callback, void *object)
550
4.27k
{
551
4.27k
    tcp_c->tcp_data_callback = tcp_data_callback;
552
4.27k
    tcp_c->tcp_data_callback_object = object;
553
4.27k
}
554
555
/** @brief Set the callback for TCP oob data packets. */
556
void set_oob_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_oob_cb *tcp_oob_callback, void *object)
557
4.27k
{
558
4.27k
    tcp_c->tcp_oob_callback = tcp_oob_callback;
559
4.27k
    tcp_c->tcp_oob_callback_object = object;
560
4.27k
}
561
562
/** @brief Set the callback for TCP onion packets. */
563
void set_onion_packet_tcp_connection_callback(TCP_Connections *tcp_c, tcp_onion_cb *tcp_onion_callback, void *object)
564
6.48k
{
565
6.48k
    tcp_c->tcp_onion_callback = tcp_onion_callback;
566
6.48k
    tcp_c->tcp_onion_callback_object = object;
567
6.48k
}
568
569
/** @brief Set the callback for TCP forwarding packets. */
570
void set_forwarding_packet_tcp_connection_callback(TCP_Connections *tcp_c,
571
        forwarded_response_cb *tcp_forwarded_response_callback,
572
        void *object)
573
20
{
574
20
    tcp_c->tcp_forwarded_response_callback = tcp_forwarded_response_callback;
575
20
    tcp_c->tcp_forwarded_response_callback_object = object;
576
20
}
577
578
/** @brief Encode tcp_connections_number as a custom ip_port.
579
 *
580
 * return ip_port.
581
 */
582
IP_Port tcp_connections_number_to_ip_port(unsigned int tcp_connections_number)
583
569
{
584
569
    IP_Port ip_port = {{{0}}};
585
569
    ip_port.ip.family = net_family_tcp_server();
586
569
    ip_port.ip.ip.v6.uint32[0] = tcp_connections_number;
587
569
    return ip_port;
588
569
}
589
590
/** @brief Decode ip_port created by tcp_connections_number_to_ip_port to tcp_connections_number.
591
 *
592
 * return true on success.
593
 * return false if ip_port is invalid.
594
 */
595
bool ip_port_to_tcp_connections_number(const IP_Port *ip_port, unsigned int *tcp_connections_number)
596
1.07k
{
597
1.07k
    *tcp_connections_number = ip_port->ip.ip.v6.uint32[0];
598
1.07k
    return net_family_is_tcp_server(ip_port->ip.family);
599
1.07k
}
600
601
/** @brief Find the TCP connection with public_key.
602
 *
603
 * return connections_number on success.
604
 * return -1 on failure.
605
 */
606
non_null()
607
static int find_tcp_connection_to(const TCP_Connections *tcp_c, const uint8_t *public_key)
608
2.74k
{
609
7.67k
    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
610
5.11k
        const TCP_Connection_to *con_to = get_connection(tcp_c, i);
611
612
5.11k
        if (con_to != nullptr) {
613
4.66k
            if (pk_equal(con_to->public_key, public_key)) {
614
181
                return i;
615
181
            }
616
4.66k
        }
617
5.11k
    }
618
619
2.56k
    return -1;
620
2.74k
}
621
622
/** @brief Find the TCP connection to a relay with relay_pk.
623
 *
624
 * return connections_number on success.
625
 * return -1 on failure.
626
 */
627
static int find_tcp_connection_relay(const TCP_Connections *tcp_c, const uint8_t *relay_pk)
628
725
{
629
743
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
630
121
        const TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
631
632
121
        if (tcp_con != nullptr) {
633
121
            if (tcp_con->status == TCP_CONN_SLEEPING) {
634
0
                if (pk_equal(tcp_con->relay_pk, relay_pk)) {
635
0
                    return i;
636
0
                }
637
121
            } else {
638
121
                if (pk_equal(tcp_con_public_key(tcp_con->connection), relay_pk)) {
639
103
                    return i;
640
103
                }
641
121
            }
642
121
        }
643
121
    }
644
645
622
    return -1;
646
725
}
647
648
bool tcp_relay_is_valid(const TCP_Connections *tcp_c, const uint8_t *relay_pk)
649
247
{
650
247
    return find_tcp_connection_relay(tcp_c, relay_pk) != -1;
651
247
}
652
653
/** @brief Create a new TCP connection to public_key.
654
 *
655
 * public_key must be the counterpart to the secret key that the other peer used with `new_tcp_connections()`.
656
 *
657
 * id is the id in the callbacks for that connection.
658
 *
659
 * return connections_number on success.
660
 * return -1 on failure.
661
 */
662
int new_tcp_connection_to(TCP_Connections *tcp_c, const uint8_t *public_key, int id)
663
2.45k
{
664
2.45k
    if (find_tcp_connection_to(tcp_c, public_key) != -1) {
665
1
        return -1;
666
1
    }
667
668
2.45k
    const int connections_number = create_connection(tcp_c);
669
670
2.45k
    if (connections_number == -1) {
671
19
        return -1;
672
19
    }
673
674
2.43k
    TCP_Connection_to *con_to = &tcp_c->connections[connections_number];
675
676
2.43k
    con_to->status = TCP_CONN_VALID;
677
2.43k
    memcpy(con_to->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
678
2.43k
    con_to->id = id;
679
680
2.43k
    return connections_number;
681
2.45k
}
682
683
/**
684
 * @retval 0 on success.
685
 * @retval -1 on failure.
686
 */
687
int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
688
1.75k
{
689
1.75k
    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
690
691
1.75k
    if (con_to == nullptr) {
692
0
        return -1;
693
0
    }
694
695
12.2k
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
696
10.5k
        if (con_to->connections[i].tcp_connection > 0) {
697
107
            const unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
698
107
            TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
699
700
107
            if (tcp_con == nullptr) {
701
0
                continue;
702
0
            }
703
704
107
            if (tcp_con->status == TCP_CONN_CONNECTED) {
705
107
                send_disconnect_request(tcp_c->logger, tcp_con->connection, con_to->connections[i].connection_id);
706
107
            }
707
708
107
            if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
709
105
                --tcp_con->lock_count;
710
711
105
                if (con_to->status == TCP_CONN_SLEEPING) {
712
0
                    --tcp_con->sleep_count;
713
0
                }
714
105
            }
715
107
        }
716
10.5k
    }
717
718
1.75k
    return wipe_connection(tcp_c, connections_number);
719
1.75k
}
720
721
/** @brief Set connection status.
722
 *
723
 * status of 1 means we are using the connection.
724
 * status of 0 means we are not using it.
725
 *
726
 * Unused tcp connections will be disconnected from but kept in case they are needed.
727
 *
728
 * return 0 on success.
729
 * return -1 on failure.
730
 */
731
int set_tcp_connection_to_status(const TCP_Connections *tcp_c, int connections_number, bool status)
732
164k
{
733
164k
    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
734
735
164k
    if (con_to == nullptr) {
736
258
        return -1;
737
258
    }
738
739
164k
    if (status) {
740
        /* Connection is unsleeping. */
741
3.40k
        if (con_to->status != TCP_CONN_SLEEPING) {
742
3.33k
            return -1;
743
3.33k
        }
744
745
490
        for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
746
420
            if (con_to->connections[i].tcp_connection > 0) {
747
0
                const unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
748
0
                TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
749
750
0
                if (tcp_con == nullptr) {
751
0
                    continue;
752
0
                }
753
754
0
                if (tcp_con->status == TCP_CONN_SLEEPING) {
755
0
                    tcp_con->unsleep = 1;
756
0
                }
757
0
            }
758
420
        }
759
760
70
        con_to->status = TCP_CONN_VALID;
761
70
        return 0;
762
3.40k
    }
763
764
    /* Connection is going to sleep. */
765
160k
    if (con_to->status != TCP_CONN_VALID) {
766
158k
        return -1;
767
158k
    }
768
769
13.5k
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
770
11.6k
        if (con_to->connections[i].tcp_connection > 0) {
771
0
            unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
772
0
            TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
773
774
0
            if (tcp_con == nullptr) {
775
0
                continue;
776
0
            }
777
778
0
            if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
779
0
                ++tcp_con->sleep_count;
780
0
            }
781
0
        }
782
11.6k
    }
783
784
1.93k
    con_to->status = TCP_CONN_SLEEPING;
785
1.93k
    return 0;
786
160k
}
787
788
non_null()
789
static bool tcp_connection_in_conn(const TCP_Connection_to *con_to, unsigned int tcp_connections_number)
790
232
{
791
886
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
792
777
        if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
793
123
            return true;
794
123
        }
795
777
    }
796
797
109
    return false;
798
232
}
799
800
/**
801
 * @return index on success.
802
 * @retval -1 on failure.
803
 */
804
non_null()
805
static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
806
155
{
807
155
    if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
808
48
        return -1;
809
48
    }
810
811
107
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
812
107
        if (con_to->connections[i].tcp_connection == 0) {
813
107
            con_to->connections[i].tcp_connection = tcp_connections_number + 1;
814
107
            con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE;
815
107
            con_to->connections[i].connection_id = 0;
816
107
            return i;
817
107
        }
818
107
    }
819
820
0
    return -1;
821
107
}
822
823
/**
824
 * @return index on success.
825
 * @retval -1 on failure.
826
 */
827
non_null()
828
static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
829
0
{
830
0
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
831
0
        if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
832
0
            con_to->connections[i].tcp_connection = 0;
833
0
            con_to->connections[i].status = TCP_CONNECTIONS_STATUS_NONE;
834
0
            con_to->connections[i].connection_id = 0;
835
0
            return i;
836
0
        }
837
0
    }
838
839
0
    return -1;
840
0
}
841
842
/**
843
 * @return number of online connections on success.
844
 * @retval -1 on failure.
845
 */
846
non_null()
847
static uint32_t online_tcp_connection_from_conn(const TCP_Connection_to *con_to)
848
97.7k
{
849
97.7k
    uint32_t count = 0;
850
851
684k
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
852
586k
        if (con_to->connections[i].tcp_connection > 0) {
853
799
            if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
854
799
                ++count;
855
799
            }
856
799
        }
857
586k
    }
858
859
97.7k
    return count;
860
97.7k
}
861
862
/**
863
 * @return index on success.
864
 * @retval -1 on failure.
865
 */
866
non_null()
867
static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp_connections_number,
868
                                     uint8_t status,
869
                                     uint8_t connection_id)
870
214
{
871
214
    for (uint32_t i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
872
214
        if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
873
874
214
            if (con_to->connections[i].status == status) {
875
0
                return -1;
876
0
            }
877
878
214
            con_to->connections[i].status = status;
879
214
            con_to->connections[i].connection_id = connection_id;
880
214
            return i;
881
214
        }
882
214
    }
883
884
0
    return -1;
885
214
}
886
887
/** @brief Kill a TCP relay connection.
888
 *
889
 * return 0 on success.
890
 * return -1 on failure.
891
 */
892
int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
893
61
{
894
61
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
895
896
61
    if (tcp_con == nullptr) {
897
0
        return -1;
898
0
    }
899
900
61
    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
901
0
        TCP_Connection_to *con_to = get_connection(tcp_c, i);
902
903
0
        if (con_to != nullptr) {
904
0
            rm_tcp_connection_from_conn(con_to, tcp_connections_number);
905
0
        }
906
0
    }
907
908
61
    if (tcp_con->onion) {
909
5
        --tcp_c->onion_num_conns;
910
5
    }
911
912
61
    kill_tcp_connection(tcp_con->connection);
913
914
61
    return wipe_tcp_connection(tcp_c, tcp_connections_number);
915
61
}
916
917
non_null()
918
static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
919
95
{
920
95
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
921
922
95
    if (tcp_con == nullptr) {
923
0
        return -1;
924
0
    }
925
926
95
    if (tcp_con->status == TCP_CONN_SLEEPING) {
927
0
        return -1;
928
0
    }
929
930
95
    IP_Port ip_port = tcp_con_ip_port(tcp_con->connection);
931
95
    uint8_t relay_pk[CRYPTO_PUBLIC_KEY_SIZE];
932
95
    memcpy(relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
933
95
    kill_tcp_connection(tcp_con->connection);
934
95
    tcp_con->connection = new_tcp_connection(tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ip_port, relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
935
936
95
    if (tcp_con->connection == nullptr) {
937
5
        kill_tcp_relay_connection(tcp_c, tcp_connections_number);
938
5
        return -1;
939
5
    }
940
941
90
    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
942
0
        TCP_Connection_to *con_to = get_connection(tcp_c, i);
943
944
0
        if (con_to != nullptr) {
945
0
            set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
946
0
        }
947
0
    }
948
949
90
    if (tcp_con->onion) {
950
90
        --tcp_c->onion_num_conns;
951
90
        tcp_con->onion = 0;
952
90
    }
953
954
90
    tcp_con->lock_count = 0;
955
90
    tcp_con->sleep_count = 0;
956
90
    tcp_con->connected_time = 0;
957
90
    tcp_con->status = TCP_CONN_VALID;
958
90
    tcp_con->unsleep = 0;
959
960
90
    return 0;
961
95
}
962
963
non_null()
964
static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
965
0
{
966
0
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
967
968
0
    if (tcp_con == nullptr) {
969
0
        return -1;
970
0
    }
971
972
0
    if (tcp_con->status != TCP_CONN_CONNECTED) {
973
0
        return -1;
974
0
    }
975
976
0
    if (tcp_con->lock_count != tcp_con->sleep_count) {
977
0
        return -1;
978
0
    }
979
980
0
    tcp_con->ip_port = tcp_con_ip_port(tcp_con->connection);
981
0
    memcpy(tcp_con->relay_pk, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
982
983
0
    kill_tcp_connection(tcp_con->connection);
984
0
    tcp_con->connection = nullptr;
985
986
0
    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
987
0
        TCP_Connection_to *con_to = get_connection(tcp_c, i);
988
989
0
        if (con_to != nullptr) {
990
0
            set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
991
0
        }
992
0
    }
993
994
0
    if (tcp_con->onion) {
995
0
        --tcp_c->onion_num_conns;
996
0
        tcp_con->onion = 0;
997
0
    }
998
999
0
    tcp_con->lock_count = 0;
1000
0
    tcp_con->sleep_count = 0;
1001
0
    tcp_con->connected_time = 0;
1002
0
    tcp_con->status = TCP_CONN_SLEEPING;
1003
0
    tcp_con->unsleep = 0;
1004
1005
0
    return 0;
1006
0
}
1007
1008
non_null()
1009
static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
1010
0
{
1011
0
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1012
1013
0
    if (tcp_con == nullptr) {
1014
0
        return -1;
1015
0
    }
1016
1017
0
    if (tcp_con->status != TCP_CONN_SLEEPING) {
1018
0
        return -1;
1019
0
    }
1020
1021
0
    tcp_con->connection = new_tcp_connection(
1022
0
            tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &tcp_con->ip_port,
1023
0
            tcp_con->relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
1024
1025
0
    if (tcp_con->connection == nullptr) {
1026
0
        kill_tcp_relay_connection(tcp_c, tcp_connections_number);
1027
0
        return -1;
1028
0
    }
1029
1030
0
    tcp_con->lock_count = 0;
1031
0
    tcp_con->sleep_count = 0;
1032
0
    tcp_con->connected_time = 0;
1033
0
    tcp_con->status = TCP_CONN_VALID;
1034
0
    tcp_con->unsleep = 0;
1035
1036
0
    return 0;
1037
0
}
1038
1039
/** @brief Send a TCP routing request.
1040
 *
1041
 * return 0 on success.
1042
 * return -1 on failure.
1043
 */
1044
non_null()
1045
static int send_tcp_relay_routing_request(const TCP_Connections *tcp_c, int tcp_connections_number,
1046
        const uint8_t *public_key)
1047
107
{
1048
107
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1049
1050
107
    if (tcp_con == nullptr) {
1051
0
        return -1;
1052
0
    }
1053
1054
107
    if (tcp_con->status == TCP_CONN_SLEEPING) {
1055
0
        return -1;
1056
0
    }
1057
1058
107
    if (send_routing_request(tcp_c->logger, tcp_con->connection, public_key) != 1) {
1059
0
        return -1;
1060
0
    }
1061
1062
107
    return 0;
1063
107
}
1064
1065
non_null()
1066
static int tcp_response_callback(void *object, uint8_t connection_id, const uint8_t *public_key)
1067
107
{
1068
107
    const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;
1069
107
    const TCP_Connections *tcp_c = (const TCP_Connections *)tcp_con_custom_object(tcp_client_con);
1070
1071
107
    const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
1072
107
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1073
1074
107
    if (tcp_con == nullptr) {
1075
0
        return -1;
1076
0
    }
1077
1078
107
    const int connections_number = find_tcp_connection_to(tcp_c, public_key);
1079
1080
107
    if (connections_number == -1) {
1081
0
        return -1;
1082
0
    }
1083
1084
107
    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1085
1086
107
    if (con_to == nullptr) {
1087
0
        return -1;
1088
0
    }
1089
1090
107
    if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
1091
0
        return -1;
1092
0
    }
1093
1094
107
    set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
1095
1096
107
    return 0;
1097
107
}
1098
1099
non_null()
1100
static int tcp_status_callback(void *object, uint32_t number, uint8_t connection_id, uint8_t status)
1101
107
{
1102
107
    const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;
1103
107
    const TCP_Connections *tcp_c = (const TCP_Connections *)tcp_con_custom_object(tcp_client_con);
1104
1105
107
    const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
1106
107
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1107
107
    TCP_Connection_to *con_to = get_connection(tcp_c, number);
1108
1109
107
    if (con_to == nullptr || tcp_con == nullptr) {
1110
0
        return -1;
1111
0
    }
1112
1113
107
    if (status == 1) {
1114
1
        if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) {
1115
0
            return -1;
1116
0
        }
1117
1118
1
        --tcp_con->lock_count;
1119
1120
1
        if (con_to->status == TCP_CONN_SLEEPING) {
1121
0
            --tcp_con->sleep_count;
1122
0
        }
1123
106
    } else if (status == 2) {
1124
106
        if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) {
1125
0
            return -1;
1126
0
        }
1127
1128
106
        ++tcp_con->lock_count;
1129
1130
106
        if (con_to->status == TCP_CONN_SLEEPING) {
1131
0
            ++tcp_con->sleep_count;
1132
0
        }
1133
106
    }
1134
1135
107
    return 0;
1136
107
}
1137
1138
non_null(1, 4) nullable(6)
1139
static int tcp_conn_data_callback(void *object, uint32_t number, uint8_t connection_id, const uint8_t *data,
1140
                                  uint16_t length, void *userdata)
1141
924
{
1142
924
    const TCP_Client_Connection *tcp_client_con = (TCP_Client_Connection *)object;
1143
1144
924
    if (length == 0) {
1145
0
        return -1;
1146
0
    }
1147
1148
924
    TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con);
1149
1150
924
    const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
1151
924
    const TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1152
1153
924
    if (tcp_con == nullptr) {
1154
0
        return -1;
1155
0
    }
1156
1157
924
    const TCP_Connection_to *con_to = get_connection(tcp_c, number);
1158
1159
924
    if (con_to == nullptr) {
1160
13
        return -1;
1161
13
    }
1162
1163
911
    if (tcp_c->tcp_data_callback != nullptr) {
1164
911
        tcp_c->tcp_data_callback(tcp_c->tcp_data_callback_object, con_to->id, data, length, userdata);
1165
911
    }
1166
1167
911
    return 0;
1168
924
}
1169
1170
non_null()
1171
static int tcp_conn_oob_callback(void *object, const uint8_t *public_key, const uint8_t *data, uint16_t length,
1172
                                 void *userdata)
1173
178
{
1174
178
    const TCP_Client_Connection *tcp_client_con = (const TCP_Client_Connection *)object;
1175
1176
178
    if (length == 0) {
1177
0
        return -1;
1178
0
    }
1179
1180
178
    TCP_Connections *tcp_c = (TCP_Connections *)tcp_con_custom_object(tcp_client_con);
1181
1182
178
    const unsigned int tcp_connections_number = tcp_con_custom_uint(tcp_client_con);
1183
178
    const TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1184
1185
178
    if (tcp_con == nullptr) {
1186
0
        return -1;
1187
0
    }
1188
1189
    /* TODO(irungentoo): optimize */
1190
178
    const int connections_number = find_tcp_connection_to(tcp_c, public_key);
1191
1192
178
    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1193
1194
178
    if (con_to != nullptr && tcp_connection_in_conn(con_to, tcp_connections_number)) {
1195
71
        return tcp_conn_data_callback(object, connections_number, 0, data, length, userdata);
1196
71
    }
1197
1198
107
    if (tcp_c->tcp_oob_callback != nullptr) {
1199
107
        tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length, userdata);
1200
107
    }
1201
1202
107
    return 0;
1203
178
}
1204
1205
non_null()
1206
static int tcp_onion_callback(void *object, const uint8_t *data, uint16_t length, void *userdata)
1207
808
{
1208
808
    TCP_Connections *tcp_c = (TCP_Connections *)object;
1209
1210
808
    if (tcp_c->tcp_onion_callback != nullptr) {
1211
808
        tcp_c->tcp_onion_callback(tcp_c->tcp_onion_callback_object, data, length, userdata);
1212
808
    }
1213
1214
808
    return 0;
1215
808
}
1216
1217
non_null()
1218
static void tcp_forwarding_callback(void *object, const uint8_t *data, uint16_t length, void *userdata)
1219
11
{
1220
11
    TCP_Connections *tcp_c = (TCP_Connections *)object;
1221
1222
11
    if (tcp_c->tcp_forwarded_response_callback != nullptr) {
1223
5
        tcp_c->tcp_forwarded_response_callback(tcp_c->tcp_forwarded_response_callback_object, data, length, userdata);
1224
5
    }
1225
11
}
1226
1227
/** @brief Set callbacks for the TCP relay connection.
1228
 *
1229
 * return 0 on success.
1230
 * return -1 on failure.
1231
 */
1232
non_null()
1233
static int tcp_relay_set_callbacks(TCP_Connections *tcp_c, int tcp_connections_number)
1234
200
{
1235
200
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1236
1237
200
    if (tcp_con == nullptr) {
1238
0
        return -1;
1239
0
    }
1240
1241
200
    TCP_Client_Connection *con = tcp_con->connection;
1242
1243
200
    tcp_con_set_custom_object(con, tcp_c);
1244
200
    tcp_con_set_custom_uint(con, tcp_connections_number);
1245
200
    onion_response_handler(con, &tcp_onion_callback, tcp_c);
1246
200
    forwarding_handler(con, &tcp_forwarding_callback, tcp_c);
1247
200
    routing_response_handler(con, &tcp_response_callback, con);
1248
200
    routing_status_handler(con, &tcp_status_callback, con);
1249
200
    routing_data_handler(con, &tcp_conn_data_callback, con);
1250
200
    oob_data_handler(con, &tcp_conn_oob_callback, con);
1251
1252
200
    return 0;
1253
200
}
1254
1255
non_null()
1256
static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_number)
1257
200
{
1258
200
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1259
1260
200
    if (tcp_con == nullptr) {
1261
0
        return -1;
1262
0
    }
1263
1264
200
    bool sent_any = false;
1265
1266
204
    for (uint32_t i = 0; i < tcp_c->connections_length; ++i) {
1267
4
        const TCP_Connection_to *con_to = get_connection(tcp_c, i);
1268
1269
4
        if (con_to != nullptr) {
1270
4
            if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
1271
4
                if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
1272
4
                    sent_any = true;
1273
4
                }
1274
4
            }
1275
4
        }
1276
4
    }
1277
1278
200
    tcp_relay_set_callbacks(tcp_c, tcp_connections_number);
1279
200
    tcp_con->status = TCP_CONN_CONNECTED;
1280
1281
    /* If this connection isn't used by any connection, we don't need to wait for them to come online. */
1282
200
    if (sent_any) {
1283
4
        tcp_con->connected_time = mono_time_get(tcp_c->mono_time);
1284
196
    } else {
1285
196
        tcp_con->connected_time = 0;
1286
196
    }
1287
1288
200
    if (tcp_c->onion_status && tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
1289
144
        tcp_con->onion = 1;
1290
144
        ++tcp_c->onion_num_conns;
1291
144
    }
1292
1293
200
    return 0;
1294
200
}
1295
1296
non_null()
1297
static int add_tcp_relay_instance(TCP_Connections *tcp_c, const IP_Port *ip_port, const uint8_t *relay_pk)
1298
375
{
1299
375
    IP_Port ipp_copy = *ip_port;
1300
1301
375
    if (net_family_is_tcp_ipv4(ipp_copy.ip.family)) {
1302
3
        ipp_copy.ip.family = net_family_ipv4();
1303
372
    } else if (net_family_is_tcp_ipv6(ipp_copy.ip.family)) {
1304
0
        ipp_copy.ip.family = net_family_ipv6();
1305
0
    }
1306
1307
375
    if (!net_family_is_ipv4(ipp_copy.ip.family) && !net_family_is_ipv6(ipp_copy.ip.family)) {
1308
0
        return -1;
1309
0
    }
1310
1311
375
    const int tcp_connections_number = create_tcp_connection(tcp_c);
1312
1313
375
    if (tcp_connections_number == -1) {
1314
36
        return -1;
1315
36
    }
1316
1317
339
    TCP_con *tcp_con = &tcp_c->tcp_connections[tcp_connections_number];
1318
1319
339
    tcp_con->connection = new_tcp_connection(
1320
339
            tcp_c->logger, tcp_c->mem, tcp_c->mono_time, tcp_c->rng, tcp_c->ns, &ipp_copy,
1321
339
            relay_pk, tcp_c->self_public_key, tcp_c->self_secret_key, &tcp_c->proxy_info);
1322
1323
339
    if (tcp_con->connection == nullptr) {
1324
20
        return -1;
1325
20
    }
1326
1327
319
    tcp_con->status = TCP_CONN_VALID;
1328
1329
319
    return tcp_connections_number;
1330
339
}
1331
1332
/** @brief Add a TCP relay to the TCP_Connections instance.
1333
 *
1334
 * return 0 on success.
1335
 * return -1 on failure.
1336
 */
1337
int add_tcp_relay_global(TCP_Connections *tcp_c, const IP_Port *ip_port, const uint8_t *relay_pk)
1338
372
{
1339
372
    const int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
1340
1341
372
    if (tcp_connections_number != -1) {
1342
1
        return -1;
1343
1
    }
1344
1345
371
    if (add_tcp_relay_instance(tcp_c, ip_port, relay_pk) == -1) {
1346
56
        return -1;
1347
56
    }
1348
1349
315
    return 0;
1350
371
}
1351
1352
/** @brief Add a TCP relay tied to a connection.
1353
 *
1354
 * NOTE: This can only be used during the tcp_oob_callback.
1355
 *
1356
 * return 0 on success.
1357
 * return -1 on failure.
1358
 */
1359
int add_tcp_number_relay_connection(const TCP_Connections *tcp_c, int connections_number,
1360
                                    unsigned int tcp_connections_number)
1361
151
{
1362
151
    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1363
1364
151
    if (con_to == nullptr) {
1365
0
        return -1;
1366
0
    }
1367
1368
151
    TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1369
1370
151
    if (tcp_con == nullptr) {
1371
0
        return -1;
1372
0
    }
1373
1374
151
    if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
1375
0
        tcp_con->unsleep = 1;
1376
0
    }
1377
1378
151
    if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
1379
48
        return -1;
1380
48
    }
1381
1382
103
    if (tcp_con->status == TCP_CONN_CONNECTED) {
1383
103
        if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
1384
103
            tcp_con->connected_time = mono_time_get(tcp_c->mono_time);
1385
103
        }
1386
103
    }
1387
1388
103
    return 0;
1389
151
}
1390
1391
/** @brief Add a TCP relay tied to a connection.
1392
 *
1393
 * This should be called with the same relay by two peers who want to create a TCP connection with each other.
1394
 *
1395
 * return 0 on success.
1396
 * return -1 on failure.
1397
 */
1398
int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, const IP_Port *ip_port,
1399
                             const uint8_t *relay_pk)
1400
106
{
1401
106
    TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1402
1403
106
    if (con_to == nullptr) {
1404
0
        return -1;
1405
0
    }
1406
1407
106
    int tcp_connections_number = find_tcp_connection_relay(tcp_c, relay_pk);
1408
1409
106
    if (tcp_connections_number != -1) {
1410
102
        return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number);
1411
102
    }
1412
1413
4
    if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1414
0
        return -1;
1415
0
    }
1416
1417
4
    tcp_connections_number = add_tcp_relay_instance(tcp_c, ip_port, relay_pk);
1418
1419
4
    const TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
1420
1421
4
    if (tcp_con == nullptr) {
1422
0
        return -1;
1423
0
    }
1424
1425
4
    if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
1426
0
        return -1;
1427
0
    }
1428
1429
4
    return 0;
1430
4
}
1431
1432
/**
1433
 * @return number of online tcp relays tied to the connection on success.
1434
 * @retval 0 on failure.
1435
 */
1436
uint32_t tcp_connection_to_online_tcp_relays(const TCP_Connections *tcp_c, int connections_number)
1437
97.7k
{
1438
97.7k
    const TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1439
1440
97.7k
    if (con_to == nullptr) {
1441
0
        return 0;
1442
0
    }
1443
1444
97.7k
    return online_tcp_connection_from_conn(con_to);
1445
97.7k
}
1446
1447
/** @brief Copies the tcp relay from tcp connections designated by `idx` to `tcp_relay`.
1448
 *
1449
 * Returns true if the relay was successfully copied.
1450
 * Returns false if the connection index is invalid, or if the relay is not connected.
1451
 */
1452
non_null()
1453
static bool copy_tcp_relay_conn(const TCP_Connections *tcp_c, Node_format *tcp_relay, uint16_t idx)
1454
472
{
1455
472
    const TCP_con *tcp_con = get_tcp_connection(tcp_c, idx);
1456
1457
472
    if (tcp_con == nullptr) {
1458
0
        return false;
1459
0
    }
1460
1461
472
    if (tcp_con->status != TCP_CONN_CONNECTED) {
1462
0
        return false;
1463
0
    }
1464
1465
472
    memcpy(tcp_relay->public_key, tcp_con_public_key(tcp_con->connection), CRYPTO_PUBLIC_KEY_SIZE);
1466
472
    tcp_relay->ip_port = tcp_con_ip_port(tcp_con->connection);
1467
1468
472
    Family *const family = &tcp_relay->ip_port.ip.family;
1469
1470
472
    if (net_family_is_ipv4(*family)) {
1471
472
        *family = net_family_tcp_ipv4();
1472
472
    } else if (net_family_is_ipv6(*family)) {
1473
0
        *family = net_family_tcp_ipv6();
1474
0
    }
1475
1476
472
    return true;
1477
472
}
1478
1479
/** @brief Copy a maximum of max_num TCP relays we are connected to to tcp_relays.
1480
 *
1481
 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
1482
 *
1483
 * return number of relays copied to tcp_relays on success.
1484
 * return 0 on failure.
1485
 */
1486
uint32_t tcp_copy_connected_relays(const TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num)
1487
15.8k
{
1488
15.8k
    const uint32_t r = random_u32(tcp_c->rng);
1489
15.8k
    uint32_t copied = 0;
1490
1491
16.3k
    for (uint32_t i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) {
1492
472
        const uint16_t idx = (i + r) % tcp_c->tcp_connections_length;
1493
1494
472
        if (copy_tcp_relay_conn(tcp_c, &tcp_relays[copied], idx)) {
1495
472
            ++copied;
1496
472
        }
1497
472
    }
1498
1499
15.8k
    return copied;
1500
15.8k
}
1501
1502
uint32_t tcp_copy_connected_relays_index(const TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num,
1503
        uint32_t idx)
1504
138k
{
1505
138k
    if (tcp_c->tcp_connections_length == 0) {
1506
138k
        return 0;
1507
138k
    }
1508
1509
461
    uint32_t copied = 0;
1510
461
    const uint16_t num_to_copy = min_u16(max_num, tcp_c->tcp_connections_length);
1511
461
    const uint16_t start = idx % tcp_c->tcp_connections_length;
1512
461
    const uint16_t end = (start + num_to_copy) % tcp_c->tcp_connections_length;
1513
1514
461
    for (uint16_t i = start; i != end; i = (i + 1) % tcp_c->tcp_connections_length) {
1515
0
        if (copy_tcp_relay_conn(tcp_c, &tcp_relays[copied], i)) {
1516
0
            ++copied;
1517
0
        }
1518
0
    }
1519
1520
461
    return copied;
1521
138k
}
1522
1523
/** @brief Set if we want TCP_connection to allocate some connection for onion use.
1524
 *
1525
 * If status is 1, allocate some connections. if status is 0, don't.
1526
 *
1527
 * return 0 on success.
1528
 * return -1 on failure.
1529
 */
1530
int set_tcp_onion_status(TCP_Connections *tcp_c, bool status)
1531
30.4k
{
1532
30.4k
    if (tcp_c->onion_status == status) {
1533
28.5k
        return -1;
1534
28.5k
    }
1535
1536
1.89k
    if (status) {
1537
2.18k
        for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
1538
287
            TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1539
1540
287
            if (tcp_con != nullptr) {
1541
267
                if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion) {
1542
52
                    ++tcp_c->onion_num_conns;
1543
52
                    tcp_con->onion = 1;
1544
52
                }
1545
267
            }
1546
1547
287
            if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS) {
1548
0
                break;
1549
0
            }
1550
287
        }
1551
1552
1.89k
        if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
1553
1.89k
            const unsigned int wakeup = NUM_ONION_TCP_CONNECTIONS - tcp_c->onion_num_conns;
1554
1555
2.18k
            for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
1556
287
                TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1557
1558
287
                if (tcp_con != nullptr) {
1559
267
                    if (tcp_con->status == TCP_CONN_SLEEPING) {
1560
0
                        tcp_con->unsleep = 1;
1561
0
                    }
1562
267
                }
1563
1564
287
                if (wakeup == 0) {
1565
0
                    break;
1566
0
                }
1567
287
            }
1568
1.89k
        }
1569
1570
1.89k
        tcp_c->onion_status = 1;
1571
1.89k
    } else {
1572
0
        for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
1573
0
            TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1574
1575
0
            if (tcp_con != nullptr) {
1576
0
                if (tcp_con->onion) {
1577
0
                    --tcp_c->onion_num_conns;
1578
0
                    tcp_con->onion = 0;
1579
0
                }
1580
0
            }
1581
0
        }
1582
1583
0
        tcp_c->onion_status = 0;
1584
0
    }
1585
1586
1.89k
    return 0;
1587
30.4k
}
1588
1589
/** @brief Returns a new TCP_Connections object associated with the secret_key.
1590
 *
1591
 * In order for others to connect to this instance `new_tcp_connection_to()` must be called with the
1592
 * public_key associated with secret_key.
1593
 *
1594
 * Returns NULL on failure.
1595
 */
1596
TCP_Connections *new_tcp_connections(const Logger *logger, const Memory *mem, const Random *rng, const Network *ns,
1597
                                     Mono_Time *mono_time, const uint8_t *secret_key, const TCP_Proxy_Info *proxy_info)
1598
4.30k
{
1599
4.30k
    assert(logger != nullptr);
1600
4.30k
    assert(mem != nullptr);
1601
4.30k
    assert(rng != nullptr);
1602
4.30k
    assert(ns != nullptr);
1603
4.30k
    assert(mono_time != nullptr);
1604
1605
4.30k
    if (secret_key == nullptr) {
1606
0
        return nullptr;
1607
0
    }
1608
1609
4.30k
    TCP_Connections *temp = (TCP_Connections *)mem_alloc(mem, sizeof(TCP_Connections));
1610
1611
4.30k
    if (temp == nullptr) {
1612
24
        return nullptr;
1613
24
    }
1614
1615
4.27k
    temp->logger = logger;
1616
4.27k
    temp->mem = mem;
1617
4.27k
    temp->rng = rng;
1618
4.27k
    temp->mono_time = mono_time;
1619
4.27k
    temp->ns = ns;
1620
1621
4.27k
    memcpy(temp->self_secret_key, secret_key, CRYPTO_SECRET_KEY_SIZE);
1622
4.27k
    crypto_derive_public_key(temp->self_public_key, temp->self_secret_key);
1623
4.27k
    temp->proxy_info = *proxy_info;
1624
1625
4.27k
    return temp;
1626
4.30k
}
1627
1628
non_null(1, 2) nullable(3)
1629
static void do_tcp_conns(const Logger *logger, TCP_Connections *tcp_c, void *userdata)
1630
227k
{
1631
247k
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
1632
19.5k
        TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1633
1634
19.5k
        if (tcp_con == nullptr) {
1635
1.81k
            continue;
1636
1.81k
        }
1637
1638
17.7k
        if (tcp_con->status != TCP_CONN_SLEEPING) {
1639
17.7k
            do_tcp_connection(logger, tcp_c->mono_time, tcp_con->connection, userdata);
1640
1641
            /* callbacks can change TCP connection address. */
1642
17.7k
            tcp_con = get_tcp_connection(tcp_c, i);
1643
1644
            // Make sure the TCP connection wasn't dropped in any of the callbacks.
1645
17.7k
            assert(tcp_con != nullptr);
1646
1647
17.7k
            if (tcp_con_status(tcp_con->connection) == TCP_CLIENT_DISCONNECTED) {
1648
151
                if (tcp_con->status == TCP_CONN_CONNECTED) {
1649
95
                    reconnect_tcp_relay_connection(tcp_c, i);
1650
95
                } else {
1651
56
                    kill_tcp_relay_connection(tcp_c, i);
1652
56
                }
1653
1654
151
                continue;
1655
151
            }
1656
1657
17.5k
            if (tcp_con->status == TCP_CONN_VALID && tcp_con_status(tcp_con->connection) == TCP_CLIENT_CONFIRMED) {
1658
200
                tcp_relay_on_online(tcp_c, i);
1659
200
            }
1660
1661
17.5k
            if (tcp_con->status == TCP_CONN_CONNECTED
1662
17.5k
                    && !tcp_con->onion && tcp_con->lock_count > 0
1663
17.5k
                    && tcp_con->lock_count == tcp_con->sleep_count
1664
17.5k
                    && mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
1665
0
                sleep_tcp_relay_connection(tcp_c, i);
1666
0
            }
1667
17.5k
        }
1668
1669
17.5k
        if (tcp_con->status == TCP_CONN_SLEEPING && tcp_con->unsleep) {
1670
0
            unsleep_tcp_relay_connection(tcp_c, i);
1671
0
        }
1672
17.5k
    }
1673
227k
}
1674
1675
non_null()
1676
static void kill_nonused_tcp(TCP_Connections *tcp_c)
1677
227k
{
1678
227k
    if (tcp_c->tcp_connections_length <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1679
227k
        return;
1680
227k
    }
1681
1682
27
    const uint32_t num_online = tcp_connected_relays_count(tcp_c);
1683
1684
27
    if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1685
27
        return;
1686
27
    }
1687
1688
0
    const uint32_t max_kill_count = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS;
1689
0
    uint32_t kill_count = 0;
1690
1691
0
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length && kill_count < max_kill_count; ++i) {
1692
0
        const TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1693
1694
0
        if (tcp_con == nullptr) {
1695
0
            continue;
1696
0
        }
1697
1698
0
        if (tcp_con->status == TCP_CONN_CONNECTED) {
1699
0
            if (tcp_con->onion || tcp_con->lock_count > 0) {  // connection is in use so we skip it
1700
0
                continue;
1701
0
            }
1702
1703
0
            if (mono_time_is_timeout(tcp_c->mono_time, tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
1704
0
                kill_tcp_relay_connection(tcp_c, i);
1705
0
                ++kill_count;
1706
0
            }
1707
0
        }
1708
0
    }
1709
0
}
1710
1711
void do_tcp_connections(const Logger *logger, TCP_Connections *tcp_c, void *userdata)
1712
227k
{
1713
227k
    do_tcp_conns(logger, tcp_c, userdata);
1714
227k
    kill_nonused_tcp(tcp_c);
1715
227k
}
1716
1717
void kill_tcp_connections(TCP_Connections *tcp_c)
1718
3.11k
{
1719
3.11k
    if (tcp_c == nullptr) {
1720
0
        return;
1721
0
    }
1722
1723
3.39k
    for (uint32_t i = 0; i < tcp_c->tcp_connections_length; ++i) {
1724
278
        kill_tcp_connection(tcp_c->tcp_connections[i].connection);
1725
278
    }
1726
1727
3.11k
    crypto_memzero(tcp_c->self_secret_key, sizeof(tcp_c->self_secret_key));
1728
1729
3.11k
    mem_delete(tcp_c->mem, tcp_c->tcp_connections);
1730
3.11k
    mem_delete(tcp_c->mem, tcp_c->connections);
1731
3.11k
    mem_delete(tcp_c->mem, tcp_c);
1732
3.11k
}