aboutsummaryrefslogtreecommitdiff
path: root/src/mesh
diff options
context:
space:
mode:
authorBart Polot <bart@net.in.tum.de>2011-11-02 18:46:43 +0000
committerBart Polot <bart@net.in.tum.de>2011-11-02 18:46:43 +0000
commit1c91d8d5152a33db3522cc98c0b44eeeffb7eaa0 (patch)
tree364160a1550865161346901130b39ab1707b551f /src/mesh
parentb8c9942ee1470ead06fbf0825a3265ebf8904ed6 (diff)
downloadgnunet-1c91d8d5152a33db3522cc98c0b44eeeffb7eaa0.tar.gz
gnunet-1c91d8d5152a33db3522cc98c0b44eeeffb7eaa0.zip
Changed tree library to be completely detached from mesh, adapted testcases
Diffstat (limited to 'src/mesh')
-rw-r--r--src/mesh/Makefile.am12
-rw-r--r--src/mesh/gnunet-service-mesh.c191
-rw-r--r--src/mesh/mesh.h5
-rw-r--r--src/mesh/mesh_tunnel_tree.c417
-rw-r--r--src/mesh/mesh_tunnel_tree.h172
-rw-r--r--src/mesh/test_mesh_path_api.c314
6 files changed, 520 insertions, 591 deletions
diff --git a/src/mesh/Makefile.am b/src/mesh/Makefile.am
index aebe06e6e..860e7a205 100644
--- a/src/mesh/Makefile.am
+++ b/src/mesh/Makefile.am
@@ -39,7 +39,7 @@ libgnunetmesh_la_LDFLAGS = \
39 39
40check_PROGRAMS = \ 40check_PROGRAMS = \
41 test_mesh_api \ 41 test_mesh_api \
42 test_mesh_path_api \ 42 test_mesh_tree_api \
43 test_mesh_local_1 \ 43 test_mesh_local_1 \
44 test_mesh_local_2 \ 44 test_mesh_local_2 \
45 test_mesh_small_unicast \ 45 test_mesh_small_unicast \
@@ -55,12 +55,12 @@ test_mesh_api_DEPENDENCIES = \
55 libgnunetmesh.la \ 55 libgnunetmesh.la \
56 $(top_builddir)/src/util/libgnunetutil.la 56 $(top_builddir)/src/util/libgnunetutil.la
57 57
58test_mesh_path_api_SOURCES = \ 58test_mesh_tree_api_SOURCES = \
59 test_mesh_path_api.c mesh_tunnel_tree.c 59 test_mesh_tree_api.c
60test_mesh_path_api_LDADD = \ 60test_mesh_tree_api_LDADD = \
61 $(top_builddir)/src/util/libgnunetutil.la \ 61 $(top_builddir)/src/util/libgnunetutil.la \
62 $(top_builddir)/src/dht/libgnunetdht.la 62 $(top_builddir)/src/dht/libgnunetdht.la
63test_mesh_path_api_DEPENDENCIES = \ 63test_mesh_tree_api_DEPENDENCIES = \
64 libgnunetmesh.la \ 64 libgnunetmesh.la \
65 $(top_builddir)/src/dht/libgnunetdht.la 65 $(top_builddir)/src/dht/libgnunetdht.la
66 66
@@ -109,7 +109,7 @@ test_mesh_small_multicast_DEPENDENCIES = \
109 109
110 110
111if ENABLE_TEST_RUN 111if ENABLE_TEST_RUN
112TESTS = test_0 test_mesh_api test_mesh_path_api test_mesh_local_1 test_mesh_local_2 test_1 test_mesh_small_unicast 112TESTS = test_0 test_mesh_api test_mesh_tree_api test_mesh_local_1 test_mesh_local_2 test_1 test_mesh_small_unicast
113endif 113endif
114 114
115EXTRA_DIST = \ 115EXTRA_DIST = \
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c
index bfcfec92b..4b1fca931 100644
--- a/src/mesh/gnunet-service-mesh.c
+++ b/src/mesh/gnunet-service-mesh.c
@@ -1883,7 +1883,7 @@ tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer)
1883 tree_add_path (t->tree, best_p, &notify_peer_disconnected, t); 1883 tree_add_path (t->tree, best_p, &notify_peer_disconnected, t);
1884 if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) 1884 if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task)
1885 t->path_refresh_task = 1885 t->path_refresh_task =
1886 GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); 1886 GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
1887 } 1887 }
1888 else 1888 else
1889 { 1889 {
@@ -1911,12 +1911,14 @@ tunnel_add_path (struct MeshTunnel *t,
1911 1911
1912 GNUNET_assert (0 != own_pos); 1912 GNUNET_assert (0 != own_pos);
1913 tree_add_path(t->tree, p, NULL, NULL); 1913 tree_add_path(t->tree, p, NULL, NULL);
1914 if (NULL == t->tree->me) 1914 if (tree_get_me (t->tree) == 0)
1915 t->tree->me = tree_find_peer(t->tree->root, p->peers[own_pos]); 1915 tree_set_me (t->tree, p->peers[own_pos]);
1916 if (own_pos < p->length - 1) 1916 if (own_pos < p->length - 1)
1917 { 1917 {
1918 GNUNET_PEER_resolve (p->peers[own_pos + 1], &id); 1918 GNUNET_PEER_resolve (p->peers[own_pos + 1], &id);
1919 tree_update_first_hops(t->tree, t->tree->me, &id); 1919 tree_update_first_hops(t->tree,
1920 tree_get_me (t->tree),
1921 &id);
1920 } 1922 }
1921} 1923}
1922 1924
@@ -1952,7 +1954,7 @@ tunnel_notify_connection_broken (struct MeshTunnel *t,
1952 } 1954 }
1953 if (pid != myid) 1955 if (pid != myid)
1954 { 1956 {
1955 if (NULL != t->tree->me->parent) 1957 if (tree_get_predecessor(t->tree) != 0)
1956 { 1958 {
1957 /* We are the peer still connected, notify owner of the disconnection. */ 1959 /* We are the peer still connected, notify owner of the disconnection. */
1958 struct GNUNET_MESH_PathBroken msg; 1960 struct GNUNET_MESH_PathBroken msg;
@@ -1964,7 +1966,7 @@ tunnel_notify_connection_broken (struct MeshTunnel *t,
1964 msg.tid = htonl (t->id.tid); 1966 msg.tid = htonl (t->id.tid);
1965 msg.peer1 = my_full_id; 1967 msg.peer1 = my_full_id;
1966 GNUNET_PEER_resolve (pid, &msg.peer2); 1968 GNUNET_PEER_resolve (pid, &msg.peer2);
1967 GNUNET_PEER_resolve (t->tree->me->parent->peer, &neighbor); 1969 GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
1968 send_message (&msg.header, &neighbor); 1970 send_message (&msg.header, &neighbor);
1969 } 1971 }
1970 } 1972 }
@@ -1972,9 +1974,13 @@ tunnel_notify_connection_broken (struct MeshTunnel *t,
1972} 1974}
1973 1975
1974 1976
1975struct AliasedData 1977struct MeshMulticastData
1976{ 1978{
1977 unsigned int reference_counter; 1979 struct MeshTunnel *t;
1980
1981 GNUNET_SCHEDULER_TaskIdentifier *task;
1982
1983 unsigned int *reference_counter;
1978 1984
1979 size_t data_len; 1985 size_t data_len;
1980 1986
@@ -1983,93 +1989,99 @@ struct AliasedData
1983 1989
1984 1990
1985/** 1991/**
1992 * Send a multicast packet to a neighbor.
1993 */
1994static void
1995tunnel_send_multicast_iterator (void *cls,
1996 GNUNET_PEER_Id neighbor_id)
1997{
1998 struct MeshMulticastData *mdata = cls;
1999 struct MeshDataDescriptor *info;
2000 struct GNUNET_PeerIdentity neighbor;
2001 unsigned int i;
2002
2003 info = GNUNET_malloc (sizeof (struct MeshDataDescriptor));
2004
2005 info->data = mdata->data;
2006 info->size = mdata->data_len;
2007 info->copies = mdata->reference_counter;
2008 (*(mdata->reference_counter))++;
2009
2010 if (NULL != mdata->t->client)
2011 {
2012 info->client = mdata->t->client->handle;
2013 info->timeout_task = mdata->task;
2014 }
2015 info->destination = neighbor_id;
2016 GNUNET_PEER_resolve (neighbor_id, &neighbor);
2017#if MESH_DEBUG
2018 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2019 "MESH: sending to %s...\n",
2020 GNUNET_i2s (&neighbor));
2021#endif
2022 info->peer = peer_info_get(&neighbor);
2023 GNUNET_assert (NULL != info->peer);
2024 i = peer_info_transmit_slot(info->peer);
2025 info->handler_n = i;
2026 info->peer->infos[i] = info;
2027 info->peer->types[i] = GNUNET_MESSAGE_TYPE_MESH_MULTICAST;
2028 info->peer->core_transmit[i] =
2029 GNUNET_CORE_notify_transmit_ready (core_handle,
2030 0,
2031 0,
2032 GNUNET_TIME_UNIT_FOREVER_REL,
2033 &neighbor,
2034 info->size,
2035 &send_core_data_multicast, info);
2036}
2037
2038/**
1986 * Send a message in a tunnel in multicast, sending a copy to each child node 2039 * Send a message in a tunnel in multicast, sending a copy to each child node
1987 * down the local one in the tunnel tree. 2040 * down the local one in the tunnel tree.
1988 * 2041 *
1989 * @param t Tunnel in which to send the data. 2042 * @param t Tunnel in which to send the data.
1990 * @param msg Message to be sent 2043 * @param msg Message to be sent
1991 *
1992 * @return Number of copies sent.
1993 *
1994 * TODO: unifiy shared resources and reference counter management
1995 */ 2044 */
1996static int 2045static void
1997tunnel_send_multicast (struct MeshTunnel *t, 2046tunnel_send_multicast (struct MeshTunnel *t,
1998 const struct GNUNET_MessageHeader *msg) 2047 const struct GNUNET_MessageHeader *msg)
1999{ 2048{
2000 struct GNUNET_PeerIdentity neighbor; 2049 struct MeshMulticastData *mdata;
2001 struct MeshDataDescriptor *info;
2002 struct MeshTunnelTreeNode *n;
2003 struct MeshTunnelTreeNode *counter;
2004 GNUNET_SCHEDULER_TaskIdentifier *task;
2005 unsigned int *copies;
2006 unsigned int i;
2007 size_t size;
2008 void *data;
2009 2050
2051#if MESH_DEBUG
2010 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2052 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2011 "MESH: sending a multicast packet...\n"); 2053 "MESH: sending a multicast packet...\n");
2012 size = ntohs (msg->size); 2054#endif
2013 GNUNET_assert (NULL != t->tree->me); 2055 GNUNET_assert (tree_get_me (t->tree) != 0);
2014 n = t->tree->me->children_head; 2056 mdata = GNUNET_malloc (sizeof (struct MeshMulticastData));
2015 if (NULL == n) 2057 mdata->data_len = ntohs (msg->size);
2016 { 2058 mdata->reference_counter = GNUNET_malloc (sizeof (unsigned int));
2017 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2059 mdata->data = GNUNET_malloc (mdata->data_len);
2018 "MESH: no children in the tree, no one to send.\n"); 2060 memcpy (mdata->data, msg, mdata->data_len);
2019 return 0;
2020 }
2021 copies = GNUNET_malloc (sizeof (unsigned int));
2022 for (counter = n; NULL != counter; counter = counter->next)
2023 (*copies)++;
2024 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: (%u copies)\n", *copies);
2025 data = GNUNET_malloc (size);
2026 memcpy (data, msg, size);
2027 if (NULL != t->client) 2061 if (NULL != t->client)
2028 { 2062 {
2029 task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier)); 2063 mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier));
2030 *task = GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT, 2064 *(mdata->task) = GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT,
2031 &client_allow_send, 2065 &client_allow_send,
2032 t->client->handle); 2066 t->client->handle);
2033 } 2067 }
2034 else
2035 task = NULL; // So GCC shuts up about task being potentially uninitialized
2036 while (NULL != n)
2037 {
2038 info = GNUNET_malloc (sizeof (struct MeshDataDescriptor));
2039 // info->shared_data = aliased_data;
2040 // info->shared_data->reference_counter++;
2041
2042 info->data = data;
2043 info->size = size;
2044 info->copies = copies;
2045 2068
2046 if (NULL != t->client) 2069 tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
2070 if (*(mdata->reference_counter) == 0)
2071 {
2072 GNUNET_free (mdata->data);
2073 GNUNET_free (mdata->reference_counter);
2074 if (NULL != mdata->task)
2047 { 2075 {
2048 info->client = t->client->handle; 2076 GNUNET_free (mdata->task);
2049 info->timeout_task = task;
2050 } 2077 }
2051 info->destination = n->peer; 2078 }
2052 GNUNET_PEER_resolve (n->peer, &neighbor); 2079 GNUNET_free (mdata);
2053 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 2080#if MESH_DEBUG
2054 "MESH: sending to %s...\n", 2081 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2055 GNUNET_i2s (&neighbor)); 2082 "MESH: sending a multicast packet done\n");
2056 info->peer = peer_info_get(&neighbor); 2083#endif
2057 GNUNET_assert (NULL != info->peer); 2084 return;
2058 i = peer_info_transmit_slot(info->peer);
2059 info->handler_n = i;
2060 info->peer->infos[i] = info;
2061 info->peer->types[i] = GNUNET_MESSAGE_TYPE_MESH_MULTICAST;
2062 info->peer->core_transmit[i] =
2063 GNUNET_CORE_notify_transmit_ready (core_handle,
2064 0,
2065 0,
2066 GNUNET_TIME_UNIT_FOREVER_REL,
2067 &neighbor,
2068 size,
2069 &send_core_data_multicast, info);
2070 n = n->next;
2071 }
2072 return *copies;
2073} 2085}
2074 2086
2075 2087
@@ -2145,7 +2157,6 @@ tunnel_destroy (struct MeshTunnel *t)
2145 GNUNET_break (GNUNET_YES == 2157 GNUNET_break (GNUNET_YES ==
2146 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t)); 2158 GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash, t));
2147 } 2159 }
2148
2149 if (NULL != t->peers) 2160 if (NULL != t->peers)
2150 { 2161 {
2151 GNUNET_CONTAINER_multihashmap_iterate(t->peers, 2162 GNUNET_CONTAINER_multihashmap_iterate(t->peers,
@@ -2186,8 +2197,7 @@ static void
2186tunnel_delete_peer (struct MeshTunnel *t, 2197tunnel_delete_peer (struct MeshTunnel *t,
2187 GNUNET_PEER_Id peer) 2198 GNUNET_PEER_Id peer)
2188{ 2199{
2189 GNUNET_break (GNUNET_OK == tree_del_peer (t->tree, peer, NULL, NULL)); 2200 if (GNUNET_NO == tree_del_peer (t->tree, peer, NULL, NULL))
2190 if (NULL == t->tree->root)
2191 tunnel_destroy (t); 2201 tunnel_destroy (t);
2192} 2202}
2193 2203
@@ -3039,7 +3049,7 @@ handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
3039 GNUNET_break (0); 3049 GNUNET_break (0);
3040 return GNUNET_OK; 3050 return GNUNET_OK;
3041 } 3051 }
3042 GNUNET_PEER_resolve (t->tree->me->parent->peer, &id); 3052 GNUNET_PEER_resolve (tree_get_predecessor(t->tree), &id);
3043 send_message (message, &id); 3053 send_message (message, &id);
3044 3054
3045 return GNUNET_OK; 3055 return GNUNET_OK;
@@ -3066,7 +3076,6 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3066{ 3076{
3067 struct GNUNET_MESH_PathACK *msg; 3077 struct GNUNET_MESH_PathACK *msg;
3068 struct GNUNET_PeerIdentity id; 3078 struct GNUNET_PeerIdentity id;
3069 struct MeshTunnelTreeNode *n;
3070 struct MeshPeerInfo *peer_info; 3079 struct MeshPeerInfo *peer_info;
3071 struct MeshTunnel *t; 3080 struct MeshTunnel *t;
3072 3081
@@ -3096,20 +3105,14 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3096 t->dht_get_type = NULL; 3105 t->dht_get_type = NULL;
3097 } 3106 }
3098 peer_info = peer_info_get (&msg->peer_id); 3107 peer_info = peer_info_get (&msg->peer_id);
3099 n = tree_find_peer(t->tree->root, peer_info->id); 3108 tree_set_status(t->tree, peer_info->id, MESH_PEER_READY);
3100 if (NULL == n)
3101 {
3102 GNUNET_break_op (0);
3103 return GNUNET_OK;
3104 }
3105 n->status = MESH_PEER_READY;
3106 send_client_peer_connected(t, peer_info->id); 3109 send_client_peer_connected(t, peer_info->id);
3107 return GNUNET_OK; 3110 return GNUNET_OK;
3108 } 3111 }
3109 3112
3110 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 3113 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3111 "MESH: not for us, retransmitting...\n"); 3114 "MESH: not for us, retransmitting...\n");
3112 GNUNET_PEER_resolve(t->tree->me->parent->peer, &id); 3115 GNUNET_PEER_resolve(tree_get_predecessor(t->tree), &id);
3113 peer_info = peer_info_get (&msg->oid); 3116 peer_info = peer_info_get (&msg->oid);
3114 if (NULL == peer_info) 3117 if (NULL == peer_info)
3115 { 3118 {
@@ -3241,7 +3244,7 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3241 tunnel_send_multicast (t, &msg->header); 3244 tunnel_send_multicast (t, &msg->header);
3242 3245
3243 t->path_refresh_task = 3246 t->path_refresh_task =
3244 GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); 3247 GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
3245 return; 3248 return;
3246} 3249}
3247 3250
@@ -3606,9 +3609,7 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
3606 return; 3609 return;
3607 } 3610 }
3608 t->tree = tree_new (myid); 3611 t->tree = tree_new (myid);
3609 t->tree->refresh = REFRESH_PATH_TIME; 3612 tree_set_me(t->tree, myid);
3610 t->tree->root->status = MESH_PEER_READY;
3611 t->tree->me = t->tree->root;
3612 3613
3613 GNUNET_SERVER_receive_done (client, GNUNET_OK); 3614 GNUNET_SERVER_receive_done (client, GNUNET_OK);
3614 return; 3615 return;
diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h
index d0648bd3e..fcddb2eb9 100644
--- a/src/mesh/mesh.h
+++ b/src/mesh/mesh.h
@@ -221,6 +221,11 @@ struct GNUNET_MESH_ConnectPeerByType
221enum MeshPeerState 221enum MeshPeerState
222{ 222{
223 /** 223 /**
224 * Uninitialized status, should never appear in operation.
225 */
226 MESH_PEER_INVALID,
227
228 /**
224 * Peer is the root and owner of the tree 229 * Peer is the root and owner of the tree
225 */ 230 */
226 MESH_PEER_ROOT, 231 MESH_PEER_ROOT,
diff --git a/src/mesh/mesh_tunnel_tree.c b/src/mesh/mesh_tunnel_tree.c
index deb702604..332a022c1 100644
--- a/src/mesh/mesh_tunnel_tree.c
+++ b/src/mesh/mesh_tunnel_tree.c
@@ -31,6 +31,83 @@
31 31
32 32
33/** 33/**
34 * Node of path tree for a tunnel
35 */
36struct MeshTunnelTreeNode
37{
38 /**
39 * Peer this node describes
40 */
41 GNUNET_PEER_Id peer;
42
43 /**
44 * Parent node in the tree
45 */
46 struct MeshTunnelTreeNode *parent;
47
48 /**
49 * DLL of siblings
50 */
51 struct MeshTunnelTreeNode *next;
52
53 /**
54 * DLL of siblings
55 */
56 struct MeshTunnelTreeNode *prev;
57
58 /**
59 * DLL of children
60 */
61 struct MeshTunnelTreeNode *children_head;
62
63 /**
64 * DLL of children
65 */
66 struct MeshTunnelTreeNode *children_tail;
67
68 /**
69 * Status of the peer in the tunnel
70 */
71 enum MeshPeerState status;
72};
73
74
75/**
76 * Tree to reach all peers in the tunnel
77 */
78struct MeshTunnelTree
79{
80 /**
81 * Root node of peer tree
82 */
83 struct MeshTunnelTreeNode *root;
84
85 /**
86 * Node that represents our position in the tree (for non local tunnels)
87 */
88 struct MeshTunnelTreeNode *me;
89
90 /**
91 * DLL of disconneted nodes
92 */
93 struct MeshTunnelTreeNode *disconnected_head;
94
95 /**
96 * DLL of disconneted nodes
97 */
98 struct MeshTunnelTreeNode *disconnected_tail;
99
100 /**
101 * Cache of all peers and the first hop to them.
102 * Indexed by PeerIdentity, contains a pointer to the PeerIdentity
103 * of 1st hop.
104 */
105 struct GNUNET_CONTAINER_MultiHashMap *first_hops;
106
107};
108
109
110/**
34 * Create a new path 111 * Create a new path
35 * 112 *
36 * @param lenght How many hops will the path have. 113 * @param lenght How many hops will the path have.
@@ -92,6 +169,19 @@ path_duplicate (struct MeshPeerPath *path)
92 169
93 170
94/** 171/**
172 * Recusively update the info about what is the first hop to reach the node
173 *
174 * @param tree Tree this nodes belongs to.
175 * @param parent_id Short ID from node form which to start updating.
176 * @param hop If known, ID of the first hop.
177 * If not known, NULL to find out and pass on children.
178 */
179static void
180tree_node_update_first_hops (struct MeshTunnelTree *tree,
181 struct MeshTunnelTreeNode *parent,
182 struct GNUNET_PeerIdentity *hop);
183
184/**
95 * Find the first peer whom to send a packet to go down this path 185 * Find the first peer whom to send a packet to go down this path
96 * 186 *
97 * @param t The tunnel tree to use 187 * @param t The tunnel tree to use
@@ -112,10 +202,10 @@ path_get_first_hop (struct MeshTunnelTree *t, GNUNET_PEER_Id peer)
112 { 202 {
113 struct MeshTunnelTreeNode *n; 203 struct MeshTunnelTreeNode *n;
114 204
115 n = tree_find_peer(t->root, peer); 205 n = tree_find_peer(t, peer);
116 if (NULL != t->me && NULL != n) 206 if (NULL != t->me && NULL != n)
117 { 207 {
118 tree_update_first_hops(t, n, NULL); 208 tree_node_update_first_hops(t, n, NULL);
119 r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey); 209 r = GNUNET_CONTAINER_multihashmap_get (t->first_hops, &id.hashPubKey);
120 GNUNET_assert (NULL != r); 210 GNUNET_assert (NULL != r);
121 } 211 }
@@ -214,6 +304,103 @@ tree_node_new(struct MeshTunnelTreeNode *parent, GNUNET_PEER_Id peer)
214} 304}
215 305
216 306
307/**
308 * Recursively find the given peer.
309 *
310 * @param parent Node where to start looking.
311 * @param peer Peer to find.
312 *
313 * @return Pointer to the node of the peer. NULL if not found.
314 */
315static struct MeshTunnelTreeNode *
316tree_node_find_peer (struct MeshTunnelTreeNode *parent,
317 GNUNET_PEER_Id peer_id)
318{
319 struct MeshTunnelTreeNode *n;
320 struct MeshTunnelTreeNode *r;
321
322 if (parent->peer == peer_id)
323 return parent;
324 for (n = parent->children_head; NULL != n; n = n->next)
325 {
326 r = tree_node_find_peer (n, peer_id);
327 if (NULL != r)
328 return r;
329 }
330 return NULL;
331}
332
333
334/**
335 * Recusively update the info about what is the first hop to reach the node
336 *
337 * @param tree Tree this nodes belongs to.
338 * @param parent_id Short ID from node form which to start updating.
339 * @param hop If known, ID of the first hop.
340 * If not known, NULL to find out and pass on children.
341 */
342static void
343tree_node_update_first_hops (struct MeshTunnelTree *tree,
344 struct MeshTunnelTreeNode *parent,
345 struct GNUNET_PeerIdentity *hop)
346{
347 struct GNUNET_PeerIdentity pi;
348 struct GNUNET_PeerIdentity *copy;
349 struct GNUNET_PeerIdentity id;
350 struct MeshTunnelTreeNode *n;
351
352#if MESH_TREE_DEBUG
353 GNUNET_PEER_resolve(parent->peer, &id);
354 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
355 "tree: Finding first hop for %s.\n",
356 GNUNET_i2s (&id));
357#endif
358 if (NULL == hop)
359 {
360 struct MeshTunnelTreeNode *aux;
361 struct MeshTunnelTreeNode *old;
362
363 aux = old = parent;
364 while (aux != tree->me)
365 {
366#if MESH_TREE_DEBUG
367 GNUNET_PEER_resolve(old->peer, &id);
368 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
369 "tree: ... its not %s.\n",
370 GNUNET_i2s (&id));
371#endif
372 old = aux;
373 aux = aux->parent;
374 GNUNET_assert(NULL != aux);
375 }
376#if MESH_TREE_DEBUG
377 GNUNET_PEER_resolve(old->peer, &id);
378 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
379 "tree: It's %s!\n",
380 GNUNET_i2s (&id));
381#endif
382 hop = &pi;
383 GNUNET_PEER_resolve(old->peer, hop);
384 }
385 GNUNET_PEER_resolve(parent->peer, &id);
386 copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
387 if (NULL == copy)
388 copy = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
389 *copy = *hop;
390
391 (void) GNUNET_CONTAINER_multihashmap_put(
392 tree->first_hops,
393 &id.hashPubKey,
394 copy,
395 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
396
397 for (n = parent->children_head; NULL != n; n = n->next)
398 {
399 tree_node_update_first_hops (tree, n, hop);
400 }
401}
402
403
217static void 404static void
218tree_node_debug(struct MeshTunnelTreeNode *n, uint16_t level) 405tree_node_debug(struct MeshTunnelTreeNode *n, uint16_t level)
219{ 406{
@@ -307,28 +494,102 @@ tree_new (GNUNET_PEER_Id peer)
307 494
308 495
309/** 496/**
310 * Recursively find the given peer in the tree. 497 * Set own identity in the tree
311 * 498 *
312 * @param t Tunnel where to look for the peer. 499 * @param tree Tree.
313 * @param peer Peer to find 500 * @param peer A short peer id of local peer.
501 */
502void
503tree_set_me (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer)
504{
505 tree->me = tree_find_peer(tree, peer);
506}
507
508
509/**
510 * Get the id of the local node of the tree.
314 * 511 *
315 * @return Pointer to the node of the peer. NULL if not found. 512 * @param tree Tree whose local id we want to now.
513 *
514 * @return Short peer id of local peer.
316 */ 515 */
317struct MeshTunnelTreeNode * 516GNUNET_PEER_Id
318tree_find_peer (struct MeshTunnelTreeNode *parent, GNUNET_PEER_Id peer_id) 517tree_get_me (struct MeshTunnelTree *tree)
518{
519 if (NULL != tree->me)
520 return tree->me->peer;
521 else
522 return (GNUNET_PEER_Id) 0;
523}
524
525/**
526 * Set the status of a node.
527 *
528 * @param tree Tree.
529 * @param peer A short peer id of local peer.
530 */
531void
532tree_set_status (struct MeshTunnelTree *tree,
533 GNUNET_PEER_Id peer,
534 enum MeshPeerState status)
319{ 535{
320 struct MeshTunnelTreeNode *n; 536 struct MeshTunnelTreeNode *n;
321 struct MeshTunnelTreeNode *r;
322 537
323 if (parent->peer == peer_id) 538 n = tree_find_peer(tree, peer);
324 return parent; 539 if (NULL == n)
325 for (n = parent->children_head; NULL != n; n = n->next) 540 return;
326 { 541 n->status = status;
327 r = tree_find_peer (n, peer_id); 542}
328 if (NULL != r) 543
329 return r; 544
330 } 545/**
331 return NULL; 546 * Get the status of a node.
547 *
548 * @param tree Tree whose local id we want to now.
549 *
550 * @return Short peer id of local peer.
551 */
552enum MeshPeerState
553tree_get_status (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer)
554{
555 struct MeshTunnelTreeNode *n;
556
557 n = tree_find_peer(tree, peer);
558 if (NULL == n)
559 return MESH_PEER_INVALID;
560 return n->status;
561}
562
563
564/**
565 * Get the id of the predecessor of the local node.
566 *
567 * @param tree Tree whose local id we want to now.
568 *
569 * @return Short peer id of local peer.
570 */
571GNUNET_PEER_Id
572tree_get_predecessor (struct MeshTunnelTree *tree)
573{
574 if (NULL != tree->me && NULL != tree->me->parent)
575 return tree->me->parent->peer;
576 else
577 return (GNUNET_PEER_Id) 0;
578}
579
580
581/**
582 * Find the given peer in the tree.
583 *
584 * @param tree Tree where to look for the peer.
585 * @param peer Peer to find.
586 *
587 * @return Pointer to the node of the peer. NULL if not found.
588 */
589struct MeshTunnelTreeNode *
590tree_find_peer (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer_id)
591{
592 return tree_node_find_peer(tree->root, peer_id);
332} 593}
333 594
334 595
@@ -342,7 +603,7 @@ tree_find_peer (struct MeshTunnelTreeNode *parent, GNUNET_PEER_Id peer_id)
342static void 603static void
343tree_mark_peers_disconnected (struct MeshTunnelTree *tree, 604tree_mark_peers_disconnected (struct MeshTunnelTree *tree,
344 struct MeshTunnelTreeNode *parent, 605 struct MeshTunnelTreeNode *parent,
345 MeshNodeDisconnectCB cb, 606 MeshTreeCallback cb,
346 void *cbcls) 607 void *cbcls)
347{ 608{
348 struct GNUNET_PeerIdentity *pi; 609 struct GNUNET_PeerIdentity *pi;
@@ -370,76 +631,51 @@ tree_mark_peers_disconnected (struct MeshTunnelTree *tree,
370 631
371 632
372/** 633/**
373 * Recusively update the info about what is the first hop to reach the node 634 * Iterate over all children of the local node.
374 * 635 *
375 * @param tree Tree this nodes belongs to 636 * @param tree Tree to use. Must have "me" set.
376 * @param parent Node to be start updating 637 * @param cb Callback to call over each child.
377 * @param hop If known, ID of the first hop. 638 * @param cls Closure.
378 * If not known, NULL to find out and pass on children.
379 */ 639 */
380void 640void
381tree_update_first_hops (struct MeshTunnelTree *tree, 641tree_iterate_children (struct MeshTunnelTree *tree,
382 struct MeshTunnelTreeNode *parent, 642 MeshTreeCallback cb,
383 struct GNUNET_PeerIdentity *hop) 643 void *cls)
384{ 644{
385 struct GNUNET_PeerIdentity pi;
386 struct GNUNET_PeerIdentity *copy;
387 struct GNUNET_PeerIdentity id;
388 struct MeshTunnelTreeNode *n; 645 struct MeshTunnelTreeNode *n;
389 646
390#if MESH_TREE_DEBUG 647 if (NULL == tree->me)
391 GNUNET_PEER_resolve(parent->peer, &id);
392 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
393 "tree: Finding first hop for %s.\n",
394 GNUNET_i2s (&id));
395#endif
396 if (NULL == hop)
397 { 648 {
398 struct MeshTunnelTreeNode *aux; 649 GNUNET_break (0);
399 struct MeshTunnelTreeNode *old; 650 return;
400
401 aux = old = parent;
402 while (aux != tree->me)
403 {
404#if MESH_TREE_DEBUG
405 GNUNET_PEER_resolve(old->peer, &id);
406 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
407 "tree: ... its not %s.\n",
408 GNUNET_i2s (&id));
409#endif
410 old = aux;
411 aux = aux->parent;
412 GNUNET_assert(NULL != aux);
413 }
414#if MESH_TREE_DEBUG
415 GNUNET_PEER_resolve(old->peer, &id);
416 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
417 "tree: It's %s!\n",
418 GNUNET_i2s (&id));
419#endif
420 hop = &pi;
421 GNUNET_PEER_resolve(old->peer, hop);
422 } 651 }
423 GNUNET_PEER_resolve(parent->peer, &id); 652 for (n = tree->me->children_head; NULL != n; n = n->next)
424 copy = GNUNET_CONTAINER_multihashmap_get (tree->first_hops, &id.hashPubKey);
425 if (NULL == copy)
426 copy = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
427 *copy = *hop;
428
429 (void) GNUNET_CONTAINER_multihashmap_put(
430 tree->first_hops,
431 &id.hashPubKey,
432 copy,
433 GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
434
435 for (n = parent->children_head; NULL != n; n = n->next)
436 { 653 {
437 tree_update_first_hops (tree, n, hop); 654 cb (cls, n->peer);
438 } 655 }
439} 656}
440 657
441 658
442/** 659/**
660 * Recusively update the info about what is the first hop to reach the node
661 *
662 * @param tree Tree this nodes belongs to.
663 * @param parent_id Short ID from node form which to start updating.
664 * @param hop If known, ID of the first hop.
665 * If not known, NULL to find out and pass on children.
666 */
667void
668tree_update_first_hops (struct MeshTunnelTree *tree,
669 GNUNET_PEER_Id parent_id,
670 struct GNUNET_PeerIdentity *hop)
671{
672 tree_node_update_first_hops(tree,
673 tree_find_peer(tree, parent_id),
674 hop);
675}
676
677
678/**
443 * Delete the current path to the peer, including all now unused relays. 679 * Delete the current path to the peer, including all now unused relays.
444 * The destination peer is NOT destroyed, it is returned in order to either set 680 * The destination peer is NOT destroyed, it is returned in order to either set
445 * a new path to it or destroy it explicitly, taking care of it's child nodes. 681 * a new path to it or destroy it explicitly, taking care of it's child nodes.
@@ -455,7 +691,7 @@ tree_update_first_hops (struct MeshTunnelTree *tree,
455struct MeshTunnelTreeNode * 691struct MeshTunnelTreeNode *
456tree_del_path (struct MeshTunnelTree *t, 692tree_del_path (struct MeshTunnelTree *t,
457 GNUNET_PEER_Id peer_id, 693 GNUNET_PEER_Id peer_id,
458 MeshNodeDisconnectCB cb, 694 MeshTreeCallback cb,
459 void *cbcls) 695 void *cbcls)
460{ 696{
461 struct MeshTunnelTreeNode *parent; 697 struct MeshTunnelTreeNode *parent;
@@ -483,7 +719,7 @@ tree_del_path (struct MeshTunnelTree *t,
483 return n; 719 return n;
484 } 720 }
485 } 721 }
486 n = tree_find_peer (t->root, peer_id); 722 n = tree_find_peer (t, peer_id);
487 if (NULL == n) 723 if (NULL == n)
488 return NULL; 724 return NULL;
489 node = n; 725 node = n;
@@ -534,7 +770,7 @@ tree_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer)
534 struct MeshPeerPath *p; 770 struct MeshPeerPath *p;
535 GNUNET_PEER_Id myid = t->me->peer; 771 GNUNET_PEER_Id myid = t->me->peer;
536 772
537 n = tree_find_peer(t->me, peer); 773 n = tree_find_peer(t, peer);
538 if (NULL == n) 774 if (NULL == n)
539 return NULL; 775 return NULL;
540 p = path_new(0); 776 p = path_new(0);
@@ -545,7 +781,8 @@ tree_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer)
545 GNUNET_array_append(p->peers, p->length, n->peer); 781 GNUNET_array_append(p->peers, p->length, n->peer);
546 GNUNET_PEER_change_rc(n->peer, 1); 782 GNUNET_PEER_change_rc(n->peer, 1);
547 n = n->parent; 783 n = n->parent;
548 GNUNET_assert(NULL != n); 784 if (NULL == n)
785 return NULL;
549 } 786 }
550 GNUNET_array_append(p->peers, p->length, myid); 787 GNUNET_array_append(p->peers, p->length, myid);
551 GNUNET_PEER_change_rc(myid, 1); 788 GNUNET_PEER_change_rc(myid, 1);
@@ -581,7 +818,7 @@ tree_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer)
581int 818int
582tree_add_path (struct MeshTunnelTree *t, 819tree_add_path (struct MeshTunnelTree *t,
583 const struct MeshPeerPath *p, 820 const struct MeshPeerPath *p,
584 MeshNodeDisconnectCB cb, 821 MeshTreeCallback cb,
585 void *cbcls) 822 void *cbcls)
586{ 823{
587 struct MeshTunnelTreeNode *parent; 824 struct MeshTunnelTreeNode *parent;
@@ -683,7 +920,7 @@ tree_add_path (struct MeshTunnelTree *t,
683 GNUNET_CONTAINER_DLL_insert(parent->children_head, 920 GNUNET_CONTAINER_DLL_insert(parent->children_head,
684 parent->children_tail, 921 parent->children_tail,
685 oldnode); 922 oldnode);
686 tree_update_first_hops (t, oldnode, NULL); 923 tree_node_update_first_hops (t, oldnode, NULL);
687 n = oldnode; 924 n = oldnode;
688 } 925 }
689 else 926 else
@@ -711,7 +948,7 @@ tree_add_path (struct MeshTunnelTree *t,
711#endif 948#endif
712 GNUNET_PEER_resolve (p->peers[me + 1], &id); 949 GNUNET_PEER_resolve (p->peers[me + 1], &id);
713 tree_update_first_hops(t, 950 tree_update_first_hops(t,
714 tree_find_peer(t->root, p->peers[p->length - 1]), 951 p->peers[p->length - 1],
715 &id); 952 &id);
716 } 953 }
717#if MESH_TREE_DEBUG 954#if MESH_TREE_DEBUG
@@ -737,13 +974,13 @@ GNUNET_PEER_Id
737tree_notify_connection_broken (struct MeshTunnelTree *t, 974tree_notify_connection_broken (struct MeshTunnelTree *t,
738 GNUNET_PEER_Id p1, 975 GNUNET_PEER_Id p1,
739 GNUNET_PEER_Id p2, 976 GNUNET_PEER_Id p2,
740 MeshNodeDisconnectCB cb, 977 MeshTreeCallback cb,
741 void *cbcls) 978 void *cbcls)
742{ 979{
743 struct MeshTunnelTreeNode *n; 980 struct MeshTunnelTreeNode *n;
744 struct MeshTunnelTreeNode *c; 981 struct MeshTunnelTreeNode *c;
745 982
746 n = tree_find_peer(t->me, p1); 983 n = tree_find_peer(t, p1);
747 if (NULL == n) 984 if (NULL == n)
748 return 0; 985 return 0;
749 if (NULL != n->parent && n->parent->peer == p2) 986 if (NULL != n->parent && n->parent->peer == p2)
@@ -791,22 +1028,26 @@ tree_notify_connection_broken (struct MeshTunnelTree *t,
791int 1028int
792tree_del_peer (struct MeshTunnelTree *t, 1029tree_del_peer (struct MeshTunnelTree *t,
793 GNUNET_PEER_Id peer, 1030 GNUNET_PEER_Id peer,
794 MeshNodeDisconnectCB cb, 1031 MeshTreeCallback cb,
795 void *cbcls) 1032 void *cbcls)
796{ 1033{
797 struct MeshTunnelTreeNode *n; 1034 struct MeshTunnelTreeNode *n;
798 1035
799 n = tree_del_path(t, peer, cb, cbcls); 1036 n = tree_del_path(t, peer, cb, cbcls);
800 if (NULL == n) 1037 if (NULL == n)
801 return GNUNET_SYSERR; 1038 {
1039 GNUNET_break (0);
1040 return GNUNET_YES;
1041 }
802 GNUNET_break_op (NULL == n->children_head); 1042 GNUNET_break_op (NULL == n->children_head);
803 tree_node_destroy(n); 1043 tree_node_destroy(n);
804 if (NULL == t->root->children_head && t->me != t->root) 1044 if (NULL == t->root->children_head && t->me != t->root)
805 { 1045 {
806 tree_node_destroy (t->root); 1046 tree_node_destroy (t->root);
807 t->root = NULL; 1047 t->root = NULL;
1048 return GNUNET_NO;
808 } 1049 }
809 return GNUNET_OK; 1050 return GNUNET_YES;
810} 1051}
811 1052
812 1053
diff --git a/src/mesh/mesh_tunnel_tree.h b/src/mesh/mesh_tunnel_tree.h
index 2cb28a28c..e946259da 100644
--- a/src/mesh/mesh_tunnel_tree.h
+++ b/src/mesh/mesh_tunnel_tree.h
@@ -58,83 +58,13 @@ struct MeshPeerPath
58/** 58/**
59 * Node of path tree for a tunnel 59 * Node of path tree for a tunnel
60 */ 60 */
61struct MeshTunnelTreeNode 61struct MeshTunnelTreeNode;
62{
63 /**
64 * Peer this node describes
65 */
66 GNUNET_PEER_Id peer;
67
68 /**
69 * Parent node in the tree
70 */
71 struct MeshTunnelTreeNode *parent;
72
73 /**
74 * DLL of siblings
75 */
76 struct MeshTunnelTreeNode *next;
77
78 /**
79 * DLL of siblings
80 */
81 struct MeshTunnelTreeNode *prev;
82
83 /**
84 * DLL of children
85 */
86 struct MeshTunnelTreeNode *children_head;
87
88 /**
89 * DLL of children
90 */
91 struct MeshTunnelTreeNode *children_tail;
92
93 /**
94 * Status of the peer in the tunnel
95 */
96 enum MeshPeerState status;
97};
98 62
99 63
100/** 64/**
101 * Tree to reach all peers in the tunnel 65 * Tree to reach all peers in the tunnel
102 */ 66 */
103struct MeshTunnelTree 67struct MeshTunnelTree;
104{
105 /**
106 * How often to refresh the path
107 */
108 struct GNUNET_TIME_Relative refresh;
109
110 /**
111 * Root node of peer tree
112 */
113 struct MeshTunnelTreeNode *root;
114
115 /**
116 * Node that represents our position in the tree (for non local tunnels)
117 */
118 struct MeshTunnelTreeNode *me;
119
120 /**
121 * DLL of disconneted nodes
122 */
123 struct MeshTunnelTreeNode *disconnected_head;
124
125 /**
126 * DLL of disconneted nodes
127 */
128 struct MeshTunnelTreeNode *disconnected_tail;
129
130 /**
131 * Cache of all peers and the first hop to them.
132 * Indexed by PeerIdentity, contains a pointer to the PeerIdentity
133 * of 1st hop.
134 */
135 struct GNUNET_CONTAINER_MultiHashMap *first_hops;
136
137};
138 68
139 69
140/******************************************************************************/ 70/******************************************************************************/
@@ -229,14 +159,13 @@ path_destroy (struct MeshPeerPath *p);
229 * @param cls Closure. 159 * @param cls Closure.
230 * @param peer_id short ID of peer that is no longer reachable. 160 * @param peer_id short ID of peer that is no longer reachable.
231 */ 161 */
232typedef void (*MeshNodeDisconnectCB) (void *cls, 162typedef void (*MeshTreeCallback) (void *cls,
233 GNUNET_PEER_Id peer_id); 163 GNUNET_PEER_Id peer_id);
234 164
235 165
236/** 166/**
237 * Create a new tunnel tree associated to a tunnel 167 * Create a new tunnel tree associated to a tunnel
238 * 168 *
239 * @param t Tunnel this tree will represent
240 * @param peer A short peer id of the root of the tree 169 * @param peer A short peer id of the root of the tree
241 * 170 *
242 * @return A newly allocated and initialized tunnel tree 171 * @return A newly allocated and initialized tunnel tree
@@ -246,29 +175,96 @@ tree_new (GNUNET_PEER_Id peer);
246 175
247 176
248/** 177/**
249 * Recursively find the given peer in the tree. 178 * Set own identity in the tree
179 *
180 * @param tree Tree.
181 * @param peer A short peer id of local peer.
182 */
183void
184tree_set_me (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer);
185
186
187/**
188 * Get the id of the local id of the tree.
189 *
190 * @param tree Tree whose local id we want to now.
191 *
192 * @return Short peer id of local peer.
193 */
194GNUNET_PEER_Id
195tree_get_me (struct MeshTunnelTree *tree);
196
197
198/**
199 * Set the status of a node.
200 *
201 * @param tree Tree.
202 * @param peer A short peer id of local peer.
203 */
204void
205tree_set_status (struct MeshTunnelTree *tree,
206 GNUNET_PEER_Id peer,
207 enum MeshPeerState status);
208
209
210/**
211 * Get the status of a node.
212 *
213 * @param tree Tree whose local id we want to now.
214 *
215 * @return Short peer id of local peer.
216 */
217enum MeshPeerState
218tree_get_status (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer);
219
220
221/**
222 * Get the id of the predecessor of the local node.
250 * 223 *
251 * @param parent Parent node where to start looking. 224 * @param tree Tree whose local id we want to now.
252 * @param peer Short ID of peer to find. 225 *
226 * @return Short peer id of local peer.
227 */
228GNUNET_PEER_Id
229tree_get_predecessor (struct MeshTunnelTree *tree);
230
231
232/**
233 * Find the given peer in the tree.
234 *
235 * @param tree Tree where to look for the peer.
236 * @param peer Peer to find.
253 * 237 *
254 * @return Pointer to the node of the peer. NULL if not found. 238 * @return Pointer to the node of the peer. NULL if not found.
255 */ 239 */
256struct MeshTunnelTreeNode * 240struct MeshTunnelTreeNode *
257tree_find_peer (struct MeshTunnelTreeNode *parent, 241tree_find_peer (struct MeshTunnelTree *tree, GNUNET_PEER_Id peer_id);
258 GNUNET_PEER_Id peer); 242
243
244/**
245 * Iterate over all children of the local node.
246 *
247 * @param tree Tree to use. Must have "me" set.
248 * @param cb Callback to call over each child.
249 * @param cls Closure.
250 */
251void
252tree_iterate_children (struct MeshTunnelTree *tree,
253 MeshTreeCallback cb,
254 void *cls);
259 255
260 256
261/** 257/**
262 * Recusively update the info about what is the first hop to reach the node 258 * Recusively update the info about what is the first hop to reach the node
263 * 259 *
264 * @param tree Tree this nodes belongs to 260 * @param tree Tree this nodes belongs to.
265 * @param parent Node to be start updating 261 * @param parent_id Short ID from node form which to start updating.
266 * @param hop If known, ID of the first hop. 262 * @param hop If known, ID of the first hop.
267 * If not known, NULL to find out and pass on children. 263 * If not known, NULL to find out and pass on children.
268 */ 264 */
269void 265void
270tree_update_first_hops (struct MeshTunnelTree *tree, 266tree_update_first_hops (struct MeshTunnelTree *tree,
271 struct MeshTunnelTreeNode *parent, 267 GNUNET_PEER_Id parent_id,
272 struct GNUNET_PeerIdentity *hop); 268 struct GNUNET_PeerIdentity *hop);
273 269
274/** 270/**
@@ -288,7 +284,7 @@ tree_update_first_hops (struct MeshTunnelTree *tree,
288struct MeshTunnelTreeNode * 284struct MeshTunnelTreeNode *
289tree_del_path (struct MeshTunnelTree *t, 285tree_del_path (struct MeshTunnelTree *t,
290 GNUNET_PEER_Id peer, 286 GNUNET_PEER_Id peer,
291 MeshNodeDisconnectCB cb, 287 MeshTreeCallback cb,
292 void *cbcls); 288 void *cbcls);
293 289
294 290
@@ -321,7 +317,7 @@ tree_get_path_to_peer(struct MeshTunnelTree *t,
321int 317int
322tree_add_path (struct MeshTunnelTree *t, 318tree_add_path (struct MeshTunnelTree *t,
323 const struct MeshPeerPath *p, 319 const struct MeshPeerPath *p,
324 MeshNodeDisconnectCB cb, 320 MeshTreeCallback cb,
325 void *cbcls); 321 void *cbcls);
326 322
327 323
@@ -341,7 +337,7 @@ GNUNET_PEER_Id
341tree_notify_connection_broken (struct MeshTunnelTree *t, 337tree_notify_connection_broken (struct MeshTunnelTree *t,
342 GNUNET_PEER_Id p1, 338 GNUNET_PEER_Id p1,
343 GNUNET_PEER_Id p2, 339 GNUNET_PEER_Id p2,
344 MeshNodeDisconnectCB cb, 340 MeshTreeCallback cb,
345 void *cbcls); 341 void *cbcls);
346 342
347 343
@@ -356,12 +352,12 @@ tree_notify_connection_broken (struct MeshTunnelTree *t,
356 * @param cb Callback to notify client of disconnected peers. 352 * @param cb Callback to notify client of disconnected peers.
357 * @param cbcls Closure for cb. 353 * @param cbcls Closure for cb.
358 * 354 *
359 * @return GNUNET_OK or GNUNET_SYSERR 355 * @return GNUNET_YES if the tunnel still has nodes
360 */ 356 */
361int 357int
362tree_del_peer (struct MeshTunnelTree *t, 358tree_del_peer (struct MeshTunnelTree *t,
363 GNUNET_PEER_Id peer, 359 GNUNET_PEER_Id peer,
364 MeshNodeDisconnectCB cb, 360 MeshTreeCallback cb,
365 void *cbcls); 361 void *cbcls);
366 362
367/** 363/**
diff --git a/src/mesh/test_mesh_path_api.c b/src/mesh/test_mesh_path_api.c
deleted file mode 100644
index 45c4f3c14..000000000
--- a/src/mesh/test_mesh_path_api.c
+++ /dev/null
@@ -1,314 +0,0 @@
1/*
2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19*/
20
21/**
22 * @file mesh/test_mesh_path.c
23 * @brief test mesh path: test of path management api
24 * @author Bartlomiej Polot
25 */
26
27#include "platform.h"
28#include "gnunet_common.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_dht_service.h"
31#include "gnunet_mesh_service.h"
32#include "mesh.h"
33#include "mesh_tunnel_tree.h"
34
35#define VERBOSE 1
36
37int failed;
38int cb_call;
39struct GNUNET_PeerIdentity* pi[10];
40struct MeshTunnelTree *tree;
41
42static void
43cb (void *cls, GNUNET_PEER_Id peer_id)
44{
45 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: CB: Disconnected %u\n", peer_id);
46 if(0 == cb_call)
47 {
48 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: and it shouldn't!\n");
49 failed++;
50 }
51 cb_call--;
52}
53
54
55/**
56 * Check if a node has all expected properties.
57 *
58 * @param peer_id Short ID of the peer to test.
59 * @param status Expected status of the peer.
60 * @param children Expected number of children of the peer.
61 * @param first_hop Short ID of the expected first hop towards the peer.
62 */
63static void
64test_assert (GNUNET_PEER_Id peer_id,
65 enum MeshPeerState status,
66 unsigned int children,
67 GNUNET_PEER_Id first_hop)
68{
69 struct MeshTunnelTreeNode *n;
70 struct MeshTunnelTreeNode *c;
71 unsigned int i;
72 int pre_failed;
73
74 pre_failed = failed;
75 n = tree_find_peer(tree->root, peer_id);
76 if (n->peer != peer_id)
77 {
78 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
79 "Retrieved peer != original (%u, %u)\n",
80 n->peer, peer_id);
81 failed++;
82 }
83 if (n->status != status)
84 {
85 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
86 "Retrieved peer has wrong status! (%u, %u)\n",
87 n->status, status);
88 failed++;
89 }
90 for (c = n->children_head, i = 0; NULL != c; c = c->next, i++);
91 if (i != children)
92 {
93 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
94 "Retrieved peer wrong has number of children! (%u, %u)\n",
95 i, children);
96 failed++;
97 }
98 if (0 != first_hop &&
99 GNUNET_PEER_search(path_get_first_hop(tree, peer_id)) != first_hop)
100 {
101 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
102 "Wrong first hop! (%u, %u)\n",
103 GNUNET_PEER_search(path_get_first_hop(tree, peer_id)),
104 first_hop);
105 failed++;
106 }
107 if (pre_failed != failed)
108 {
109 struct GNUNET_PeerIdentity id;
110 GNUNET_PEER_resolve (peer_id, &id);
111 GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
112 "*** Peer %s (%u) has failed %d checks! (real, expected)\n",
113 GNUNET_i2s (&id), peer_id, failed - pre_failed);
114 }
115}
116
117
118static void
119finish(void)
120{
121 unsigned int i;
122
123 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Finishing...\n");
124 for (i = 0; i < 10; i++)
125 {
126 GNUNET_free(pi[i]);
127 }
128 exit(0);
129}
130
131/**
132 * Convert an integer int to a peer identity
133 */
134static struct GNUNET_PeerIdentity *
135get_pi (uint32_t id)
136{
137 struct GNUNET_PeerIdentity *pi;
138
139 pi = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity));
140 pi->hashPubKey.bits[0] = id + 1;
141 return pi;
142}
143
144
145int
146main (int argc, char *argv[])
147{
148 struct MeshTunnelTreeNode *node;
149 struct MeshTunnelTreeNode *node2;
150 struct MeshPeerPath *path;
151 struct MeshPeerPath *path1;
152 unsigned int i;
153
154 failed = 0;
155 cb_call = 0;
156 GNUNET_log_setup ("test_mesh_api_path",
157#if VERBOSE
158 "DEBUG",
159#else
160 "WARNING",
161#endif
162 NULL);
163 for (i = 0; i < 10; i++)
164 {
165 pi[i] = get_pi(i);
166 GNUNET_break (i + 1 == GNUNET_PEER_intern(pi[i]));
167 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n",
168 i + 1,
169 GNUNET_h2s(&pi[i]->hashPubKey));
170 }
171 tree = GNUNET_malloc(sizeof(struct MeshTunnelTree));
172 tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32);
173 tree->root = GNUNET_malloc(sizeof(struct MeshTunnelTreeNode));
174 tree->root->peer = 1;
175 tree->me = tree->root;
176 path = path_new (4);
177 path->peers[0] = 1;
178 path->peers[1] = 2;
179 path->peers[2] = 3;
180 path->peers[3] = 4;
181 path->length = 4;
182
183 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3 4\n");
184 tree_add_path(tree, path, &cb, NULL);
185 tree_debug(tree);
186 path1 = tree_get_path_to_peer(tree, 4);
187 if (path->length != path1->length ||
188 memcmp(path->peers, path1->peers, path->length) != 0)
189 {
190 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Retrieved path != original\n");
191 failed++;
192 }
193 path_destroy(path1);
194 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
195 test_assert (3, MESH_PEER_RELAY, 1, 0);
196 test_assert (2, MESH_PEER_RELAY, 1, 0);
197 test_assert (1, MESH_PEER_ROOT, 1, 0);
198
199 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding second path: 1 2 3\n");
200 path->length--;
201 tree_add_path(tree, path, &cb, NULL);
202 tree_debug(tree);
203
204 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
205 test_assert (3, MESH_PEER_SEARCHING, 1, 2);
206 test_assert (2, MESH_PEER_RELAY, 1, 0);
207 test_assert (1, MESH_PEER_ROOT, 1, 0);
208
209 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding third path...\n");
210 path->length++;
211 path->peers[3] = 5;
212 tree_add_path(tree, path, &cb, NULL);
213 tree_debug(tree);
214
215 test_assert (5, MESH_PEER_SEARCHING, 0, 2);
216 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
217 test_assert (3, MESH_PEER_SEARCHING, 2, 2);
218 test_assert (2, MESH_PEER_RELAY, 1, 0);
219 test_assert (1, MESH_PEER_ROOT, 1, 0);
220
221 node = tree_find_peer(tree->root, 5);
222 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Deleting third path...\n");
223 node->status = MESH_PEER_READY;
224 cb_call = 1;
225 node2 = tree_del_path(tree, 5, &cb, NULL);
226 tree_debug(tree);
227 if (cb_call != 0)
228 {
229 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
230 failed++;
231 }
232 if (node2->peer != 5)
233 {
234 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Retrieved peer != original\n");
235 failed++;
236 }
237
238 test_assert (4, MESH_PEER_SEARCHING, 0, 2);
239 test_assert (3, MESH_PEER_SEARCHING, 1, 2);
240 test_assert (2, MESH_PEER_RELAY, 1, 0);
241 test_assert (1, MESH_PEER_ROOT, 1, 0);
242
243 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Destroying node copy...\n");
244 GNUNET_free (node2);
245
246 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
247 "test: Adding new shorter first path...\n");
248 path->length = 2;
249 path->peers[1] = 4;
250 cb_call = 1;
251 tree_find_peer(tree->root, 4)->status = MESH_PEER_READY;
252 tree_add_path(tree, path, &cb, NULL);
253 tree_debug(tree);
254 if (cb_call != 0)
255 {
256 GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "%u callbacks missed!\n", cb_call);
257 failed++;
258 }
259
260 test_assert (4, MESH_PEER_SEARCHING, 0, 4);
261 test_assert (3, MESH_PEER_SEARCHING, 0, 2);
262 test_assert (2, MESH_PEER_RELAY, 1, 0);
263 test_assert (1, MESH_PEER_ROOT, 2, 0);
264
265 GNUNET_free (path->peers);
266 GNUNET_free (path);
267 tree_destroy (tree);
268
269 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test:\n");
270 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Testing relay trees\n");
271 for (i = 0; i < 10; i++)
272 {
273 pi[i] = get_pi(i);
274 GNUNET_break (i + 1 == GNUNET_PEER_intern(pi[i]));
275 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer %u: %s\n",
276 i + 1,
277 GNUNET_h2s(&pi[i]->hashPubKey));
278 }
279 tree = GNUNET_malloc(sizeof(struct MeshTunnelTree));
280 tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32);
281 tree->root = GNUNET_malloc(sizeof(struct MeshTunnelTreeNode));
282 tree->root->peer = 1;
283 path = path_new (3);
284 path->peers[0] = 1;
285 path->peers[1] = 2;
286 path->peers[2] = 3;
287 path->length = 3;
288
289 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding first path: 1 2 3\n");
290 tree_add_path(tree, path, &cb, NULL);
291 tree_debug(tree);
292 tree->me = tree_find_peer (tree->root, 2);
293
294 test_assert (3, MESH_PEER_SEARCHING, 0, 3);
295 test_assert (2, MESH_PEER_RELAY, 1, 0);
296 test_assert (1, MESH_PEER_ROOT, 1, 0);
297
298 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "test: Adding same path: 1 2 3\n");
299 tree_add_path(tree, path, &cb, NULL);
300
301 GNUNET_free (path->peers);
302 GNUNET_free (path);
303 tree_destroy (tree);
304
305 if (failed > 0)
306 {
307 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "%u tests failed\n", failed);
308 return 1;
309 }
310 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: OK\n");
311 finish();
312
313 return 0;
314}