[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [gnunet] 02/14: fix shutdown sequence, start to handle loop
From: |
gnunet |
Subject: |
[GNUnet-SVN] [gnunet] 02/14: fix shutdown sequence, start to handle loopback |
Date: |
Mon, 23 Jan 2017 14:42:42 +0100 |
This is an automated email from the git hooks/post-receive script.
grothoff pushed a commit to branch master
in repository gnunet.
commit 60ebf6febc36dffdcdec32d8968ec9706802e6f7
Author: Christian Grothoff <address@hidden>
AuthorDate: Mon Jan 23 11:14:37 2017 +0100
fix shutdown sequence, start to handle loopback
---
src/cadet/gnunet-service-cadet-new.c | 41 +++++---
src/cadet/gnunet-service-cadet-new.h | 5 +
src/cadet/gnunet-service-cadet-new_channel.c | 145 ++++++++++++++++++---------
src/cadet/gnunet-service-cadet-new_channel.h | 14 +--
src/cadet/gnunet-service-cadet-new_tunnels.c | 24 +++++
5 files changed, 155 insertions(+), 74 deletions(-)
diff --git a/src/cadet/gnunet-service-cadet-new.c
b/src/cadet/gnunet-service-cadet-new.c
index bb251c307..c9a2fb437 100644
--- a/src/cadet/gnunet-service-cadet-new.c
+++ b/src/cadet/gnunet-service-cadet-new.c
@@ -131,7 +131,7 @@ struct GNUNET_PeerIdentity my_full_id;
struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
/**
- * Signal that shutdown is happening: prevent recover measures.
+ * Signal that shutdown is happening: prevent recovery measures.
*/
int shutting_down;
@@ -356,17 +356,11 @@ destroy_paths_now (void *cls,
/**
- * Task run during shutdown.
- *
- * @param cls unused
+ * Shutdown everything once the clients have disconnected.
*/
static void
-shutdown_task (void *cls)
+shutdown_rest ()
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Shutting down\n");
- shutting_down = GNUNET_YES;
- GCO_shutdown ();
if (NULL != stats)
{
GNUNET_STATISTICS_destroy (stats,
@@ -414,6 +408,23 @@ shutdown_task (void *cls)
/**
+ * Task run during shutdown.
+ *
+ * @param cls unused
+ */
+static void
+shutdown_task (void *cls)
+{
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Shutting down\n");
+ shutting_down = GNUNET_YES;
+ GCO_shutdown ();
+ if (NULL == clients_head)
+ shutdown_rest ();
+}
+
+
+/**
* We had a remote connection @a value to port @a port before
* client @a cls opened port @a port. Bind them now.
*
@@ -608,7 +619,8 @@ handle_channel_destroy (void *cls,
GNUNET_CONTAINER_multihashmap32_remove (c->channels,
ntohl
(msg->ccn.channel_of_client),
ch));
- GCCH_channel_local_destroy (ch);
+ GCCH_channel_local_destroy (ch,
+ c);
GNUNET_SERVICE_client_continue (c->client);
}
@@ -1196,10 +1208,8 @@ channel_destroy_iterator (void *cls,
GNUNET_CONTAINER_multihashmap32_remove (c->channels,
key,
ch));
- if (key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
- GCCH_channel_local_destroy (ch);
- else
- GCCH_channel_incoming_destroy (ch);
+ GCCH_channel_local_destroy (ch,
+ c);
return GNUNET_OK;
}
@@ -1275,6 +1285,9 @@ client_disconnect_cb (void *cls,
-1,
GNUNET_NO);
GNUNET_free (c);
+ if ( (NULL == clients_head) &&
+ (GNUNET_YES == shutting_down) )
+ shutdown_rest ();
}
diff --git a/src/cadet/gnunet-service-cadet-new.h
b/src/cadet/gnunet-service-cadet-new.h
index cb289e9c3..4a76c578b 100644
--- a/src/cadet/gnunet-service-cadet-new.h
+++ b/src/cadet/gnunet-service-cadet-new.h
@@ -225,6 +225,11 @@ extern unsigned long long ratchet_messages;
*/
extern struct GNUNET_TIME_Relative ratchet_time;
+/**
+ * Signal that shutdown is happening: prevent recovery measures.
+ */
+extern int shutting_down;
+
/**
* Send a message to a client.
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
int out_of_order;
/**
+ * Is this channel a loopback channel, where the destination is us again?
+ */
+ int is_loopback;
+
+ /**
* Flag to signal the destruction of the channel. If this is set to
* #GNUNET_YES the channel will be destroyed once the queue is
* empty.
@@ -523,11 +528,38 @@ GCCH_channel_local_new (struct CadetClient *owner,
ch->owner = owner;
ch->ccn = ccn;
ch->port = *port;
- ch->t = GCP_get_tunnel (destination,
- GNUNET_YES);
- ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
- ch->ctn = GCT_add_channel (ch->t,
- ch);
+ if (0 == memcmp (&my_full_id,
+ GCP_get_id (destination),
+ sizeof (struct GNUNET_PeerIdentity)))
+ {
+ ch->is_loopback = GNUNET_YES;
+ ch->dest = GNUNET_CONTAINER_multihashmap_get (open_ports,
+ port);
+ if (NULL == ch->dest)
+ {
+ /* port closed, wait for it to possibly open */
+ (void) GNUNET_CONTAINER_multihashmap_put (loose_channels,
+ port,
+ ch,
+
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Created loose incoming loopback channel to port %s\n",
+ GNUNET_h2s (&ch->port));
+ }
+ else
+ {
+ GCCH_bind (ch,
+ ch->dest);
+ }
+ }
+ else
+ {
+ ch->t = GCP_get_tunnel (destination,
+ GNUNET_YES);
+ ch->retry_time = CADET_INITIAL_RETRANSMIT_TIME;
+ ch->ctn = GCT_add_channel (ch->t,
+ ch);
+ }
GNUNET_STATISTICS_update (stats,
"# channels",
1,
@@ -537,7 +569,7 @@ GCCH_channel_local_new (struct CadetClient *owner,
GNUNET_h2s (port),
GCP_2s (destination),
GSC_2s (owner),
- GCT_2s (ch->t));
+ (GNUNET_YES == ch->is_loopback) ? "loopback" : GCT_2s (ch->t));
return ch;
}
@@ -791,11 +823,18 @@ GCCH_bind (struct CadetChannel *ch,
&ch->port,
options);
ch->mid_recv.mid = htonl (1); /* The CONNECT counts as message 0! */
-
- /* notify other peer that we accepted the connection */
- ch->retry_control_task
- = GNUNET_SCHEDULER_add_now (&send_open_ack,
- ch);
+ if (GNUNET_YES == ch->is_loopback)
+ {
+ ch->state = CADET_CHANNEL_OPEN_SENT;
+ GCCH_handle_channel_open_ack (ch);
+ }
+ else
+ {
+ /* notify other peer that we accepted the connection */
+ ch->retry_control_task
+ = GNUNET_SCHEDULER_add_now (&send_open_ack,
+ ch);
+ }
/* give client it's initial supply of ACKs */
env = GNUNET_MQ_msg (tcm,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_CREATE);
@@ -812,17 +851,27 @@ GCCH_bind (struct CadetChannel *ch,
/**
- * Destroy locally created channel. Called by the
- * local client, so no need to tell the client.
+ * Destroy locally created channel. Called by the local client, so no
+ * need to tell the client.
*
* @param ch channel to destroy
+ * @param c client that caused the destruction
*/
void
-GCCH_channel_local_destroy (struct CadetChannel *ch)
+GCCH_channel_local_destroy (struct CadetChannel *ch,
+ struct CadetClient *c)
{
LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Local client asks for destruction of %s which it initiated\n",
+ "%s asks for destruction of %s\n",
+ GSC_2s (c),
GCCH_2s (ch));
+ GNUNET_assert (NULL != c);
+ if (c == ch->owner)
+ ch->owner = NULL;
+ else if (c == ch->dest)
+ ch->dest = NULL;
+ else
+ GNUNET_assert (0);
if (GNUNET_YES == ch->destroy)
{
/* other end already destroyed, with the local client gone, no need
@@ -830,9 +879,12 @@ GCCH_channel_local_destroy (struct CadetChannel *ch)
channel_destroy (ch);
return;
}
- if (NULL != ch->head_sent)
+ if ( (NULL != ch->head_sent) ||
+ (NULL != ch->owner) ||
+ (NULL != ch->dest) )
{
- /* allow send queue to train first */
+ /* Wait for other end to destroy us as well,
+ and otherwise allow send queue to be transmitted first */
ch->destroy = GNUNET_YES;
return;
}
@@ -840,39 +892,7 @@ GCCH_channel_local_destroy (struct CadetChannel *ch)
if (CADET_CHANNEL_NEW != ch->state)
GCT_send_channel_destroy (ch->t,
ch->ctn);
- /* Now finish our clean up */
- channel_destroy (ch);
-}
-
-
-/**
- * Destroy channel that was incoming. Called by the
- * local client, so no need to tell the client.
- *
- * @param ch channel to destroy
- */
-void
-GCCH_channel_incoming_destroy (struct CadetChannel *ch)
-{
- LOG (GNUNET_ERROR_TYPE_DEBUG,
- "Local client asks for destruction of %s which it accepted\n",
- GCCH_2s (ch));
- if (GNUNET_YES == ch->destroy)
- {
- /* other end already destroyed, with the remote client gone, no need
- to finish transmissions, just destroy immediately. */
- channel_destroy (ch);
- return;
- }
- if (NULL != ch->head_recv)
- {
- /* allow local client to see all data first */
- ch->destroy = GNUNET_YES;
- return;
- }
/* Nothing left to do, just finish destruction */
- GCT_send_channel_destroy (ch->t,
- ch->ctn);
channel_destroy (ch);
}
@@ -980,6 +1000,12 @@ GCCH_handle_channel_plaintext_data (struct CadetChannel
*ch,
"Receicved %u bytes of application data on %s\n",
(unsigned int) payload_size,
GCCH_2s (ch));
+ if (GNUNET_YES == ch->is_loopback)
+ {
+ GNUNET_break (0); // FIXME: not implemented
+ return;
+ }
+
env = GNUNET_MQ_msg_extra (ld,
payload_size,
GNUNET_MESSAGE_TYPE_CADET_LOCAL_DATA);
@@ -1054,6 +1080,7 @@ GCCH_handle_channel_plaintext_data_ack (struct
CadetChannel *ch,
{
struct CadetReliableMessage *crm;
+ GNUNET_break (GNUNET_NO == ch->is_loopback);
if (GNUNET_NO == ch->reliable)
{
/* not expecting ACKs on unreliable channel, odd */
@@ -1104,9 +1131,23 @@ GCCH_handle_channel_plaintext_data_ack (struct
CadetChannel *ch,
void
GCCH_handle_remote_destroy (struct CadetChannel *ch)
{
+ GNUNET_break (GNUNET_NO == ch->is_loopback);
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received remote channel DESTROY for %s\n",
GCCH_2s (ch));
+ if (GNUNET_YES == ch->destroy)
+ {
+ /* Local client already gone, this is instant-death. */
+ channel_destroy (ch);
+ return;
+ }
+ if (NULL != ch->head_recv)
+ {
+ LOG (GNUNET_ERROR_TYPE_WARNING,
+ "Lost end of transmission due to remote shutdown on channel %s\n",
+ GCCH_2s (ch));
+ /* FIXME: change API to notify client about truncated transmission! */
+ }
ch->destroy = GNUNET_YES;
GSC_handle_remote_channel_destroy ((NULL != ch->owner) ? ch->owner :
ch->dest,
ch->ccn,
@@ -1290,6 +1331,12 @@ GCCH_handle_local_data (struct CadetChannel *ch,
}
ch->pending_messages++;
+ if (GNUNET_YES == ch->is_loopback)
+ {
+ GNUNET_break (0); // fIXME: not implemented
+ return GNUNET_SYSERR;
+ }
+
/* Everything is correct, send the message. */
crm = GNUNET_malloc (sizeof (*crm) + buf_len);
crm->ch = ch;
diff --git a/src/cadet/gnunet-service-cadet-new_channel.h
b/src/cadet/gnunet-service-cadet-new_channel.h
index 3a931499e..a473fd3e4 100644
--- a/src/cadet/gnunet-service-cadet-new_channel.h
+++ b/src/cadet/gnunet-service-cadet-new_channel.h
@@ -113,9 +113,11 @@ GCCH_bind (struct CadetChannel *ch,
* local client, so no need to tell the client.
*
* @param ch channel to destroy
+ * @param c client that caused the destruction
*/
void
-GCCH_channel_local_destroy (struct CadetChannel *ch);
+GCCH_channel_local_destroy (struct CadetChannel *ch,
+ struct CadetClient *c);
/**
@@ -150,16 +152,6 @@ GCCH_channel_incoming_new (struct CadetTunnel *t,
/**
- * Destroy channel that was incoming. Called by the
- * local client, so no need to tell the client.
- *
- * @param ch channel to destroy
- */
-void
-GCCH_channel_incoming_destroy (struct CadetChannel *ch);
-
-
-/**
* We got a #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN message again for
* this channel. If the binding was successful, (re)transmit the
* #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK.
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c
b/src/cadet/gnunet-service-cadet-new_tunnels.c
index 20ab8f4e9..b85f1b321 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.c
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.c
@@ -1624,6 +1624,26 @@ GCT_remove_channel (struct CadetTunnel *t,
/**
+ * Destroy remaining channels during shutdown.
+ *
+ * @param cls the `struct CadetTunnel` of the channel
+ * @param key key of the channel
+ * @param value the `struct CadetChannel`
+ * @return #GNUNET_OK (continue to iterate)
+ */
+static int
+destroy_remaining_channels (void *cls,
+ uint32_t key,
+ void *value)
+{
+ struct CadetChannel *ch = value;
+
+ GCCH_handle_remote_destroy (ch);
+ return GNUNET_OK;
+}
+
+
+/**
* Destroys the tunnel @a t now, without delay. Used during shutdown.
*
* @param t tunnel to destroy
@@ -1631,6 +1651,10 @@ GCT_remove_channel (struct CadetTunnel *t,
void
GCT_destroy_tunnel_now (struct CadetTunnel *t)
{
+ GNUNET_assert (GNUNET_YES == shutting_down);
+ GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
+ &destroy_remaining_channels,
+ t);
GNUNET_assert (0 ==
GNUNET_CONTAINER_multihashmap32_size (t->channels));
if (NULL != t->destroy_task)
--
To stop receiving notification emails like this one, please contact
address@hidden
- [GNUnet-SVN] [gnunet] branch master updated (52255b0df -> ec8163cd8), gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 07/14: handle disconnect properly in test, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 06/14: add generated file to ignore list, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 05/14: get rid of redundant, confusing state, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 12/14: add sender argument to GCCH_handle_local_data so we can implement loopback, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 10/14: towards path desirability calculations, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 02/14: fix shutdown sequence, start to handle loopback,
gnunet <=
- [GNUnet-SVN] [gnunet] 11/14: use correct header size calculation in test, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 01/14: allow more than one ACK being given to us at a time, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 09/14: another special case for loopback, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 13/14: avoid asserting in API on timeout destruction, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 03/14: fix unaligned access, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 04/14: more implementation of loopback handling, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 08/14: beautify disconnect logic a bit, gnunet, 2017/01/23
- [GNUnet-SVN] [gnunet] 14/14: more work on loopback, this time payload transmission (for now without flow control), gnunet, 2017/01/23