diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/mesh/gnunet-service-mesh.c | 440 | ||||
-rw-r--r-- | src/mesh/mesh.h | 381 | ||||
-rw-r--r-- | src/mesh/mesh_tunnel_tree.c | 234 | ||||
-rw-r--r-- | src/mesh/mesh_tunnel_tree.h | 176 | ||||
-rw-r--r-- | src/mesh/test_mesh_path_api.c | 2 |
5 files changed, 616 insertions, 617 deletions
diff --git a/src/mesh/gnunet-service-mesh.c b/src/mesh/gnunet-service-mesh.c index 75fa973e0..811553e08 100644 --- a/src/mesh/gnunet-service-mesh.c +++ b/src/mesh/gnunet-service-mesh.c | |||
@@ -62,6 +62,298 @@ | |||
62 | GNUNET_TIME_UNIT_SECONDS,\ | 62 | GNUNET_TIME_UNIT_SECONDS,\ |
63 | 5) | 63 | 5) |
64 | 64 | ||
65 | |||
66 | /******************************************************************************/ | ||
67 | /************************ DATA STRUCTURES ****************************/ | ||
68 | /******************************************************************************/ | ||
69 | |||
70 | /** FWD declaration */ | ||
71 | struct MeshPeerInfo; | ||
72 | |||
73 | /** | ||
74 | * Struct containing all info possibly needed to build a package when called | ||
75 | * back by core. | ||
76 | */ | ||
77 | struct MeshDataDescriptor | ||
78 | { | ||
79 | /** ID of the tunnel this packet travels in */ | ||
80 | struct MESH_TunnelID *origin; | ||
81 | |||
82 | /** Ultimate destination of the packet */ | ||
83 | GNUNET_PEER_Id destination; | ||
84 | |||
85 | /** Number of identical messages sent to different hops (multicast) */ | ||
86 | unsigned int copies; | ||
87 | |||
88 | /** Size of the data */ | ||
89 | size_t size; | ||
90 | |||
91 | /** Client that asked for the transmission, if any */ | ||
92 | struct GNUNET_SERVER_Client *client; | ||
93 | |||
94 | /** Who was is message being sent to */ | ||
95 | struct MeshPeerInfo *peer; | ||
96 | |||
97 | /** Which handler was used to request the transmission */ | ||
98 | unsigned int handler_n; | ||
99 | |||
100 | /* Data at the end */ | ||
101 | }; | ||
102 | |||
103 | |||
104 | /** | ||
105 | * Struct containing all information regarding a given peer | ||
106 | */ | ||
107 | struct MeshPeerInfo | ||
108 | { | ||
109 | /** | ||
110 | * ID of the peer | ||
111 | */ | ||
112 | GNUNET_PEER_Id id; | ||
113 | |||
114 | /** | ||
115 | * Last time we heard from this peer | ||
116 | */ | ||
117 | struct GNUNET_TIME_Absolute last_contact; | ||
118 | |||
119 | /** | ||
120 | * Number of attempts to reconnect so far | ||
121 | */ | ||
122 | int n_reconnect_attempts; | ||
123 | |||
124 | /** | ||
125 | * Paths to reach the peer, ordered by ascending hop count | ||
126 | */ | ||
127 | struct MeshPeerPath *path_head; | ||
128 | |||
129 | /** | ||
130 | * Paths to reach the peer, ordered by ascending hop count | ||
131 | */ | ||
132 | struct MeshPeerPath *path_tail; | ||
133 | |||
134 | /** | ||
135 | * Handle to stop the DHT search for a path to this peer | ||
136 | */ | ||
137 | struct GNUNET_DHT_GetHandle *dhtget; | ||
138 | |||
139 | /** | ||
140 | * Handles to stop queued transmissions for this peer | ||
141 | */ | ||
142 | struct GNUNET_CORE_TransmitHandle *core_transmit[CORE_QUEUE_SIZE]; | ||
143 | |||
144 | /** | ||
145 | * Pointer to info stuctures used as cls for queued transmissions | ||
146 | */ | ||
147 | struct MeshDataDescriptor *infos[CORE_QUEUE_SIZE]; | ||
148 | |||
149 | /** | ||
150 | * Array of tunnels this peer participates in | ||
151 | * (most probably a small amount, therefore not a hashmap) | ||
152 | * When the path to the peer changes, notify these tunnels to let them | ||
153 | * re-adjust their path trees. | ||
154 | */ | ||
155 | struct MeshTunnel **tunnels; | ||
156 | |||
157 | /** | ||
158 | * Number of tunnels above | ||
159 | */ | ||
160 | unsigned int ntunnels; | ||
161 | }; | ||
162 | |||
163 | |||
164 | /** | ||
165 | * Data scheduled to transmit (to local client or remote peer) | ||
166 | */ | ||
167 | struct MeshQueue | ||
168 | { | ||
169 | /** | ||
170 | * Double linked list | ||
171 | */ | ||
172 | struct MeshQueue *next; | ||
173 | struct MeshQueue *prev; | ||
174 | |||
175 | /** | ||
176 | * Target of the data (NULL if target is client) | ||
177 | */ | ||
178 | struct MeshPeerInfo *peer; | ||
179 | |||
180 | /** | ||
181 | * Client to send the data to (NULL if target is peer) | ||
182 | */ | ||
183 | struct MeshClient *client; | ||
184 | |||
185 | /** | ||
186 | * Size of the message to transmit | ||
187 | */ | ||
188 | unsigned int size; | ||
189 | |||
190 | /** | ||
191 | * How old is the data? | ||
192 | */ | ||
193 | struct GNUNET_TIME_Absolute timestamp; | ||
194 | |||
195 | /** | ||
196 | * Data itself | ||
197 | */ | ||
198 | struct GNUNET_MessageHeader *data; | ||
199 | }; | ||
200 | |||
201 | /** | ||
202 | * Globally unique tunnel identification (owner + number) | ||
203 | * DO NOT USE OVER THE NETWORK | ||
204 | */ | ||
205 | struct MESH_TunnelID | ||
206 | { | ||
207 | /** | ||
208 | * Node that owns the tunnel | ||
209 | */ | ||
210 | GNUNET_PEER_Id oid; | ||
211 | |||
212 | /** | ||
213 | * Tunnel number to differentiate all the tunnels owned by the node oid | ||
214 | * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI ) | ||
215 | */ | ||
216 | MESH_TunnelNumber tid; | ||
217 | }; | ||
218 | |||
219 | |||
220 | struct MeshClient; /* FWD declaration */ | ||
221 | |||
222 | /** | ||
223 | * Struct containing all information regarding a tunnel | ||
224 | * For an intermediate node the improtant info used will be: | ||
225 | * - id Tunnel unique identification | ||
226 | * - paths[0] To know where to send it next | ||
227 | * - metainfo: ready, speeds, accounting | ||
228 | */ | ||
229 | struct MeshTunnel | ||
230 | { | ||
231 | /** | ||
232 | * Tunnel ID | ||
233 | */ | ||
234 | struct MESH_TunnelID id; | ||
235 | |||
236 | /** | ||
237 | * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 ) | ||
238 | */ | ||
239 | MESH_TunnelNumber local_tid; | ||
240 | |||
241 | /** | ||
242 | * Last time the tunnel was used | ||
243 | */ | ||
244 | struct GNUNET_TIME_Absolute timestamp; | ||
245 | |||
246 | /** | ||
247 | * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo) | ||
248 | */ | ||
249 | struct GNUNET_CONTAINER_MultiHashMap *peers; | ||
250 | |||
251 | /** | ||
252 | * Number of peers that are connected and potentially ready to receive data | ||
253 | */ | ||
254 | unsigned int peers_ready; | ||
255 | |||
256 | /** | ||
257 | * Number of peers that have been added to the tunnel | ||
258 | */ | ||
259 | unsigned int peers_total; | ||
260 | |||
261 | /** | ||
262 | * Client owner of the tunnel, if any | ||
263 | */ | ||
264 | struct MeshClient *client; | ||
265 | |||
266 | /** | ||
267 | * Messages ready to transmit | ||
268 | */ | ||
269 | struct MeshQueue *queue_head; | ||
270 | struct MeshQueue *queue_tail; | ||
271 | |||
272 | /** | ||
273 | * Tunnel paths | ||
274 | */ | ||
275 | struct MeshTunnelTree *tree; | ||
276 | |||
277 | /** | ||
278 | * Task to keep the used paths alive | ||
279 | */ | ||
280 | GNUNET_SCHEDULER_TaskIdentifier path_refresh_task; | ||
281 | }; | ||
282 | |||
283 | |||
284 | /** | ||
285 | * Info needed to work with tunnel paths and peers | ||
286 | */ | ||
287 | struct MeshPathInfo | ||
288 | { | ||
289 | /** | ||
290 | * Tunnel | ||
291 | */ | ||
292 | struct MeshTunnel *t; | ||
293 | |||
294 | /** | ||
295 | * Destination peer | ||
296 | */ | ||
297 | struct MeshPeerInfo *peer; | ||
298 | |||
299 | /** | ||
300 | * Path itself | ||
301 | */ | ||
302 | struct MeshPeerPath *path; | ||
303 | }; | ||
304 | |||
305 | |||
306 | /** | ||
307 | * Struct containing information about a client of the service | ||
308 | */ | ||
309 | struct MeshClient | ||
310 | { | ||
311 | /** | ||
312 | * Linked list | ||
313 | */ | ||
314 | struct MeshClient *next; | ||
315 | struct MeshClient *prev; | ||
316 | |||
317 | /** | ||
318 | * Tunnels that belong to this client, indexed by local id | ||
319 | */ | ||
320 | struct GNUNET_CONTAINER_MultiHashMap *tunnels; | ||
321 | |||
322 | /** | ||
323 | * Handle to communicate with the client | ||
324 | */ | ||
325 | struct GNUNET_SERVER_Client *handle; | ||
326 | |||
327 | /** | ||
328 | * Applications that this client has claimed to provide | ||
329 | */ | ||
330 | struct GNUNET_CONTAINER_MultiHashMap *apps; | ||
331 | |||
332 | /** | ||
333 | * Messages that this client has declared interest in | ||
334 | */ | ||
335 | struct GNUNET_CONTAINER_MultiHashMap *types; | ||
336 | |||
337 | /** | ||
338 | * Used to search peers offering a service | ||
339 | */ | ||
340 | struct GNUNET_DHT_GetHandle *dht_get_type; | ||
341 | |||
342 | #if MESH_DEBUG | ||
343 | /** | ||
344 | * ID of the client, for debug messages | ||
345 | */ | ||
346 | unsigned int id; | ||
347 | #endif | ||
348 | |||
349 | }; | ||
350 | |||
351 | |||
352 | |||
353 | /******************************************************************************/ | ||
354 | /************************ DEBUG FUNCTIONS ****************************/ | ||
355 | /******************************************************************************/ | ||
356 | |||
65 | #if MESH_DEBUG | 357 | #if MESH_DEBUG |
66 | /** | 358 | /** |
67 | * GNUNET_SCHEDULER_Task for printing a message after some operation is done | 359 | * GNUNET_SCHEDULER_Task for printing a message after some operation is done |
@@ -199,7 +491,7 @@ iterate_collect_neighbors (void *cls, const GNUNET_HashCode * key, void *value) | |||
199 | { | 491 | { |
200 | return GNUNET_YES; | 492 | return GNUNET_YES; |
201 | } | 493 | } |
202 | id = path_get_first_hop (neighbors->t, peer_info); | 494 | id = path_get_first_hop (neighbors->t->tree, peer_info->id); |
203 | peer_id = GNUNET_PEER_search(id); | 495 | peer_id = GNUNET_PEER_search(id); |
204 | for (i = 0; i < neighbors->path->length; i++) | 496 | for (i = 0; i < neighbors->path->length; i++) |
205 | { | 497 | { |
@@ -443,6 +735,54 @@ path_remove_from_peer (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1, | |||
443 | 735 | ||
444 | 736 | ||
445 | /** | 737 | /** |
738 | * Add the path to the peer and update the path used to reach it in case this | ||
739 | * is the shortest. | ||
740 | * | ||
741 | * @param peer_info Destination peer to add the path to. | ||
742 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
743 | * Path will be either used of freed if already known. | ||
744 | * | ||
745 | * TODO: trim the part from origin to us? Add it as path to origin? | ||
746 | */ | ||
747 | void | ||
748 | path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path) | ||
749 | { | ||
750 | struct MeshPeerPath *aux; | ||
751 | unsigned int l; | ||
752 | unsigned int l2; | ||
753 | |||
754 | if (NULL == peer_info || NULL == path) | ||
755 | { | ||
756 | GNUNET_break (0); | ||
757 | return; | ||
758 | } | ||
759 | |||
760 | l = path_get_length (path); | ||
761 | |||
762 | for (aux = peer_info->path_head; aux != NULL; aux = aux->next) | ||
763 | { | ||
764 | l2 = path_get_length (aux); | ||
765 | if (l2 > l) | ||
766 | { | ||
767 | GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head, | ||
768 | peer_info->path_tail, aux, path); | ||
769 | } | ||
770 | else | ||
771 | { | ||
772 | if (l2 == l && memcmp(path->peers, aux->peers, l) == 0) | ||
773 | { | ||
774 | path_destroy(path); | ||
775 | return; | ||
776 | } | ||
777 | } | ||
778 | } | ||
779 | GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail, | ||
780 | path); | ||
781 | return; | ||
782 | } | ||
783 | |||
784 | |||
785 | /** | ||
446 | * Add the path to the origin peer and update the path used to reach it in case | 786 | * Add the path to the origin peer and update the path used to reach it in case |
447 | * this is the shortest. | 787 | * this is the shortest. |
448 | * The path is given in peer_info -> destination, therefore we turn the path | 788 | * The path is given in peer_info -> destination, therefore we turn the path |
@@ -531,6 +871,41 @@ path_build_from_dht (const struct GNUNET_PeerIdentity *const *get_path, | |||
531 | 871 | ||
532 | 872 | ||
533 | /** | 873 | /** |
874 | * Send keepalive packets for a peer | ||
875 | * | ||
876 | * @param cls unused | ||
877 | * @param tc unused | ||
878 | * | ||
879 | * FIXME path | ||
880 | */ | ||
881 | void | ||
882 | path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
883 | { | ||
884 | struct MeshTunnel *t = cls; | ||
885 | |||
886 | // struct GNUNET_PeerIdentity id; | ||
887 | |||
888 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
889 | { | ||
890 | return; | ||
891 | } | ||
892 | /* FIXME implement multicast keepalive. Just an empty multicast packet? */ | ||
893 | // GNUNET_PEER_resolve (path_get_first_hop (path->t, path->peer)->id, &id); | ||
894 | // GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | ||
895 | // GNUNET_TIME_UNIT_FOREVER_REL, &id, | ||
896 | // sizeof (struct GNUNET_MESH_ManipulatePath) | ||
897 | // + | ||
898 | // (path->path->length * | ||
899 | // sizeof (struct GNUNET_PeerIdentity)), | ||
900 | // &send_core_create_path, | ||
901 | // t); | ||
902 | t->path_refresh_task = | ||
903 | GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); | ||
904 | return; | ||
905 | } | ||
906 | |||
907 | |||
908 | /** | ||
534 | * Check if client has registered with the service and has not disconnected | 909 | * Check if client has registered with the service and has not disconnected |
535 | * | 910 | * |
536 | * @param client the client to check | 911 | * @param client the client to check |
@@ -628,6 +1003,51 @@ tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid) | |||
628 | } | 1003 | } |
629 | 1004 | ||
630 | 1005 | ||
1006 | void | ||
1007 | notify_peer_disconnected (struct MeshTunnelTreeNode *n) | ||
1008 | { | ||
1009 | |||
1010 | } | ||
1011 | |||
1012 | |||
1013 | /** | ||
1014 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all | ||
1015 | * needed rescources. | ||
1016 | * | ||
1017 | * @param t Tunnel we want to add a new peer to | ||
1018 | * @param peer PeerInfo of the peer being added | ||
1019 | * | ||
1020 | */ | ||
1021 | void | ||
1022 | tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) | ||
1023 | { | ||
1024 | struct MeshPeerPath *p; | ||
1025 | struct MeshPeerPath *best_p; | ||
1026 | unsigned int best_cost; | ||
1027 | unsigned int cost; | ||
1028 | |||
1029 | GNUNET_array_append (peer->tunnels, peer->ntunnels, t); | ||
1030 | if (NULL == (p = peer->path_head)) | ||
1031 | return; | ||
1032 | |||
1033 | best_p = p; | ||
1034 | best_cost = UINT_MAX; | ||
1035 | while (NULL != p) | ||
1036 | { | ||
1037 | if ((cost = path_get_cost (t->tree, p)) < best_cost) | ||
1038 | { | ||
1039 | best_cost = cost; | ||
1040 | best_p = p; | ||
1041 | } | ||
1042 | p = p->next; | ||
1043 | } | ||
1044 | tunnel_add_path (t->tree, best_p, ¬ify_peer_disconnected); | ||
1045 | if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) | ||
1046 | t->path_refresh_task = | ||
1047 | GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); | ||
1048 | } | ||
1049 | |||
1050 | |||
631 | /** | 1051 | /** |
632 | * Notify a tunnel that a connection has broken that affects at least | 1052 | * Notify a tunnel that a connection has broken that affects at least |
633 | * some of its peers. | 1053 | * some of its peers. |
@@ -656,7 +1076,7 @@ tunnel_notify_connection_broken (struct MeshTunnel *t, | |||
656 | * @return GNUNET_OK on success | 1076 | * @return GNUNET_OK on success |
657 | */ | 1077 | */ |
658 | static void | 1078 | static void |
659 | tunnel_destroy_tree_node (struct MeshTunnelPathNode *n) | 1079 | tunnel_destroy_tree_node (struct MeshTunnelTreeNode *n) |
660 | { | 1080 | { |
661 | unsigned int i; | 1081 | unsigned int i; |
662 | 1082 | ||
@@ -784,7 +1204,7 @@ send_core_create_path (void *cls, size_t size, void *buf) | |||
784 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n"); | 1204 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n"); |
785 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 1205 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
786 | GNUNET_TIME_UNIT_FOREVER_REL, | 1206 | GNUNET_TIME_UNIT_FOREVER_REL, |
787 | path_get_first_hop (t, peer), | 1207 | path_get_first_hop (t->tree, peer->id), |
788 | size_needed, &send_core_create_path, | 1208 | size_needed, &send_core_create_path, |
789 | info); | 1209 | info); |
790 | return 0; | 1210 | return 0; |
@@ -1310,7 +1730,8 @@ handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1310 | memcpy (msg, message, size); | 1730 | memcpy (msg, message, size); |
1311 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 1731 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
1312 | GNUNET_TIME_UNIT_FOREVER_REL, | 1732 | GNUNET_TIME_UNIT_FOREVER_REL, |
1313 | path_get_first_hop (t, pi), size, | 1733 | path_get_first_hop (t->tree, pi->id), |
1734 | size, | ||
1314 | &send_core_data_raw, msg); | 1735 | &send_core_data_raw, msg); |
1315 | return GNUNET_OK; | 1736 | return GNUNET_OK; |
1316 | } | 1737 | } |
@@ -1537,7 +1958,8 @@ handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer, | |||
1537 | memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK)); | 1958 | memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK)); |
1538 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 1959 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
1539 | GNUNET_TIME_UNIT_FOREVER_REL, | 1960 | GNUNET_TIME_UNIT_FOREVER_REL, |
1540 | path_get_first_hop (t, peer_info), | 1961 | path_get_first_hop (t->tree, |
1962 | peer_info->id), | ||
1541 | sizeof (struct GNUNET_MESH_PathACK), | 1963 | sizeof (struct GNUNET_MESH_PathACK), |
1542 | &send_core_data_raw, msg); | 1964 | &send_core_data_raw, msg); |
1543 | return GNUNET_OK; | 1965 | return GNUNET_OK; |
@@ -1755,7 +2177,7 @@ dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp, | |||
1755 | p = path_build_from_dht (get_path, put_path); | 2177 | p = path_build_from_dht (get_path, put_path); |
1756 | path_add_to_peer (peer_info, p); | 2178 | path_add_to_peer (peer_info, p); |
1757 | tunnel_add_peer(t, peer_info); | 2179 | tunnel_add_peer(t, peer_info); |
1758 | p = tunnel_get_path_to_peer(t, peer_info); | 2180 | p = tunnel_get_path_to_peer(t->tree, peer_info->id); |
1759 | #if MESH_DEBUG | 2181 | #if MESH_DEBUG |
1760 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 2182 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1761 | "MESH: new route for tunnel 0x%x found, has %u hops\n", | 2183 | "MESH: new route for tunnel 0x%x found, has %u hops\n", |
@@ -2045,11 +2467,11 @@ handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client, | |||
2045 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | 2467 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); |
2046 | return; | 2468 | return; |
2047 | } | 2469 | } |
2048 | t->tree = GNUNET_malloc (sizeof(struct MeshTunnelPath)); | 2470 | t->tree = GNUNET_malloc (sizeof(struct MeshTunnelTree)); |
2049 | t->tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32); | 2471 | t->tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32); |
2050 | t->tree->t = t; | 2472 | t->tree->t = t; |
2051 | t->tree->refresh = REFRESH_PATH_TIME; | 2473 | t->tree->refresh = REFRESH_PATH_TIME; |
2052 | t->tree->root = GNUNET_malloc(sizeof(struct MeshTunnelPathNode)); | 2474 | t->tree->root = GNUNET_malloc(sizeof(struct MeshTunnelTreeNode)); |
2053 | t->tree->root->status = MESH_PEER_READY; | 2475 | t->tree->root->status = MESH_PEER_READY; |
2054 | t->tree->root->t = t; | 2476 | t->tree->root->t = t; |
2055 | t->tree->root->peer = myid; | 2477 | t->tree->root->peer = myid; |
@@ -2428,7 +2850,7 @@ handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client, | |||
2428 | info->client = client; | 2850 | info->client = client; |
2429 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | 2851 | GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, |
2430 | GNUNET_TIME_UNIT_FOREVER_REL, | 2852 | GNUNET_TIME_UNIT_FOREVER_REL, |
2431 | path_get_first_hop (t, pi), | 2853 | path_get_first_hop (t->tree, pi->id), |
2432 | /* FIXME re-check types */ | 2854 | /* FIXME re-check types */ |
2433 | data_size + | 2855 | data_size + |
2434 | sizeof (struct GNUNET_MESH_Unicast), | 2856 | sizeof (struct GNUNET_MESH_Unicast), |
diff --git a/src/mesh/mesh.h b/src/mesh/mesh.h index 2a7133a55..e816e5ddc 100644 --- a/src/mesh/mesh.h +++ b/src/mesh/mesh.h | |||
@@ -246,386 +246,5 @@ enum MeshPeerState | |||
246 | }; | 246 | }; |
247 | 247 | ||
248 | 248 | ||
249 | /******************************************************************************/ | ||
250 | /************************ DATA STRUCTURES ****************************/ | ||
251 | /******************************************************************************/ | ||
252 | |||
253 | /** | ||
254 | * Information regarding a possible path to reach a single peer | ||
255 | */ | ||
256 | struct MeshPeerPath | ||
257 | { | ||
258 | |||
259 | /** | ||
260 | * Linked list | ||
261 | */ | ||
262 | struct MeshPeerPath *next; | ||
263 | struct MeshPeerPath *prev; | ||
264 | |||
265 | /** | ||
266 | * List of all the peers that form the path from origin to target. | ||
267 | */ | ||
268 | GNUNET_PEER_Id *peers; | ||
269 | |||
270 | /** | ||
271 | * Number of peers (hops) in the path | ||
272 | */ | ||
273 | unsigned int length; | ||
274 | |||
275 | }; | ||
276 | |||
277 | |||
278 | /** | ||
279 | * Node of path tree for a tunnel | ||
280 | */ | ||
281 | struct MeshTunnelPathNode | ||
282 | { | ||
283 | /** | ||
284 | * Tunnel this node belongs to (and therefore tree) | ||
285 | */ | ||
286 | struct MeshTunnel *t; | ||
287 | |||
288 | /** | ||
289 | * Peer this node describes | ||
290 | */ | ||
291 | GNUNET_PEER_Id peer; | ||
292 | |||
293 | /** | ||
294 | * Parent node in the tree | ||
295 | */ | ||
296 | struct MeshTunnelPathNode *parent; | ||
297 | |||
298 | /** | ||
299 | * Array of children | ||
300 | */ | ||
301 | struct MeshTunnelPathNode *children; | ||
302 | |||
303 | /** | ||
304 | * Number of children | ||
305 | */ | ||
306 | unsigned int nchildren; | ||
307 | |||
308 | /** | ||
309 | * Status of the peer in the tunnel | ||
310 | */ | ||
311 | enum MeshPeerState status; | ||
312 | }; | ||
313 | |||
314 | |||
315 | /** | ||
316 | * Tree to reach all peers in the tunnel | ||
317 | */ | ||
318 | struct MeshTunnelPath | ||
319 | { | ||
320 | /** | ||
321 | * How often to refresh the path | ||
322 | */ | ||
323 | struct GNUNET_TIME_Relative refresh; | ||
324 | |||
325 | /** | ||
326 | * Tunnel this path belongs to | ||
327 | */ | ||
328 | struct MeshTunnel *t; | ||
329 | |||
330 | /** | ||
331 | * Root node of peer tree | ||
332 | */ | ||
333 | struct MeshTunnelPathNode *root; | ||
334 | |||
335 | /** | ||
336 | * Node that represents our position in the tree (for non local tunnels) | ||
337 | */ | ||
338 | struct MeshTunnelPathNode *me; | ||
339 | |||
340 | /** | ||
341 | * Cache of all peers and the first hop to them. | ||
342 | * Indexed by Peer_Identity, contains a pointer to the PeerIdentity | ||
343 | * of 1st hop. | ||
344 | */ | ||
345 | struct GNUNET_CONTAINER_MultiHashMap *first_hops; | ||
346 | |||
347 | }; | ||
348 | |||
349 | |||
350 | /** FWD declaration */ | ||
351 | struct MeshPeerInfo; | ||
352 | |||
353 | /** | ||
354 | * Struct containing all info possibly needed to build a package when called | ||
355 | * back by core. | ||
356 | */ | ||
357 | struct MeshDataDescriptor | ||
358 | { | ||
359 | /** ID of the tunnel this packet travels in */ | ||
360 | struct MESH_TunnelID *origin; | ||
361 | |||
362 | /** Ultimate destination of the packet */ | ||
363 | GNUNET_PEER_Id destination; | ||
364 | |||
365 | /** Number of identical messages sent to different hops (multicast) */ | ||
366 | unsigned int copies; | ||
367 | |||
368 | /** Size of the data */ | ||
369 | size_t size; | ||
370 | |||
371 | /** Client that asked for the transmission, if any */ | ||
372 | struct GNUNET_SERVER_Client *client; | ||
373 | |||
374 | /** Who was is message being sent to */ | ||
375 | struct MeshPeerInfo *peer; | ||
376 | |||
377 | /** Which handler was used to request the transmission */ | ||
378 | unsigned int handler_n; | ||
379 | |||
380 | /* Data at the end */ | ||
381 | }; | ||
382 | |||
383 | |||
384 | /** | ||
385 | * Struct containing all information regarding a given peer | ||
386 | */ | ||
387 | struct MeshPeerInfo | ||
388 | { | ||
389 | /** | ||
390 | * ID of the peer | ||
391 | */ | ||
392 | GNUNET_PEER_Id id; | ||
393 | |||
394 | /** | ||
395 | * Last time we heard from this peer | ||
396 | */ | ||
397 | struct GNUNET_TIME_Absolute last_contact; | ||
398 | |||
399 | /** | ||
400 | * Number of attempts to reconnect so far | ||
401 | */ | ||
402 | int n_reconnect_attempts; | ||
403 | |||
404 | /** | ||
405 | * Paths to reach the peer, ordered by ascending hop count | ||
406 | */ | ||
407 | struct MeshPeerPath *path_head; | ||
408 | |||
409 | /** | ||
410 | * Paths to reach the peer, ordered by ascending hop count | ||
411 | */ | ||
412 | struct MeshPeerPath *path_tail; | ||
413 | |||
414 | /** | ||
415 | * Handle to stop the DHT search for a path to this peer | ||
416 | */ | ||
417 | struct GNUNET_DHT_GetHandle *dhtget; | ||
418 | |||
419 | /** | ||
420 | * Handles to stop queued transmissions for this peer | ||
421 | */ | ||
422 | struct GNUNET_CORE_TransmitHandle *core_transmit[CORE_QUEUE_SIZE]; | ||
423 | |||
424 | /** | ||
425 | * Pointer to info stuctures used as cls for queued transmissions | ||
426 | */ | ||
427 | struct MeshDataDescriptor *infos[CORE_QUEUE_SIZE]; | ||
428 | |||
429 | /** | ||
430 | * Array of tunnels this peer participates in | ||
431 | * (most probably a small amount, therefore not a hashmap) | ||
432 | * When the path to the peer changes, notify these tunnels to let them | ||
433 | * re-adjust their path trees. | ||
434 | */ | ||
435 | struct MeshTunnel **tunnels; | ||
436 | |||
437 | /** | ||
438 | * Number of tunnels above | ||
439 | */ | ||
440 | unsigned int ntunnels; | ||
441 | }; | ||
442 | |||
443 | |||
444 | /** | ||
445 | * Data scheduled to transmit (to local client or remote peer) | ||
446 | */ | ||
447 | struct MeshQueue | ||
448 | { | ||
449 | /** | ||
450 | * Double linked list | ||
451 | */ | ||
452 | struct MeshQueue *next; | ||
453 | struct MeshQueue *prev; | ||
454 | |||
455 | /** | ||
456 | * Target of the data (NULL if target is client) | ||
457 | */ | ||
458 | struct MeshPeerInfo *peer; | ||
459 | |||
460 | /** | ||
461 | * Client to send the data to (NULL if target is peer) | ||
462 | */ | ||
463 | struct MeshClient *client; | ||
464 | |||
465 | /** | ||
466 | * Size of the message to transmit | ||
467 | */ | ||
468 | unsigned int size; | ||
469 | |||
470 | /** | ||
471 | * How old is the data? | ||
472 | */ | ||
473 | struct GNUNET_TIME_Absolute timestamp; | ||
474 | |||
475 | /** | ||
476 | * Data itself | ||
477 | */ | ||
478 | struct GNUNET_MessageHeader *data; | ||
479 | }; | ||
480 | |||
481 | /** | ||
482 | * Globally unique tunnel identification (owner + number) | ||
483 | * DO NOT USE OVER THE NETWORK | ||
484 | */ | ||
485 | struct MESH_TunnelID | ||
486 | { | ||
487 | /** | ||
488 | * Node that owns the tunnel | ||
489 | */ | ||
490 | GNUNET_PEER_Id oid; | ||
491 | |||
492 | /** | ||
493 | * Tunnel number to differentiate all the tunnels owned by the node oid | ||
494 | * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI ) | ||
495 | */ | ||
496 | MESH_TunnelNumber tid; | ||
497 | }; | ||
498 | |||
499 | |||
500 | struct MeshClient; /* FWD declaration */ | ||
501 | |||
502 | /** | ||
503 | * Struct containing all information regarding a tunnel | ||
504 | * For an intermediate node the improtant info used will be: | ||
505 | * - id Tunnel unique identification | ||
506 | * - paths[0] To know where to send it next | ||
507 | * - metainfo: ready, speeds, accounting | ||
508 | */ | ||
509 | struct MeshTunnel | ||
510 | { | ||
511 | /** | ||
512 | * Tunnel ID | ||
513 | */ | ||
514 | struct MESH_TunnelID id; | ||
515 | |||
516 | /** | ||
517 | * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 ) | ||
518 | */ | ||
519 | MESH_TunnelNumber local_tid; | ||
520 | |||
521 | /** | ||
522 | * Last time the tunnel was used | ||
523 | */ | ||
524 | struct GNUNET_TIME_Absolute timestamp; | ||
525 | |||
526 | /** | ||
527 | * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo) | ||
528 | */ | ||
529 | struct GNUNET_CONTAINER_MultiHashMap *peers; | ||
530 | |||
531 | /** | ||
532 | * Number of peers that are connected and potentially ready to receive data | ||
533 | */ | ||
534 | unsigned int peers_ready; | ||
535 | |||
536 | /** | ||
537 | * Number of peers that have been added to the tunnel | ||
538 | */ | ||
539 | unsigned int peers_total; | ||
540 | |||
541 | /** | ||
542 | * Client owner of the tunnel, if any | ||
543 | */ | ||
544 | struct MeshClient *client; | ||
545 | |||
546 | /** | ||
547 | * Messages ready to transmit | ||
548 | */ | ||
549 | struct MeshQueue *queue_head; | ||
550 | struct MeshQueue *queue_tail; | ||
551 | |||
552 | /** | ||
553 | * Tunnel paths | ||
554 | */ | ||
555 | struct MeshTunnelPath *tree; | ||
556 | |||
557 | /** | ||
558 | * Task to keep the used paths alive | ||
559 | */ | ||
560 | GNUNET_SCHEDULER_TaskIdentifier path_refresh_task; | ||
561 | }; | ||
562 | |||
563 | |||
564 | /** | ||
565 | * Info needed to work with tunnel paths and peers | ||
566 | */ | ||
567 | struct MeshPathInfo | ||
568 | { | ||
569 | /** | ||
570 | * Tunnel | ||
571 | */ | ||
572 | struct MeshTunnel *t; | ||
573 | |||
574 | /** | ||
575 | * Destination peer | ||
576 | */ | ||
577 | struct MeshPeerInfo *peer; | ||
578 | |||
579 | /** | ||
580 | * Path itself | ||
581 | */ | ||
582 | struct MeshPeerPath *path; | ||
583 | }; | ||
584 | |||
585 | |||
586 | /** | ||
587 | * Struct containing information about a client of the service | ||
588 | */ | ||
589 | struct MeshClient | ||
590 | { | ||
591 | /** | ||
592 | * Linked list | ||
593 | */ | ||
594 | struct MeshClient *next; | ||
595 | struct MeshClient *prev; | ||
596 | |||
597 | /** | ||
598 | * Tunnels that belong to this client, indexed by local id | ||
599 | */ | ||
600 | struct GNUNET_CONTAINER_MultiHashMap *tunnels; | ||
601 | |||
602 | /** | ||
603 | * Handle to communicate with the client | ||
604 | */ | ||
605 | struct GNUNET_SERVER_Client *handle; | ||
606 | |||
607 | /** | ||
608 | * Applications that this client has claimed to provide | ||
609 | */ | ||
610 | struct GNUNET_CONTAINER_MultiHashMap *apps; | ||
611 | |||
612 | /** | ||
613 | * Messages that this client has declared interest in | ||
614 | */ | ||
615 | struct GNUNET_CONTAINER_MultiHashMap *types; | ||
616 | |||
617 | /** | ||
618 | * Used to search peers offering a service | ||
619 | */ | ||
620 | struct GNUNET_DHT_GetHandle *dht_get_type; | ||
621 | |||
622 | #if MESH_DEBUG | ||
623 | /** | ||
624 | * ID of the client, for debug messages | ||
625 | */ | ||
626 | unsigned int id; | ||
627 | #endif | ||
628 | |||
629 | }; | ||
630 | 249 | ||
631 | #endif | 250 | #endif |
diff --git a/src/mesh/mesh_tunnel_tree.c b/src/mesh/mesh_tunnel_tree.c index 10298ca5a..e838cefc1 100644 --- a/src/mesh/mesh_tunnel_tree.c +++ b/src/mesh/mesh_tunnel_tree.c | |||
@@ -28,10 +28,6 @@ | |||
28 | #include "mesh_tunnel_tree.h" | 28 | #include "mesh_tunnel_tree.h" |
29 | 29 | ||
30 | 30 | ||
31 | extern GNUNET_PEER_Id myid; | ||
32 | extern struct GNUNET_PeerIdentity my_full_id; | ||
33 | |||
34 | |||
35 | /** | 31 | /** |
36 | * Invert the path | 32 | * Invert the path |
37 | * | 33 | * |
@@ -72,19 +68,19 @@ path_destroy (struct MeshPeerPath *p) | |||
72 | /** | 68 | /** |
73 | * Find the first peer whom to send a packet to go down this path | 69 | * Find the first peer whom to send a packet to go down this path |
74 | * | 70 | * |
75 | * @param t The tunnel to use | 71 | * @param t The tunnel tree to use |
76 | * @param peer The peerinfo of the peer we are trying to reach | 72 | * @param peer The peerinfo of the peer we are trying to reach |
77 | * | 73 | * |
78 | * @return peerinfo of the peer who is the first hop in the tunnel | 74 | * @return peerinfo of the peer who is the first hop in the tunnel |
79 | * NULL on error | 75 | * NULL on error |
80 | */ | 76 | */ |
81 | struct GNUNET_PeerIdentity * | 77 | struct GNUNET_PeerIdentity * |
82 | path_get_first_hop (struct MeshTunnel *t, struct MeshPeerInfo *peer) | 78 | path_get_first_hop (struct MeshTunnelTree *t, GNUNET_PEER_Id peer) |
83 | { | 79 | { |
84 | struct GNUNET_PeerIdentity id; | 80 | struct GNUNET_PeerIdentity id; |
85 | 81 | ||
86 | GNUNET_PEER_resolve (peer->id, &id); | 82 | GNUNET_PEER_resolve (peer, &id); |
87 | return GNUNET_CONTAINER_multihashmap_get (t->tree->first_hops, | 83 | return GNUNET_CONTAINER_multihashmap_get (t->first_hops, |
88 | &id.hashPubKey); | 84 | &id.hashPubKey); |
89 | } | 85 | } |
90 | 86 | ||
@@ -109,7 +105,7 @@ path_get_length (struct MeshPeerPath *path) | |||
109 | /** | 105 | /** |
110 | * Get the cost of the path relative to the already built tunnel tree | 106 | * Get the cost of the path relative to the already built tunnel tree |
111 | * | 107 | * |
112 | * @param t The tunnel to which compare | 108 | * @param t The tunnel tree to which compare |
113 | * @param path The individual path to reach a peer | 109 | * @param path The individual path to reach a peer |
114 | * | 110 | * |
115 | * @return Number of hops to reach destination, UINT_MAX in case the peer is not | 111 | * @return Number of hops to reach destination, UINT_MAX in case the peer is not |
@@ -118,97 +114,13 @@ path_get_length (struct MeshPeerPath *path) | |||
118 | * TODO: remove dummy implementation, look into the tunnel tree | 114 | * TODO: remove dummy implementation, look into the tunnel tree |
119 | */ | 115 | */ |
120 | unsigned int | 116 | unsigned int |
121 | path_get_cost (struct MeshTunnel *t, struct MeshPeerPath *path) | 117 | path_get_cost (struct MeshTunnelTree *t, struct MeshPeerPath *path) |
122 | { | 118 | { |
123 | return path_get_length (path); | 119 | return path_get_length (path); |
124 | } | 120 | } |
125 | 121 | ||
126 | 122 | ||
127 | /** | 123 | /** |
128 | * Add the path to the peer and update the path used to reach it in case this | ||
129 | * is the shortest. | ||
130 | * | ||
131 | * @param peer_info Destination peer to add the path to. | ||
132 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
133 | * Path will be either used of freed if already known. | ||
134 | * | ||
135 | * TODO: trim the part from origin to us? Add it as path to origin? | ||
136 | */ | ||
137 | void | ||
138 | path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path) | ||
139 | { | ||
140 | struct MeshPeerPath *aux; | ||
141 | unsigned int l; | ||
142 | unsigned int l2; | ||
143 | |||
144 | if (NULL == peer_info || NULL == path) | ||
145 | { | ||
146 | GNUNET_break (0); | ||
147 | return; | ||
148 | } | ||
149 | |||
150 | l = path_get_length (path); | ||
151 | |||
152 | for (aux = peer_info->path_head; aux != NULL; aux = aux->next) | ||
153 | { | ||
154 | l2 = path_get_length (aux); | ||
155 | if (l2 > l) | ||
156 | { | ||
157 | GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head, | ||
158 | peer_info->path_tail, aux, path); | ||
159 | } | ||
160 | else | ||
161 | { | ||
162 | if (l2 == l && memcmp(path->peers, aux->peers, l) == 0) | ||
163 | { | ||
164 | path_destroy(path); | ||
165 | return; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail, | ||
170 | path); | ||
171 | return; | ||
172 | } | ||
173 | |||
174 | |||
175 | /** | ||
176 | * Send keepalive packets for a peer | ||
177 | * | ||
178 | * @param cls unused | ||
179 | * @param tc unused | ||
180 | * | ||
181 | * FIXME path | ||
182 | */ | ||
183 | void | ||
184 | path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
185 | { | ||
186 | struct MeshTunnel *t = cls; | ||
187 | |||
188 | // struct GNUNET_PeerIdentity id; | ||
189 | |||
190 | if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) | ||
191 | { | ||
192 | return; | ||
193 | } | ||
194 | /* FIXME implement multicast keepalive. Just an empty multicast packet? */ | ||
195 | // GNUNET_PEER_resolve (path_get_first_hop (path->t, path->peer)->id, &id); | ||
196 | // GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0, | ||
197 | // GNUNET_TIME_UNIT_FOREVER_REL, &id, | ||
198 | // sizeof (struct GNUNET_MESH_ManipulatePath) | ||
199 | // + | ||
200 | // (path->path->length * | ||
201 | // sizeof (struct GNUNET_PeerIdentity)), | ||
202 | // &send_core_create_path, | ||
203 | // t); | ||
204 | t->path_refresh_task = | ||
205 | GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); | ||
206 | return; | ||
207 | } | ||
208 | |||
209 | |||
210 | |||
211 | /** | ||
212 | * Recursively find the given peer in the tree. | 124 | * Recursively find the given peer in the tree. |
213 | * | 125 | * |
214 | * @param t Tunnel where to look for the peer. | 126 | * @param t Tunnel where to look for the peer. |
@@ -216,10 +128,10 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
216 | * | 128 | * |
217 | * @return Pointer to the node of the peer. NULL if not found. | 129 | * @return Pointer to the node of the peer. NULL if not found. |
218 | */ | 130 | */ |
219 | struct MeshTunnelPathNode * | 131 | struct MeshTunnelTreeNode * |
220 | tunnel_find_peer (struct MeshTunnelPathNode *root, GNUNET_PEER_Id peer_id) | 132 | tunnel_find_peer (struct MeshTunnelTreeNode *root, GNUNET_PEER_Id peer_id) |
221 | { | 133 | { |
222 | struct MeshTunnelPathNode *n; | 134 | struct MeshTunnelTreeNode *n; |
223 | unsigned int i; | 135 | unsigned int i; |
224 | 136 | ||
225 | if (root->peer == peer_id) | 137 | if (root->peer == peer_id) |
@@ -238,30 +150,34 @@ tunnel_find_peer (struct MeshTunnelPathNode *root, GNUNET_PEER_Id peer_id) | |||
238 | * Recusively mark peer and children as disconnected, notify client | 150 | * Recusively mark peer and children as disconnected, notify client |
239 | * | 151 | * |
240 | * @param parent Node to be clean, potentially with children | 152 | * @param parent Node to be clean, potentially with children |
241 | * @param nc Notification context to use to alert the client | 153 | * @param cb Callback to use to notify about disconnected peers. |
242 | */ | 154 | */ |
243 | void | 155 | void |
244 | tunnel_mark_peers_disconnected (struct MeshTunnelPathNode *parent, | 156 | tunnel_mark_peers_disconnected (struct MeshTunnelTreeNode *parent, |
245 | struct GNUNET_SERVER_NotificationContext *nc) | 157 | MeshNodeDisconnectCB cb) |
246 | { | 158 | { |
247 | struct GNUNET_MESH_PeerControl msg; | ||
248 | unsigned int i; | 159 | unsigned int i; |
249 | 160 | ||
161 | if (MESH_PEER_READY == parent->status) | ||
162 | { | ||
163 | cb (parent); | ||
164 | } | ||
250 | parent->status = MESH_PEER_RECONNECTING; | 165 | parent->status = MESH_PEER_RECONNECTING; |
251 | for (i = 0; i < parent->nchildren; i++) | 166 | for (i = 0; i < parent->nchildren; i++) |
252 | { | 167 | { |
253 | tunnel_mark_peers_disconnected (&parent->children[i], nc); | 168 | tunnel_mark_peers_disconnected (&parent->children[i], cb); |
254 | } | 169 | } |
255 | if (NULL == parent->t->client) | 170 | // struct GNUNET_MESH_PeerControl msg; |
256 | return; | 171 | // if (NULL == parent->t->client) |
257 | msg.header.size = htons (sizeof (msg)); | 172 | // return; |
258 | msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); | 173 | // msg.header.size = htons (sizeof (msg)); |
259 | msg.tunnel_id = htonl (parent->t->local_tid); | 174 | // msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL); |
260 | GNUNET_PEER_resolve (parent->peer, &msg.peer); | 175 | // msg.tunnel_id = htonl (parent->t->local_tid); |
261 | if (NULL == nc) | 176 | // GNUNET_PEER_resolve (parent->peer, &msg.peer); |
262 | return; | 177 | // if (NULL == nc) |
263 | GNUNET_SERVER_notification_context_unicast (nc, parent->t->client->handle, | 178 | // return; |
264 | &msg.header, GNUNET_NO); | 179 | // GNUNET_SERVER_notification_context_unicast (nc, parent->t->client->handle, |
180 | // &msg.header, GNUNET_NO); | ||
265 | } | 181 | } |
266 | 182 | ||
267 | 183 | ||
@@ -272,23 +188,23 @@ tunnel_mark_peers_disconnected (struct MeshTunnelPathNode *parent, | |||
272 | * The destination peer is NOT destroyed, it is returned in order to either set | 188 | * The destination peer is NOT destroyed, it is returned in order to either set |
273 | * a new path to it or destroy it explicitly, taking care of it's child nodes. | 189 | * a new path to it or destroy it explicitly, taking care of it's child nodes. |
274 | * | 190 | * |
275 | * @param t Tunnel where to delete the path from. | 191 | * @param t Tunnel tree where to delete the path from. |
276 | * @param peer Destination peer whose path we want to remove. | 192 | * @param peer Destination peer whose path we want to remove. |
277 | * @param nc Notification context to alert the client of disconnected peers. | 193 | * @param cb Callback to use to notify about disconnected peers. |
278 | * | 194 | * |
279 | * @return pointer to the pathless node, NULL on error | 195 | * @return pointer to the pathless node, NULL on error |
280 | */ | 196 | */ |
281 | struct MeshTunnelPathNode * | 197 | struct MeshTunnelTreeNode * |
282 | tunnel_del_path (struct MeshTunnel *t, GNUNET_PEER_Id peer_id, | 198 | tunnel_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, |
283 | struct GNUNET_SERVER_NotificationContext *nc) | 199 | MeshNodeDisconnectCB cb) |
284 | { | 200 | { |
285 | struct MeshTunnelPathNode *parent; | 201 | struct MeshTunnelTreeNode *parent; |
286 | struct MeshTunnelPathNode *node; | 202 | struct MeshTunnelTreeNode *node; |
287 | struct MeshTunnelPathNode *n; | 203 | struct MeshTunnelTreeNode *n; |
288 | 204 | ||
289 | if (peer_id == t->tree->root->peer) | 205 | if (peer_id == t->root->peer) |
290 | return NULL; | 206 | return NULL; |
291 | node = n = tunnel_find_peer (t->tree->me, peer_id); | 207 | node = n = tunnel_find_peer (t->me, peer_id); |
292 | if (NULL == n) | 208 | if (NULL == n) |
293 | return NULL; | 209 | return NULL; |
294 | parent = n->parent; | 210 | parent = n->parent; |
@@ -306,7 +222,7 @@ tunnel_del_path (struct MeshTunnel *t, GNUNET_PEER_Id peer_id, | |||
306 | parent->nchildren--; | 222 | parent->nchildren--; |
307 | parent->children = GNUNET_realloc (parent->children, parent->nchildren); | 223 | parent->children = GNUNET_realloc (parent->children, parent->nchildren); |
308 | 224 | ||
309 | tunnel_mark_peers_disconnected (node, nc); | 225 | tunnel_mark_peers_disconnected (node, cb); |
310 | 226 | ||
311 | return node; | 227 | return node; |
312 | } | 228 | } |
@@ -323,13 +239,13 @@ tunnel_del_path (struct MeshTunnel *t, GNUNET_PEER_Id peer_id, | |||
323 | * Path must be destroyed afterwards. | 239 | * Path must be destroyed afterwards. |
324 | */ | 240 | */ |
325 | struct MeshPeerPath * | 241 | struct MeshPeerPath * |
326 | tunnel_get_path_to_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer_info) | 242 | tunnel_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer) |
327 | { | 243 | { |
328 | struct MeshTunnelPathNode *n; | 244 | struct MeshTunnelTreeNode *n; |
329 | struct MeshPeerPath *p; | 245 | struct MeshPeerPath *p; |
330 | GNUNET_PEER_Id myid = t->tree->me->peer; | 246 | GNUNET_PEER_Id myid = t->me->peer; |
331 | 247 | ||
332 | n = tunnel_find_peer(t->tree->me, peer_info->id); | 248 | n = tunnel_find_peer(t->me, peer); |
333 | p = GNUNET_malloc(sizeof(struct MeshPeerPath)); | 249 | p = GNUNET_malloc(sizeof(struct MeshPeerPath)); |
334 | 250 | ||
335 | /* Building the path (inverted!) */ | 251 | /* Building the path (inverted!) */ |
@@ -354,8 +270,7 @@ tunnel_get_path_to_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer_info) | |||
354 | * | 270 | * |
355 | * @param t Tunnel where to add the new path. | 271 | * @param t Tunnel where to add the new path. |
356 | * @param p Path to be integrated. | 272 | * @param p Path to be integrated. |
357 | * @param nc Notification context to alert clients of peers | 273 | * @param cb Callback to use to notify about peers temporarily disconnecting |
358 | * temporarily disconnected | ||
359 | * | 274 | * |
360 | * @return GNUNET_OK in case of success. | 275 | * @return GNUNET_OK in case of success. |
361 | * GNUNET_SYSERR in case of error. | 276 | * GNUNET_SYSERR in case of error. |
@@ -365,20 +280,21 @@ tunnel_get_path_to_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer_info) | |||
365 | * - do not disconnect peers until new path is created & connected | 280 | * - do not disconnect peers until new path is created & connected |
366 | */ | 281 | */ |
367 | int | 282 | int |
368 | tunnel_add_path (struct MeshTunnel *t, const struct MeshPeerPath *p) | 283 | tunnel_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, |
284 | MeshNodeDisconnectCB cb) | ||
369 | { | 285 | { |
370 | struct MeshTunnelPathNode *parent; | 286 | struct MeshTunnelTreeNode *parent; |
371 | struct MeshTunnelPathNode *oldnode; | 287 | struct MeshTunnelTreeNode *oldnode; |
372 | struct MeshTunnelPathNode *n; | 288 | struct MeshTunnelTreeNode *n; |
373 | struct GNUNET_PeerIdentity id; | 289 | struct GNUNET_PeerIdentity id; |
374 | struct GNUNET_PeerIdentity *hop; | 290 | struct GNUNET_PeerIdentity *hop; |
375 | GNUNET_PEER_Id myid = t->tree->me->peer; | 291 | GNUNET_PEER_Id myid = t->me->peer; |
376 | int me; | 292 | int me; |
377 | unsigned int i; | 293 | unsigned int i; |
378 | unsigned int j; | 294 | unsigned int j; |
379 | 295 | ||
380 | GNUNET_assert(0 != p->length); | 296 | GNUNET_assert(0 != p->length); |
381 | n = t->tree->root; | 297 | n = t->root; |
382 | if (n->peer != p->peers[0]) | 298 | if (n->peer != p->peers[0]) |
383 | { | 299 | { |
384 | GNUNET_break (0); | 300 | GNUNET_break (0); |
@@ -386,7 +302,7 @@ tunnel_add_path (struct MeshTunnel *t, const struct MeshPeerPath *p) | |||
386 | } | 302 | } |
387 | if (1 == p->length) | 303 | if (1 == p->length) |
388 | return GNUNET_OK; | 304 | return GNUNET_OK; |
389 | oldnode = tunnel_del_path (t, p->peers[p->length - 1], NULL); | 305 | oldnode = tunnel_del_path (t, p->peers[p->length - 1], cb); |
390 | /* Look for the first node that is not already present in the tree | 306 | /* Look for the first node that is not already present in the tree |
391 | * | 307 | * |
392 | * Assuming that the tree is somewhat balanced, O(log n * log N). | 308 | * Assuming that the tree is somewhat balanced, O(log n * log N). |
@@ -423,17 +339,17 @@ tunnel_add_path (struct MeshTunnel *t, const struct MeshPeerPath *p) | |||
423 | parent->nchildren++; | 339 | parent->nchildren++; |
424 | parent->children = GNUNET_realloc (parent->children, | 340 | parent->children = GNUNET_realloc (parent->children, |
425 | parent->nchildren * | 341 | parent->nchildren * |
426 | sizeof(struct MeshTunnelPathNode)); | 342 | sizeof(struct MeshTunnelTreeNode)); |
427 | n = &parent->children[parent->nchildren - 1]; | 343 | n = &parent->children[parent->nchildren - 1]; |
428 | if (i == p->length - 1 && NULL != oldnode) | 344 | if (i == p->length - 1 && NULL != oldnode) |
429 | { | 345 | { |
430 | /* Assignation and free can be misleading, using explicit mempcy */ | 346 | /* Assignation and free can be misleading, using explicit mempcy */ |
431 | memcpy (n, oldnode, sizeof (struct MeshTunnelPathNode)); | 347 | memcpy (n, oldnode, sizeof (struct MeshTunnelTreeNode)); |
432 | GNUNET_free (oldnode); | 348 | GNUNET_free (oldnode); |
433 | } | 349 | } |
434 | else | 350 | else |
435 | { | 351 | { |
436 | n->t = t; | 352 | n->t = t->t; |
437 | n->status = MESH_PEER_RELAY; | 353 | n->status = MESH_PEER_RELAY; |
438 | n->peer = p->peers[i]; | 354 | n->peer = p->peers[i]; |
439 | } | 355 | } |
@@ -448,47 +364,9 @@ tunnel_add_path (struct MeshTunnel *t, const struct MeshPeerPath *p) | |||
448 | GNUNET_PEER_resolve (p->peers[p->length - 1], &id); | 364 | GNUNET_PEER_resolve (p->peers[p->length - 1], &id); |
449 | hop = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); | 365 | hop = GNUNET_malloc(sizeof(struct GNUNET_PeerIdentity)); |
450 | GNUNET_PEER_resolve (p->peers[me + 1], hop); | 366 | GNUNET_PEER_resolve (p->peers[me + 1], hop); |
451 | GNUNET_CONTAINER_multihashmap_put (t->tree->first_hops, &id.hashPubKey, | 367 | GNUNET_CONTAINER_multihashmap_put (t->first_hops, &id.hashPubKey, |
452 | hop, | 368 | hop, |
453 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); | 369 | GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST); |
454 | } | 370 | } |
455 | return GNUNET_OK; | 371 | return GNUNET_OK; |
456 | } | 372 | } |
457 | |||
458 | |||
459 | /** | ||
460 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all | ||
461 | * needed rescources. | ||
462 | * | ||
463 | * @param t Tunnel we want to add a new peer to | ||
464 | * @param peer PeerInfo of the peer being added | ||
465 | * | ||
466 | */ | ||
467 | void | ||
468 | tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer) | ||
469 | { | ||
470 | struct MeshPeerPath *p; | ||
471 | struct MeshPeerPath *best_p; | ||
472 | unsigned int best_cost; | ||
473 | unsigned int cost; | ||
474 | |||
475 | GNUNET_array_append (peer->tunnels, peer->ntunnels, t); | ||
476 | if (NULL == (p = peer->path_head)) | ||
477 | return; | ||
478 | |||
479 | best_p = p; | ||
480 | best_cost = UINT_MAX; | ||
481 | while (NULL != p) | ||
482 | { | ||
483 | if ((cost = path_get_cost (t, p)) < best_cost) | ||
484 | { | ||
485 | best_cost = cost; | ||
486 | best_p = p; | ||
487 | } | ||
488 | p = p->next; | ||
489 | } | ||
490 | tunnel_add_path (t, best_p); | ||
491 | if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task) | ||
492 | t->path_refresh_task = | ||
493 | GNUNET_SCHEDULER_add_delayed (t->tree->refresh, &path_refresh, t); | ||
494 | } | ||
diff --git a/src/mesh/mesh_tunnel_tree.h b/src/mesh/mesh_tunnel_tree.h index be4509c9c..fddc9b46d 100644 --- a/src/mesh/mesh_tunnel_tree.h +++ b/src/mesh/mesh_tunnel_tree.h | |||
@@ -26,6 +26,119 @@ | |||
26 | 26 | ||
27 | #include "mesh.h" | 27 | #include "mesh.h" |
28 | 28 | ||
29 | /******************************************************************************/ | ||
30 | /************************ DATA STRUCTURES ****************************/ | ||
31 | /******************************************************************************/ | ||
32 | |||
33 | /** | ||
34 | * Information regarding a possible path to reach a single peer | ||
35 | */ | ||
36 | struct MeshPeerPath | ||
37 | { | ||
38 | |||
39 | /** | ||
40 | * Linked list | ||
41 | */ | ||
42 | struct MeshPeerPath *next; | ||
43 | struct MeshPeerPath *prev; | ||
44 | |||
45 | /** | ||
46 | * List of all the peers that form the path from origin to target. | ||
47 | */ | ||
48 | GNUNET_PEER_Id *peers; | ||
49 | |||
50 | /** | ||
51 | * Number of peers (hops) in the path | ||
52 | */ | ||
53 | unsigned int length; | ||
54 | |||
55 | }; | ||
56 | |||
57 | |||
58 | /** | ||
59 | * Node of path tree for a tunnel | ||
60 | */ | ||
61 | struct MeshTunnelTreeNode | ||
62 | { | ||
63 | /** | ||
64 | * Tunnel this node belongs to (and therefore tree) | ||
65 | */ | ||
66 | struct MeshTunnel *t; | ||
67 | |||
68 | /** | ||
69 | * Peer this node describes | ||
70 | */ | ||
71 | GNUNET_PEER_Id peer; | ||
72 | |||
73 | /** | ||
74 | * Parent node in the tree | ||
75 | */ | ||
76 | struct MeshTunnelTreeNode *parent; | ||
77 | |||
78 | /** | ||
79 | * Array of children | ||
80 | */ | ||
81 | struct MeshTunnelTreeNode *children; | ||
82 | |||
83 | /** | ||
84 | * Number of children | ||
85 | */ | ||
86 | unsigned int nchildren; | ||
87 | |||
88 | /** | ||
89 | * Status of the peer in the tunnel | ||
90 | */ | ||
91 | enum MeshPeerState status; | ||
92 | }; | ||
93 | |||
94 | |||
95 | /** | ||
96 | * Tree to reach all peers in the tunnel | ||
97 | */ | ||
98 | struct MeshTunnelTree | ||
99 | { | ||
100 | /** | ||
101 | * How often to refresh the path | ||
102 | */ | ||
103 | struct GNUNET_TIME_Relative refresh; | ||
104 | |||
105 | /** | ||
106 | * Tunnel this path belongs to | ||
107 | */ | ||
108 | struct MeshTunnel *t; | ||
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 | * Cache of all peers and the first hop to them. | ||
122 | * Indexed by Peer_Identity, contains a pointer to the PeerIdentity | ||
123 | * of 1st hop. | ||
124 | */ | ||
125 | struct GNUNET_CONTAINER_MultiHashMap *first_hops; | ||
126 | |||
127 | }; | ||
128 | |||
129 | |||
130 | /******************************************************************************/ | ||
131 | /************************* FUNCTIONS *****************************/ | ||
132 | /******************************************************************************/ | ||
133 | |||
134 | |||
135 | /** | ||
136 | * Method called whenever a node has been marked as disconnected. | ||
137 | * | ||
138 | * @param node peer identity the tunnel stopped working with | ||
139 | */ | ||
140 | typedef void (*MeshNodeDisconnectCB) (const struct MeshTunnelTreeNode * node); | ||
141 | |||
29 | 142 | ||
30 | /** | 143 | /** |
31 | * Invert the path | 144 | * Invert the path |
@@ -58,7 +171,7 @@ path_destroy (struct MeshPeerPath *p); | |||
58 | * NULL on error | 171 | * NULL on error |
59 | */ | 172 | */ |
60 | struct GNUNET_PeerIdentity * | 173 | struct GNUNET_PeerIdentity * |
61 | path_get_first_hop (struct MeshTunnel *t, struct MeshPeerInfo *peer); | 174 | path_get_first_hop (struct MeshTunnelTree *t, GNUNET_PEER_Id peer); |
62 | 175 | ||
63 | 176 | ||
64 | /** | 177 | /** |
@@ -83,28 +196,7 @@ path_get_length (struct MeshPeerPath *path); | |||
83 | * in the path | 196 | * in the path |
84 | */ | 197 | */ |
85 | unsigned int | 198 | unsigned int |
86 | path_get_cost (struct MeshTunnel *t, struct MeshPeerPath *path); | 199 | path_get_cost (struct MeshTunnelTree *t, struct MeshPeerPath *path); |
87 | |||
88 | /** | ||
89 | * Add the path to the peer and update the path used to reach it in case this | ||
90 | * is the shortest. | ||
91 | * | ||
92 | * @param peer_info Destination peer to add the path to. | ||
93 | * @param path New path to add. Last peer must be the peer in arg 1. | ||
94 | * Path will be either used of freed if already known. | ||
95 | */ | ||
96 | void | ||
97 | path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path); | ||
98 | |||
99 | |||
100 | /** | ||
101 | * Send keepalive packets for a peer | ||
102 | * | ||
103 | * @param cls unused | ||
104 | * @param tc unused | ||
105 | */ | ||
106 | void | ||
107 | path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | ||
108 | 200 | ||
109 | 201 | ||
110 | /** | 202 | /** |
@@ -115,19 +207,19 @@ path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); | |||
115 | * | 207 | * |
116 | * @return Pointer to the node of the peer. NULL if not found. | 208 | * @return Pointer to the node of the peer. NULL if not found. |
117 | */ | 209 | */ |
118 | struct MeshTunnelPathNode * | 210 | struct MeshTunnelTreeNode * |
119 | tunnel_find_peer (struct MeshTunnelPathNode *root, GNUNET_PEER_Id peer_id); | 211 | tunnel_find_peer (struct MeshTunnelTreeNode *root, GNUNET_PEER_Id peer_id); |
120 | 212 | ||
121 | 213 | ||
122 | /** | 214 | /** |
123 | * Recusively mark peer and children as disconnected, notify client | 215 | * Recusively mark peer and children as disconnected, notify client |
124 | * | 216 | * |
125 | * @param parent Node to be clean, potentially with children | 217 | * @param parent Node to be clean, potentially with children |
126 | * @param nc Notification context to use to alert the client | 218 | * @param cb Callback to use to notify about disconnected peers |
127 | */ | 219 | */ |
128 | void | 220 | void |
129 | tunnel_mark_peers_disconnected (struct MeshTunnelPathNode *parent, | 221 | tunnel_mark_peers_disconnected (struct MeshTunnelTreeNode *parent, |
130 | struct GNUNET_SERVER_NotificationContext *nc); | 222 | MeshNodeDisconnectCB cb); |
131 | 223 | ||
132 | 224 | ||
133 | /** | 225 | /** |
@@ -137,13 +229,13 @@ tunnel_mark_peers_disconnected (struct MeshTunnelPathNode *parent, | |||
137 | * | 229 | * |
138 | * @param t Tunnel where to delete the path from. | 230 | * @param t Tunnel where to delete the path from. |
139 | * @param peer Destination peer whose path we want to remove. | 231 | * @param peer Destination peer whose path we want to remove. |
140 | * @param nc Notification context to alert the client of disconnected peers. | 232 | * @param cb Callback to use to notify about disconnected peers |
141 | * | 233 | * |
142 | * @return pointer to the pathless node, NULL on error | 234 | * @return pointer to the pathless node, NULL on error |
143 | */ | 235 | */ |
144 | struct MeshTunnelPathNode * | 236 | struct MeshTunnelTreeNode * |
145 | tunnel_del_path (struct MeshTunnel *t, GNUNET_PEER_Id peer_id, | 237 | tunnel_del_path (struct MeshTunnelTree *t, GNUNET_PEER_Id peer_id, |
146 | struct GNUNET_SERVER_NotificationContext *nc); | 238 | MeshNodeDisconnectCB cb); |
147 | 239 | ||
148 | 240 | ||
149 | /** | 241 | /** |
@@ -157,7 +249,7 @@ tunnel_del_path (struct MeshTunnel *t, GNUNET_PEER_Id peer_id, | |||
157 | * Path must be destroyed afterwards. | 249 | * Path must be destroyed afterwards. |
158 | */ | 250 | */ |
159 | struct MeshPeerPath * | 251 | struct MeshPeerPath * |
160 | tunnel_get_path_to_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer_info); | 252 | tunnel_get_path_to_peer(struct MeshTunnelTree *t, GNUNET_PEER_Id peer); |
161 | 253 | ||
162 | 254 | ||
163 | /** | 255 | /** |
@@ -165,23 +257,11 @@ tunnel_get_path_to_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer_info); | |||
165 | * | 257 | * |
166 | * @param t Tunnel where to add the new path. | 258 | * @param t Tunnel where to add the new path. |
167 | * @param p Path to be integrated. | 259 | * @param p Path to be integrated. |
168 | * @param nc Notification context to alert clients of peers | 260 | * @param cb Callback to use to notify about peers temporarily disconnecting |
169 | * temporarily disconnected | ||
170 | * | 261 | * |
171 | * @return GNUNET_OK in case of success. | 262 | * @return GNUNET_OK in case of success. |
172 | * GNUNET_SYSERR in case of error. | 263 | * GNUNET_SYSERR in case of error. |
173 | */ | 264 | */ |
174 | int | 265 | int |
175 | tunnel_add_path (struct MeshTunnel *t, const struct MeshPeerPath *p); | 266 | tunnel_add_path (struct MeshTunnelTree *t, const struct MeshPeerPath *p, |
176 | 267 | MeshNodeDisconnectCB cb); \ No newline at end of file | |
177 | |||
178 | /** | ||
179 | * Add a peer to a tunnel, accomodating paths accordingly and initializing all | ||
180 | * needed rescources. | ||
181 | * | ||
182 | * @param t Tunnel we want to add a new peer to | ||
183 | * @param peer PeerInfo of the peer being added | ||
184 | * | ||
185 | */ | ||
186 | void | ||
187 | tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer); \ No newline at end of file | ||
diff --git a/src/mesh/test_mesh_path_api.c b/src/mesh/test_mesh_path_api.c index d14d15958..cc0cbc558 100644 --- a/src/mesh/test_mesh_path_api.c +++ b/src/mesh/test_mesh_path_api.c | |||
@@ -51,7 +51,6 @@ int | |||
51 | main (int argc, char *argv[]) | 51 | main (int argc, char *argv[]) |
52 | { | 52 | { |
53 | struct GNUNET_PeerIdentity* pi; | 53 | struct GNUNET_PeerIdentity* pi; |
54 | // struct MeshTunnel *t; | ||
55 | int result; | 54 | int result; |
56 | 55 | ||
57 | GNUNET_log_setup ("test_mesh_api_path", | 56 | GNUNET_log_setup ("test_mesh_api_path", |
@@ -61,6 +60,7 @@ main (int argc, char *argv[]) | |||
61 | "WARNING", | 60 | "WARNING", |
62 | #endif | 61 | #endif |
63 | NULL); | 62 | NULL); |
63 | |||
64 | pi = get_pi(1); | 64 | pi = get_pi(1); |
65 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer 1: %s\n", GNUNET_h2s(&pi->hashPubKey)); | 65 | GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Peer 1: %s\n", GNUNET_h2s(&pi->hashPubKey)); |
66 | 66 | ||