+/**
+ * Add the path to the peer and update the path used to reach it in case this
+ * is the shortest.
+ *
+ * @param peer_info Destination peer to add the path to.
+ * @param path New path to add. Last peer must be the peer in arg 1.
+ * Path will be either used of freed if already known.
+ * @param trusted Do we trust that this path is real?
+ */
+void
+GMP_add_path (struct MeshPeer *peer_info, struct MeshPeerPath *path,
+ int trusted)
+{
+ struct MeshPeerPath *aux;
+ unsigned int l;
+ unsigned int l2;
+
+ if ((NULL == peer_info) || (NULL == path))
+ {
+ GNUNET_break (0);
+ path_destroy (path);
+ return;
+ }
+ if (path->peers[path->length - 1] != peer_info->id)
+ {
+ GNUNET_break (0);
+ path_destroy (path);
+ return;
+ }
+ if (2 >= path->length && GNUNET_NO == trusted)
+ {
+ /* Only allow CORE to tell us about direct paths */
+ path_destroy (path);
+ return;
+ }
+ for (l = 1; l < path->length; l++)
+ {
+ if (path->peers[l] == myid)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
+ for (l2 = 0; l2 < path->length - l; l2++)
+ {
+ path->peers[l2] = path->peers[l + l2];
+ }
+ path->length -= l;
+ l = 1;
+ path->peers =
+ GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
+ }
+ }
+
+ LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
+ path->length, GMP_2s (peer_info));
+
+ l = path_get_length (path);
+ if (0 == l)
+ {
+ path_destroy (path);
+ return;
+ }
+
+ GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
+ for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
+ {
+ l2 = path_get_length (aux);
+ if (l2 > l)
+ {
+ GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
+ peer_info->path_tail, aux, path);
+ return;
+ }
+ else
+ {
+ if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
+ {
+ path_destroy (path);
+ return;
+ }
+ }
+ }
+ GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
+ path);
+ return;
+}
+
+
+/**
+ * Add the path to the origin peer and update the path used to reach it in case
+ * this is the shortest.
+ * The path is given in peer_info -> destination, therefore we turn the path
+ * upside down first.
+ *
+ * @param peer_info Peer to add the path to, being the origin of the path.
+ * @param path New path to add after being inversed.
+ * Path will be either used or freed.
+ * @param trusted Do we trust that this path is real?
+ */
+void
+GMP_add_path_to_origin (struct MeshPeer *peer,
+ struct MeshPeerPath *path,
+ int trusted)
+{
+ if (NULL == path)
+ return;
+ path_invert (path);
+ GMP_add_path (peer, path, trusted);
+}
+
+
+/**
+ * Adds a path to the info of all the peers in the path
+ *
+ * @param p Path to process.
+ * @param confirmed Whether we know if the path works or not.
+ */
+void
+GMP_add_path_to_all (const struct MeshPeerPath *p, int confirmed)
+{
+ unsigned int i;
+
+ /* TODO: invert and add */
+ for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
+ for (i++; i < p->length; i++)
+ {
+ struct MeshPeer *aux;
+ struct MeshPeerPath *copy;
+
+ aux = GMP_get_short (p->peers[i]);
+ copy = path_duplicate (p);
+ copy->length = i + 1;
+ GMP_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
+ }
+}
+
+