summaryrefslogtreecommitdiff
path: root/toxcore/TCP_connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'toxcore/TCP_connection.c')
-rw-r--r--toxcore/TCP_connection.c480
1 files changed, 433 insertions, 47 deletions
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c
index e11e1318..fe39dc52 100644
--- a/toxcore/TCP_connection.c
+++ b/toxcore/TCP_connection.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include "TCP_connection.h" 28#include "TCP_connection.h"
29#include "util.h"
29 30
30/* Set the size of the array to num. 31/* Set the size of the array to num.
31 * 32 *
@@ -212,6 +213,8 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
212 unsigned int i; 213 unsigned int i;
213 int ret = -1; 214 int ret = -1;
214 215
216 _Bool limit_reached = 0;
217
215 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 218 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
216 uint32_t tcp_con_num = con_to->connections[i].tcp_connection; 219 uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
217 uint8_t status = con_to->connections[i].status; 220 uint8_t status = con_to->connections[i].status;
@@ -227,6 +230,10 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
227 230
228 ret = send_data(tcp_con->connection, connection_id, packet, length); 231 ret = send_data(tcp_con->connection, connection_id, packet, length);
229 232
233 if (ret == 0) {
234 limit_reached = 1;
235 }
236
230 if (ret == 1) { 237 if (ret == 1) {
231 break; 238 break;
232 } 239 }
@@ -235,7 +242,10 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
235 242
236 if (ret == 1) { 243 if (ret == 1) {
237 return 0; 244 return 0;
238 } else { 245 } else if (!limit_reached) {
246 ret = 0;
247
248 /* Send oob packets to all relays tied to the connection. */
239 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 249 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
240 uint32_t tcp_con_num = con_to->connections[i].tcp_connection; 250 uint32_t tcp_con_num = con_to->connections[i].tcp_connection;
241 uint8_t status = con_to->connections[i].status; 251 uint8_t status = con_to->connections[i].status;
@@ -249,19 +259,19 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
249 continue; 259 continue;
250 } 260 }
251 261
252 ret = send_oob_packet(tcp_con->connection, con_to->public_key, packet, length); 262 if (send_oob_packet(tcp_con->connection, con_to->public_key, packet, length) == 1) {
253 263 ret += 1;
254 if (ret == 1) {
255 break;
256 } 264 }
257 } 265 }
258 } 266 }
259 267
260 if (ret == 1) { 268 if (ret >= 1) {
261 return 0; 269 return 0;
262 } else { 270 } else {
263 return -1; 271 return -1;
264 } 272 }
273 } else {
274 return -1;
265 } 275 }
266} 276}
267 277
@@ -273,13 +283,15 @@ int send_packet_tcp_connection(TCP_Connections *tcp_c, int connections_number, c
273 * return TCP connection number on success. 283 * return TCP connection number on success.
274 * return -1 on failure. 284 * return -1 on failure.
275 */ 285 */
276int get_random_tcp_conn_number(TCP_Connections *tcp_c) 286int get_random_tcp_onion_conn_number(TCP_Connections *tcp_c)
277{ 287{
278 unsigned int i, r = rand(); 288 unsigned int i, r = rand();
279 289
280 for (i = 0; i < tcp_c->tcp_connections_length; ++i) { 290 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
281 if (tcp_c->tcp_connections[(i + r) % tcp_c->tcp_connections_length].status == TCP_CONN_CONNECTED) { 291 unsigned int index = ((i + r) % tcp_c->tcp_connections_length);
282 return ((i + r) % tcp_c->tcp_connections_length); 292
293 if (tcp_c->tcp_connections[index].onion && tcp_c->tcp_connections[index].status == TCP_CONN_CONNECTED) {
294 return index;
283 } 295 }
284 } 296 }
285 297
@@ -321,6 +333,9 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num
321 if (!tcp_con) 333 if (!tcp_con)
322 return -1; 334 return -1;
323 335
336 if (tcp_con->status != TCP_CONN_CONNECTED)
337 return -1;
338
324 int ret = send_oob_packet(tcp_con->connection, public_key, packet, length); 339 int ret = send_oob_packet(tcp_con->connection, public_key, packet, length);
325 340
326 if (ret == 1) 341 if (ret == 1)
@@ -392,8 +407,14 @@ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *rela
392 TCP_con *tcp_con = get_tcp_connection(tcp_c, i); 407 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
393 408
394 if (tcp_con) { 409 if (tcp_con) {
395 if (memcmp(tcp_con->connection->public_key, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) { 410 if (tcp_con->status == TCP_CONN_SLEEPING) {
396 return i; 411 if (memcmp(tcp_con->relay_pk, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) {
412 return i;
413 }
414 } else {
415 if (memcmp(tcp_con->connection->public_key, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) {
416 return i;
417 }
397 } 418 }
398 } 419 }
399 } 420 }
@@ -451,14 +472,86 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number)
451 send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id); 472 send_disconnect_request(tcp_con->connection, con_to->connections[i].connection_id);
452 } 473 }
453 474
454 --tcp_con->lock_count; 475 if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
476 --tcp_con->lock_count;
477
478 if (con_to->status == TCP_CONN_SLEEPING) {
479 --tcp_con->sleep_count;
480 }
481 }
455 } 482 }
456 } 483 }
457 484
458 return wipe_connection(tcp_c, connections_number); 485 return wipe_connection(tcp_c, connections_number);
459} 486}
460 487
461static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connections_number) 488/* Set connection status.
489 *
490 * status of 1 means we are using the connection.
491 * status of 0 means we are not using it.
492 *
493 * Unused tcp connections will be disconnected from but kept in case they are needed.
494 *
495 * return 0 on success.
496 * return -1 on failure.
497 */
498int set_tcp_connection_to_status(TCP_Connections *tcp_c, int connections_number, _Bool status)
499{
500 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
501
502 if (!con_to)
503 return -1;
504
505 if (status) {
506 /* Conection is unsleeping. */
507 if (con_to->status != TCP_CONN_SLEEPING)
508 return -1;
509
510 unsigned int i;
511
512 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
513 if (con_to->connections[i].tcp_connection) {
514 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
515 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
516
517 if (!tcp_con)
518 continue;
519
520 if (tcp_con->status == TCP_CONN_SLEEPING) {
521 tcp_con->unsleep = 1;
522 }
523 }
524 }
525
526 con_to->status = TCP_CONN_VALID;
527 return 0;
528 } else {
529 /* Conection is going to sleep. */
530 if (con_to->status != TCP_CONN_VALID)
531 return -1;
532
533 unsigned int i;
534
535 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
536 if (con_to->connections[i].tcp_connection) {
537 unsigned int tcp_connections_number = con_to->connections[i].tcp_connection - 1;
538 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
539
540 if (!tcp_con)
541 continue;
542
543 if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
544 ++tcp_con->sleep_count;
545 }
546 }
547 }
548
549 con_to->status = TCP_CONN_SLEEPING;
550 return 0;
551 }
552}
553
554static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
462{ 555{
463 unsigned int i; 556 unsigned int i;
464 557
@@ -474,7 +567,7 @@ static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connectio
474/* return index on success. 567/* return index on success.
475 * return -1 on failure. 568 * return -1 on failure.
476 */ 569 */
477static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, int tcp_connections_number) 570static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
478{ 571{
479 unsigned int i; 572 unsigned int i;
480 573
@@ -496,7 +589,7 @@ static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, int tcp_connect
496/* return index on success. 589/* return index on success.
497 * return -1 on failure. 590 * return -1 on failure.
498 */ 591 */
499static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, int tcp_connections_number) 592static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, unsigned int tcp_connections_number)
500{ 593{
501 unsigned int i; 594 unsigned int i;
502 595
@@ -512,16 +605,39 @@ static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, int tcp_connec
512 return -1; 605 return -1;
513} 606}
514 607
608/* return number of online connections on success.
609 * return -1 on failure.
610 */
611static unsigned int online_tcp_connection_from_conn(TCP_Connection_to *con_to)
612{
613 unsigned int i, count = 0;
614
615 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
616 if (con_to->connections[i].tcp_connection) {
617 if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) {
618 ++count;
619 }
620 }
621 }
622
623 return count;
624}
625
515/* return index on success. 626/* return index on success.
516 * return -1 on failure. 627 * return -1 on failure.
517 */ 628 */
518static int set_tcp_connection_status(TCP_Connection_to *con_to, int tcp_connections_number, unsigned int status, 629static int set_tcp_connection_status(TCP_Connection_to *con_to, unsigned int tcp_connections_number,
519 uint8_t connection_id) 630 unsigned int status, uint8_t connection_id)
520{ 631{
521 unsigned int i; 632 unsigned int i;
522 633
523 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) { 634 for (i = 0; i < MAX_FRIEND_TCP_CONNECTIONS; ++i) {
524 if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) { 635 if (con_to->connections[i].tcp_connection == (tcp_connections_number + 1)) {
636
637 if (con_to->connections[i].status == status) {
638 return -1;
639 }
640
525 con_to->connections[i].status = status; 641 con_to->connections[i].status = status;
526 con_to->connections[i].connection_id = connection_id; 642 con_to->connections[i].connection_id = connection_id;
527 return i; 643 return i;
@@ -553,11 +669,130 @@ static int kill_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections
553 } 669 }
554 } 670 }
555 671
672 if (tcp_con->onion) {
673 --tcp_c->onion_num_conns;
674 }
675
556 kill_TCP_connection(tcp_con->connection); 676 kill_TCP_connection(tcp_con->connection);
557 677
558 return wipe_tcp_connection(tcp_c, tcp_connections_number); 678 return wipe_tcp_connection(tcp_c, tcp_connections_number);
559} 679}
560 680
681static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
682{
683 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
684
685 if (!tcp_con)
686 return -1;
687
688 if (tcp_con->status == TCP_CONN_SLEEPING)
689 return -1;
690
691 IP_Port ip_port = tcp_con->connection->ip_port;
692 uint8_t relay_pk[crypto_box_PUBLICKEYBYTES];
693 memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES);
694 kill_TCP_connection(tcp_con->connection);
695 tcp_con->connection = new_TCP_connection(ip_port, relay_pk, tcp_c->dht->self_public_key, tcp_c->dht->self_secret_key,
696 &tcp_c->proxy_info);
697
698 if (!tcp_con->connection) {
699 kill_tcp_relay_connection(tcp_c, tcp_connections_number);
700 return -1;
701 }
702
703 unsigned int i;
704
705 for (i = 0; i < tcp_c->connections_length; ++i) {
706 TCP_Connection_to *con_to = get_connection(tcp_c, i);
707
708 if (con_to) {
709 set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
710 }
711 }
712
713 if (tcp_con->onion) {
714 --tcp_c->onion_num_conns;
715 tcp_con->onion = 0;
716 }
717
718 tcp_con->lock_count = 0;
719 tcp_con->sleep_count = 0;
720 tcp_con->connected_time = 0;
721 tcp_con->status = TCP_CONN_VALID;
722 tcp_con->unsleep = 0;
723
724 return 0;
725}
726
727static int sleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
728{
729 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
730
731 if (!tcp_con)
732 return -1;
733
734 if (tcp_con->status != TCP_CONN_CONNECTED)
735 return -1;
736
737 if (tcp_con->lock_count != tcp_con->sleep_count)
738 return -1;
739
740 tcp_con->ip_port = tcp_con->connection->ip_port;
741 memcpy(tcp_con->relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES);
742
743 kill_TCP_connection(tcp_con->connection);
744 tcp_con->connection = NULL;
745
746 unsigned int i;
747
748 for (i = 0; i < tcp_c->connections_length; ++i) {
749 TCP_Connection_to *con_to = get_connection(tcp_c, i);
750
751 if (con_to) {
752 set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_NONE, 0);
753 }
754 }
755
756 if (tcp_con->onion) {
757 --tcp_c->onion_num_conns;
758 tcp_con->onion = 0;
759 }
760
761 tcp_con->lock_count = 0;
762 tcp_con->sleep_count = 0;
763 tcp_con->connected_time = 0;
764 tcp_con->status = TCP_CONN_SLEEPING;
765 tcp_con->unsleep = 0;
766
767 return 0;
768}
769
770static int unsleep_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connections_number)
771{
772 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
773
774 if (!tcp_con)
775 return -1;
776
777 if (tcp_con->status != TCP_CONN_SLEEPING)
778 return -1;
779
780 tcp_con->connection = new_TCP_connection(tcp_con->ip_port, tcp_con->relay_pk, tcp_c->dht->self_public_key,
781 tcp_c->dht->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 tcp_con->lock_count = 0;
789 tcp_con->sleep_count = 0;
790 tcp_con->connected_time = 0;
791 tcp_con->status = TCP_CONN_VALID;
792 tcp_con->unsleep = 0;
793 return 0;
794}
795
561/* Send a TCP routing request. 796/* Send a TCP routing request.
562 * 797 *
563 * return 0 on success. 798 * return 0 on success.
@@ -570,6 +805,9 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec
570 if (!tcp_con) 805 if (!tcp_con)
571 return -1; 806 return -1;
572 807
808 if (tcp_con->status == TCP_CONN_SLEEPING)
809 return -1;
810
573 if (send_routing_request(tcp_con->connection, public_key) != 1) 811 if (send_routing_request(tcp_con->connection, public_key) != 1)
574 return -1; 812 return -1;
575 813
@@ -592,8 +830,6 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint
592 if (connections_number == -1) 830 if (connections_number == -1)
593 return -1; 831 return -1;
594 832
595 set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
596
597 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number); 833 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
598 834
599 if (con_to == NULL) 835 if (con_to == NULL)
@@ -602,6 +838,8 @@ static int tcp_response_callback(void *object, uint8_t connection_id, const uint
602 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) 838 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1)
603 return -1; 839 return -1;
604 840
841 set_tcp_connection_number(tcp_con->connection, connection_id, connections_number);
842
605 return 0; 843 return 0;
606} 844}
607 845
@@ -621,10 +859,20 @@ static int tcp_status_callback(void *object, uint32_t number, uint8_t connection
621 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1) 859 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_REGISTERED, connection_id) == -1)
622 return -1; 860 return -1;
623 861
862 --tcp_con->lock_count;
863
864 if (con_to->status == TCP_CONN_SLEEPING) {
865 --tcp_con->sleep_count;
866 }
624 } else if (status == 2) { 867 } else if (status == 2) {
625 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1) 868 if (set_tcp_connection_status(con_to, tcp_connections_number, TCP_CONNECTIONS_STATUS_ONLINE, connection_id) == -1)
626 return -1; 869 return -1;
627 870
871 ++tcp_con->lock_count;
872
873 if (con_to->status == TCP_CONN_SLEEPING) {
874 ++tcp_con->sleep_count;
875 }
628 } 876 }
629 877
630 return 0; 878 return 0;
@@ -673,11 +921,13 @@ static int tcp_oob_callback(void *object, const uint8_t *public_key, const uint8
673 /* TODO: optimize */ 921 /* TODO: optimize */
674 int connections_number = find_tcp_connection_to(tcp_c, public_key); 922 int connections_number = find_tcp_connection_to(tcp_c, public_key);
675 923
676 if (connections_number == -1) { 924 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
925
926 if (con_to && tcp_connection_in_conn(con_to, tcp_connections_number)) {
927 return tcp_data_callback(object, connections_number, 0, data, length);
928 } else {
677 if (tcp_c->tcp_oob_callback) 929 if (tcp_c->tcp_oob_callback)
678 tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length); 930 tcp_c->tcp_oob_callback(tcp_c->tcp_oob_callback_object, public_key, tcp_connections_number, data, length);
679 } else {
680 return tcp_data_callback(object, connections_number, 0, data, length);
681 } 931 }
682 932
683 return 0; 933 return 0;
@@ -725,20 +975,35 @@ static int tcp_relay_on_online(TCP_Connections *tcp_c, int tcp_connections_numbe
725 if (!tcp_con) 975 if (!tcp_con)
726 return -1; 976 return -1;
727 977
728 unsigned int i; 978 unsigned int i, sent = 0;
729 979
730 for (i = 0; i < tcp_c->connections_length; ++i) { 980 for (i = 0; i < tcp_c->connections_length; ++i) {
731 TCP_Connection_to *con_to = get_connection(tcp_c, i); 981 TCP_Connection_to *con_to = get_connection(tcp_c, i);
732 982
733 if (con_to) { 983 if (con_to) {
734 if (tcp_connection_in_conn(con_to, tcp_connections_number)) { 984 if (tcp_connection_in_conn(con_to, tcp_connections_number)) {
735 send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key); 985 if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
986 ++sent;
987 }
736 } 988 }
737 } 989 }
738 } 990 }
739 991
740 tcp_relay_set_callbacks(tcp_c, tcp_connections_number); 992 tcp_relay_set_callbacks(tcp_c, tcp_connections_number);
741 tcp_con->status = TCP_CONN_CONNECTED; 993 tcp_con->status = TCP_CONN_CONNECTED;
994
995 /* If this connection isn't used by any connection, we don't need to wait for them to come online. */
996 if (sent) {
997 tcp_con->connected_time = unix_time();
998 } else {
999 tcp_con->connected_time = 0;
1000 }
1001
1002 if (tcp_c->onion_status && tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
1003 tcp_con->onion = 1;
1004 ++tcp_c->onion_num_conns;
1005 }
1006
742 return 0; 1007 return 0;
743} 1008}
744 1009
@@ -807,13 +1072,17 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb
807 if (!tcp_con) 1072 if (!tcp_con)
808 return -1; 1073 return -1;
809 1074
1075 if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) {
1076 tcp_con->unsleep = 1;
1077 }
1078
810 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) 1079 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1)
811 return -1; 1080 return -1;
812 1081
813 ++tcp_con->lock_count;
814
815 if (tcp_con->status == TCP_CONN_CONNECTED) { 1082 if (tcp_con->status == TCP_CONN_CONNECTED) {
816 send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key); 1083 if (send_tcp_relay_routing_request(tcp_c, tcp_connections_number, con_to->public_key) == 0) {
1084 tcp_con->connected_time = unix_time();
1085 }
817 } 1086 }
818 1087
819 return 0; 1088 return 0;
@@ -836,22 +1105,38 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_
836 if (tcp_connections_number != -1) { 1105 if (tcp_connections_number != -1) {
837 return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number); 1106 return add_tcp_number_relay_connection(tcp_c, connections_number, tcp_connections_number);
838 } else { 1107 } else {
839 int tcp_connections_number = add_tcp_relay(tcp_c, ip_port, relay_pk); 1108 if (online_tcp_connection_from_conn(con_to) >= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
840
841 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
842 return -1; 1109 return -1;
843 } 1110 }
844 1111
1112 int tcp_connections_number = add_tcp_relay(tcp_c, ip_port, relay_pk);
1113
845 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number); 1114 TCP_con *tcp_con = get_tcp_connection(tcp_c, tcp_connections_number);
846 1115
847 if (!tcp_con) 1116 if (!tcp_con)
848 return -1; 1117 return -1;
849 1118
850 ++tcp_con->lock_count; 1119 if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) {
1120 return -1;
1121 }
1122
851 return 0; 1123 return 0;
852 } 1124 }
853} 1125}
854 1126
1127/* return number of online tcp relays tied to the connection on success.
1128 * return 0 on failure.
1129 */
1130unsigned int tcp_connection_to_online_tcp_relays(TCP_Connections *tcp_c, int connections_number)
1131{
1132 TCP_Connection_to *con_to = get_connection(tcp_c, connections_number);
1133
1134 if (!con_to)
1135 return 0;
1136
1137 return online_tcp_connection_from_conn(con_to);
1138}
1139
855/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays. 1140/* Copy a maximum of max_num TCP relays we are connected to to tcp_relays.
856 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6. 1141 * NOTE that the family of the copied ip ports will be set to TCP_INET or TCP_INET6.
857 * 1142 *
@@ -860,10 +1145,10 @@ int add_tcp_relay_connection(TCP_Connections *tcp_c, int connections_number, IP_
860 */ 1145 */
861unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num) 1146unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num)
862{ 1147{
863 unsigned int i, copied = 0; 1148 unsigned int i, copied = 0, r = rand();
864 1149
865 for (i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) { 1150 for (i = 0; (i < tcp_c->tcp_connections_length) && (copied < max_num); ++i) {
866 TCP_con *tcp_con = get_tcp_connection(tcp_c, i); 1151 TCP_con *tcp_con = get_tcp_connection(tcp_c, (i + r) % tcp_c->tcp_connections_length);
867 1152
868 if (!tcp_con) { 1153 if (!tcp_con) {
869 continue; 1154 continue;
@@ -886,7 +1171,74 @@ unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_
886 return copied; 1171 return copied;
887} 1172}
888 1173
889TCP_Connections *new_tcp_connections(DHT *dht) 1174/* Set if we want TCP_connection to allocate some connection for onion use.
1175 *
1176 * If status is 1, allocate some connections. if status is 0, don't.
1177 *
1178 * return 0 on success.
1179 * return -1 on failure.
1180 */
1181int set_tcp_onion_status(TCP_Connections *tcp_c, _Bool status)
1182{
1183 if (tcp_c->onion_status == status)
1184 return -1;
1185
1186 if (status) {
1187 unsigned int i;
1188
1189 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
1190 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1191
1192 if (tcp_con) {
1193 if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion) {
1194 ++tcp_c->onion_num_conns;
1195 tcp_con->onion = 1;
1196 }
1197 }
1198
1199 if (tcp_c->onion_num_conns >= NUM_ONION_TCP_CONNECTIONS)
1200 break;
1201 }
1202
1203 if (tcp_c->onion_num_conns < NUM_ONION_TCP_CONNECTIONS) {
1204 unsigned int wakeup = NUM_ONION_TCP_CONNECTIONS - tcp_c->onion_num_conns;
1205
1206 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
1207 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1208
1209 if (tcp_con) {
1210 if (tcp_con->status == TCP_CONN_SLEEPING) {
1211 tcp_con->unsleep = 1;
1212 }
1213 }
1214
1215 if (!wakeup)
1216 break;
1217 }
1218 }
1219
1220 tcp_c->onion_status = 1;
1221 } else {
1222 unsigned int i;
1223
1224 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
1225 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
1226
1227 if (tcp_con) {
1228 if (tcp_con->onion) {
1229 --tcp_c->onion_num_conns;
1230 tcp_con->onion = 0;
1231 }
1232 }
1233 }
1234
1235 tcp_c->onion_status = 0;
1236 }
1237
1238 return 0;
1239}
1240
1241TCP_Connections *new_tcp_connections(DHT *dht, TCP_Proxy_Info *proxy_info)
890{ 1242{
891 if (dht == NULL) 1243 if (dht == NULL)
892 return NULL; 1244 return NULL;
@@ -897,6 +1249,8 @@ TCP_Connections *new_tcp_connections(DHT *dht)
897 return NULL; 1249 return NULL;
898 1250
899 temp->dht = dht; 1251 temp->dht = dht;
1252 temp->proxy_info = *proxy_info;
1253
900 return temp; 1254 return temp;
901} 1255}
902 1256
@@ -908,18 +1262,35 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
908 TCP_con *tcp_con = get_tcp_connection(tcp_c, i); 1262 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
909 1263
910 if (tcp_con) { 1264 if (tcp_con) {
911 do_TCP_connection(tcp_con->connection); 1265 if (tcp_con->status != TCP_CONN_SLEEPING) {
1266 do_TCP_connection(tcp_con->connection);
912 1267
913 /* callbacks can change TCP connection address. */ 1268 /* callbacks can change TCP connection address. */
914 tcp_con = get_tcp_connection(tcp_c, i); 1269 tcp_con = get_tcp_connection(tcp_c, i);
915 1270
916 if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) { 1271 if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) {
917 kill_tcp_relay_connection(tcp_c, i); 1272 if (tcp_con->status == TCP_CONN_CONNECTED) {
918 continue; 1273 reconnect_tcp_relay_connection(tcp_c, i);
1274 } else {
1275 kill_tcp_relay_connection(tcp_c, i);
1276 }
1277
1278 continue;
1279 }
1280
1281 if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) {
1282 tcp_relay_on_online(tcp_c, i);
1283 }
1284
1285 if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count
1286 && tcp_con->lock_count == tcp_con->sleep_count
1287 && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
1288 sleep_tcp_relay_connection(tcp_c, i);
1289 }
919 } 1290 }
920 1291
921 if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) { 1292 if (tcp_con->status == TCP_CONN_SLEEPING && tcp_con->unsleep) {
922 tcp_relay_on_online(tcp_c, i); 1293 unsleep_tcp_relay_connection(tcp_c, i);
923 } 1294 }
924 } 1295 }
925 } 1296 }
@@ -927,27 +1298,42 @@ static void do_tcp_conns(TCP_Connections *tcp_c)
927 1298
928static void kill_nonused_tcp(TCP_Connections *tcp_c) 1299static void kill_nonused_tcp(TCP_Connections *tcp_c)
929{ 1300{
930 unsigned int i, num_online = 0; 1301 if (tcp_c->tcp_connections_length == 0)
1302 return;
1303
1304 unsigned int i, num_online = 0, num_kill = 0, to_kill[tcp_c->tcp_connections_length];
931 1305
932 for (i = 0; i < tcp_c->tcp_connections_length; ++i) { 1306 for (i = 0; i < tcp_c->tcp_connections_length; ++i) {
933 TCP_con *tcp_con = get_tcp_connection(tcp_c, i); 1307 TCP_con *tcp_con = get_tcp_connection(tcp_c, i);
934 1308
935 if (tcp_con) { 1309 if (tcp_con) {
936 if (tcp_con->status == TCP_CONN_CONNECTED) { 1310 if (tcp_con->status == TCP_CONN_CONNECTED) {
937 if (!tcp_con->lock_count && num_online >= MAX_FRIEND_TCP_CONNECTIONS) { 1311 if (!tcp_con->onion && !tcp_con->lock_count && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) {
938 kill_tcp_relay_connection(tcp_c, i); 1312 to_kill[num_kill] = i;
939 continue; 1313 ++num_kill;
940 } 1314 }
941 1315
942 ++num_online; 1316 ++num_online;
943 } 1317 }
944 } 1318 }
945 } 1319 }
1320
1321 if (num_online <= RECOMMENDED_FRIEND_TCP_CONNECTIONS) {
1322 return;
1323 } else {
1324 unsigned int n = num_online - RECOMMENDED_FRIEND_TCP_CONNECTIONS;
1325
1326 if (n < num_kill)
1327 num_kill = n;
1328 }
1329
1330 for (i = 0; i < num_kill; ++i) {
1331 kill_tcp_relay_connection(tcp_c, to_kill[i]);
1332 }
946} 1333}
947 1334
948void do_tcp_connections(TCP_Connections *tcp_c) 1335void do_tcp_connections(TCP_Connections *tcp_c)
949{ 1336{
950 //TODO reconnect to TCP relays if disconnects happen.
951 do_tcp_conns(tcp_c); 1337 do_tcp_conns(tcp_c);
952 kill_nonused_tcp(tcp_c); 1338 kill_nonused_tcp(tcp_c);
953} 1339}