X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fmesh_tunnel_tree.c;h=c2fe6c3d98776e90c4527d0882f42dd0d6228580;hb=0f6d24a229e9149db26a4e667ed25032d19f533a;hp=e39558c0b829b8b3fb08c8038650c49a9cad0771;hpb=829b321293d77c3501d7ad9d4f05e1234b85f349;p=oweals%2Fgnunet.git diff --git a/src/mesh/mesh_tunnel_tree.c b/src/mesh/mesh_tunnel_tree.c index e39558c0b..c2fe6c3d9 100644 --- a/src/mesh/mesh_tunnel_tree.c +++ b/src/mesh/mesh_tunnel_tree.c @@ -110,7 +110,7 @@ struct MeshTunnelTree /** * Create a new path * - * @param lenght How many hops will the path have. + * @param length How many hops will the path have. * * @return A newly allocated path with a peer array of the specified length. */ @@ -132,7 +132,7 @@ path_new (unsigned int length) /** * Invert the path * - * @param p the path to invert + * @param path the path to invert */ void path_invert (struct MeshPeerPath *path) @@ -152,7 +152,7 @@ path_invert (struct MeshPeerPath *path) /** * Duplicate a path, incrementing short peer's rc. * - * @param p The path to duplicate. + * @param path The path to duplicate. */ struct MeshPeerPath * path_duplicate (struct MeshPeerPath *path) @@ -172,7 +172,7 @@ path_duplicate (struct MeshPeerPath *path) * Recusively update the info about what is the first hop to reach the node * * @param tree Tree this nodes belongs to. - * @param parent_id Short ID from node form which to start updating. + * @param parent The node form which to start updating. * @param hop If known, ID of the first hop. * If not known, NULL to find out and pass on children. */ @@ -183,12 +183,12 @@ tree_node_update_first_hops (struct MeshTunnelTree *tree, /** - * Get the length of a path + * Get the length of a path. * - * @param path The path to measure, with the local peer at any point of it + * @param path The path to measure, with the local peer at any point of it. * - * @return Number of hops to reach destination - * UINT_MAX in case the peer is not in the path + * @return Number of hops to reach destination. + * UINT_MAX in case the peer is not in the path. */ unsigned int path_get_length (struct MeshPeerPath *path) @@ -199,24 +199,6 @@ path_get_length (struct MeshPeerPath *path) } -/** - * 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 - * - * @return Number of hops to reach destination, UINT_MAX in case the peer is not - * in the path - * - * TODO: remove dummy implementation, look into the tunnel tree - */ -unsigned int -path_get_cost (struct MeshTunnelTree *t, struct MeshPeerPath *path) -{ - return path_get_length (path); -} - - /** * Destroy the path and free any allocated resources linked to it * @@ -267,7 +249,7 @@ tree_node_new (struct MeshTunnelTreeNode *parent, GNUNET_PEER_Id peer) * Recursively find the given peer. * * @param parent Node where to start looking. - * @param peer Peer to find. + * @param peer_id Short ID of the peer to find. * * @return Pointer to the node of the peer. NULL if not found. */ @@ -293,7 +275,7 @@ tree_node_find_peer (struct MeshTunnelTreeNode *parent, GNUNET_PEER_Id peer_id) * Recusively update the info about what is the first hop to reach the node * * @param tree Tree this nodes belongs to. - * @param parent_id Short ID from node form which to start updating. + * @param parent ID from node form which to start updating. * @param hop If known, ID of the first hop. * If not known, NULL to find out and pass on children. */ @@ -362,25 +344,25 @@ tree_node_debug (struct MeshTunnelTreeNode *n, uint16_t level) uint16_t i; for (i = 0; i < level; i++) - fprintf (stderr, " "); + FPRINTF (stderr, "%s", " "); if (n->status == MESH_PEER_READY) - fprintf (stderr, "#"); + FPRINTF (stderr, "%s", "#"); if (n->status == MESH_PEER_SEARCHING) - fprintf (stderr, "+"); + FPRINTF (stderr, "%s", "+"); if (n->status == MESH_PEER_RELAY) - fprintf (stderr, "-"); + FPRINTF (stderr, "%s", "-"); if (n->status == MESH_PEER_RECONNECTING) - fprintf (stderr, "*"); + FPRINTF (stderr, "%s", "*"); GNUNET_PEER_resolve (n->peer, &id); - fprintf (stderr, "%s, [%u, %p] ", GNUNET_i2s (&id), n->peer, n); + FPRINTF (stderr, "%s, [%u, %p] ", GNUNET_i2s (&id), n->peer, n); if (NULL != n->parent) { GNUNET_PEER_resolve (n->parent->peer, &id); - fprintf (stderr, "(-> %s [%u])\n", GNUNET_i2s (&id), n->parent->peer); + FPRINTF (stderr, "(-> %s [%u])\n", GNUNET_i2s (&id), n->parent->peer); } else - fprintf (stderr, "(root)\n"); + FPRINTF (stderr, "%s", "(root)\n"); for (c = n->children_head; NULL != c; c = c->next) tree_node_debug (c, level + 1); } @@ -389,7 +371,7 @@ tree_node_debug (struct MeshTunnelTreeNode *n, uint16_t level) /** * Destroys and frees the node and all children * - * @param n Parent node to be destroyed + * @param parent Parent node to be destroyed */ static void tree_node_destroy (struct MeshTunnelTreeNode *parent) @@ -397,6 +379,8 @@ tree_node_destroy (struct MeshTunnelTreeNode *parent) struct MeshTunnelTreeNode *n; struct MeshTunnelTreeNode *next; + if (NULL == parent) + return; #if MESH_TREE_DEBUG struct GNUNET_PeerIdentity id; @@ -422,12 +406,11 @@ tree_node_destroy (struct MeshTunnelTreeNode *parent) /** - * Create a new tunnel tree associated to a tunnel + * Create a new tree. * - * @param t Tunnel this tree will represent - * @param peer A short peer id of the root of the tree + * @param peer A short peer id of the root of the tree. * - * @return A newly allocated and initialized tunnel tree + * @return A newly allocated and initialized tunnel tree. */ struct MeshTunnelTree * tree_new (GNUNET_PEER_Id peer) @@ -435,10 +418,15 @@ tree_new (GNUNET_PEER_Id peer) struct MeshTunnelTree *tree; tree = GNUNET_malloc (sizeof (struct MeshTunnelTree)); - tree->first_hops = GNUNET_CONTAINER_multihashmap_create (32); + tree->first_hops = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_NO); tree->root = tree_node_new (NULL, peer); tree->root->status = MESH_PEER_ROOT; + if (1 == peer) + { + tree->me = tree->root; + } + return tree; } @@ -447,7 +435,8 @@ tree_new (GNUNET_PEER_Id peer) * Set the status of a node. * * @param tree Tree. - * @param peer A short peer id of local peer. + * @param peer A short peer id of the node. + * @param status New status to set. */ void tree_set_status (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer, @@ -465,9 +454,10 @@ tree_set_status (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer, /** * Get the status of a node. * - * @param tree Tree whose local id we want to now. + * @param tree Tree whose node's status we want to now. + * @param peer A short peer id of the node. * - * @return Short peer id of local peer. + * @return Status of the peer. */ enum MeshPeerState tree_get_status (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer) @@ -506,6 +496,8 @@ tree_get_predecessor (struct MeshTunnelTree *tree) * * @return peerinfo of the peer who is the first hop in the tunnel * NULL on error + * + * FIXME use PEER_Id */ struct GNUNET_PeerIdentity * tree_get_first_hop (struct MeshTunnelTree *t, GNUNET_PEER_Id peer) @@ -542,7 +534,7 @@ tree_get_first_hop (struct MeshTunnelTree *t, GNUNET_PEER_Id peer) * Find the given peer in the tree. * * @param tree Tree where to look for the peer. - * @param peer Peer to find. + * @param peer_id Short ID of the peer to find. * * @return Pointer to the node of the peer. NULL if not found. */ @@ -559,6 +551,7 @@ tree_find_peer (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer_id) * @param tree Tree this node belongs to * @param parent Node to be clean, potentially with children * @param cb Callback to use to notify about disconnected peers. + * @param cbcls Closure for cb. */ static void tree_mark_peers_disconnected (struct MeshTunnelTree *tree, @@ -594,26 +587,117 @@ tree_mark_peers_disconnected (struct MeshTunnelTree *tree, * * @param tree Tree to use. Must have "me" set. * @param cb Callback to call over each child. - * @param cls Closure. + * @param cb_cls Closure for @c cb. */ void tree_iterate_children (struct MeshTunnelTree *tree, MeshTreeCallback cb, - void *cls) + void *cb_cls) { struct MeshTunnelTreeNode *n; if (NULL == tree->me) - { - GNUNET_break (0); return; - } for (n = tree->me->children_head; NULL != n; n = n->next) { - cb (cls, n->peer); + cb (cb_cls, n->peer); + } +} + + +/** + * Struct to contain a list of pending nodes when iterating a tree. + */ +struct MeshTreePendingNode { + + /** + * DLL next. + */ + struct MeshTreePendingNode *next; + + /** + * DLL prev. + */ + struct MeshTreePendingNode *prev; + + /** + * Pending node. + */ + struct MeshTunnelTreeNode *node; +}; + + +/** + * Iterate over all nodes in the tree. + * + * @param tree Tree to use.. + * @param cb Callback to call over each child. + * @param cb_cls Closure for @c cb. + * + * TODO: recursive implementation? (s/heap/stack/g) + */ +void +tree_iterate_all (struct MeshTunnelTree *tree, + MeshWholeTreeCallback cb, + void *cb_cls) +{ + struct MeshTunnelTreeNode *parent; + struct MeshTunnelTreeNode *n; + struct MeshTreePendingNode *head; + struct MeshTreePendingNode *tail; + struct MeshTreePendingNode *pending; + + cb (cb_cls, tree->root->peer, 0); + pending = GNUNET_malloc (sizeof (struct MeshTreePendingNode)); + pending->node = tree->root; + head = tail = NULL; + GNUNET_CONTAINER_DLL_insert (head, tail, pending); + + while (NULL != head) + { + pending = head; + parent = pending->node; + GNUNET_CONTAINER_DLL_remove (head, tail, pending); + GNUNET_free (pending); + for (n = parent->children_head; NULL != n; n = n->next) + { + cb (cb_cls, n->peer, parent->peer); + pending = GNUNET_malloc (sizeof (struct MeshTreePendingNode)); + pending->node = n; + /* Insert_tail: breadth first, Insert: depth first */ + GNUNET_CONTAINER_DLL_insert (head, tail, pending); + } } } +/** + * Iterator to count the children in a tree. + */ +static void +count_children_cb (void *cls, GNUNET_PEER_Id peer) +{ + unsigned int *i = cls; + + (*i)++; +} + + +/** + * Count how many children does the local node have in the tree. + * + * @param tree Tree to use. Must have "me" set. + */ +unsigned int +tree_count_children (struct MeshTunnelTree *tree) +{ + unsigned int i; + + i = 0; + tree_iterate_children(tree, &count_children_cb, &i); + return i; +} + + /** * Recusively update the info about what is the first hop to reach the node * @@ -636,7 +720,7 @@ tree_update_first_hops (struct MeshTunnelTree *tree, GNUNET_PEER_Id parent_id, * a new path to it or destroy it explicitly, taking care of it's child nodes. * * @param t Tunnel tree where to delete the path from. - * @param peer Destination peer whose path we want to remove. + * @param peer_id Short ID of the destination peer whose path we want to remove. * @param cb Callback to use to notify about disconnected peers. * @param cbcls Closure for cb. * @@ -658,7 +742,7 @@ tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Deleting path to %s.\n", GNUNET_i2s (&id)); #endif - if (peer_id == t->root->peer) + if (NULL == t->root || peer_id == t->root->peer) return NULL; for (n = t->disconnected_head; NULL != n; n = n->next) @@ -680,7 +764,8 @@ tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, GNUNET_CONTAINER_DLL_remove (parent->children_head, parent->children_tail, n); n->parent = NULL; - while (MESH_PEER_RELAY == parent->status && NULL == parent->children_head) + while (MESH_PEER_RELAY == parent->status && + NULL == parent->children_head) { #if MESH_TREE_DEBUG GNUNET_PEER_resolve (parent->peer, &id); @@ -688,6 +773,8 @@ tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, GNUNET_i2s (&id)); #endif n = parent->parent; + if (parent == t->me) + t->me = NULL; tree_node_destroy (parent); parent = n; } @@ -707,8 +794,8 @@ tree_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, * Return a newly allocated individual path to reach a peer from the local peer, * according to the path tree of some tunnel. * - * @param t Tunnel from which to read the path tree - * @param peer_info Destination peer to whom we want a path + * @param t Tunnel from which to read the path tree. + * @param peer Short ID of the destination peer to whom we want a path. * * @return A newly allocated individual path to reach the destination peer. * Path must be destroyed afterwards. @@ -721,7 +808,10 @@ tree_get_path_to_peer (struct MeshTunnelTree *t, GNUNET_PEER_Id peer) n = tree_find_peer (t, peer); if (NULL == n) + { + GNUNET_break (0); return NULL; + } p = path_new (0); /* Building the path (inverted!) */ @@ -732,6 +822,7 @@ tree_get_path_to_peer (struct MeshTunnelTree *t, GNUNET_PEER_Id peer) n = n->parent; if (NULL == n) { + GNUNET_break (0); path_destroy (p); return NULL; } @@ -844,7 +935,7 @@ tree_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: Adding peer %s.\n", GNUNET_i2s (&id)); GNUNET_PEER_resolve (parent->peer, &id); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: to %s.\n", + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: to %s.\n", GNUNET_i2s (&id)); #endif @@ -867,11 +958,11 @@ tree_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, #endif n = tree_node_new (parent, p->peers[i]); n->status = MESH_PEER_RELAY; - if (n->peer == 1) - { - t->me = n; - me = i; - } + } + if (n->peer == 1) + { + t->me = n; + me = i; } i++; parent = n; @@ -900,6 +991,8 @@ tree_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tree: New node added.\n"); #endif + if (NULL == t->me) + t->me = tree_find_peer (t, 1); return GNUNET_OK; } @@ -975,7 +1068,6 @@ tree_del_peer (struct MeshTunnelTree *t, GNUNET_PEER_Id peer, GNUNET_break (0); return GNUNET_YES; } - GNUNET_break_op (NULL == n->children_head); tree_node_destroy (n); if (NULL == t->root->children_head && t->me != t->root) { @@ -987,6 +1079,52 @@ tree_del_peer (struct MeshTunnelTree *t, GNUNET_PEER_Id peer, } + +/** + * 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 * @@ -996,6 +1134,8 @@ 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); } @@ -1009,7 +1149,7 @@ tree_debug (struct MeshTunnelTree *t) * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not. */ static int -iterate_free (void *cls, const GNUNET_HashCode * key, void *value) +iterate_free (void *cls, const struct GNUNET_HashCode * key, void *value) { GNUNET_free (value); return GNUNET_YES;