}
+/**
+ * A channel was destroyed by the other peer. Tell our client.
+ *
+ * @param c client that lost a channel
+ * @param ccn channel identification number for the client
+ * @param ch the channel object
+ */
+void
+GSC_handle_remote_channel_destroy (struct CadetClient *c,
+ struct GNUNET_CADET_ClientChannelNumber ccn,
+ struct CadetChannel *ch)
+{
+ struct GNUNET_MQ_Envelope *env;
+ struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
+
+ env = GNUNET_MQ_msg (tdm,
+ GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
+ tdm->ccn = ccn;
+ GSC_send_to_client (c,
+ env);
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap32_remove (c->channels,
+ ntohl (ccn.channel_of_client),
+ ch));
+}
+
+
/**
* Iterator for deleting each channel whose client endpoint disconnected.
*
struct CadetClient *c = cls;
struct CadetChannel *ch = value;
- GNUNET_assert (GNUNET_YES ==
- GNUNET_CONTAINER_multihashmap32_remove (c->channels,
- key,
- ch));
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Destroying channel %s, due to client %s disconnecting.\n",
GCCH_2s (ch),
GSC_2s (c));
+ GNUNET_assert (GNUNET_YES ==
+ GNUNET_CONTAINER_multihashmap32_remove (c->channels,
+ key,
+ ch));
if (key < GNUNET_CADET_LOCAL_CHANNEL_ID_CLI)
GCCH_channel_local_destroy (ch);
else
#include "gnunet_util_lib.h"
#define NEW_CADET 1
+#include "cadet_protocol.h"
/**
* A client to the CADET service. Each client gets a unique handle.
struct GNUNET_MQ_Envelope *env);
+/**
+ * A channel was destroyed by the other peer. Tell our client.
+ *
+ * @param c client that lost a channel
+ * @param ccn channel identification number for the client
+ * @param ch the channel object
+ */
+void
+GSC_handle_remote_channel_destroy (struct CadetClient *c,
+ struct GNUNET_CADET_ClientChannelNumber ccn,
+ struct CadetChannel *ch);
+
+
/**
* Bind incoming channel to this client, and notify client
* about incoming connection.
*/
struct CadetTunnel *t;
- /**
- * Last entry in the tunnel's queue relating to control messages
- * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
- * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
- * transmission in case we receive updated information.
- */
- struct CadetTunnelQueueEntry *last_control_qe;
-
/**
* Client owner of the tunnel, if any.
* (Used if this channel represends the initiating end of the tunnel.)
*/
struct CadetClient *dest;
+ /**
+ * Last entry in the tunnel's queue relating to control messages
+ * (#GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN or
+ * #GNUNET_MESSAGE_TYPE_CADET_CHANNEL_OPEN_ACK). Used to cancel
+ * transmission in case we receive updated information.
+ */
+ struct CadetTunnelQueueEntry *last_control_qe;
+
/**
* Head of DLL of messages sent and not yet ACK'd.
*/
{
struct CadetChannel *ch = cls;
+ GNUNET_assert (NULL != ch->last_control_qe);
ch->last_control_qe = NULL;
ch->retry_time = GNUNET_TIME_STD_BACKOFF (ch->retry_time);
ch->retry_task = GNUNET_SCHEDULER_add_delayed (ch->retry_time,
{
struct CadetChannel *ch = cls;
+ GNUNET_assert (NULL != ch->last_control_qe);
ch->last_control_qe = NULL;
}
void
GCCH_handle_remote_destroy (struct CadetChannel *ch)
{
- struct GNUNET_MQ_Envelope *env;
- struct GNUNET_CADET_LocalChannelDestroyMessage *tdm;
-
LOG (GNUNET_ERROR_TYPE_DEBUG,
"Received remote channel DESTROY for %s\n",
GCCH_2s (ch));
ch->destroy = GNUNET_YES;
- env = GNUNET_MQ_msg (tdm,
- GNUNET_MESSAGE_TYPE_CADET_LOCAL_CHANNEL_DESTROY);
- tdm->ccn = ch->ccn;
- GSC_send_to_client ((NULL != ch->owner) ? ch->owner : ch->dest,
- env);
+ GSC_handle_remote_channel_destroy ((NULL != ch->owner) ? ch->owner : ch->dest,
+ ch->ccn,
+ ch);
channel_destroy (ch);
}
*/
struct GNUNET_SCHEDULER_Task *maintain_connections_task;
+ /**
+ * Task to send messages from queue (if possible).
+ */
+ struct GNUNET_SCHEDULER_Task *send_task;
+
/**
* Task to trigger KX.
*/
* at our message queue and if there is a message, picks a connection
* to send it on.
*
- * @param t tunnel to process messages on
+ * @param cls the `struct CadetTunnel` to process messages on
*/
static void
-trigger_transmissions (struct CadetTunnel *t);
+trigger_transmissions (void *cls);
/* ************************************** start core crypto ***************************** */
we can start transmitting! */
GCT_change_estate (t,
CADET_TUNNEL_KEY_OK);
- trigger_transmissions (t);
+ if (NULL != t->send_task)
+ GNUNET_SCHEDULER_cancel (t->send_task);
+ t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
+ t);
break;
case CADET_TUNNEL_KEY_PING:
/* Got a key yet again; need encrypted payload to advance */
GNUNET_SCHEDULER_cancel (t->maintain_connections_task);
t->maintain_connections_task = NULL;
}
+ if (NULL != t->send_task)
+ {
+ GNUNET_SCHEDULER_cancel (t->send_task);
+ t->send_task = NULL;
+ }
+ if (NULL != t->kx_task)
+ {
+ GNUNET_SCHEDULER_cancel (t->kx_task);
+ t->kx_task = NULL;
+ }
GNUNET_MST_destroy (t->mst);
GNUNET_MQ_destroy (t->mq);
while (NULL != t->ax.skipped_head)
* at our message queue and if there is a message, picks a connection
* to send it on.
*
- * @param t tunnel to process messages on
+ * @param cls the `struct CadetTunnel` to process messages on
*/
static void
-trigger_transmissions (struct CadetTunnel *t)
+trigger_transmissions (void *cls)
{
+ struct CadetTunnel *t = cls;
struct CadetTConnection *ct;
+ t->send_task = NULL;
if (NULL == t->tq_head)
return; /* no messages pending right now */
ct = get_ready_connection (t);
{
GCT_change_estate (t,
CADET_TUNNEL_KEY_OK);
- trigger_transmissions (t);
+ if (NULL != t->send_task)
+ GNUNET_SCHEDULER_cancel (t->send_task);
+ t->send_task = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
+ t);
}
/* The MST will ultimately call #handle_decrypted() on each message. */
GNUNET_break_op (GNUNET_OK ==
GNUNET_CONTAINER_DLL_insert_tail (t->tq_head,
t->tq_tail,
tq);
- trigger_transmissions (t);
+ if (NULL != t->send_task)
+ GNUNET_SCHEDULER_cancel (t->send_task);
+ t->send_task
+ = GNUNET_SCHEDULER_add_now (&trigger_transmissions,
+ t);
return tq;
}