{
LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
LOG (GNUNET_ERROR_TYPE_DEBUG,
- " last pid recv: %u, last ack sent: %u\n",
- prev_fc->last_pid_recv, prev_fc->last_ack_sent);
+ " last pid recv: %u, last ack sent: %u\n",
+ prev_fc->last_pid_recv, prev_fc->last_ack_sent);
return;
}
ack = prev_fc->last_pid_recv + delta;
LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
LOG (GNUNET_ERROR_TYPE_DEBUG,
- " last pid %u, last ack %u, qmax %u, q %u\n",
- prev_fc->last_pid_recv, prev_fc->last_ack_sent,
- next_fc->queue_max, next_fc->queue_n);
+ " last pid %u, last ack %u, qmax %u, q %u\n",
+ prev_fc->last_pid_recv, prev_fc->last_ack_sent,
+ next_fc->queue_max, next_fc->queue_n);
if (ack == prev_fc->last_ack_sent)
{
LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
LOG (GNUNET_ERROR_TYPE_DEBUG,
"send ack %s on %p %p\n",
fwd ? "FWD" : "BCK", c, ch);
+
+ /* Get available bufffer space */
if (NULL == c || GMC_is_terminal (c, fwd))
{
struct MeshTunnel3 *t;
}
LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
+ /* Send available buffer space */
if ( (NULL != ch && GMCH_is_origin (ch, fwd)) ||
(NULL != c && GMC_is_origin (c, fwd)) )
{
return (fc->queue_max - fc->queue_n);
}
+/**
+ * Get how many messages have we allowed to send to us from a direction..
+ *
+ * @param c Connection.
+ * @param fwd Are we asking about traffic from FWD (BCK messages)?
+ *
+ * @return last_ack_sent - last_pid_recv
+ */
+unsigned int
+GMC_get_allowed (struct MeshConnection *c, int fwd)
+{
+ struct MeshFlowControl *fc;
+
+ fc = fwd ? &c->fwd_fc : &c->bck_fc;
+ if (GMC_is_pid_bigger(fc->last_pid_recv, fc->last_ack_sent))
+ {
+ return 0;
+ }
+ return (fc->last_ack_sent - fc->last_pid_recv);
+}
+
/**
* Get messages queued in a connection.
*
unsigned int ch_buf;
if (NULL == t->channel_head)
+ {
+ /* Probably getting buffer for a channel create. */
return 64;
+ }
for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next)
{
}
+/**
+ * Send ACK on one or more connections due to buffer space to the client.
+ *
+ * Iterates all connections of the tunnel and sends ACKs appropriately.
+ *
+ * @param ch Channel which has some free buffer space.
+ * @param fwd Is this in for FWD traffic? (ACK goes dest->root)
+ */
+static void
+GMT_send_acks (struct MeshTunnel3 *t,
+ unsigned int buffer,
+ int fwd)
+{
+ struct MeshTConnection *iter;
+ uint32_t allowed;
+ uint32_t to_allow;
+ uint32_t allow_per_connection;
+ unsigned int cs;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Tunnel send acks on %s:%X\n",
+ fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid);
+
+ /* Count connections, how many messages are already allowed */
+ cs = GMT_count_connections (t);
+ for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next)
+ {
+ allowed += GMC_get_allowed (iter->c, fwd);
+ }
+
+ /* Make sure there is no overflow */
+ if (allowed > buffer)
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ /* Authorize connections to send more data */
+ to_allow = buffer - allowed;
+
+ for (iter = t->connection_head; NULL != iter && to_allow > 0; iter = iter->next)
+ {
+ allow_per_connection = to_allow/cs;
+ to_allow -= allow_per_connection;
+ cs--;
+ if (GMC_get_allowed (iter->c, fwd) > 64 / 3)
+ {
+ continue;
+ }
+ GMC_send_ack (iter->c, NULL, fwd);
+ connection_send_ack (iter, allow_per_connection, fwd);
+ }
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Channel send connection %s ack on %s:%X\n",
+ fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid);
+ GNUNET_break (to_allow == 0);
+}
+
+
/**
* Sends an already built message on a tunnel, GMT_encrypting it and
* choosing the best connection.