- if (NULL != t->owner)
- {
- send_client_tunnel_ack (t->owner, t);
- return;
- }
- /* Is it after unicast / multicast retransmission? */
- if (GNUNET_MESSAGE_TYPE_MESH_ACK != type)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "ACK via DATA retransmission\n");
- if (GNUNET_YES == t->nobuffer)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
- return;
- }
- if (t->queue_max > t->queue_n * 2)
- {
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
- return;
- }
- }
+ GNUNET_PEER_resolve (t->id.oid, &msg.oid);
+ msg.header.size = htons (sizeof (msg));
+ msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
+ msg.pid = htonl (ack);
+ msg.tid = htonl (t->id.tid);
+
+ send_prebuilt_message (&msg.header, peer, t);
+}
+
+
+/**
+ * Notify a the owner of a tunnel about how many more
+ * payload packages will we accept on a given tunnel.
+ *
+ * @param t Tunnel on which to send the ACK.
+ */
+static void
+tunnel_send_client_fwd_ack (struct MeshTunnel *t)
+{
+ uint32_t ack;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Sending client FWD ACK on tunnel %X\n",
+ t->local_tid);
+
+ ack = tunnel_get_fwd_ack (t);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ack);
+ if (t->last_fwd_ack == ack)
+ return;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending!\n");
+ t->last_fwd_ack = ack;
+ send_local_ack (t, t->owner, ack);
+}
+
+
+/**
+ * Send an ACK informing the predecessor about the available buffer space.
+ * In case there is no predecessor, inform the owning client.
+ * If buffering is off, send only on behalf of children or self if endpoint.
+ * If buffering is on, send when sent to children and buffer space is free.
+ * Note that although the name is fwd_ack, the FWD mean forward *traffic*,
+ * the ACK itself goes "back" (towards root).
+ *
+ * @param t Tunnel on which to send the ACK.
+ * @param type Type of message that triggered the ACK transmission.
+ */
+static void
+tunnel_send_fwd_ack (struct MeshTunnel *t, uint16_t type)
+{
+ struct GNUNET_PeerIdentity id;
+ uint32_t ack;
+
+ if (NULL != t->owner)
+ {
+ tunnel_send_client_fwd_ack (t);
+ return;
+ }
+ /* Is it after unicast / multicast retransmission? */
+ switch (type)
+ {
+ case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+ case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "ACK due to FWD DATA retransmission\n");
+ if (GNUNET_YES == t->nobuffer)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, nobuffer\n");
+ return;
+ }
+ break;
+ case GNUNET_MESSAGE_TYPE_MESH_ACK:
+ case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
+ break;
+ default:
+ GNUNET_break (0);
+ }
+
+ /* Check if we need no retransmit the ACK */
+ if (t->fwd_queue_max > t->fwd_queue_n * 4 &&
+ GMC_is_pid_bigger(t->last_fwd_ack, t->fwd_pid))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer free\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " t->qmax: %u, t->qn: %u\n",
+ t->fwd_queue_max, t->fwd_queue_n);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ " t->pid: %u, t->ack: %u\n",
+ t->fwd_pid, t->last_fwd_ack);
+ return;
+ }