+
+
+/**
+ * Notifies a tree that a connection it might be using is broken.
+ * Marks all peers down the paths as disconnected and notifies the client.
+ *
+ * @param t Tree to use.
+ * @param p1 Short id of one of the peers (order unimportant)
+ * @param p2 Short id of one of the peers (order unimportant)
+ * @param cb Function to call for every peer that is marked as disconnected.
+ * @param cbcls Closure for cb.
+ *
+ * @return Short ID of the first disconnected peer in the tree.
+ */
+GNUNET_PEER_Id
+tree_notify_connection_broken (struct MeshTunnelTree *t, GNUNET_PEER_Id p1,
+ GNUNET_PEER_Id p2, MeshTreeCallback cb,
+ void *cbcls)
+{
+ struct MeshTunnelTreeNode *n;
+ struct MeshTunnelTreeNode *c;
+
+ n = tree_find_peer (t, p1);
+ if (NULL == n)
+ return 0;
+ if (NULL != n->parent && n->parent->peer == p2)
+ {
+ tree_mark_peers_disconnected (t, n, cb, cbcls);
+ GNUNET_CONTAINER_DLL_remove (n->parent->children_head,
+ n->parent->children_tail, n);
+ GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail, n);
+ return p1;
+ }
+ for (c = n->children_head; NULL != c; c = c->next)
+ {
+ if (c->peer == p2)
+ {
+ tree_mark_peers_disconnected (t, c, cb, cbcls);
+ GNUNET_CONTAINER_DLL_remove (n->children_head, n->children_tail, c);
+ GNUNET_CONTAINER_DLL_insert (t->disconnected_head, t->disconnected_tail,
+ c);
+ return p2;
+ }
+ }
+ return 0;
+}
+
+
+/**
+ * Deletes a peer from a tunnel, liberating all unused resources on the path to
+ * it. It shouldn't have children, if it has they will be destroyed as well.
+ * If the tree is not local and no longer has any paths, the root node will be
+ * destroyed and marked as NULL.
+ *
+ * @param t Tunnel tree to use.
+ * @param peer Short ID of the peer to remove from the tunnel tree.
+ * @param cb Callback to notify client of disconnected peers.
+ * @param cbcls Closure for cb.
+ *
+ * @return GNUNET_OK or GNUNET_SYSERR
+ */
+int
+tree_del_peer (struct MeshTunnelTree *t, GNUNET_PEER_Id peer,
+ MeshTreeCallback cb, void *cbcls)
+{
+ struct MeshTunnelTreeNode *n;
+
+ n = tree_del_path (t, peer, cb, cbcls);
+ if (NULL == n)
+ {
+ GNUNET_break (0);
+ return GNUNET_YES;
+ }
+ tree_node_destroy (n);
+ if (NULL == t->root->children_head && t->me != t->root)
+ {
+ tree_node_destroy (t->root);
+ t->root = NULL;
+ return GNUNET_NO;
+ }
+ return GNUNET_YES;
+}
+
+
+
+/**
+ * Get the cost of the path relative to the already built tunnel tree.
+ *
+ * @param t The tunnel tree to which compare.
+ * @param path The individual path to reach a peer. It has to start at the
+ * root of the tree to be comparable.
+ *
+ * @return Number of hops to reach destination, UINT_MAX in case the peer is not
+ * in the path.
+ *
+ * TODO: adapt to allow any start / root combination
+ * TODO: take in account state of the nodes
+ */
+unsigned int
+tree_get_path_cost (struct MeshTunnelTree *t, struct MeshPeerPath *path)
+{
+ struct MeshTunnelTreeNode *n;
+ struct MeshTunnelTreeNode *p;
+ unsigned int i;
+ unsigned int l;
+
+ l = path_get_length (path);
+ p = t->root;
+ if (t->root->peer != path->peers[0])
+ {
+ GNUNET_break (0);
+ return UINT_MAX;
+ }
+ for (i = 1; i < l; i++)
+ {
+ for (n = p->children_head; NULL != n; n = n->next)
+ {
+ if (path->peers[i] == n->peer)
+ {
+ break;
+ }
+ }
+ if (NULL == n)
+ return l - i;
+ p = n;
+ }
+ return l - i;
+}
+
+
+/**
+ * Print the tree on stderr
+ *
+ * @param t The tree
+ */
+void
+tree_debug (struct MeshTunnelTree *t)
+{
+ tree_node_debug (t->root, 0);
+ FPRINTF (stderr, "root: %p\n", t->root);
+ FPRINTF (stderr, "me: %p\n", t->me);
+}
+
+
+/**
+ * Iterator over hash map peer entries and frees all data in it.
+ * Used prior to destroying a hashmap. Makes you miss anonymous functions in C.
+ *
+ * @param cls closure
+ * @param key current key code (will no longer contain valid data!!)
+ * @param value value in the hash map (treated as void *)
+ * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
+ */
+static int
+iterate_free (void *cls, const struct GNUNET_HashCode * key, void *value)
+{
+ GNUNET_free (value);
+ return GNUNET_YES;
+}
+
+
+/**
+ * Destroy the whole tree and free all used memory and Peer_Ids
+ *
+ * @param t Tree to be destroyed
+ */
+void
+tree_destroy (struct MeshTunnelTree *t)
+{
+#if MESH_TREE_DEBUG
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Destroying tree\n");
+#endif
+ tree_node_destroy (t->root);
+ GNUNET_CONTAINER_multihashmap_iterate (t->first_hops, &iterate_free, NULL);
+ GNUNET_CONTAINER_multihashmap_destroy (t->first_hops);
+ GNUNET_free (t);
+}