+/**
+ * Send an ACK on the connection, informing the predecessor about
+ * the available buffer space. Should not be called in case the peer
+ * is origin (no predecessor).
+ *
+ * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
+ * the ACK itself goes "back" (dest->root).
+ *
+ * @param c Connection on which to send the ACK.
+ * @param buffer How much space free to advertise?
+ * @param fwd Is this FWD ACK? (Going dest->owner)
+ */
+static void
+send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
+{
+ struct MeshFlowControl *next_fc;
+ struct MeshFlowControl *prev_fc;
+ struct GNUNET_MESH_ACK msg;
+ uint32_t ack;
+ int delta;
+
+ /* If origin, there is no connection to send ACKs. Wrong function! */
+ if (GMC_is_origin (c, fwd))
+ {
+ GNUNET_break (0);
+ return;
+ }
+
+ next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
+ prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "connection send %s ack on %s\n",
+ fwd ? "FWD" : "BCK", GMC_2s (c));
+
+ /* Check if we need to transmit the ACK */
+ delta = prev_fc->last_ack_sent - prev_fc->last_pid_recv;
+ if (3 < delta && buffer < delta)
+ {
+ 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);
+ return;
+ }
+
+ /* Ok, ACK might be necessary, what PID to ACK? */
+ ack = prev_fc->last_pid_recv + buffer;
+ 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);
+ if (ack == prev_fc->last_ack_sent)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
+ return;
+ }
+
+ prev_fc->last_ack_sent = ack;
+
+ /* Build ACK message and send on connection */
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
+ msg.ack = htonl (ack);
+ msg.cid = c->id;
+
+ GMC_send_prebuilt_message (&msg.header, c, NULL, !fwd);
+}
+
+