+static void
+connection_change_state (struct MeshConnection* c,
+ enum MeshConnectionState state)
+{
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection %s state was %s\n",
+ GNUNET_h2s (&c->id), GMC_state2s (c->state));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Connection %s state is now %s\n",
+ GNUNET_h2s (&c->id), GMC_state2s (state));
+ c->state = state;
+}
+
+
+/**
+ * Callback called when a queued message is sent.
+ *
+ * Calculates the average time and connection packet tracking.
+ *
+ * @param cls Closure.
+ * @param c Connection this message was on.
+ * @param type Type of message sent.
+ * @param fwd Was this a FWD going message?
+ * @param size Size of the message.
+ * @param wait Time spent waiting for core (only the time for THIS message)
+ */
+static void
+message_sent (void *cls,
+ struct MeshConnection *c, uint16_t type,
+ int fwd, size_t size,
+ struct GNUNET_TIME_Relative wait)
+{
+ struct MeshConnectionPerformance *p;
+ struct MeshFlowControl *fc;
+ double usecsperbyte;
+
+ fc = fwd ? &c->fwd_fc : &c->bck_fc;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "! Q_N- %p %u\n", fc, fc->queue_n);
+ fc->queue_n--;
+ c->pending_messages--;
+ if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "! destroying connection!\n");
+ GMC_destroy (c);
+ }
+ /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
+ switch (type)
+ {
+ case GNUNET_MESSAGE_TYPE_MESH_ENCRYPTED:
+ fc->last_pid_sent++;
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "! accounting pid %u\n", fc->last_pid_sent);
+// send_ack (c, ch, fwd);
+ break;
+ default:
+ break;
+ }
+
+ if (NULL == c->perf)
+ return; /* Only endpoints are interested in timing. */
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "! message sent!\n");
+ p = c->perf;
+ usecsperbyte = ((double) wait.rel_value_us) / size;
+ if (p->size == AVG_MSGS)
+ {
+ /* Array is full. Substract oldest value, add new one and store. */
+ p->avg -= (p->usecsperbyte[p->idx] / AVG_MSGS);
+ p->usecsperbyte[p->idx] = usecsperbyte;
+ p->avg += (p->usecsperbyte[p->idx] / AVG_MSGS);
+ }
+ else
+ {
+ /* Array not yet full. Add current value to avg and store. */
+ p->usecsperbyte[p->idx] = usecsperbyte;
+ p->avg *= p->size;
+ p->avg += p->usecsperbyte[p->idx];
+ p->size++;
+ p->avg /= p->size;
+ }
+ p->idx = (p->idx + 1) % AVG_MSGS;
+
+// if (NULL != c->t)
+// {
+// c->t->pending_messages--;
+// if (GNUNET_YES == c->t->destroy && 0 == t->pending_messages)
+// {
+// LOG (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n");
+// GMT_destroy (c->t);
+// }
+// }
+}
+
+
+/**
+ * Get the previous hop in a connection
+ *
+ * @param c Connection.
+ *
+ * @return Previous peer in the connection.
+ */
+static struct MeshPeer *
+get_prev_hop (const struct MeshConnection *c)
+{
+ GNUNET_PEER_Id id;
+
+ if (0 == c->own_pos || c->path->length < 2)
+ id = c->path->peers[0];
+ else
+ id = c->path->peers[c->own_pos - 1];
+
+ return GMP_get_short (id);
+}
+
+
+/**
+ * Get the next hop in a connection
+ *
+ * @param c Connection.
+ *
+ * @return Next peer in the connection.
+ */
+static struct MeshPeer *
+get_next_hop (const struct MeshConnection *c)
+{
+ GNUNET_PEER_Id id;
+
+ if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
+ id = c->path->peers[c->path->length - 1];
+ else
+ id = c->path->peers[c->own_pos + 1];
+
+ return GMP_get_short (id);
+}
+
+
+/**
+ * Get the hop in a connection.
+ *
+ * @param c Connection.
+ * @param fwd Next hop?
+ *
+ * @return Next peer in the connection.
+ */
+static struct MeshPeer *
+get_hop (struct MeshConnection *c, int fwd)
+{
+ if (fwd)
+ return get_next_hop (c);
+ return get_prev_hop (c);
+}
+
+