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