diff options
Diffstat (limited to 'toxcore/TCP_connection.c')
-rw-r--r-- | toxcore/TCP_connection.c | 480 |
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 | */ |
276 | int get_random_tcp_conn_number(TCP_Connections *tcp_c) | 286 | int 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 | ||
461 | static _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 | */ | ||
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 | |||
554 | static _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 | */ |
477 | static int add_tcp_connection_to_conn(TCP_Connection_to *con_to, int tcp_connections_number) | 570 | static 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 | */ |
499 | static int rm_tcp_connection_from_conn(TCP_Connection_to *con_to, int tcp_connections_number) | 592 | static 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 | */ | ||
611 | static 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 | */ |
518 | static int set_tcp_connection_status(TCP_Connection_to *con_to, int tcp_connections_number, unsigned int status, | 629 | static 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 | ||
681 | static 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 | |||
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 | |||
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 | */ | ||
1130 | unsigned 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 | */ |
861 | unsigned int tcp_copy_connected_relays(TCP_Connections *tcp_c, Node_format *tcp_relays, uint16_t max_num) | 1146 | unsigned 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 | ||
889 | TCP_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 | */ | ||
1181 | int 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 | |||
1241 | TCP_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 | ||
928 | static void kill_nonused_tcp(TCP_Connections *tcp_c) | 1299 | static 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 | ||
948 | void do_tcp_connections(TCP_Connections *tcp_c) | 1335 | void 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 | } |