gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [gnunet] branch master updated (f61c5da9a -> 271dd457b)


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated (f61c5da9a -> 271dd457b)
Date: Sun, 29 Jan 2017 14:10:05 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a change to branch master
in repository gnunet.

    from f61c5da9a when applicable, do connection selection outside of send_kx*
     new ae117b6b4 provide stricter assurances about when we call ready_cb, 
avoiding supurious calls that merely reinforce what tunnel already knows about 
the connection state
     new f2aa85678 separate connection DLL into a list for ready connections 
and a list of busy connections, and count them separately; make iterator 
tolerate modifications to current element of DLL during iteration
     new 271dd457b implement basics of connection management for tunnels (in 
particular destruction of bad connections, eventual selection of new ones

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/cadet/gnunet-service-cadet-new.c            |   7 +-
 src/cadet/gnunet-service-cadet-new_connection.c |  21 +-
 src/cadet/gnunet-service-cadet-new_tunnels.c    | 373 ++++++++++++++++++------
 src/cadet/gnunet-service-cadet-new_tunnels.h    |   6 +-
 4 files changed, 308 insertions(+), 99 deletions(-)

diff --git a/src/cadet/gnunet-service-cadet-new.c 
b/src/cadet/gnunet-service-cadet-new.c
index d40d4f10e..55c7d1bdb 100644
--- a/src/cadet/gnunet-service-cadet-new.c
+++ b/src/cadet/gnunet-service-cadet-new.c
@@ -967,17 +967,18 @@ handle_info_tunnels (void *cls,
  * Update the message with information about the connection.
  *
  * @param cls a `struct GNUNET_CADET_LocalInfoTunnel` message to update
- * @param c a connection about which we should store information in @a cls
+ * @param ct a connection about which we should store information in @a cls
  */
 static void
 iter_connection (void *cls,
-                 struct CadetConnection *c)
+                 struct CadetTConnection *ct)
 {
   struct GNUNET_CADET_LocalInfoTunnel *msg = cls;
+  struct CadetConnection *cc = ct->cc;
   struct GNUNET_CADET_ConnectionTunnelIdentifier *h;
 
   h = (struct GNUNET_CADET_ConnectionTunnelIdentifier *) &msg[1];
-  h[msg->connections++] = *(GCC_get_id (c));
+  h[msg->connections++] = *(GCC_get_id (cc));
 }
 
 
diff --git a/src/cadet/gnunet-service-cadet-new_connection.c 
b/src/cadet/gnunet-service-cadet-new_connection.c
index 11044d9e6..ac16f1a9e 100644
--- a/src/cadet/gnunet-service-cadet-new_connection.c
+++ b/src/cadet/gnunet-service-cadet-new_connection.c
@@ -26,7 +26,9 @@
  * @author Christian Grothoff
  *
  * TODO:
- * - Optimization: keep per-connection performance metrics (?)
+ * - keep per-connection performance metrics
+ * - in particular, interact with channel (!) to see
+ *   if we get ACKs indicating successful payload delivery.
  */
 #include "platform.h"
 #include "gnunet-service-cadet-new.h"
@@ -345,6 +347,8 @@ GCC_handle_connection_create_ack (struct CadetConnection 
*cc)
        GCC_2s (cc),
        cc->state,
        (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
+  if (CADET_CONNECTION_READY == cc->state)
+    return; /* Duplicate ACK, ignore */
   if (NULL != cc->task)
   {
     GNUNET_SCHEDULER_cancel (cc->task);
@@ -522,8 +526,9 @@ GCC_handle_duplicate_create (struct CadetConnection *cc)
          (GNUNET_YES == cc->mqm_ready) ? "MQM ready" : "MQM busy");
     /* Tell tunnel that we are not ready for transmission anymore
        (until CREATE_ACK is done) */
-    cc->ready_cb (cc->ready_cb_cls,
-                  GNUNET_NO);
+    if (CADET_CONNECTION_READY == cc->state)
+      cc->ready_cb (cc->ready_cb_cls,
+                    GNUNET_NO);
     /* Revert back to the state of having only received the 'CREATE',
        and immediately proceed to send the CREATE_ACK. */
     cc->state = CADET_CONNECTION_CREATE_RECEIVED;
@@ -566,7 +571,6 @@ manage_first_hop_mq (void *cls,
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Core MQ for %s went down\n",
          GCC_2s (cc));
-    cc->mqm_ready = GNUNET_NO;
     cc->state = CADET_CONNECTION_NEW;
     cc->retry_delay = GNUNET_TIME_UNIT_ZERO;
     if (NULL != cc->task)
@@ -574,8 +578,13 @@ manage_first_hop_mq (void *cls,
       GNUNET_SCHEDULER_cancel (cc->task);
       cc->task = NULL;
     }
-    cc->ready_cb (cc->ready_cb_cls,
-                  GNUNET_NO);
+    if (GNUNET_YES == cc->mqm_ready)
+    {
+      cc->mqm_ready = GNUNET_NO;
+      if (CADET_CONNECTION_READY == cc->state)
+        cc->ready_cb (cc->ready_cb_cls,
+                      GNUNET_NO);
+    }
     return;
   }
 
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.c 
b/src/cadet/gnunet-service-cadet-new_tunnels.c
index c08a01f1a..3c0271c71 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.c
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.c
@@ -24,11 +24,14 @@
  * @author Christian Grothoff
  *
  * FIXME:
- * - connection management
- *   + properly (evaluate, kill old ones, search for new ones)
+ * - proper connection evaluation during connection management:
  *   + when managing connections, distinguish those that
  *     have (recently) had traffic from those that were
  *     never ready (or not recently)
+ *   + consider quality of current connection set when deciding
+ *     how often to do maintenance
+ *   + interact with PEER to drive DHT GET/PUT operations based
+ *     on how much we like our connections
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
@@ -365,14 +368,24 @@ struct CadetTunnel
   struct GNUNET_MQ_Handle *mq;
 
   /**
-   * DLL of connections that are actively used to reach the destination peer.
+   * DLL of ready connections that are actively used to reach the destination 
peer.
    */
-  struct CadetTConnection *connection_head;
+  struct CadetTConnection *connection_ready_head;
 
   /**
-   * DLL of connections that are actively used to reach the destination peer.
+   * DLL of ready connections that are actively used to reach the destination 
peer.
    */
-  struct CadetTConnection *connection_tail;
+  struct CadetTConnection *connection_ready_tail;
+
+  /**
+   * DLL of connections that we maintain that might be used to reach the 
destination peer.
+   */
+  struct CadetTConnection *connection_busy_head;
+
+  /**
+   * DLL of connections that we maintain that might be used to reach the 
destination peer.
+   */
+  struct CadetTConnection *connection_busy_tail;
 
   /**
    * Channels inside this tunnel. Maps
@@ -406,9 +419,14 @@ struct CadetTunnel
   struct GNUNET_TIME_Absolute next_kx_attempt;
 
   /**
-   * Number of connections in the @e connection_head DLL.
+   * Number of connections in the @e connection_ready_head DLL.
    */
-  unsigned int num_connections;
+  unsigned int num_ready_connections;
+
+  /**
+   * Number of connections in the @e connection_busy_head DLL.
+   */
+  unsigned int num_busy_connections;
 
   /**
    * How often have we tried and failed to decrypt a message using
@@ -436,6 +454,31 @@ struct CadetTunnel
 
 
 /**
+ * Connection @a ct is now unready, clear it's ready flag
+ * and move it from the ready DLL to the busy DLL.
+ *
+ * @param ct connection to move to unready status
+ */
+static void
+mark_connection_unready (struct CadetTConnection *ct)
+{
+  struct CadetTunnel *t = ct->t;
+
+  GNUNET_assert (GNUNET_YES == ct->is_ready);
+  GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
+                               t->connection_ready_tail,
+                               ct);
+  GNUNET_assert (0 < t->num_ready_connections);
+  t->num_ready_connections--;
+  ct->is_ready = GNUNET_NO;
+  GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
+                               t->connection_busy_tail,
+                               ct);
+  t->num_busy_connections++;
+}
+
+
+/**
  * Get the static string for the peer this tunnel is directed.
  *
  * @param t Tunnel.
@@ -544,9 +587,9 @@ lookup_channel (struct CadetTunnel *t,
  * @return Number of connections created, either being established or ready.
  */
 unsigned int
-GCT_count_any_connections (struct CadetTunnel *t)
+GCT_count_any_connections (const struct CadetTunnel *t)
 {
-  return t->num_connections;
+  return t->num_ready_connections + t->num_busy_connections;
 }
 
 
@@ -560,25 +603,7 @@ GCT_count_any_connections (struct CadetTunnel *t)
 static struct CadetTConnection *
 get_ready_connection (struct CadetTunnel *t)
 {
-  for (struct CadetTConnection *pos = t->connection_head;
-       NULL != pos;
-       pos = pos->next)
-    if (GNUNET_YES == pos->is_ready)
-    {
-      if (pos != t->connection_tail)
-      {
-        /* move 'pos' to the end, so we try other ready connections
-           first next time (round-robin, modulo availability) */
-        GNUNET_CONTAINER_DLL_remove (t->connection_head,
-                                     t->connection_tail,
-                                     pos);
-        GNUNET_CONTAINER_DLL_insert_tail (t->connection_head,
-                                          t->connection_tail,
-                                          pos);
-      }
-      return pos;
-    }
-  return NULL;
+  return t->connection_ready_head;
 }
 
 
@@ -1316,7 +1341,7 @@ send_kx (struct CadetTunnel *t,
                                       &msg->ephemeral_key);
   GNUNET_CRYPTO_ecdhe_key_get_public (ax->DHRs,
                                       &msg->ratchet_key);
-  ct->is_ready = GNUNET_NO;
+  mark_connection_unready (ct);
   t->kx_retry_delay = GNUNET_TIME_STD_BACKOFF (t->kx_retry_delay);
   t->next_kx_attempt = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
   if (CADET_TUNNEL_KEY_UNINITIALIZED == t->estate)
@@ -1394,7 +1419,7 @@ send_kx_auth (struct CadetTunnel *t,
     = GNUNET_TIME_relative_to_absolute (t->kx_retry_delay);
 
   /* Send via cc, mark it as unready */
-  ct->is_ready = GNUNET_NO;
+  mark_connection_unready (ct);
 
   /* Update state machine, unless we are already OK */
   if (CADET_TUNNEL_KEY_OK != t->estate)
@@ -1926,14 +1951,38 @@ GCT_connection_lost (struct CadetTConnection *ct)
 {
   struct CadetTunnel *t = ct->t;
 
-  GNUNET_CONTAINER_DLL_remove (t->connection_head,
-                               t->connection_tail,
-                               ct);
+  if (GNUNET_YES == ct->is_ready)
+    GNUNET_CONTAINER_DLL_remove (t->connection_ready_head,
+                                 t->connection_ready_tail,
+                                 ct);
+  else
+    GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
+                                 t->connection_busy_tail,
+                                 ct);
   GNUNET_free (ct);
 }
 
 
 /**
+ * Clean up connection @a ct of a tunnel.
+ *
+ * @param cls the `struct CadetTunnel`
+ * @param ct connection to clean up
+ */
+static void
+destroy_t_connection (void *cls,
+                      struct CadetTConnection *ct)
+{
+  struct CadetTunnel *t = cls;
+  struct CadetConnection *cc = ct->cc;
+
+  GNUNET_assert (ct->t == t);
+  GCT_connection_lost (ct);
+  GCC_destroy_without_tunnel (cc);
+}
+
+
+/**
  * This tunnel is no longer used, destroy it.
  *
  * @param cls the idle tunnel
@@ -1942,7 +1991,6 @@ static void
 destroy_tunnel (void *cls)
 {
   struct CadetTunnel *t = cls;
-  struct CadetTConnection *ct;
   struct CadetTunnelQueueEntry *tq;
 
   t->destroy_task = NULL;
@@ -1950,15 +1998,11 @@ destroy_tunnel (void *cls)
        "Destroying idle %s\n",
        GCT_2s (t));
   GNUNET_assert (0 == GCT_count_channels (t));
-  while (NULL != (ct = t->connection_head))
-  {
-    struct CadetConnection *cc;
-
-    GNUNET_assert (ct->t == t);
-    cc = ct->cc;
-    GCT_connection_lost (ct);
-    GCC_destroy_without_tunnel (cc);
-  }
+  GCT_iterate_connections (t,
+                           &destroy_t_connection,
+                           t);
+  GNUNET_assert (NULL == t->connection_ready_head);
+  GNUNET_assert (NULL == t->connection_busy_head);
   while (NULL != (tq = t->tq_head))
   {
     if (NULL != tq->cont)
@@ -2101,7 +2145,7 @@ try_send_normal_payload (struct CadetTunnel *t,
                                tq);
   if (NULL != tq->cid)
     *tq->cid = *GCC_get_id (ct->cc);
-  ct->is_ready = GNUNET_NO;
+  mark_connection_unready (ct);
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Sending payload of %s on %s\n",
        GCT_2s (t),
@@ -2135,10 +2179,21 @@ connection_ready_cb (void *cls,
          "%s no longer ready for %s\n",
          GCC_2s (ct->cc),
          GCT_2s (t));
-    ct->is_ready = GNUNET_NO;
+    mark_connection_unready (ct);
     return;
   }
+  GNUNET_assert (GNUNET_NO == ct->is_ready);
+  GNUNET_CONTAINER_DLL_remove (t->connection_busy_head,
+                               t->connection_busy_tail,
+                               ct);
+  GNUNET_assert (0 < t->num_busy_connections);
+  t->num_busy_connections--;
   ct->is_ready = GNUNET_YES;
+  GNUNET_CONTAINER_DLL_insert_tail (t->connection_ready_head,
+                                    t->connection_ready_tail,
+                                    ct);
+  t->num_ready_connections++;
+
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "%s now ready for %s in state %s\n",
        GCC_2s (ct->cc),
@@ -2219,6 +2274,108 @@ trigger_transmissions (void *cls)
 
 
 /**
+ * Closure for #evaluate_connection. Used to assemble summary information
+ * about the existing connections so we can evaluate a new path.
+ */
+struct EvaluationSummary
+{
+
+  /**
+   * Minimum length of any of our connections, `UINT_MAX` if we have none.
+   */
+  unsigned int min_length;
+
+  /**
+   * Maximum length of any of our connections, 0 if we have none.
+   */
+  unsigned int max_length;
+
+  /**
+   * Minimum desirability of any of our connections, UINT64_MAX if we have 
none.
+   */
+  GNUNET_CONTAINER_HeapCostType min_desire;
+
+  /**
+   * Maximum desirability of any of our connections, 0 if we have none.
+   */
+  GNUNET_CONTAINER_HeapCostType max_desire;
+
+  /**
+   * Path we are comparing against for #evaluate_connection, can be NULL.
+   */
+  struct CadetPeerPath *path;
+
+  /**
+   * Connection deemed the "worst" so far encountered by #evaluate_connection,
+   * NULL if we did not yet encounter any connections.
+   */
+  struct CadetTConnection *worst;
+
+  /**
+   * Numeric score of @e worst, only set if @e worst is non-NULL.
+   */
+  double worst_score;
+
+  /**
+   * Set to #GNUNET_YES if we have a connection over @e path already.
+   */
+  int duplicate;
+
+};
+
+
+/**
+ * Evaluate a connection, updating our summary information in @a cls about
+ * what kinds of connections we have.
+ *
+ * @param cls the `struct EvaluationSummary *` to update
+ * @param ct a connection to include in the summary
+ */
+static void
+evaluate_connection (void *cls,
+                     struct CadetTConnection *ct)
+{
+  struct EvaluationSummary *es = cls;
+  struct CadetConnection *cc = ct->cc;
+  struct CadetPeerPath *ps = GCC_get_path (cc);
+  GNUNET_CONTAINER_HeapCostType ct_desirability;
+  uint32_t ct_length;
+  double score;
+
+  if (ps == es->path)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Ignoring duplicate path %s.\n",
+         GCPP_2s (es->path));
+    es->duplicate = GNUNET_YES;
+    return;
+  }
+  ct_desirability = GCPP_get_desirability (ps);
+  ct_length = GCPP_get_length (ps);
+
+  /* FIXME: calculate score on more than path,
+     include connection performance metrics like
+     last successful transmission, uptime, etc. */
+  score = ct_desirability + ct_length; /* FIXME: weigh these as well! */
+
+  if ( (NULL == es->worst) ||
+       (score < es->worst_score) )
+  {
+    es->worst = ct;
+    es->worst_score = score;
+  }
+  es->min_length = GNUNET_MIN (es->min_length,
+                               ct_length);
+  es->max_length = GNUNET_MAX (es->max_length,
+                               ct_length);
+  es->min_desire = GNUNET_MIN (es->min_desire,
+                               ct_desirability);
+  es->max_desire = GNUNET_MAX (es->max_desire,
+                               ct_desirability);
+}
+
+
+/**
  * Consider using the path @a p for the tunnel @a t.
  * The tunnel destination is at offset @a off in path @a p.
  *
@@ -2233,31 +2390,22 @@ consider_path_cb (void *cls,
                   unsigned int off)
 {
   struct CadetTunnel *t = cls;
-  unsigned int min_length = UINT_MAX;
-  GNUNET_CONTAINER_HeapCostType max_desire = 0;
+  struct EvaluationSummary es;
   struct CadetTConnection *ct;
 
-  /* Check if we care about the new path. */
-  for (ct = t->connection_head;
-       NULL != ct;
-       ct = ct->next)
-  {
-    struct CadetPeerPath *ps;
-
-    ps = GCC_get_path (ct->cc);
-    if (ps == path)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Ignoring duplicate path %s for %s.\n",
-           GCPP_2s (path),
-           GCT_2s (t));
-      return GNUNET_YES; /* duplicate */
-    }
-    min_length = GNUNET_MIN (min_length,
-                             GCPP_get_length (ps));
-    max_desire = GNUNET_MAX (max_desire,
-                             GCPP_get_desirability (ps));
-  }
+  es.min_length = UINT_MAX;
+  es.max_length = 0;
+  es.max_desire = 0;
+  es.min_desire = UINT64_MAX;
+  es.path = path;
+  es.duplicate = GNUNET_NO;
+
+  /* Compute evaluation summary over existing connections. */
+  GCT_iterate_connections (t,
+                           &evaluate_connection,
+                           &es);
+  if (GNUNET_YES == es.duplicate)
+    return GNUNET_YES;
 
   /* FIXME: not sure we should really just count
      'num_connections' here, as they may all have
@@ -2266,18 +2414,20 @@ consider_path_cb (void *cls,
   /* We iterate by increasing path length; if we have enough paths and
      this one is more than twice as long than what we are currently
      using, then ignore all of these super-long ones! */
-  if ( (t->num_connections > DESIRED_CONNECTIONS_PER_TUNNEL) &&
-       (min_length * 2 < off) )
+  if ( (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) &&
+       (es.min_length * 2 < off) &&
+       (es.max_length < off) )
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Ignoring paths of length %u, they are way too long.\n",
-         min_length * 2);
+         es.min_length * 2);
     return GNUNET_NO;
   }
   /* If we have enough paths and this one looks no better, ignore it. */
-  if ( (t->num_connections >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
-       (min_length < GCPP_get_length (path)) &&
-       (max_desire > GCPP_get_desirability (path)) )
+  if ( (GCT_count_any_connections (t) >= DESIRED_CONNECTIONS_PER_TUNNEL) &&
+       (es.min_length < GCPP_get_length (path)) &&
+       (es.min_desire > GCPP_get_desirability (path)) &&
+       (es.max_length < off) )
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Ignoring path (%u/%llu) to %s, got something better already.\n",
@@ -2297,14 +2447,15 @@ consider_path_cb (void *cls,
                        ct,
                        &connection_ready_cb,
                        ct);
+
   /* FIXME: schedule job to kill connection (and path?)  if it takes
      too long to get ready! (And track performance data on how long
      other connections took with the tunnel!)
      => Note: to be done within 'connection'-logic! */
-  GNUNET_CONTAINER_DLL_insert (t->connection_head,
-                               t->connection_tail,
+  GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
+                               t->connection_busy_tail,
                                ct);
-  t->num_connections++;
+  t->num_busy_connections++;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Found interesting path %s for %s, created %s\n",
        GCPP_2s (path),
@@ -2331,17 +2482,50 @@ static void
 maintain_connections_cb (void *cls)
 {
   struct CadetTunnel *t = cls;
+  struct GNUNET_TIME_Relative delay;
+  struct EvaluationSummary es;
 
   t->maintain_connections_task = NULL;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Performing connection maintenance for %s.\n",
        GCT_2s (t));
 
+  es.min_length = UINT_MAX;
+  es.max_length = 0;
+  es.max_desire = 0;
+  es.min_desire = UINT64_MAX;
+  es.path = NULL;
+  es.worst = NULL;
+  es.duplicate = GNUNET_NO;
+  GCT_iterate_connections (t,
+                           &evaluate_connection,
+                           &es);
+  if ( (NULL != es.worst) &&
+       (GCT_count_any_connections (t) > DESIRED_CONNECTIONS_PER_TUNNEL) )
+  {
+    /* Clear out worst-performing connection 'es.worst'. */
+    destroy_t_connection (t,
+                          es.worst);
+  }
+
+  /* Consider additional paths */
   (void) GCP_iterate_paths (t->destination,
                             &consider_path_cb,
                             t);
 
-  GNUNET_break (0); // FIXME: implement!
+  /* FIXME: calculate when to try again based on how well we are doing;
+     in particular, if we have to few connections, we might be able
+     to do without this (as PATHS should tell us whenever a new path
+     is available instantly; however, need to make sure this job is
+     restarted after that happens).
+     Furthermore, if the paths we do know are in a reasonably narrow
+     quality band and are plentyful, we might also consider us stabilized
+     and then reduce the frequency accordingly.  */
+  delay = GNUNET_TIME_UNIT_MINUTES;
+  t->maintain_connections_task
+    = GNUNET_SCHEDULER_add_delayed (delay,
+                                    &maintain_connections_cb,
+                                    t);
 }
 
 
@@ -2737,10 +2921,10 @@ GCT_add_inbound_connection (struct CadetTunnel *t,
      too long to get ready! (And track performance data on how long
      other connections took with the tunnel!)
      => Note: to be done within 'connection'-logic! */
-  GNUNET_CONTAINER_DLL_insert (t->connection_head,
-                               t->connection_tail,
+  GNUNET_CONTAINER_DLL_insert (t->connection_busy_head,
+                               t->connection_busy_tail,
                                ct);
-  t->num_connections++;
+  t->num_busy_connections++;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "%s has new %s\n",
        GCT_2s (t),
@@ -3015,11 +3199,23 @@ GCT_iterate_connections (struct CadetTunnel *t,
                          GCT_ConnectionIterator iter,
                          void *iter_cls)
 {
-  for (struct CadetTConnection *ct = t->connection_head;
+  struct CadetTConnection *n;
+  for (struct CadetTConnection *ct = t->connection_ready_head;
+       NULL != ct;
+       ct = n)
+  {
+    n = ct->next;
+    iter (iter_cls,
+          ct);
+  }
+  for (struct CadetTConnection *ct = t->connection_busy_head;
        NULL != ct;
-       ct = ct->next)
+       ct = n)
+  {
+    n = ct->next;
     iter (iter_cls,
-          ct->cc);
+          ct);
+  }
 }
 
 
@@ -3133,7 +3329,7 @@ GCT_debug (const struct CadetTunnel *t,
         GCT_2s (t),
         estate2s (t->estate),
         t->tq_len,
-        t->num_connections);
+        GCT_count_any_connections (t));
   LOG2 (level,
         "TTT channels:\n");
   GNUNET_CONTAINER_multihashmap32_iterate (t->channels,
@@ -3141,7 +3337,10 @@ GCT_debug (const struct CadetTunnel *t,
                                            &level);
   LOG2 (level,
         "TTT connections:\n");
-  for (iter_c = t->connection_head; NULL != iter_c; iter_c = iter_c->next)
+  for (iter_c = t->connection_ready_head; NULL != iter_c; iter_c = 
iter_c->next)
+    GCC_debug (iter_c->cc,
+               level);
+  for (iter_c = t->connection_busy_head; NULL != iter_c; iter_c = iter_c->next)
     GCC_debug (iter_c->cc,
                level);
 
diff --git a/src/cadet/gnunet-service-cadet-new_tunnels.h 
b/src/cadet/gnunet-service-cadet-new_tunnels.h
index 2655f57f1..d18abeb3c 100644
--- a/src/cadet/gnunet-service-cadet-new_tunnels.h
+++ b/src/cadet/gnunet-service-cadet-new_tunnels.h
@@ -246,18 +246,18 @@ GCT_count_channels (struct CadetTunnel *t);
  * @return number of connections available for the tunnel
  */
 unsigned int
-GCT_count_any_connections (struct CadetTunnel *t);
+GCT_count_any_connections (const struct CadetTunnel *t);
 
 
 /**
  * Iterator over connections.
  *
  * @param cls closure
- * @param c one of the connections
+ * @param ct one of the connections
  */
 typedef void
 (*GCT_ConnectionIterator) (void *cls,
-                           struct CadetConnection *c);
+                           struct CadetTConnection *ct);
 
 
 /**

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]