aboutsummaryrefslogtreecommitdiff
path: root/src/cadet/gnunet-service-cadet-new_channel.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2017-01-23 11:14:37 +0100
committerChristian Grothoff <christian@grothoff.org>2017-01-23 11:14:37 +0100
commit60ebf6febc36dffdcdec32d8968ec9706802e6f7 (patch)
treedd432b87d4fd9b9edaa6cbea0f8f38ba7e3c9418 /src/cadet/gnunet-service-cadet-new_channel.c
parent64f3755912bb85593f92a7e2e63810dbb3ab98ea (diff)
downloadgnunet-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.c145
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 */
820void 860void
821GCCH_channel_local_destroy (struct CadetChannel *ch) 861GCCH_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 */
854void
855GCCH_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,
1104void 1131void
1105GCCH_handle_remote_destroy (struct CadetChannel *ch) 1132GCCH_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;