diff options
author | Christian Grothoff <christian@grothoff.org> | 2017-01-23 11:14:37 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2017-01-23 11:14:37 +0100 |
commit | 60ebf6febc36dffdcdec32d8968ec9706802e6f7 (patch) | |
tree | dd432b87d4fd9b9edaa6cbea0f8f38ba7e3c9418 /src/cadet/gnunet-service-cadet-new_channel.c | |
parent | 64f3755912bb85593f92a7e2e63810dbb3ab98ea (diff) | |
download | gnunet-60ebf6febc36dffdcdec32d8968ec9706802e6f7.tar.gz gnunet-60ebf6febc36dffdcdec32d8968ec9706802e6f7.zip |
fix shutdown sequence, start to handle loopback
Diffstat (limited to 'src/cadet/gnunet-service-cadet-new_channel.c')
-rw-r--r-- | src/cadet/gnunet-service-cadet-new_channel.c | 145 |
1 files changed, 96 insertions, 49 deletions
diff --git a/src/cadet/gnunet-service-cadet-new_channel.c b/src/cadet/gnunet-service-cadet-new_channel.c index f45c5e5ce..870732192 100644 --- a/src/cadet/gnunet-service-cadet-new_channel.c +++ b/src/cadet/gnunet-service-cadet-new_channel.c | |||
@@ -302,6 +302,11 @@ struct CadetChannel | |||
302 | int out_of_order; | 302 | int out_of_order; |
303 | 303 | ||
304 | /** | 304 | /** |
305 | * Is this channel a loopback channel, where the destination is us again? | ||
306 | */ | ||
307 | int is_loopback; | ||
308 | |||
309 | /** | ||
305 | * Flag to signal the destruction of the channel. If this is set to | 310 | * Flag to signal the destruction of the channel. If this is set to |
306 | * #GNUNET_YES the channel will be destroyed once the queue is | 311 | * #GNUNET_YES the channel will be destroyed once the queue is |
307 | * empty. | 312 | * empty. |
@@ -523,11 +528,38 @@ GCCH_channel_local_new (struct CadetClient *owner, | |||
523 | ch->owner = owner; | 528 | ch->owner = owner; |
524 | ch->ccn = ccn; | 529 | ch->ccn = ccn; |
525 | ch->port = *port; | 530 | ch->port = *port; |
526 | ch->t = GCP_get_tunnel (destination, | 531 | if (0 == memcmp (&my_full_id, |
527 | GNUNET_YES); | 532 | GCP_get_id (destination), |
528 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | 533 | sizeof (struct GNUNET_PeerIdentity))) |
529 | ch->ctn = GCT_add_channel (ch->t, | 534 | { |
530 | ch); | 535 | ch->is_loopback = GNUNET_YES; |
536 | ch->dest = GNUNET_CONTAINER_multihashmap_get (open_ports, | ||
537 | port); | ||
538 | if (NULL == ch->dest) | ||
539 | { | ||
540 | /* port closed, wait for it to possibly open */ | ||
541 | (void) GNUNET_CONTAINER_multihashmap_put (loose_channels, | ||
542 | port, | ||
543 | ch, | ||
544 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE); | ||
545 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
546 | "Created loose incoming loopback channel to port %s\n", | ||
547 | GNUNET_h2s (&ch->port)); | ||
548 | } | ||
549 | else | ||
550 | { | ||
551 | GCCH_bind (ch, | ||
552 | ch->dest); | ||
553 | } | ||
554 | } | ||
555 | else | ||
556 | { | ||
557 | ch->t = GCP_get_tunnel (destination, | ||
558 | GNUNET_YES); | ||
559 | ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME; | ||
560 | ch->ctn = GCT_add_channel (ch->t, | ||
561 | ch); | ||
562 | } | ||
531 | GNUNET_STATISTICS_update (stats, | 563 | GNUNET_STATISTICS_update (stats, |
532 | "# channels", | 564 | "# channels", |
533 | 1, | 565 | 1, |
@@ -537,7 +569,7 @@ GCCH_channel_local_new (struct CadetClient *owner, | |||
537 | GNUNET_h2s (port), | 569 | GNUNET_h2s (port), |
538 | GCP_2s (destination), | 570 | GCP_2s (destination), |
539 | GSC_2s (owner), | 571 | GSC_2s (owner), |
540 | GCT_2s (ch->t)); | 572 | (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t)); |
541 | return ch; | 573 | return ch; |
542 | } | 574 | } |
543 | 575 | ||
@@ -791,11 +823,18 @@ GCCH_bind (struct CadetChannel *ch, | |||
791 | &ch->port, | 823 | &ch->port, |
792 | options); | 824 | options); |
793 | ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */ | 825 | ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */ |
794 | 826 | if (GNUNET_YES == ch->is_loopback) | |
795 | /* notify other peer that we accepted the connection */ | 827 | { |
796 | ch->retry_control_task | 828 | ch->state = CADET_CHANNEL_OPEN_SENT; |
797 | = GNUNET_SCHEDULER_add_now (&send_open_ack, | 829 | GCCH_handle_channel_open_ack (ch); |
798 | ch); | 830 | } |
831 | else | ||
832 | { | ||
833 | /* notify other peer that we accepted the connection */ | ||
834 | ch->retry_control_task | ||
835 | = GNUNET_SCHEDULER_add_now (&send_open_ack, | ||
836 | ch); | ||
837 | } | ||
799 | /* give client it's initial supply of ACKs */ | 838 | /* give client it's initial supply of ACKs */ |
800 | env = GNUNET_MQ_msg (tcm, | 839 | env = GNUNET_MQ_msg (tcm, |
801 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); | 840 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE); |
@@ -812,17 +851,27 @@ GCCH_bind (struct CadetChannel *ch, | |||
812 | 851 | ||
813 | 852 | ||
814 | /** | 853 | /** |
815 | * Destroy locally created channel. Called by the | 854 | * Destroy locally created channel. Called by the local client, so no |
816 | * local client, so no need to tell the client. | 855 | * need to tell the client. |
817 | * | 856 | * |
818 | * @param ch channel to destroy | 857 | * @param ch channel to destroy |
858 | * @param c client that caused the destruction | ||
819 | */ | 859 | */ |
820 | void | 860 | void |
821 | GCCH_channel_local_destroy (struct CadetChannel *ch) | 861 | GCCH_channel_local_destroy (struct CadetChannel *ch, |
862 | struct CadetClient *c) | ||
822 | { | 863 | { |
823 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 864 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
824 | "Local client asks for destruction of %s which it initiated\n", | 865 | "%s asks for destruction of %s\n", |
866 | GSC_2s (c), | ||
825 | GCCH_2s (ch)); | 867 | GCCH_2s (ch)); |
868 | GNUNET_assert (NULL != c); | ||
869 | if (c == ch->owner) | ||
870 | ch->owner = NULL; | ||
871 | else if (c == ch->dest) | ||
872 | ch->dest = NULL; | ||
873 | else | ||
874 | GNUNET_assert (0); | ||
826 | if (GNUNET_YES == ch->destroy) | 875 | if (GNUNET_YES == ch->destroy) |
827 | { | 876 | { |
828 | /* other end already destroyed, with the local client gone, no need | 877 | /* other end already destroyed, with the local client gone, no need |
@@ -830,9 +879,12 @@ GCCH_channel_local_destroy (struct CadetChannel *ch) | |||
830 | channel_destroy (ch); | 879 | channel_destroy (ch); |
831 | return; | 880 | return; |
832 | } | 881 | } |
833 | if (NULL != ch->head_sent) | 882 | if ( (NULL != ch->head_sent) || |
883 | (NULL != ch->owner) || | ||
884 | (NULL != ch->dest) ) | ||
834 | { | 885 | { |
835 | /* allow send queue to train first */ | 886 | /* Wait for other end to destroy us as well, |
887 | and otherwise allow send queue to be transmitted first */ | ||
836 | ch->destroy = GNUNET_YES; | 888 | ch->destroy = GNUNET_YES; |
837 | return; | 889 | return; |
838 | } | 890 | } |
@@ -840,39 +892,7 @@ GCCH_channel_local_destroy (struct CadetChannel *ch) | |||
840 | if (CADET_CHANNEL_NEW != ch->state) | 892 | if (CADET_CHANNEL_NEW != ch->state) |
841 | GCT_send_channel_destroy (ch->t, | 893 | GCT_send_channel_destroy (ch->t, |
842 | ch->ctn); | 894 | ch->ctn); |
843 | /* Now finish our clean up */ | ||
844 | channel_destroy (ch); | ||
845 | } | ||
846 | |||
847 | |||
848 | /** | ||
849 | * Destroy channel that was incoming. Called by the | ||
850 | * local client, so no need to tell the client. | ||
851 | * | ||
852 | * @param ch channel to destroy | ||
853 | */ | ||
854 | void | ||
855 | GCCH_channel_incoming_destroy (struct CadetChannel *ch) | ||
856 | { | ||
857 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
858 | "Local client asks for destruction of %s which it accepted\n", | ||
859 | GCCH_2s (ch)); | ||
860 | if (GNUNET_YES == ch->destroy) | ||
861 | { | ||
862 | /* other end already destroyed, with the remote client gone, no need | ||
863 | to finish transmissions, just destroy immediately. */ | ||
864 | channel_destroy (ch); | ||
865 | return; | ||
866 | } | ||
867 | if (NULL != ch->head_recv) | ||
868 | { | ||
869 | /* allow local client to see all data first */ | ||
870 | ch->destroy = GNUNET_YES; | ||
871 | return; | ||
872 | } | ||
873 | /* Nothing left to do, just finish destruction */ | 895 | /* Nothing left to do, just finish destruction */ |
874 | GCT_send_channel_destroy (ch->t, | ||
875 | ch->ctn); | ||
876 | channel_destroy (ch); | 896 | channel_destroy (ch); |
877 | } | 897 | } |
878 | 898 | ||
@@ -980,6 +1000,12 @@ GCCH_handle_channel_plaintext_data (struct CadetChannel *ch, | |||
980 | "Receicved %u bytes of application data on %s\n", | 1000 | "Receicved %u bytes of application data on %s\n", |
981 | (unsigned int) payload_size, | 1001 | (unsigned int) payload_size, |
982 | GCCH_2s (ch)); | 1002 | GCCH_2s (ch)); |
1003 | if (GNUNET_YES == ch->is_loopback) | ||
1004 | { | ||
1005 | GNUNET_break (0); // FIXME: not implemented | ||
1006 | return; | ||
1007 | } | ||
1008 | |||
983 | env = GNUNET_MQ_msg_extra (ld, | 1009 | env = GNUNET_MQ_msg_extra (ld, |
984 | payload_size, | 1010 | payload_size, |
985 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); | 1011 | GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA); |
@@ -1054,6 +1080,7 @@ GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, | |||
1054 | { | 1080 | { |
1055 | struct CadetReliableMessage *crm; | 1081 | struct CadetReliableMessage *crm; |
1056 | 1082 | ||
1083 | GNUNET_break (GNUNET_NO == ch->is_loopback); | ||
1057 | if (GNUNET_NO == ch->reliable) | 1084 | if (GNUNET_NO == ch->reliable) |
1058 | { | 1085 | { |
1059 | /* not expecting ACKs on unreliable channel, odd */ | 1086 | /* not expecting ACKs on unreliable channel, odd */ |
@@ -1104,9 +1131,23 @@ GCCH_handle_channel_plaintext_data_ack (struct CadetChannel *ch, | |||
1104 | void | 1131 | void |
1105 | GCCH_handle_remote_destroy (struct CadetChannel *ch) | 1132 | GCCH_handle_remote_destroy (struct CadetChannel *ch) |
1106 | { | 1133 | { |
1134 | GNUNET_break (GNUNET_NO == ch->is_loopback); | ||
1107 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1135 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1108 | "Received remote channel DESTROY for %s\n", | 1136 | "Received remote channel DESTROY for %s\n", |
1109 | GCCH_2s (ch)); | 1137 | GCCH_2s (ch)); |
1138 | if (GNUNET_YES == ch->destroy) | ||
1139 | { | ||
1140 | /* Local client already gone, this is instant-death. */ | ||
1141 | channel_destroy (ch); | ||
1142 | return; | ||
1143 | } | ||
1144 | if (NULL != ch->head_recv) | ||
1145 | { | ||
1146 | LOG (GNUNET_ERROR_TYPE_WARNING, | ||
1147 | "Lost end of transmission due to remote shutdown on channel %s\n", | ||
1148 | GCCH_2s (ch)); | ||
1149 | /* FIXME: change API to notify client about truncated transmission! */ | ||
1150 | } | ||
1110 | ch->destroy = GNUNET_YES; | 1151 | ch->destroy = GNUNET_YES; |
1111 | GSC_handle_remote_channel_destroy ((NULL != ch->owner) ? ch->owner : ch->dest, | 1152 | GSC_handle_remote_channel_destroy ((NULL != ch->owner) ? ch->owner : ch->dest, |
1112 | ch->ccn, | 1153 | ch->ccn, |
@@ -1290,6 +1331,12 @@ GCCH_handle_local_data (struct CadetChannel *ch, | |||
1290 | } | 1331 | } |
1291 | ch->pending_messages++; | 1332 | ch->pending_messages++; |
1292 | 1333 | ||
1334 | if (GNUNET_YES == ch->is_loopback) | ||
1335 | { | ||
1336 | GNUNET_break (0); // fIXME: not implemented | ||
1337 | return GNUNET_SYSERR; | ||
1338 | } | ||
1339 | |||
1293 | /* Everything is correct, send the message. */ | 1340 | /* Everything is correct, send the message. */ |
1294 | crm = GNUNET_malloc (sizeof (*crm) + buf_len); | 1341 | crm = GNUNET_malloc (sizeof (*crm) + buf_len); |
1295 | crm->ch = ch; | 1342 | crm->ch = ch; |