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