+/**
+ * @brief Get the next transmittable message from the queue.
+ *
+ * This will be the head, except in the case of being a data packet
+ * not allowed by the destination peer.
+ *
+ * @param peer Destination peer.
+ *
+ * @return The next viable MeshPeerQueue element to send to that peer.
+ * NULL when there are no transmittable messages.
+ */
+struct MeshPeerQueue *
+queue_get_next (const struct MeshPeerInfo *peer)
+{
+ struct MeshPeerQueue *q;
+ struct MeshTunnel *t;
+ struct MeshTransmissionDescriptor *info;
+ struct MeshTunnelChildInfo *cinfo;
+ struct GNUNET_MESH_Unicast *ucast;
+ struct GNUNET_MESH_ToOrigin *to_orig;
+ struct GNUNET_MESH_Multicast *mcast;
+ struct GNUNET_PeerIdentity id;
+ uint32_t pid;
+ uint32_t ack;
+
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "********* selecting message\n");
+ for (q = peer->queue_head; NULL != q; q = q->next)
+ {
+ t = q->tunnel;
+ info = q->cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "********* %s\n",
+ GNUNET_MESH_DEBUG_M2S(q->type));
+ switch (q->type)
+ {
+ case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
+ ucast = (struct GNUNET_MESH_Unicast *) info->mesh_data->data;
+ pid = ntohl (ucast->pid);
+ GNUNET_PEER_resolve (info->peer->id, &id);
+ cinfo = tunnel_get_neighbor_fc(t, &id);
+ ack = cinfo->fwd_ack;
+ break;
+ case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
+ to_orig = (struct GNUNET_MESH_ToOrigin *) info->mesh_data->data;
+ pid = ntohl (to_orig->pid);
+ ack = t->bck_ack;
+ break;
+ case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
+ mcast = (struct GNUNET_MESH_Multicast *) info->mesh_data->data;
+ if (GNUNET_MESSAGE_TYPE_MESH_MULTICAST != ntohs(mcast->header.type))
+ {
+ // Not a multicast payload: multicast control traffic (destroy, etc)
+ return q;
+ }
+ pid = ntohl (mcast->pid);
+ GNUNET_PEER_resolve (info->peer->id, &id);
+ cinfo = tunnel_get_neighbor_fc(t, &id);
+ ack = cinfo->fwd_ack;
+ break;
+ default:
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "********* OK!\n");
+ return q;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "********* ACK: %u, PID: %u\n",
+ ack, pid);
+ if (GNUNET_NO == GMC_is_pid_bigger(pid, ack))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "********* OK!\n");
+ return q;
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "********* NEXT!\n");
+ }
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "********* nothing found\n");
+ return NULL;
+}
+
+