+
+/**
+ * Get the tunnel's destination.
+ *
+ * @param t Tunnel.
+ *
+ * @return ID of the destination peer.
+ */
+const struct GNUNET_PeerIdentity *
+GMT_get_destination (struct MeshTunnel3 *t)
+{
+ return GMP_get_id (t->peer);
+}
+
+
+/**
+ * Get the tunnel's next free global channel ID.
+ *
+ * @param t Tunnel.
+ *
+ * @return GID of a channel free to use.
+ */
+MESH_ChannelNumber
+GMT_get_next_chid (struct MeshTunnel3 *t)
+{
+ MESH_ChannelNumber chid;
+
+ while (NULL != GMT_get_channel (t, t->next_chid))
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", t->next_chid);
+ t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI;
+ }
+ chid = t->next_chid;
+ t->next_chid = (t->next_chid + 1) & ~GNUNET_MESH_LOCAL_CHANNEL_ID_CLI;
+
+ return chid;
+}
+
+
+/**
+ * Send ACK on one or more channels due to buffer in connections..
+ *
+ * @param t Channel which has some free buffer space.
+ * @param fwd Is this for FWD traffic? (ACK goes to root)
+ */
+void
+GMT_unchoke_channels (struct MeshTunnel3 *t, int fwd)
+{
+ struct MeshTChannel *iter;
+ unsigned int buffer;
+ unsigned int channels = GMT_count_channels (t);
+ unsigned int choked_n;
+ struct MeshChannel *choked[channels];
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t));
+
+ if (NULL == t)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ /* Get buffer space */
+ buffer = GMT_get_buffer (t, fwd);
+ if (0 == buffer)
+ {
+ return;
+ }
+
+ /* Count and remember choked channels */
+ choked_n = 0;
+ for (iter = t->channel_head; NULL != iter; iter = iter->next)
+ {
+ if (GNUNET_NO == GMCH_get_allowed (iter->ch, fwd))
+ {
+ choked[choked_n++] = iter->ch;
+ }
+ }
+
+ /* Unchoke random channels */
+ while (0 < buffer && 0 < choked_n)
+ {
+ unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+ choked_n);
+ GMCH_allow_client (choked[r], fwd);
+ choked_n--;
+ buffer--;
+ choked[r] = choked[choked_n];
+ }
+}
+
+