diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-05-20 00:35:13 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-05-20 00:36:20 +0200 |
commit | 0be37e812d034754eb725701f237fbc81b973904 (patch) | |
tree | c50481209ec97b5dbbd075489255477c5e761d3d /src/cadet/gnunet-service-cadet_connection.c | |
parent | c227e3f00efb4b3677e9b85c0273a7bf5fbcb4a9 (diff) | |
download | gnunet-0be37e812d034754eb725701f237fbc81b973904.tar.gz gnunet-0be37e812d034754eb725701f237fbc81b973904.zip |
fix off-by-one error in cadet connection construction, also enforce better timeouts for retransmissions of handshake
Diffstat (limited to 'src/cadet/gnunet-service-cadet_connection.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet_connection.c | 96 |
1 files changed, 69 insertions, 27 deletions
diff --git a/src/cadet/gnunet-service-cadet_connection.c b/src/cadet/gnunet-service-cadet_connection.c index 82ab5cc2c..9ff62b29f 100644 --- a/src/cadet/gnunet-service-cadet_connection.c +++ b/src/cadet/gnunet-service-cadet_connection.c | |||
@@ -39,6 +39,13 @@ | |||
39 | 39 | ||
40 | 40 | ||
41 | /** | 41 | /** |
42 | * How long do we wait initially before retransmitting the KX? | ||
43 | * TODO: replace by 2 RTT if/once we have connection-level RTT data! | ||
44 | */ | ||
45 | #define INITIAL_CONNECTION_CREATE_RETRY_DELAY GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MILLISECONDS, 200) | ||
46 | |||
47 | |||
48 | /** | ||
42 | * All the states a connection can be in. | 49 | * All the states a connection can be in. |
43 | */ | 50 | */ |
44 | enum CadetConnectionState | 51 | enum CadetConnectionState |
@@ -134,6 +141,16 @@ struct CadetConnection | |||
134 | struct GNUNET_TIME_Relative retry_delay; | 141 | struct GNUNET_TIME_Relative retry_delay; |
135 | 142 | ||
136 | /** | 143 | /** |
144 | * Earliest time for re-trying CREATE | ||
145 | */ | ||
146 | struct GNUNET_TIME_Absolute create_at; | ||
147 | |||
148 | /** | ||
149 | * Earliest time for re-trying CREATE_ACK | ||
150 | */ | ||
151 | struct GNUNET_TIME_Absolute create_ack_at; | ||
152 | |||
153 | /** | ||
137 | * Performance metrics for this connection. | 154 | * Performance metrics for this connection. |
138 | */ | 155 | */ |
139 | struct CadetConnectionMetrics metrics; | 156 | struct CadetConnectionMetrics metrics; |
@@ -482,8 +499,9 @@ GCC_latency_observed (const struct GNUNET_CADET_ConnectionTunnelIdentifier *cid, | |||
482 | 499 | ||
483 | 500 | ||
484 | /** | 501 | /** |
485 | * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for this connection, implying | 502 | * A #GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK was received for |
486 | * that the end-to-end connection is up. Process it. | 503 | * this connection, implying that the end-to-end connection is up. |
504 | * Process it. | ||
487 | * | 505 | * |
488 | * @param cc the connection that got the ACK. | 506 | * @param cc the connection that got the ACK. |
489 | */ | 507 | */ |
@@ -525,6 +543,11 @@ void | |||
525 | GCC_handle_kx (struct CadetConnection *cc, | 543 | GCC_handle_kx (struct CadetConnection *cc, |
526 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) | 544 | const struct GNUNET_CADET_TunnelKeyExchangeMessage *msg) |
527 | { | 545 | { |
546 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
547 | "Received KX message with ephermal %s on CC %s in state %d\n", | ||
548 | GNUNET_e2s (&msg->ephemeral_key), | ||
549 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
550 | cc->state); | ||
528 | if (CADET_CONNECTION_SENT == cc->state) | 551 | if (CADET_CONNECTION_SENT == cc->state) |
529 | { | 552 | { |
530 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | 553 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, |
@@ -549,6 +572,11 @@ void | |||
549 | GCC_handle_kx_auth (struct CadetConnection *cc, | 572 | GCC_handle_kx_auth (struct CadetConnection *cc, |
550 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) | 573 | const struct GNUNET_CADET_TunnelKeyExchangeAuthMessage *msg) |
551 | { | 574 | { |
575 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
576 | "Received KX AUTH message with ephermal %s on CC %s in state %d\n", | ||
577 | GNUNET_e2s (&msg->kx.ephemeral_key), | ||
578 | GNUNET_sh2s (&cc->cid.connection_of_tunnel), | ||
579 | cc->state); | ||
552 | if (CADET_CONNECTION_SENT == cc->state) | 580 | if (CADET_CONNECTION_SENT == cc->state) |
553 | { | 581 | { |
554 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, | 582 | /* We didn't get the CADET_CONNECTION_CREATE_ACK, but instead got payload. That's fine, |
@@ -601,25 +629,26 @@ send_create (void *cls) | |||
601 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; | 629 | struct GNUNET_CADET_ConnectionCreateMessage *create_msg; |
602 | struct GNUNET_PeerIdentity *pids; | 630 | struct GNUNET_PeerIdentity *pids; |
603 | struct GNUNET_MQ_Envelope *env; | 631 | struct GNUNET_MQ_Envelope *env; |
604 | unsigned int path_length; | ||
605 | 632 | ||
606 | cc->task = NULL; | 633 | cc->task = NULL; |
607 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); | 634 | GNUNET_assert (GNUNET_YES == cc->mqm_ready); |
608 | path_length = GCPP_get_length (cc->path); | ||
609 | env = GNUNET_MQ_msg_extra (create_msg, | 635 | env = GNUNET_MQ_msg_extra (create_msg, |
610 | (1 + path_length) * sizeof (struct GNUNET_PeerIdentity), | 636 | (2 + cc->off) * sizeof (struct GNUNET_PeerIdentity), |
611 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); | 637 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE); |
612 | create_msg->options = htonl ((uint32_t) cc->options); | 638 | create_msg->options = htonl ((uint32_t) cc->options); |
613 | create_msg->cid = cc->cid; | 639 | create_msg->cid = cc->cid; |
614 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; | 640 | pids = (struct GNUNET_PeerIdentity *) &create_msg[1]; |
615 | pids[0] = my_full_id; | 641 | pids[0] = my_full_id; |
616 | for (unsigned int i=0;i<path_length;i++) | 642 | for (unsigned int i=0;i<=cc->off;i++) |
617 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, | 643 | pids[i + 1] = *GCP_get_id (GCPP_get_peer_at_offset (cc->path, |
618 | i)); | 644 | i)); |
619 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 645 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
620 | "Sending CADET_CONNECTION_CREATE message for %s\n", | 646 | "Sending CADET_CONNECTION_CREATE message for %s with %u hops\n", |
621 | GCC_2s (cc)); | 647 | GCC_2s (cc), |
648 | cc->off + 2); | ||
622 | cc->env = env; | 649 | cc->env = env; |
650 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | ||
651 | cc->create_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay); | ||
623 | update_state (cc, | 652 | update_state (cc, |
624 | CADET_CONNECTION_SENT, | 653 | CADET_CONNECTION_SENT, |
625 | GNUNET_NO); | 654 | GNUNET_NO); |
@@ -641,7 +670,6 @@ send_create_ack (void *cls) | |||
641 | struct GNUNET_MQ_Envelope *env; | 670 | struct GNUNET_MQ_Envelope *env; |
642 | 671 | ||
643 | cc->task = NULL; | 672 | cc->task = NULL; |
644 | GNUNET_assert (CADET_CONNECTION_CREATE_RECEIVED == cc->state); | ||
645 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 673 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
646 | "Sending CONNECTION_CREATE_ACK message for %s\n", | 674 | "Sending CONNECTION_CREATE_ACK message for %s\n", |
647 | GCC_2s (cc)); | 675 | GCC_2s (cc)); |
@@ -650,9 +678,16 @@ send_create_ack (void *cls) | |||
650 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); | 678 | GNUNET_MESSAGE_TYPE_CADET_CONNECTION_CREATE_ACK); |
651 | ack_msg->cid = cc->cid; | 679 | ack_msg->cid = cc->cid; |
652 | cc->env = env; | 680 | cc->env = env; |
653 | update_state (cc, | 681 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); |
654 | CADET_CONNECTION_READY, | 682 | cc->create_ack_at = GNUNET_TIME_relative_to_absolute (cc->retry_delay); |
655 | GNUNET_NO); | 683 | if (CADET_CONNECTION_CREATE_RECEIVED == cc->state) |
684 | update_state (cc, | ||
685 | CADET_CONNECTION_READY, | ||
686 | GNUNET_NO); | ||
687 | if (CADET_CONNECTION_READY == cc->state) | ||
688 | cc->task = GNUNET_SCHEDULER_add_delayed (keepalive_period, | ||
689 | &send_keepalive, | ||
690 | cc); | ||
656 | GCP_send (cc->mq_man, | 691 | GCP_send (cc->mq_man, |
657 | env); | 692 | env); |
658 | } | 693 | } |
@@ -681,8 +716,9 @@ GCC_handle_duplicate_create (struct CadetConnection *cc) | |||
681 | cc->mqm_ready); | 716 | cc->mqm_ready); |
682 | if (NULL != cc->task) | 717 | if (NULL != cc->task) |
683 | GNUNET_SCHEDULER_cancel (cc->task); | 718 | GNUNET_SCHEDULER_cancel (cc->task); |
684 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | 719 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_ack_at, |
685 | cc); | 720 | &send_create_ack, |
721 | cc); | ||
686 | } | 722 | } |
687 | else | 723 | else |
688 | { | 724 | { |
@@ -721,7 +757,7 @@ manage_first_hop_mq (void *cls, | |||
721 | update_state (cc, | 757 | update_state (cc, |
722 | CADET_CONNECTION_NEW, | 758 | CADET_CONNECTION_NEW, |
723 | GNUNET_NO); | 759 | GNUNET_NO); |
724 | cc->retry_delay = GNUNET_TIME_UNIT_ZERO; | 760 | cc->retry_delay = INITIAL_CONNECTION_CREATE_RETRY_DELAY; |
725 | if (NULL != cc->task) | 761 | if (NULL != cc->task) |
726 | { | 762 | { |
727 | GNUNET_SCHEDULER_cancel (cc->task); | 763 | GNUNET_SCHEDULER_cancel (cc->task); |
@@ -741,8 +777,9 @@ manage_first_hop_mq (void *cls, | |||
741 | { | 777 | { |
742 | case CADET_CONNECTION_NEW: | 778 | case CADET_CONNECTION_NEW: |
743 | /* Transmit immediately */ | 779 | /* Transmit immediately */ |
744 | cc->task = GNUNET_SCHEDULER_add_now (&send_create, | 780 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, |
745 | cc); | 781 | &send_create, |
782 | cc); | ||
746 | break; | 783 | break; |
747 | case CADET_CONNECTION_SENDING_CREATE: | 784 | case CADET_CONNECTION_SENDING_CREATE: |
748 | /* Should not be possible to be called in this state. */ | 785 | /* Should not be possible to be called in this state. */ |
@@ -750,16 +787,16 @@ manage_first_hop_mq (void *cls, | |||
750 | break; | 787 | break; |
751 | case CADET_CONNECTION_SENT: | 788 | case CADET_CONNECTION_SENT: |
752 | /* Retry a bit later... */ | 789 | /* Retry a bit later... */ |
753 | cc->retry_delay = GNUNET_TIME_STD_BACKOFF (cc->retry_delay); | 790 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_at, |
754 | cc->task = GNUNET_SCHEDULER_add_delayed (cc->retry_delay, | 791 | &send_create, |
755 | &send_create, | 792 | cc); |
756 | cc); | ||
757 | break; | 793 | break; |
758 | case CADET_CONNECTION_CREATE_RECEIVED: | 794 | case CADET_CONNECTION_CREATE_RECEIVED: |
759 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ | 795 | /* We got the 'CREATE' (incoming connection), should send the CREATE_ACK */ |
760 | cc->metrics.age = GNUNET_TIME_absolute_get (); | 796 | cc->metrics.age = GNUNET_TIME_absolute_get (); |
761 | cc->task = GNUNET_SCHEDULER_add_now (&send_create_ack, | 797 | cc->task = GNUNET_SCHEDULER_add_at (cc->create_ack_at, |
762 | cc); | 798 | &send_create_ack, |
799 | cc); | ||
763 | break; | 800 | break; |
764 | case CADET_CONNECTION_READY: | 801 | case CADET_CONNECTION_READY: |
765 | if ( (NULL == cc->keepalive_qe) && | 802 | if ( (NULL == cc->keepalive_qe) && |
@@ -814,6 +851,8 @@ connection_create (struct CadetPeer *destination, | |||
814 | cc->state = init_state; | 851 | cc->state = init_state; |
815 | cc->ct = ct; | 852 | cc->ct = ct; |
816 | cc->cid = *cid; | 853 | cc->cid = *cid; |
854 | cc->retry_delay = GNUNET_TIME_relative_multiply (INITIAL_CONNECTION_CREATE_RETRY_DELAY, | ||
855 | off); | ||
817 | GNUNET_assert (GNUNET_OK == | 856 | GNUNET_assert (GNUNET_OK == |
818 | GNUNET_CONTAINER_multishortmap_put (connections, | 857 | GNUNET_CONTAINER_multishortmap_put (connections, |
819 | &GCC_get_id (cc)->connection_of_tunnel, | 858 | &GCC_get_id (cc)->connection_of_tunnel, |
@@ -824,9 +863,10 @@ connection_create (struct CadetPeer *destination, | |||
824 | cc->path = path; | 863 | cc->path = path; |
825 | cc->off = off; | 864 | cc->off = off; |
826 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 865 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
827 | "Creating %s using path %s\n", | 866 | "Creating %s using path %s (offset: %u)\n", |
828 | GCC_2s (cc), | 867 | GCC_2s (cc), |
829 | GCPP_2s (path)); | 868 | GCPP_2s (path), |
869 | off); | ||
830 | GCPP_add_connection (path, | 870 | GCPP_add_connection (path, |
831 | off, | 871 | off, |
832 | cc); | 872 | cc); |
@@ -834,7 +874,6 @@ connection_create (struct CadetPeer *destination, | |||
834 | GCP_add_connection (GCPP_get_peer_at_offset (path, | 874 | GCP_add_connection (GCPP_get_peer_at_offset (path, |
835 | i), | 875 | i), |
836 | cc); | 876 | cc); |
837 | |||
838 | first_hop = GCPP_get_peer_at_offset (path, | 877 | first_hop = GCPP_get_peer_at_offset (path, |
839 | 0); | 878 | 0); |
840 | cc->mq_man = GCP_request_mq (first_hop, | 879 | cc->mq_man = GCP_request_mq (first_hop, |
@@ -1001,11 +1040,14 @@ GCC_transmit (struct CadetConnection *cc, | |||
1001 | * Obtain the path used by this connection. | 1040 | * Obtain the path used by this connection. |
1002 | * | 1041 | * |
1003 | * @param cc connection | 1042 | * @param cc connection |
1043 | * @param off[out] set to the length of the path we use | ||
1004 | * @return path to @a cc | 1044 | * @return path to @a cc |
1005 | */ | 1045 | */ |
1006 | struct CadetPeerPath * | 1046 | struct CadetPeerPath * |
1007 | GCC_get_path (struct CadetConnection *cc) | 1047 | GCC_get_path (struct CadetConnection *cc, |
1048 | unsigned int *off) | ||
1008 | { | 1049 | { |
1050 | *off = cc->off; | ||
1009 | return cc->path; | 1051 | return cc->path; |
1010 | } | 1052 | } |
1011 | 1053 | ||