diff options
author | irungentoo <irungentoo@gmail.com> | 2015-04-21 14:30:39 -0400 |
---|---|---|
committer | irungentoo <irungentoo@gmail.com> | 2015-04-21 14:30:39 -0400 |
commit | 0a0ed452026129fc9055c35ab75cfadab6f0dc06 (patch) | |
tree | 5367d65cde7398bf39a45e3622a02f3b7fad9247 /toxcore/TCP_connection.c | |
parent | e4ae993a80261d12cf7adb7f797a56579c39ea91 (diff) |
If a net_crypto connection isn't using the TCP relays, disconnect from them.
TCP_connections can now be put to sleep, a state where they store what they
were connected to without being connected and then resumed from sleep.
Diffstat (limited to 'toxcore/TCP_connection.c')
-rw-r--r-- | toxcore/TCP_connection.c | 206 |
1 files changed, 193 insertions, 13 deletions
diff --git a/toxcore/TCP_connection.c b/toxcore/TCP_connection.c index 912f4be4..d2aa3d96 100644 --- a/toxcore/TCP_connection.c +++ b/toxcore/TCP_connection.c | |||
@@ -333,6 +333,9 @@ int tcp_send_oob_packet(TCP_Connections *tcp_c, unsigned int tcp_connections_num | |||
333 | if (!tcp_con) | 333 | if (!tcp_con) |
334 | return -1; | 334 | return -1; |
335 | 335 | ||
336 | if (tcp_con->status != TCP_CONN_CONNECTED) | ||
337 | return -1; | ||
338 | |||
336 | 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); |
337 | 340 | ||
338 | if (ret == 1) | 341 | if (ret == 1) |
@@ -404,8 +407,14 @@ static int find_tcp_connection_relay(TCP_Connections *tcp_c, const uint8_t *rela | |||
404 | TCP_con *tcp_con = get_tcp_connection(tcp_c, i); | 407 | TCP_con *tcp_con = get_tcp_connection(tcp_c, i); |
405 | 408 | ||
406 | if (tcp_con) { | 409 | if (tcp_con) { |
407 | if (memcmp(tcp_con->connection->public_key, relay_pk, crypto_box_PUBLICKEYBYTES) == 0) { | 410 | if (tcp_con->status == TCP_CONN_SLEEPING) { |
408 | 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 | } | ||
409 | } | 418 | } |
410 | } | 419 | } |
411 | } | 420 | } |
@@ -465,6 +474,10 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number) | |||
465 | 474 | ||
466 | if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) { | 475 | if (con_to->connections[i].status == TCP_CONNECTIONS_STATUS_ONLINE) { |
467 | --tcp_con->lock_count; | 476 | --tcp_con->lock_count; |
477 | |||
478 | if (con_to->status == TCP_CONN_SLEEPING) { | ||
479 | --tcp_con->sleep_count; | ||
480 | } | ||
468 | } | 481 | } |
469 | } | 482 | } |
470 | } | 483 | } |
@@ -472,6 +485,72 @@ int kill_tcp_connection_to(TCP_Connections *tcp_c, int connections_number) | |||
472 | return wipe_connection(tcp_c, connections_number); | 485 | return wipe_connection(tcp_c, connections_number); |
473 | } | 486 | } |
474 | 487 | ||
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 | */ | ||
498 | int 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 | |||
475 | static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connections_number) | 554 | static _Bool tcp_connection_in_conn(TCP_Connection_to *con_to, int tcp_connections_number) |
476 | { | 555 | { |
477 | unsigned int i; | 556 | unsigned int i; |
@@ -606,6 +685,9 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec | |||
606 | if (!tcp_con) | 685 | if (!tcp_con) |
607 | return -1; | 686 | return -1; |
608 | 687 | ||
688 | if (tcp_con->status == TCP_CONN_SLEEPING) | ||
689 | return -1; | ||
690 | |||
609 | IP_Port ip_port = tcp_con->connection->ip_port; | 691 | IP_Port ip_port = tcp_con->connection->ip_port; |
610 | uint8_t relay_pk[crypto_box_PUBLICKEYBYTES]; | 692 | uint8_t relay_pk[crypto_box_PUBLICKEYBYTES]; |
611 | memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES); | 693 | memcpy(relay_pk, tcp_con->connection->public_key, crypto_box_PUBLICKEYBYTES); |
@@ -634,12 +716,83 @@ static int reconnect_tcp_relay_connection(TCP_Connections *tcp_c, int tcp_connec | |||
634 | } | 716 | } |
635 | 717 | ||
636 | tcp_con->lock_count = 0; | 718 | tcp_con->lock_count = 0; |
719 | tcp_con->sleep_count = 0; | ||
637 | tcp_con->connected_time = 0; | 720 | tcp_con->connected_time = 0; |
638 | tcp_con->status = TCP_CONN_VALID; | 721 | tcp_con->status = TCP_CONN_VALID; |
722 | tcp_con->unsleep = 0; | ||
639 | 723 | ||
640 | return 0; | 724 | return 0; |
641 | } | 725 | } |
642 | 726 | ||
727 | static 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 | |||
770 | static 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 | |||
643 | /* Send a TCP routing request. | 796 | /* Send a TCP routing request. |
644 | * | 797 | * |
645 | * return 0 on success. | 798 | * return 0 on success. |
@@ -652,6 +805,9 @@ static int send_tcp_relay_routing_request(TCP_Connections *tcp_c, int tcp_connec | |||
652 | if (!tcp_con) | 805 | if (!tcp_con) |
653 | return -1; | 806 | return -1; |
654 | 807 | ||
808 | if (tcp_con->status == TCP_CONN_SLEEPING) | ||
809 | return -1; | ||
810 | |||
655 | if (send_routing_request(tcp_con->connection, public_key) != 1) | 811 | if (send_routing_request(tcp_con->connection, public_key) != 1) |
656 | return -1; | 812 | return -1; |
657 | 813 | ||
@@ -704,11 +860,19 @@ static int tcp_status_callback(void *object, uint32_t number, uint8_t connection | |||
704 | return -1; | 860 | return -1; |
705 | 861 | ||
706 | --tcp_con->lock_count; | 862 | --tcp_con->lock_count; |
863 | |||
864 | if (con_to->status == TCP_CONN_SLEEPING) { | ||
865 | --tcp_con->sleep_count; | ||
866 | } | ||
707 | } else if (status == 2) { | 867 | } else if (status == 2) { |
708 | 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) |
709 | return -1; | 869 | return -1; |
710 | 870 | ||
711 | ++tcp_con->lock_count; | 871 | ++tcp_con->lock_count; |
872 | |||
873 | if (con_to->status == TCP_CONN_SLEEPING) { | ||
874 | ++tcp_con->sleep_count; | ||
875 | } | ||
712 | } | 876 | } |
713 | 877 | ||
714 | return 0; | 878 | return 0; |
@@ -906,6 +1070,10 @@ int add_tcp_number_relay_connection(TCP_Connections *tcp_c, int connections_numb | |||
906 | if (!tcp_con) | 1070 | if (!tcp_con) |
907 | return -1; | 1071 | return -1; |
908 | 1072 | ||
1073 | if (con_to->status != TCP_CONN_SLEEPING && tcp_con->status == TCP_CONN_SLEEPING) { | ||
1074 | tcp_con->unsleep = 1; | ||
1075 | } | ||
1076 | |||
909 | if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) | 1077 | if (add_tcp_connection_to_conn(con_to, tcp_connections_number) == -1) |
910 | return -1; | 1078 | return -1; |
911 | 1079 | ||
@@ -1012,23 +1180,35 @@ static void do_tcp_conns(TCP_Connections *tcp_c) | |||
1012 | TCP_con *tcp_con = get_tcp_connection(tcp_c, i); | 1180 | TCP_con *tcp_con = get_tcp_connection(tcp_c, i); |
1013 | 1181 | ||
1014 | if (tcp_con) { | 1182 | if (tcp_con) { |
1015 | do_TCP_connection(tcp_con->connection); | 1183 | if (tcp_con->status != TCP_CONN_SLEEPING) { |
1184 | do_TCP_connection(tcp_con->connection); | ||
1185 | |||
1186 | /* callbacks can change TCP connection address. */ | ||
1187 | tcp_con = get_tcp_connection(tcp_c, i); | ||
1016 | 1188 | ||
1017 | /* callbacks can change TCP connection address. */ | 1189 | if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) { |
1018 | tcp_con = get_tcp_connection(tcp_c, i); | 1190 | if (tcp_con->status == TCP_CONN_CONNECTED) { |
1191 | reconnect_tcp_relay_connection(tcp_c, i); | ||
1192 | } else { | ||
1193 | kill_tcp_relay_connection(tcp_c, i); | ||
1194 | } | ||
1019 | 1195 | ||
1020 | if (tcp_con->connection->status == TCP_CLIENT_DISCONNECTED) { | 1196 | continue; |
1021 | if (tcp_con->status == TCP_CONN_CONNECTED) { | ||
1022 | reconnect_tcp_relay_connection(tcp_c, i); | ||
1023 | } else { | ||
1024 | kill_tcp_relay_connection(tcp_c, i); | ||
1025 | } | 1197 | } |
1026 | 1198 | ||
1027 | continue; | 1199 | if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) { |
1200 | tcp_relay_on_online(tcp_c, i); | ||
1201 | } | ||
1202 | |||
1203 | if (tcp_con->status == TCP_CONN_CONNECTED && !tcp_con->onion && tcp_con->lock_count | ||
1204 | && tcp_con->lock_count == tcp_con->sleep_count | ||
1205 | && is_timeout(tcp_con->connected_time, TCP_CONNECTION_ANNOUNCE_TIMEOUT)) { | ||
1206 | sleep_tcp_relay_connection(tcp_c, i); | ||
1207 | } | ||
1028 | } | 1208 | } |
1029 | 1209 | ||
1030 | if (tcp_con->status == TCP_CONN_VALID && tcp_con->connection->status == TCP_CLIENT_CONFIRMED) { | 1210 | if (tcp_con->status == TCP_CONN_SLEEPING && tcp_con->unsleep) { |
1031 | tcp_relay_on_online(tcp_c, i); | 1211 | unsleep_tcp_relay_connection(tcp_c, i); |
1032 | } | 1212 | } |
1033 | } | 1213 | } |
1034 | } | 1214 | } |