Added path testcase
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001 - 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/gnunet-service-mesh.c
23  * @brief GNUnet MESH service
24  * @author Bartlomiej Polot
25  *
26  * STRUCTURE:
27  * - DATA STRUCTURES
28  * - GLOBAL VARIABLES
29  * - GENERAL HELPERS
30  * - PERIODIC FUNCTIONS
31  * - MESH NETWORK HANDLER HELPERS
32  * - MESH NETWORK HANDLES
33  * - MESH LOCAL HANDLER HELPERS
34  * - MESH LOCAL HANDLES
35  * - MAIN FUNCTIONS (main & run)
36  *
37  * TODO:
38  * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
39  * - partial disconnect reporting -- same as error reporting?
40  * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
41  * - speed requirement specification (change?) in mesh API -- API call
42  * - add ping message
43  * - add connection confirmation message
44  * - handle trnsmt_rdy return values
45  */
46
47 #include "platform.h"
48 #include "mesh.h"
49 #include "mesh_protocol.h"
50 #include "gnunet_dht_service.h"
51 #include "mesh_tunnel_tree.h"
52
53 /* TODO: move into configuration file */
54 #define REFRESH_PATH_TIME       GNUNET_TIME_relative_multiply(\
55                                     GNUNET_TIME_UNIT_SECONDS,\
56                                     300)
57 #define APP_ANNOUNCE_TIME       GNUNET_TIME_relative_multiply(\
58                                     GNUNET_TIME_UNIT_SECONDS,\
59                                     5)
60
61 #define ID_ANNOUNCE_TIME        GNUNET_TIME_relative_multiply(\
62                                     GNUNET_TIME_UNIT_SECONDS,\
63                                     5)
64
65 #if MESH_DEBUG
66 /**
67  * GNUNET_SCHEDULER_Task for printing a message after some operation is done
68  * @param cls string to print
69  * @param tc task context
70  */
71 static void
72 mesh_debug (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
73 {
74   char *s = cls;
75
76   if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason)
77   {
78     return;
79   }
80   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: %s\n", s);
81 }
82 #endif
83
84
85 /******************************************************************************/
86 /***********************      GLOBAL VARIABLES     ****************************/
87 /******************************************************************************/
88
89 /**
90  * All the clients
91  */
92 static struct MeshClient *clients;
93 static struct MeshClient *clients_tail;
94
95 /**
96  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
97  */
98 static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
99
100 /**
101  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
102  */
103 static struct GNUNET_CONTAINER_MultiHashMap *peers;
104
105 /**
106  * Handle to communicate with core
107  */
108 static struct GNUNET_CORE_Handle *core_handle;
109
110 /**
111  * Handle to use DHT
112  */
113 static struct GNUNET_DHT_Handle *dht_handle;
114
115 /**
116  * Handle to server
117  */
118 static struct GNUNET_SERVER_Handle *server_handle;
119
120 /**
121  * Notification context, to send messages to local clients
122  */
123 static struct GNUNET_SERVER_NotificationContext *nc;
124
125 /**
126  * Local peer own ID (memory efficient handle)
127  */
128 static GNUNET_PEER_Id myid;
129
130 /**
131  * Local peer own ID (full value)
132  */
133 static struct GNUNET_PeerIdentity my_full_id;
134
135 /**
136  * Own private key
137  */
138 static struct GNUNET_CRYPTO_RsaPrivateKey* my_private_key;
139
140 /**
141  * Own public key.
142  */
143 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
144
145 /**
146  * Tunnel ID for the next created tunnel (global tunnel number)
147  */
148 static MESH_TunnelNumber next_tid;
149
150 /**
151  * All application types provided by this peer
152  */
153 static struct GNUNET_CONTAINER_MultiHashMap *applications;
154
155 /**
156  * All message types clients of this peer are interested in
157  */
158 static struct GNUNET_CONTAINER_MultiHashMap *types;
159
160 /**
161  * Task to periodically announce provided applications
162  */
163 GNUNET_SCHEDULER_TaskIdentifier announce_applications_task;
164
165 /**
166  * Task to periodically announce itself in the network
167  */
168 GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
169
170 #if MESH_DEBUG
171 unsigned int next_client_id;
172 #endif
173
174
175 /******************************************************************************/
176 /************************         ITERATORS        ****************************/
177 /******************************************************************************/
178
179
180 /**
181  * Iterator over hash map peer entries collect all neighbors who to resend the
182  * data to.
183  *
184  * @param cls closure (**GNUNET_PEER_Id to store hops to send packet)
185  * @param key current key code (peer id hash)
186  * @param value value in the hash map (peer_info)
187  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
188  */
189 static int
190 iterate_collect_neighbors (void *cls, const GNUNET_HashCode * key, void *value)
191 {
192   struct MeshPeerInfo *peer_info = value;
193   struct MeshPathInfo *neighbors = cls;
194   struct GNUNET_PeerIdentity *id;
195   GNUNET_PEER_Id peer_id;
196   unsigned int i;
197
198   if (peer_info->id == myid)
199   {
200     return GNUNET_YES;
201   }
202   id = path_get_first_hop (neighbors->t, peer_info);
203   peer_id = GNUNET_PEER_search(id);
204   for (i = 0; i < neighbors->path->length; i++)
205   {
206     if (neighbors->path->peers[i] == peer_id)
207       return GNUNET_YES;
208   }
209   GNUNET_array_append (neighbors->path->peers, neighbors->path->length,
210                        peer_id);
211
212   return GNUNET_YES;
213 }
214
215
216 /**
217  * Iterator over hash map peer entries and frees all data in it.
218  * Used prior to destroying a hashmap. Makes you miss anonymous functions in C.
219  *
220  * @param cls closure
221  * @param key current key code (will no longer contain valid data!!)
222  * @param value value in the hash map (treated as void *)
223  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
224  */
225 static int
226 iterate_free (void *cls, const GNUNET_HashCode * key, void *value)
227 {
228   GNUNET_free(value);
229   return GNUNET_YES;
230 }
231
232
233 /******************************************************************************/
234 /************************    PERIODIC FUNCTIONS    ****************************/
235 /******************************************************************************/
236
237 /**
238  * Announce iterator over for each application provided by the peer
239  *
240  * @param cls closure
241  * @param key current key code
242  * @param value value in the hash map
243  * @return GNUNET_YES if we should continue to
244  *         iterate,
245  *         GNUNET_NO if not.
246  */
247 static int
248 announce_application (void *cls, const GNUNET_HashCode * key, void *value)
249 {
250   /* FIXME are hashes in multihash map equal on all aquitectures? */
251   GNUNET_DHT_put (dht_handle, key, 10U, GNUNET_DHT_RO_RECORD_ROUTE,
252                   GNUNET_BLOCK_TYPE_TEST, sizeof (struct GNUNET_PeerIdentity),
253                   (const char *) &my_full_id,
254 #if MESH_DEBUG
255                   GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL,
256                   &mesh_debug, "DHT_put for app completed");
257 #else
258                   GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
259                                             APP_ANNOUNCE_TIME),
260                   APP_ANNOUNCE_TIME, NULL, NULL);
261 #endif
262   return GNUNET_OK;
263 }
264
265
266 /**
267  * Periodically announce what applications are provided by local clients
268  *
269  * @param cls closure
270  * @param tc task context
271  */
272 static void
273 announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
274 {
275   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
276   {
277     announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
278     return;
279   }
280   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Starting PUT for apps\n");
281   GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application,
282                                          NULL);
283   announce_applications_task =
284       GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_applications,
285                                     cls);
286   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Finished PUT for apps\n");
287   return;
288 }
289
290
291 /**
292  * Periodically announce self id in the DHT
293  *
294  * @param cls closure
295  * @param tc task context
296  */
297 static void
298 announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
299 {
300   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
301   {
302     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
303     return;
304   }
305   /* TODO
306    * - Set data expiration in function of X
307    * - Adapt X to churn
308    */
309   GNUNET_DHT_put (dht_handle,   /* DHT handle */
310                   &my_full_id.hashPubKey,       /* Key to use */
311                   10U,          /* Replication level */
312                   GNUNET_DHT_RO_RECORD_ROUTE,   /* DHT options */
313                   GNUNET_BLOCK_TYPE_TEST,       /* Block type */
314                   0,            /* Size of the data */
315                   NULL,         /* Data itself */
316                   GNUNET_TIME_absolute_get_forever (),  /* Data expiration */
317                   GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
318 #if MESH_DEBUG
319                   &mesh_debug, "DHT_put for id completed");
320 #else
321                   NULL,         /* Continuation */
322                   NULL);        /* Continuation closure */
323 #endif
324   announce_id_task =
325       GNUNET_SCHEDULER_add_delayed (ID_ANNOUNCE_TIME, &announce_id, cls);
326 }
327
328
329 /******************************************************************************/
330 /******************      GENERAL HELPER FUNCTIONS      ************************/
331 /******************************************************************************/
332
333 /**
334  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
335  * and insert it in the appropiate structures if the peer is not known yet.
336  *
337  * @param peer Identity of the peer
338  *
339  * @return Existing or newly created peer info
340  */
341 static struct MeshPeerInfo *
342 peer_info_get (const struct GNUNET_PeerIdentity *peer)
343 {
344   struct MeshPeerInfo *peer_info;
345
346   peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
347   if (NULL == peer_info)
348   {
349     peer_info =
350         (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
351     GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
352                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
353     peer_info->id = GNUNET_PEER_intern (peer);
354   }
355
356   return peer_info;
357 }
358
359
360 #if LATER
361 /**
362  * Destroy the peer_info and free any allocated resources linked to it
363  * @param t tunnel the path belongs to
364  * @param pi the peer_info to destroy
365  * @return GNUNET_OK on success
366  */
367 static int
368 peer_info_destroy (struct MeshPeerInfo *pi)
369 {
370   GNUNET_HashCode hash;
371   struct GNUNET_PeerIdentity id;
372
373   GNUNET_PEER_resolve (pi->id, &id);
374   GNUNET_PEER_change_rc (pi->id, -1);
375   GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &hash);
376
377   GNUNET_CONTAINER_multihashmap_remove (peers, &hash, pi);
378   GNUNET_SCHEDULER_cancel (pi->path_refresh_task);
379   GNUNET_free (pi);
380   return GNUNET_OK;
381 }
382 #endif
383
384
385 /**
386  * Notify a tunnel that a connection has broken that affects at least
387  * some of its peers.
388  *
389  * @param t Tunnel affected
390  * @param peer Peer that (at least) has been affected by the disconnection
391  * @param p1 Peer that got disconnected from p2
392  * @param p2 Peer that got disconnected from p1
393  */
394 static void
395 tunnel_notify_connection_broken (struct MeshTunnel *t,
396                                  struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
397                                  GNUNET_PEER_Id p2);
398
399
400 /**
401  * Remove all paths that rely on a direct connection between p1 and p2
402  * from the peer itself and notify all tunnels about it.
403  *
404  * @param pi PeerInfo of affected peer
405  * @param p1 GNUNET_PEER_Id of one peer.
406  * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
407  *           no longer is.
408  */
409 static void
410 path_remove_from_peer (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
411                        GNUNET_PEER_Id p2)
412 {
413   struct MeshPeerPath *p;
414   struct MeshPeerPath *aux;
415   unsigned int destroyed;
416   unsigned int i;
417
418   destroyed = 0;
419   p = peer->path_head;
420   while (NULL != p)
421   {
422     aux = p->next;
423     for (i = 0; i < (p->length - 1); i++)
424     {
425       if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
426           (p->peers[i] == p2 && p->peers[i + 1] == p1))
427       {
428         path_destroy (p);
429         destroyed++;
430         break;
431       }
432     }
433     p = aux;
434   }
435   if (0 == destroyed)
436     return;
437
438   for (i = 0; i < peer->ntunnels; i++)
439   {
440     tunnel_notify_connection_broken (peer->tunnels[i], peer, p1, p2);
441   }
442 }
443
444
445 /**
446  * Add the path to the origin peer and update the path used to reach it in case
447  * this is the shortest.
448  * The path is given in peer_info -> destination, therefore we turn the path
449  * upside down first.
450  *
451  * @param peer_info Peer to add the path to, being the origin of the path.
452  * @param path New path to add after being inversed.
453  */
454 static void
455 path_add_to_origin (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path)
456 {
457   path_invert(path);
458   path_add_to_peer (peer_info, path);
459 }
460
461
462 /**
463  * Build a PeerPath from the paths returned from the DHT, reversing the paths
464  * to obtain a local peer -> destination path and interning the peer ids.
465  *
466  * @param get_path NULL-terminated array of pointers
467  *                 to the peers on reverse GET path (or NULL if not recorded)
468  * @param put_path NULL-terminated array of pointers
469  *                 to the peers on the PUT path (or NULL if not recorded)
470  *
471  * @return Newly allocated and created path
472  */
473 static struct MeshPeerPath *
474 path_build_from_dht (const struct GNUNET_PeerIdentity *const *get_path,
475                      const struct GNUNET_PeerIdentity *const *put_path)
476 {
477   struct MeshPeerPath *p;
478   GNUNET_PEER_Id id;
479   int i;
480
481   p = GNUNET_malloc (sizeof (struct MeshPeerPath));
482   for (i = 0; get_path[i] != NULL; i++) ;
483   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESH:    GET has %d hops.\n", i);
484   for (i--; i >= 0; i--)
485   {
486     id = GNUNET_PEER_intern (get_path[i]);
487     if (p->length > 0 && id == p->peers[p->length - 1])
488     {
489       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESH:    Optimizing 1 hop out.\n");
490       GNUNET_PEER_change_rc(id, -1);
491     }
492     else
493     {
494       p->peers =
495         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
496       p->peers[p->length] = id;
497       p->length++;
498     }
499   }
500   for (i = 0; put_path[i] != NULL; i++) ;
501   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESH:    PUT has %d hops.\n", i);
502   for (i--; i >= 0; i--)
503   {
504     id = GNUNET_PEER_intern (put_path[i]);
505     if (p->length > 0 && id == p->peers[p->length - 1])
506     {
507       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESH:    Optimizing 1 hop out.\n");
508       GNUNET_PEER_change_rc(id, -1);
509     }
510     else
511     {
512       p->peers =
513         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
514       p->peers[p->length] = id;
515       p->length++;
516     }
517   }
518 #if MESH_DEBUG
519   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
520               "MESH:    (first of GET: %s)\n",
521               GNUNET_h2s_full(&get_path[0]->hashPubKey));
522   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
523               "MESH:    (first of PUT: %s)\n",
524               GNUNET_h2s_full(&put_path[0]->hashPubKey));
525   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
526               "MESH:    In total: %d hops\n",
527               p->length);
528 #endif
529   return p;
530 }
531
532
533 /**
534  * Check if client has registered with the service and has not disconnected
535  *
536  * @param client the client to check
537  *
538  * @return non-NULL if client exists in the global DLL
539  */
540 static struct MeshClient *
541 client_get (struct GNUNET_SERVER_Client *client)
542 {
543   struct MeshClient *c;
544
545   c = clients;
546   while (NULL != c)
547   {
548     if (c->handle == client)
549       return c;
550     c = c->next;
551   }
552   return NULL;
553 }
554
555
556 /**
557  * Checks if a given client has subscribed to certain message type
558  *
559  * @param message_type Type of message to check
560  * @param c Client to check
561  *
562  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
563  *
564  * TODO inline?
565  */
566 static int
567 client_is_subscribed (uint16_t message_type, struct MeshClient *c)
568 {
569   GNUNET_HashCode hc;
570
571   GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc);
572   return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc);
573 }
574
575
576 /**
577  * Search for a tunnel among the tunnels for a client
578  *
579  * @param c the client whose tunnels to search in
580  * @param tid the local id of the tunnel
581  *
582  * @return tunnel handler, NULL if doesn't exist
583  */
584 static struct MeshTunnel *
585 tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
586 {
587   GNUNET_HashCode hash;
588
589   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
590   return GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
591 }
592
593
594 /**
595  * Search for a tunnel by global ID using PEER_ID
596  *
597  * @param pi owner of the tunnel
598  * @param tid global tunnel number
599  *
600  * @return tunnel handler, NULL if doesn't exist
601  */
602 static struct MeshTunnel *
603 tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
604 {
605   struct MESH_TunnelID id;
606   GNUNET_HashCode hash;
607
608   id.oid = pi;
609   id.tid = tid;
610
611   GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
612   return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
613 }
614
615
616 /**
617  * Search for a tunnel by global ID using full PeerIdentities
618  *
619  * @param oid owner of the tunnel
620  * @param tid global tunnel number
621  *
622  * @return tunnel handler, NULL if doesn't exist
623  */
624 static struct MeshTunnel *
625 tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
626 {
627   return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
628 }
629
630
631 /**
632  * Notify a tunnel that a connection has broken that affects at least
633  * some of its peers.
634  *
635  * @param t Tunnel affected
636  * @param peer Peer that (at least) has been affected by the disconnection
637  * @param p1 Peer that got disconnected from p2
638  * @param p2 Peer that got disconnected from p1
639  * 
640  * FIXME path
641  */
642 static void
643 tunnel_notify_connection_broken (struct MeshTunnel *t,
644                                  struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
645                                  GNUNET_PEER_Id p2)
646 {
647 }
648
649
650 /**
651  * Recursively destory the path tree of a tunnel.
652  * Note: it does not liberate memory for itself, parent must do it!
653  *
654  * @param n The node to destroy, along with children.
655  *
656  * @return GNUNET_OK on success
657  */
658 static void
659 tunnel_destroy_tree_node (struct MeshTunnelPathNode *n)
660 {
661   unsigned int i;
662
663   for (i = 0; i < n->nchildren; i++)
664   {
665     tunnel_destroy_tree_node(&n->children[i]);
666   }
667   if (NULL != n->children)
668     GNUNET_free (n->children);
669 }
670
671
672 /**
673  * Destroy the tunnel and free any allocated resources linked to it
674  *
675  * @param t the tunnel to destroy
676  *
677  * @return GNUNET_OK on success
678  */
679 static int
680 tunnel_destroy (struct MeshTunnel *t)
681 {
682   struct MeshClient *c;
683   struct MeshQueue *q;
684   struct MeshQueue *qn;
685   GNUNET_HashCode hash;
686   int r;
687
688   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: DESTROYING TUNNEL at %p\n", t);
689   if (NULL == t)
690     return GNUNET_OK;
691
692   c = t->client;
693 #if MESH_DEBUG
694   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
695 #endif
696
697   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
698   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
699   {
700     r = GNUNET_SYSERR;
701   }
702
703   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
704   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t))
705   {
706     r = GNUNET_SYSERR;
707   }
708   GNUNET_CONTAINER_multihashmap_destroy (t->peers);
709   q = t->queue_head;
710   while (NULL != q)
711   {
712     if (NULL != q->data)
713       GNUNET_free (q->data);
714     qn = q->next;
715     GNUNET_free (q);
716     q = qn;
717     /* TODO cancel core transmit ready in case it was active */
718   }
719
720   GNUNET_CONTAINER_multihashmap_iterate(t->tree->first_hops, &iterate_free, t);
721   GNUNET_CONTAINER_multihashmap_destroy(t->tree->first_hops);
722   tunnel_destroy_tree_node(t->tree->root);
723   GNUNET_free(t->tree->root);
724   GNUNET_free (t->tree);
725   GNUNET_free (t);
726   return r;
727 }
728
729
730 /**
731  * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
732  * client when the client disconnects.
733  * 
734  * @param cls closure (client that is disconnecting)
735  * @param key the hash of the local tunnel id (used to access the hashmap)
736  * @param value the value stored at the key (tunnel to destroy)
737  * 
738  * @return GNUNET_OK on success
739  */
740 static int
741 tunnel_destroy_iterator (void *cls, const GNUNET_HashCode * key, void *value)
742 {
743   int r;
744
745   r = tunnel_destroy ((struct MeshTunnel *) value);
746   return r;
747 }
748
749
750 /******************************************************************************/
751 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
752 /******************************************************************************/
753
754
755 /**
756  * Function called to notify a client about the socket
757  * being ready to queue more data.  "buf" will be
758  * NULL and "size" zero if the socket was closed for
759  * writing in the meantime.
760  *
761  * @param cls closure
762  * @param size number of bytes available in buf
763  * @param buf where the callee should write the message
764  * @return number of bytes written to buf
765  */
766 static size_t
767 send_core_create_path (void *cls, size_t size, void *buf)
768 {
769   struct MeshPathInfo *info = cls;
770   struct GNUNET_MESH_ManipulatePath *msg;
771   struct GNUNET_PeerIdentity *peer_ptr;
772   struct MeshPeerInfo *peer = info->peer;
773   struct MeshTunnel *t = info->t;
774   struct MeshPeerPath *p = info->path;
775   size_t size_needed;
776   int i;
777
778   size_needed =
779       sizeof (struct GNUNET_MESH_ManipulatePath) +
780       p->length * sizeof (struct GNUNET_PeerIdentity);
781
782   if (size < size_needed || NULL == buf)
783   {
784     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n");
785     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
786                                        GNUNET_TIME_UNIT_FOREVER_REL,
787                                        path_get_first_hop (t, peer),
788                                        size_needed, &send_core_create_path,
789                                        info);
790     return 0;
791   }
792
793   msg = (struct GNUNET_MESH_ManipulatePath *) buf;
794   msg->header.size = htons (size_needed);
795   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
796   msg->tid = ntohl (t->id.tid);
797
798   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
799   for (i = 0; i < p->length; i++)
800   {
801     GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
802   }
803
804   path_destroy (p);
805   GNUNET_free (info);
806
807   return size_needed;
808 }
809
810
811 #if LATER
812 /**
813  * Function called to notify a client about the socket
814  * being ready to queue more data.  "buf" will be
815  * NULL and "size" zero if the socket was closed for
816  * writing in the meantime.
817  *
818  * @param cls closure (MeshDataDescriptor with all info to build packet)
819  * @param size number of bytes available in buf
820  * @param buf where the callee should write the message
821  * @return number of bytes written to buf
822  */
823 static size_t
824 send_core_data_to_origin (void *cls, size_t size, void *buf)
825 {
826   struct MeshDataDescriptor *info = cls;
827   struct GNUNET_MESH_ToOrigin *msg = buf;
828   size_t total_size;
829
830   GNUNET_assert (NULL != info);
831   total_size = sizeof (struct GNUNET_MESH_ToOrigin) + info->size;
832   GNUNET_assert (total_size < 65536);   /* UNIT16_MAX */
833
834   if (total_size > size)
835   {
836     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
837                 "not enough buffer to send data to origin\n");
838     return 0;
839   }
840   msg->header.size = htons (total_size);
841   msg->header.type = htons (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
842   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
843   msg->tid = htonl (info->origin->tid);
844   if (0 != info->size)
845   {
846     memcpy (&msg[1], &info[1], info->size);
847   }
848   if (NULL != info->client)
849   {
850     GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
851   }
852   GNUNET_free (info);
853   return total_size;
854 }
855 #endif
856
857 /**
858  * Function called to notify a client about the socket
859  * being ready to queue more data.  "buf" will be
860  * NULL and "size" zero if the socket was closed for
861  * writing in the meantime.
862  *
863  * @param cls closure (data itself)
864  * @param size number of bytes available in buf
865  * @param buf where the callee should write the message
866  * @return number of bytes written to buf
867  */
868 static size_t
869 send_core_data_unicast (void *cls, size_t size, void *buf)
870 {
871   struct MeshDataDescriptor *info = cls;
872   struct GNUNET_MESH_Unicast *msg = buf;
873   size_t total_size;
874
875   GNUNET_assert (NULL != info);
876   total_size = sizeof (struct GNUNET_MESH_Unicast) + info->size;
877   GNUNET_assert (total_size < 65536);   /* UNIT16_MAX */
878
879   if (total_size > size)
880   {
881     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
882                 "not enough buffer to send data to peer\n");
883     return 0;
884   }
885   msg->header.size = htons (total_size);
886   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
887   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
888   GNUNET_PEER_resolve (info->destination, &msg->destination);
889   msg->tid = htonl (info->origin->tid);
890   if (0 != info->size)
891   {
892     memcpy (&msg[1], &info[1], info->size);
893   }
894   if (NULL != info->client)
895   {
896     GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
897   }
898   GNUNET_free (info);
899   return total_size;
900 }
901
902
903 /**
904  * Function called to notify a client about the socket
905  * being ready to queue more data.  "buf" will be
906  * NULL and "size" zero if the socket was closed for
907  * writing in the meantime.
908  *
909  * @param cls closure (data itself)
910  * @param size number of bytes available in buf
911  * @param buf where the callee should write the message
912  * @return number of bytes written to buf
913  */
914 static size_t
915 send_core_data_multicast (void *cls, size_t size, void *buf)
916 {
917   struct MeshDataDescriptor *info = cls;
918   struct GNUNET_MESH_Multicast *msg = buf;
919   size_t total_size;
920
921   GNUNET_assert (NULL != info);
922   total_size = info->size + sizeof (struct GNUNET_MESH_Multicast);
923   GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
924
925   if (info->peer)
926   {
927     info->peer->core_transmit[info->handler_n] = NULL;
928   }
929   if (total_size > size)
930   {
931     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
932                 "not enough buffer to send data futher\n");
933     return 0;
934   }
935   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
936   msg->header.size = htons (total_size);
937   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
938   msg->tid = htonl (info->origin->tid);
939   memcpy (&msg[1], &info[1], total_size);
940   if (0 == --info->copies)
941   {
942     if (NULL != info->client)
943     {
944       GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
945     }
946     GNUNET_free (info);
947   }
948   return total_size;
949 }
950
951
952 /**
953  * Function called to notify a client about the socket
954  * being ready to queue more data.  "buf" will be
955  * NULL and "size" zero if the socket was closed for
956  * writing in the meantime.
957  *
958  * @param cls closure (MeshDataDescriptor)
959  * @param size number of bytes available in buf
960  * @param buf where the callee should write the message
961  * @return number of bytes written to buf
962  */
963 static size_t
964 send_core_path_ack (void *cls, size_t size, void *buf)
965 {
966   struct MeshDataDescriptor *info = cls;
967   struct GNUNET_MESH_PathACK *msg = buf;
968
969   GNUNET_assert (NULL != info);
970   if (info->peer)
971   {
972     info->peer->core_transmit[info->handler_n] = NULL;
973   }
974   if (sizeof (struct GNUNET_MESH_PathACK) > size)
975   {
976     GNUNET_break (0);
977     return 0;
978   }
979   msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
980   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
981   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
982   msg->tid = htonl (info->origin->tid);
983   msg->peer_id = my_full_id;
984   GNUNET_free (info);
985   /* TODO add signature */
986
987   return sizeof (struct GNUNET_MESH_PathACK);
988 }
989
990
991 /**
992  * Function called to notify a client about the socket
993  * being ready to queue more data.  "buf" will be
994  * NULL and "size" zero if the socket was closed for
995  * writing in the meantime.
996  *
997  * @param cls closure (data itself)
998  * @param size number of bytes available in buf
999  * @param buf where the callee should write the message
1000  * @return number of bytes written to buf
1001  */
1002 static size_t
1003 send_core_data_raw (void *cls, size_t size, void *buf)
1004 {
1005   struct GNUNET_MessageHeader *msg = cls;
1006   size_t total_size;
1007
1008   GNUNET_assert (NULL != msg);
1009   total_size = ntohs (msg->size);
1010
1011   if (total_size > size)
1012   {
1013     GNUNET_break (0);
1014     return 0;
1015   }
1016   memcpy (buf, msg, total_size);
1017   GNUNET_free (cls);
1018   return total_size;
1019 }
1020
1021
1022 #if LATER
1023 /**
1024  * Send another peer a notification to destroy a tunnel
1025  * @param cls The tunnel to destroy
1026  * @param size Size in the buffer
1027  * @param buf Memory where to put the data to transmit
1028  * @return Size of data put in buffer
1029  */
1030 static size_t
1031 send_p2p_tunnel_destroy (void *cls, size_t size, void *buf)
1032 {
1033   struct MeshTunnel *t = cls;
1034   struct MeshClient *c;
1035   struct GNUNET_MESH_TunnelMessage *msg;
1036
1037   c = t->client;
1038   msg = buf;
1039   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1040    /*FIXME*/ msg->header.size =
1041       htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1042   msg->tunnel_id = htonl (t->id.tid);
1043
1044   tunnel_destroy (c, t);
1045   return sizeof (struct GNUNET_MESH_TunnelMessage);
1046 }
1047 #endif
1048
1049
1050 /**
1051  * Send the message to all clients that have subscribed to its type
1052  *
1053  * @param msg Pointer to the message itself
1054  * @return number of clients this message was sent to
1055  */
1056 static unsigned int
1057 send_subscribed_clients (struct GNUNET_MessageHeader *msg)
1058 {
1059   struct MeshClient *c;
1060   unsigned int count;
1061   uint16_t type;
1062
1063   type = ntohs (msg->type);
1064   for (count = 0, c = clients; c != NULL; c = c->next)
1065   {
1066     if (client_is_subscribed (type, c))
1067     {
1068       count++;
1069       GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg,
1070                                                   GNUNET_YES);
1071     }
1072   }
1073   return count;
1074 }
1075
1076
1077
1078 /**
1079  * Notify the client that owns the tunnel that a peer has connected to it
1080  * 
1081  * @param t Tunnel whose owner to notify
1082  * @param id Short id of the peer that has connected
1083  */
1084 static void
1085 send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id)
1086 {
1087   struct GNUNET_MESH_PeerControl pc;
1088
1089   pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
1090   pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1091   pc.tunnel_id = htonl (t->local_tid);
1092   GNUNET_PEER_resolve (id, &pc.peer);
1093   GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
1094                                               &pc.header, GNUNET_NO);
1095 }
1096
1097
1098 /******************************************************************************/
1099 /********************      MESH NETWORK HANDLERS     **************************/
1100 /******************************************************************************/
1101
1102
1103 /**
1104  * Core handler for path creation
1105  * struct GNUNET_CORE_MessageHandler
1106  *
1107  * @param cls closure
1108  * @param message message
1109  * @param peer peer identity this notification is about
1110  * @param atsi performance data
1111  * @return GNUNET_OK to keep the connection open,
1112  *         GNUNET_SYSERR to close it (signal serious error)
1113  *
1114  */
1115 static int
1116 handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1117                          const struct GNUNET_MessageHeader *message,
1118                          const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1119 {
1120   unsigned int own_pos;
1121   uint16_t size;
1122   uint16_t i;
1123   MESH_TunnelNumber tid;
1124   struct GNUNET_MESH_ManipulatePath *msg;
1125   struct GNUNET_PeerIdentity *pi;
1126   struct GNUNET_PeerIdentity id;
1127   GNUNET_HashCode hash;
1128   struct MeshPeerPath *path;
1129   struct MeshPeerInfo *dest_peer_info;
1130   struct MeshPeerInfo *orig_peer_info;
1131   struct MeshTunnel *t;
1132
1133   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1134               "MESH: Received a MESH path create msg\n");
1135   size = ntohs (message->size);
1136   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
1137   {
1138     GNUNET_break_op (0);
1139     return GNUNET_OK;
1140   }
1141
1142   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
1143   if (size % sizeof (struct GNUNET_PeerIdentity))
1144   {
1145     GNUNET_break_op (0);
1146     return GNUNET_OK;
1147   }
1148   size /= sizeof (struct GNUNET_PeerIdentity);
1149   if (size < 2)
1150   {
1151     GNUNET_break_op (0);
1152     return GNUNET_OK;
1153   }
1154   msg = (struct GNUNET_MESH_ManipulatePath *) message;
1155
1156   tid = ntohl (msg->tid);
1157   pi = (struct GNUNET_PeerIdentity *) &msg[1];
1158   t = tunnel_get (pi, tid);
1159
1160   if (NULL == t)
1161   {
1162     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Creating tunnel\n");
1163     t = GNUNET_malloc (sizeof (struct MeshTunnel));
1164     t->id.oid = GNUNET_PEER_intern (pi);
1165     t->id.tid = tid;
1166     t->peers = GNUNET_CONTAINER_multihashmap_create (32);
1167
1168     GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
1169     if (GNUNET_OK !=
1170         GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
1171                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1172     {
1173       GNUNET_break (0);
1174       return GNUNET_OK;
1175     }
1176
1177   }
1178   dest_peer_info =
1179       GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
1180   if (NULL == dest_peer_info)
1181   {
1182     dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1183     dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
1184     GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
1185                                        dest_peer_info,
1186                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1187   }
1188   orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
1189   if (NULL == orig_peer_info)
1190   {
1191     orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1192     orig_peer_info->id = GNUNET_PEER_intern (pi);
1193     GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
1194                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1195   }
1196
1197   path = GNUNET_malloc (sizeof (struct MeshPeerPath));
1198   path->length = size;
1199   path->peers = GNUNET_malloc (size * sizeof (GNUNET_PEER_Id));
1200   own_pos = 0;
1201   for (i = 0; i < size; i++)
1202   {
1203     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
1204     if (path->peers[i] == myid)
1205       own_pos = i;
1206   }
1207   if (own_pos == 0)
1208   {                             /* cannot be self, must be 'not found' */
1209     /* create path: self not found in path through self */
1210     GNUNET_break_op (0);
1211     path_destroy (path);
1212     /* FIXME error. destroy tunnel? leave for timeout? */
1213     return 0;
1214   }
1215   if (own_pos == size - 1)
1216   {
1217     /* It is for us! Send ack. */
1218     struct MeshDataDescriptor *info;
1219     unsigned int j;
1220
1221     path_add_to_origin (orig_peer_info, path);  /* inverts path!  */
1222     info = GNUNET_malloc (sizeof (struct MeshDataDescriptor));
1223     info->origin = &t->id;
1224     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
1225     GNUNET_assert (info->peer);
1226     for (j = 0; info->peer->core_transmit[j]; j++)
1227     {
1228       if (j == 9)
1229       {
1230         GNUNET_break (0);
1231         return GNUNET_OK;
1232       }
1233     }
1234     info->handler_n = j;
1235     info->peer->core_transmit[j] =
1236         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
1237                                            GNUNET_TIME_UNIT_FOREVER_REL, peer,
1238                                            sizeof (struct GNUNET_MessageHeader),
1239                                            &send_core_path_ack, info);
1240   }
1241   else
1242   {
1243     /* It's for somebody else! Retransmit. */
1244     struct MeshPathInfo *path_info;
1245
1246     path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
1247     path_info->t = t;
1248     path_info->path = path;
1249     path_info->peer = dest_peer_info;
1250
1251     path_add_to_peer (dest_peer_info, path);
1252     GNUNET_PEER_resolve (path->peers[own_pos + 1], &id);
1253     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1254                                        GNUNET_TIME_UNIT_FOREVER_REL, &id,
1255                                        sizeof (struct GNUNET_MessageHeader),
1256                                        &send_core_create_path, path_info);
1257   }
1258   return GNUNET_OK;
1259 }
1260
1261
1262 /**
1263  * Core handler for mesh network traffic going from the origin to a peer
1264  *
1265  * @param cls closure
1266  * @param peer peer identity this notification is about
1267  * @param message message
1268  * @param atsi performance data
1269  * @return GNUNET_OK to keep the connection open,
1270  *         GNUNET_SYSERR to close it (signal serious error)
1271  */
1272 static int
1273 handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
1274                           const struct GNUNET_MessageHeader *message,
1275                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1276 {
1277   struct GNUNET_MESH_Unicast *msg;
1278   struct MeshTunnel *t;
1279   struct MeshPeerInfo *pi;
1280   size_t size;
1281
1282   size = ntohs (message->size);
1283   if (size <
1284       sizeof (struct GNUNET_MESH_Unicast) +
1285       sizeof (struct GNUNET_MessageHeader))
1286   {
1287     GNUNET_break (0);
1288     return GNUNET_OK;
1289   }
1290   msg = (struct GNUNET_MESH_Unicast *) message;
1291   t = tunnel_get (&msg->oid, ntohl (msg->tid));
1292   if (NULL == t)
1293   {
1294     /* TODO notify back: we don't know this tunnel */
1295     return GNUNET_OK;
1296   }
1297   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
1298                                           &msg->destination.hashPubKey);
1299   if (NULL == pi)
1300   {
1301     /* TODO maybe feedback, log to statistics */
1302     return GNUNET_OK;
1303   }
1304   if (pi->id == myid)
1305   {
1306     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
1307     return GNUNET_OK;
1308   }
1309   msg = GNUNET_malloc (size);
1310   memcpy (msg, message, size);
1311   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1312                                      GNUNET_TIME_UNIT_FOREVER_REL,
1313                                      path_get_first_hop (t, pi), size,
1314                                      &send_core_data_raw, msg);
1315   return GNUNET_OK;
1316 }
1317
1318
1319 /**
1320  * Core handler for mesh network traffic going from the origin to all peers
1321  *
1322  * @param cls closure
1323  * @param message message
1324  * @param peer peer identity this notification is about
1325  * @param atsi performance data
1326  * @return GNUNET_OK to keep the connection open,
1327  *         GNUNET_SYSERR to close it (signal serious error)
1328  */
1329 static int
1330 handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
1331                             const struct GNUNET_MessageHeader *message,
1332                             const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1333 {
1334   struct GNUNET_MESH_Multicast *msg;
1335   struct GNUNET_PeerIdentity id;
1336   struct MeshDataDescriptor *info;
1337   struct MeshPathInfo neighbors;
1338   struct MeshTunnel *t;
1339   size_t size;
1340   uint16_t i;
1341   uint16_t j;
1342
1343
1344   size = ntohs (message->size);
1345   if (size <
1346       sizeof (struct GNUNET_MESH_Multicast) +
1347       sizeof (struct GNUNET_MessageHeader))
1348   {
1349     GNUNET_break_op (0);
1350     return GNUNET_OK;
1351   }
1352   msg = (struct GNUNET_MESH_Multicast *) message;
1353   t = tunnel_get (&msg->oid, ntohl (msg->tid));
1354
1355   if (NULL == t)
1356   {
1357     /* TODO notify that we dont know that tunnel */
1358     return GNUNET_OK;
1359   }
1360
1361   /* Transmit to locally interested clients */
1362   if (GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey))
1363   {
1364     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
1365   }
1366
1367   /* Retransmit to other peers.
1368    * Using path here as just a collection of peers, not a path per se.
1369    */
1370   neighbors.t = t;
1371   neighbors.path = GNUNET_malloc (sizeof (struct MeshPeerPath));
1372   GNUNET_CONTAINER_multihashmap_iterate (t->peers, &iterate_collect_neighbors,
1373                                          &neighbors);
1374   if (0 == neighbors.path->length)
1375   {
1376     GNUNET_free (neighbors.path);
1377     return GNUNET_OK;
1378   }
1379   size -= sizeof (struct GNUNET_MESH_Multicast);
1380   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + size);
1381   info->origin = &t->id;
1382   info->copies = neighbors.path->length;
1383   for (i = 0; i < info->copies; i++)
1384   {
1385     GNUNET_PEER_resolve (neighbors.path->peers[i], &id);
1386     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
1387     GNUNET_assert (NULL != info->peer);
1388     for (j = 0; 0 != info->peer->core_transmit[j]; j++)
1389     {
1390       if (j == (CORE_QUEUE_SIZE - 1))
1391       {
1392         GNUNET_break (0);
1393         return GNUNET_OK;
1394       }
1395     }
1396     info->handler_n = j;
1397     info->peer->infos[j] = info;
1398     info->peer->core_transmit[j] =
1399         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1400                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
1401                                            ntohs (msg->header.size),
1402                                            &send_core_data_multicast, info);
1403   }
1404   GNUNET_free (neighbors.path->peers);
1405   GNUNET_free (neighbors.path);
1406   return GNUNET_OK;
1407 }
1408
1409
1410 /**
1411  * Core handler for mesh network traffic
1412  *
1413  * @param cls closure
1414  * @param message message
1415  * @param peer peer identity this notification is about
1416  * @param atsi performance data
1417  *
1418  * @return GNUNET_OK to keep the connection open,
1419  *         GNUNET_SYSERR to close it (signal serious error)
1420  */
1421 static int
1422 handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
1423                           const struct GNUNET_MessageHeader *message,
1424                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1425 {
1426   struct GNUNET_MESH_ToOrigin *msg;
1427   struct GNUNET_PeerIdentity id;
1428   struct MeshPeerInfo *peer_info;
1429   struct MeshTunnel *t;
1430   size_t size;
1431
1432   size = ntohs (message->size);
1433   if (size < sizeof (struct GNUNET_MESH_ToOrigin) +     /* Payload must be */
1434       sizeof (struct GNUNET_MessageHeader))     /* at least a header */
1435   {
1436     GNUNET_break_op (0);
1437     return GNUNET_OK;
1438   }
1439   msg = (struct GNUNET_MESH_ToOrigin *) message;
1440   t = tunnel_get (&msg->oid, ntohl (msg->tid));
1441
1442   if (NULL == t)
1443   {
1444     /* TODO notify that we dont know this tunnel (whom)? */
1445     return GNUNET_OK;
1446   }
1447
1448   if (t->id.oid == myid)
1449   {
1450     if (NULL == t->client)
1451     {
1452       /* got data packet for ownerless tunnel */
1453       GNUNET_break_op (0);
1454       return GNUNET_OK;
1455     }
1456     /* TODO signature verification */
1457     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, message,
1458                                                 GNUNET_YES);
1459     return GNUNET_OK;
1460   }
1461   peer_info = peer_info_get (&msg->oid);
1462   if (NULL == peer_info)
1463   {
1464     /* unknown origin of tunnel */
1465     GNUNET_break (0);
1466     return GNUNET_OK;
1467   }
1468   GNUNET_PEER_resolve (t->tree->me->parent->peer, &id);
1469   msg = GNUNET_malloc (size);
1470   memcpy (msg, message, size);
1471   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1472                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
1473                                      &send_core_data_raw, msg);
1474
1475   return GNUNET_OK;
1476 }
1477
1478
1479 /**
1480  * Core handler for path ACKs
1481  *
1482  * @param cls closure
1483  * @param message message
1484  * @param peer peer identity this notification is about
1485  * @param atsi performance data
1486  *
1487  * @return GNUNET_OK to keep the connection open,
1488  *         GNUNET_SYSERR to close it (signal serious error)
1489  *
1490  * FIXME path change state
1491  */
1492 static int
1493 handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1494                       const struct GNUNET_MessageHeader *message,
1495                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1496 {
1497   struct GNUNET_MESH_PathACK *msg;
1498   struct MeshTunnel *t;
1499   struct MeshPeerInfo *peer_info;
1500
1501   msg = (struct GNUNET_MESH_PathACK *) message;
1502   t = tunnel_get (&msg->oid, msg->tid);
1503   if (NULL == t)
1504   {
1505     /* TODO notify that we don't know the tunnel */
1506     return GNUNET_OK;
1507   }
1508
1509   /* Message for us? */
1510   if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
1511   {
1512
1513     if (NULL == t->client)
1514     {
1515       GNUNET_break (0);
1516       return GNUNET_OK;
1517     }
1518     peer_info = peer_info_get (&msg->peer_id);
1519     if (NULL == peer_info)
1520     {
1521       GNUNET_break_op (0);
1522       return GNUNET_OK;
1523     }
1524     /* FIXME change state of peer */
1525     send_client_peer_connected(t, peer_info->id);
1526     return GNUNET_OK;
1527   }
1528
1529   peer_info = peer_info_get (&msg->oid);
1530   if (NULL == peer_info)
1531   {
1532     /* If we know the tunnel, we should DEFINITELY know the peer */
1533     GNUNET_break (0);
1534     return GNUNET_OK;
1535   }
1536   msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PathACK));
1537   memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK));
1538   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1539                                      GNUNET_TIME_UNIT_FOREVER_REL,
1540                                      path_get_first_hop (t, peer_info),
1541                                      sizeof (struct GNUNET_MESH_PathACK),
1542                                      &send_core_data_raw, msg);
1543   return GNUNET_OK;
1544 }
1545
1546
1547 /**
1548  * Functions to handle messages from core
1549  */
1550 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1551   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1552   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
1553   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
1554   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
1555   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
1556    sizeof (struct GNUNET_MESH_PathACK)},
1557   {NULL, 0, 0}
1558 };
1559
1560
1561
1562 /******************************************************************************/
1563 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
1564 /******************************************************************************/
1565
1566 /**
1567  * deregister_app: iterator for removing each application registered by a client
1568  * 
1569  * @param cls closure
1570  * @param key the hash of the application id (used to access the hashmap)
1571  * @param value the value stored at the key (client)
1572  * 
1573  * @return GNUNET_OK on success
1574  */
1575 static int
1576 deregister_app (void *cls, const GNUNET_HashCode * key, void *value)
1577 {
1578   GNUNET_CONTAINER_multihashmap_remove (applications, key, value);
1579   return GNUNET_OK;
1580 }
1581
1582 #if LATER
1583 /**
1584  * notify_client_connection_failure: notify a client that the connection to the
1585  * requested remote peer is not possible (for instance, no route found)
1586  * Function called when the socket is ready to queue more data. "buf" will be
1587  * NULL and "size" zero if the socket was closed for writing in the meantime.
1588  *
1589  * @param cls closure
1590  * @param size number of bytes available in buf
1591  * @param buf where the callee should write the message
1592  * @return number of bytes written to buf
1593  */
1594 static size_t
1595 notify_client_connection_failure (void *cls, size_t size, void *buf)
1596 {
1597   int size_needed;
1598   struct MeshPeerInfo *peer_info;
1599   struct GNUNET_MESH_PeerControl *msg;
1600   struct GNUNET_PeerIdentity id;
1601
1602   if (0 == size && NULL == buf)
1603   {
1604     // TODO retry? cancel?
1605     return 0;
1606   }
1607
1608   size_needed = sizeof (struct GNUNET_MESH_PeerControl);
1609   peer_info = (struct MeshPeerInfo *) cls;
1610   msg = (struct GNUNET_MESH_PeerControl *) buf;
1611   msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1612   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1613 //     msg->tunnel_id = htonl(peer_info->t->tid);
1614   GNUNET_PEER_resolve (peer_info->id, &id);
1615   memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
1616
1617   return size_needed;
1618 }
1619 #endif
1620
1621
1622 /**
1623  * Function to process paths received for a new peer addition. The recorded
1624  * paths form the initial tunnel, which can be optimized later.
1625  * Called on each result obtained for the DHT search.
1626  *
1627  * @param cls closure
1628  * @param exp when will this value expire
1629  * @param key key of the result
1630  * @param get_path NULL-terminated array of pointers
1631  *                 to the peers on reverse GET path (or NULL if not recorded)
1632  * @param put_path NULL-terminated array of pointers
1633  *                 to the peers on the PUT path (or NULL if not recorded)
1634  * @param type type of the result
1635  * @param size number of bytes in data
1636  * @param data pointer to the result data
1637  *
1638  * FIXME path
1639  */
1640 static void
1641 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
1642                     const GNUNET_HashCode * key,
1643                     const struct GNUNET_PeerIdentity *const *get_path,
1644                     const struct GNUNET_PeerIdentity *const *put_path,
1645                     enum GNUNET_BLOCK_Type type, size_t size, const void *data)
1646 {
1647   struct MeshPathInfo *path_info = cls;
1648   struct MeshPeerPath *p;
1649   struct GNUNET_PeerIdentity pi;
1650   int i;
1651
1652   if (NULL == get_path || NULL == put_path)
1653   {
1654     if (NULL == path_info->peer->path_head)
1655     {
1656       // Find ourselves some alternate initial path to the destination: retry
1657       GNUNET_DHT_get_stop (path_info->peer->dhtget);
1658       GNUNET_PEER_resolve (path_info->peer->id, &pi);
1659       path_info->peer->dhtget = GNUNET_DHT_get_start (dht_handle,       /* handle */
1660                                                       GNUNET_TIME_UNIT_FOREVER_REL,     /* timeout */
1661                                                       GNUNET_BLOCK_TYPE_TEST,   /* type */
1662                                                       &pi.hashPubKey,   /*key to search */
1663                                                       4,        /* replication level */
1664                                                       GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
1665                                                       0,        /* mutator */
1666                                                       NULL,     /* xquery */
1667                                                       0,        /* xquery bits */
1668                                                       dht_get_id_handler,
1669                                                       (void *) path_info);
1670       return;
1671     }
1672   }
1673
1674   p = path_build_from_dht (get_path, put_path);
1675   path_add_to_peer (path_info->peer, p);
1676   for (i = 0; i < path_info->peer->ntunnels; i++)
1677   {
1678     tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer);
1679   }
1680   GNUNET_free (path_info);
1681
1682   return;
1683 }
1684
1685
1686 /**
1687  * Function to process paths received for a new peer addition. The recorded
1688  * paths form the initial tunnel, which can be optimized later.
1689  * Called on each result obtained for the DHT search.
1690  *
1691  * @param cls closure
1692  * @param exp when will this value expire
1693  * @param key key of the result
1694  * @param get_path NULL-terminated array of pointers
1695  *                 to the peers on reverse GET path (or NULL if not recorded)
1696  * @param put_path NULL-terminated array of pointers
1697  *                 to the peers on the PUT path (or NULL if not recorded)
1698  * @param type type of the result
1699  * @param size number of bytes in data
1700  * @param data pointer to the result data
1701  */
1702 static void
1703 dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
1704                       const GNUNET_HashCode * key,
1705                       const struct GNUNET_PeerIdentity *const *get_path,
1706                       const struct GNUNET_PeerIdentity *const *put_path,
1707                       enum GNUNET_BLOCK_Type type, size_t size,
1708                       const void *data)
1709 {
1710   const struct GNUNET_PeerIdentity *pi = data;
1711   struct GNUNET_PeerIdentity id;
1712   struct MeshTunnel *t = cls;
1713   struct MeshPeerInfo *peer_info;
1714   struct MeshPathInfo *path_info;
1715   struct MeshPeerPath *p;
1716   int i;
1717
1718   if (size != sizeof (struct GNUNET_PeerIdentity))
1719   {
1720     GNUNET_break_op (0);
1721     return;
1722   }
1723   GNUNET_assert (NULL != t->client);
1724   GNUNET_DHT_get_stop (t->client->dht_get_type);
1725   t->client->dht_get_type = NULL;
1726   peer_info = peer_info_get (pi);
1727   GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, peer_info,
1728                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1729
1730   if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path_head &&
1731       NULL == peer_info->dhtget)
1732   {
1733     /* we don't have a route to the peer, let's try a direct lookup */
1734     peer_info->dhtget = GNUNET_DHT_get_start (dht_handle,
1735                                               /* handle */
1736                                               GNUNET_TIME_UNIT_FOREVER_REL,
1737                                               /* timeout */
1738                                               GNUNET_BLOCK_TYPE_TEST,
1739                                               /* block type */
1740                                               &pi->hashPubKey,
1741                                               /* key to look up */
1742                                               10U,
1743                                               /* replication level */
1744                                               GNUNET_DHT_RO_RECORD_ROUTE,
1745                                               /* option to dht: record route */
1746                                               NULL,     /* bloom filter */
1747                                               0,        /* mutator */
1748                                               NULL,     /* xquery */
1749                                               0,        /* xquery bits */
1750                                               dht_get_id_handler,
1751                                               /* callback */
1752                                               peer_info);       /* closure */
1753   }
1754
1755   p = path_build_from_dht (get_path, put_path);
1756   path_add_to_peer (peer_info, p);
1757   tunnel_add_peer(t, peer_info);
1758   p = tunnel_get_path_to_peer(t, peer_info);
1759 #if MESH_DEBUG
1760   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1761               "MESH: new route for tunnel 0x%x found, has %u hops\n",
1762               t->local_tid, p->length);
1763   for (i = 0; i < p->length; i++)
1764   {
1765     GNUNET_PEER_resolve (p->peers[0], &id);
1766     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:\t%d\t%s\n", i,
1767                 GNUNET_h2s_full (&id.hashPubKey));
1768   }
1769 #endif
1770
1771   if (p->length > 1)
1772   {
1773     path_info = GNUNET_malloc(sizeof(struct MeshPathInfo));
1774     path_info->t = t;
1775     path_info->peer = peer_info;
1776     path_info->path = p;
1777     GNUNET_PEER_resolve (p->peers[1], &id);
1778     GNUNET_CORE_notify_transmit_ready (core_handle,
1779                                      /* handle */
1780                                      0,
1781                                      /* cork */
1782                                      0,
1783                                      /* priority */
1784                                      GNUNET_TIME_UNIT_FOREVER_REL,
1785                                      /* timeout */
1786                                      &id,
1787                                      /* target */
1788                                      sizeof (struct GNUNET_MESH_ManipulatePath)
1789                                      +
1790                                      (p->length *
1791                                       sizeof (struct GNUNET_PeerIdentity)),
1792                                      /*size */
1793                                      &send_core_create_path,
1794                                      /* callback */
1795                                      path_info);        /* cls */
1796     return;
1797   }
1798   path_destroy(p);
1799   send_client_peer_connected(t, myid);
1800 }
1801
1802 /******************************************************************************/
1803 /*********************       MESH LOCAL HANDLES      **************************/
1804 /******************************************************************************/
1805
1806
1807 /**
1808  * Handler for client disconnection
1809  *
1810  * @param cls closure
1811  * @param client identification of the client; NULL
1812  *        for the last call when the server is destroyed
1813  */
1814 static void
1815 handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1816 {
1817   struct MeshClient *c;
1818   struct MeshClient *next;
1819
1820   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n");
1821   if (client == NULL)
1822      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    (SERVER DOWN)\n");
1823   c = clients;
1824   while (NULL != c)
1825   {
1826     if (c->handle != client && NULL != client)
1827     {
1828       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    ... searching\n");
1829       c = c->next;
1830       continue;
1831     }
1832     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: matching client found\n");
1833     if (NULL != c->tunnels)
1834     {
1835       GNUNET_CONTAINER_multihashmap_iterate (c->tunnels,
1836                                              &tunnel_destroy_iterator,
1837                                              c);
1838       GNUNET_CONTAINER_multihashmap_destroy (c->tunnels);
1839     }
1840
1841     /* deregister clients applications */
1842     if (NULL != c->apps)
1843     {
1844       GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, NULL);
1845       GNUNET_CONTAINER_multihashmap_destroy (c->apps);
1846     }
1847     if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
1848         GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
1849     {
1850       GNUNET_SCHEDULER_cancel (announce_applications_task);
1851       announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
1852     }
1853     if (NULL != c->types)
1854       GNUNET_CONTAINER_multihashmap_destroy (c->types);
1855     if (NULL != c->dht_get_type)
1856       GNUNET_DHT_get_stop (c->dht_get_type);
1857     GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
1858     next = c->next;
1859     GNUNET_free (c);
1860     c = next;
1861   }
1862
1863   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    done!\n");
1864   return;
1865 }
1866
1867
1868 /**
1869  * Handler for new clients
1870  *
1871  * @param cls closure
1872  * @param client identification of the client
1873  * @param message the actual message, which includes messages the client wants
1874  */
1875 static void
1876 handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
1877                          const struct GNUNET_MessageHeader *message)
1878 {
1879   struct GNUNET_MESH_ClientConnect *cc_msg;
1880   struct MeshClient *c;
1881   GNUNET_MESH_ApplicationType *a;
1882   unsigned int size;
1883   uint16_t ntypes;
1884   uint16_t *t;
1885   uint16_t napps;
1886   uint16_t i;
1887
1888   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n");
1889   /* Check data sanity */
1890   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
1891   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1892   ntypes = ntohs (cc_msg->types);
1893   napps = ntohs (cc_msg->applications);
1894   if (size !=
1895       ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType))
1896   {
1897     GNUNET_break (0);
1898     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1899     return;
1900   }
1901
1902   /* Create new client structure */
1903   c = GNUNET_malloc (sizeof (struct MeshClient));
1904 #if MESH_DEBUG
1905   c->id = next_client_id++;
1906 #endif
1907   c->handle = client;
1908   a = (GNUNET_MESH_ApplicationType *) &cc_msg[1];
1909   if (napps > 0)
1910   {
1911     GNUNET_MESH_ApplicationType at;
1912     GNUNET_HashCode hc;
1913
1914     c->apps = GNUNET_CONTAINER_multihashmap_create (napps);
1915     for (i = 0; i < napps; i++)
1916     {
1917       at = ntohl (a[i]);
1918       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   app type: %u\n", at);
1919       GNUNET_CRYPTO_hash (&at, sizeof (at), &hc);
1920       /* store in clients hashmap */
1921       GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, c,
1922                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1923       /* store in global hashmap, for announcements */
1924       GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
1925                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1926     }
1927     if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
1928       announce_applications_task =
1929           GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
1930
1931   }
1932   if (ntypes > 0)
1933   {
1934     uint16_t u16;
1935     GNUNET_HashCode hc;
1936
1937     t = (uint16_t *) & a[napps];
1938     c->types = GNUNET_CONTAINER_multihashmap_create (ntypes);
1939     for (i = 0; i < ntypes; i++)
1940     {
1941       u16 = ntohs (t[i]);
1942       GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
1943
1944       /* store in clients hashmap */
1945       GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
1946                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1947       /* store in global hashmap */
1948       GNUNET_CONTAINER_multihashmap_put (types, &hc, c,
1949                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
1950     }
1951   }
1952   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1953               "MESH:  client has %u+%u subscriptions\n", napps, ntypes);
1954
1955   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
1956   c->tunnels = GNUNET_CONTAINER_multihashmap_create (32);
1957   GNUNET_SERVER_notification_context_add (nc, client);
1958
1959   GNUNET_SERVER_receive_done (client, GNUNET_OK);
1960 #if MESH_DEBUG
1961   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client processed\n");
1962 #endif
1963 }
1964
1965
1966 /**
1967  * Handler for requests of new tunnels
1968  *
1969  * @param cls closure
1970  * @param client identification of the client
1971  * @param message the actual message
1972  */
1973 static void
1974 handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
1975                             const struct GNUNET_MessageHeader *message)
1976 {
1977   struct GNUNET_MESH_TunnelMessage *t_msg;
1978   struct MeshTunnel *t;
1979   struct MeshClient *c;
1980   GNUNET_HashCode hash;
1981
1982   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n");
1983
1984   /* Sanity check for client registration */
1985   if (NULL == (c = client_get (client)))
1986   {
1987     GNUNET_break (0);
1988     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
1989     return;
1990   }
1991 #if MESH_DEBUG
1992   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
1993 #endif
1994
1995   /* Message sanity check */
1996   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
1997   {
1998     GNUNET_break (0);
1999     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2000     return;
2001   }
2002
2003   t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2004   /* Sanity check for tunnel numbering */
2005   if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
2006   {
2007     GNUNET_break (0);
2008     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2009     return;
2010   }
2011   /* Sanity check for duplicate tunnel IDs */
2012   if (NULL != tunnel_get_by_local_id (c, ntohl (t_msg->tunnel_id)))
2013   {
2014     GNUNET_break (0);
2015     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2016     return;
2017   }
2018
2019   t = GNUNET_malloc (sizeof (struct MeshTunnel));
2020   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL at %p\n", t);
2021   while (NULL != tunnel_get_by_pi (myid, next_tid))
2022     next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
2023   t->id.tid = next_tid++;
2024   t->id.oid = myid;
2025   t->local_tid = ntohl (t_msg->tunnel_id);
2026   t->client = c;
2027   t->peers = GNUNET_CONTAINER_multihashmap_create (32);
2028
2029   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2030   if (GNUNET_OK !=
2031       GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
2032                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2033   {
2034     GNUNET_break (0);
2035     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2036     return;
2037   }
2038
2039   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2040   if (GNUNET_OK !=
2041       GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
2042                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2043   {
2044     GNUNET_break (0);
2045     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2046     return;
2047   }
2048   t->tree = GNUNET_malloc (sizeof(struct MeshTunnelPath));
2049   t->tree->first_hops = GNUNET_CONTAINER_multihashmap_create(32);
2050   t->tree->t = t;
2051   t->tree->refresh = REFRESH_PATH_TIME;
2052   t->tree->root = GNUNET_malloc(sizeof(struct MeshTunnelPathNode));
2053   t->tree->root->status = MESH_PEER_READY;
2054   t->tree->root->t = t;
2055   t->tree->root->peer = myid;
2056   t->tree->me = t->tree->root;
2057
2058   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2059   return;
2060 }
2061
2062
2063 /**
2064  * Handler for requests of deleting tunnels
2065  *
2066  * @param cls closure
2067  * @param client identification of the client
2068  * @param message the actual message
2069  */
2070 static void
2071 handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2072                              const struct GNUNET_MessageHeader *message)
2073 {
2074   struct GNUNET_MESH_TunnelMessage *tunnel_msg;
2075   struct MeshClient *c;
2076   struct MeshTunnel *t;
2077   MESH_TunnelNumber tid;
2078   GNUNET_HashCode hash;
2079
2080   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel\n");
2081
2082   /* Sanity check for client registration */
2083   if (NULL == (c = client_get (client)))
2084   {
2085     GNUNET_break (0);
2086     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2087     return;
2088   }
2089   /* Message sanity check */
2090   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2091   {
2092     GNUNET_break (0);
2093     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2094     return;
2095   }
2096 #if MESH_DEBUG
2097   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
2098 #endif
2099   tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2100
2101   /* Retrieve tunnel */
2102   tid = ntohl (tunnel_msg->tunnel_id);
2103
2104   /* Remove from local id hashmap */
2105   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
2106   t = GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
2107   GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t);
2108
2109   /* Remove from global id hashmap */
2110   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2111   GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t);
2112
2113 //     notify_tunnel_destroy(t); FIXME
2114   tunnel_destroy(t);
2115   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2116   return;
2117 }
2118
2119
2120 /**
2121  * Handler for connection requests to new peers
2122  *
2123  * @param cls closure
2124  * @param client identification of the client
2125  * @param message the actual message (PeerControl)
2126  *
2127  * FIXME path
2128  */
2129 static void
2130 handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
2131                           const struct GNUNET_MessageHeader *message)
2132 {
2133   struct GNUNET_MESH_PeerControl *peer_msg;
2134   struct MeshClient *c;
2135   struct MeshTunnel *t;
2136   MESH_TunnelNumber tid;
2137   struct MeshPeerInfo *peer_info;
2138
2139
2140   /* Sanity check for client registration */
2141   if (NULL == (c = client_get (client)))
2142   {
2143     GNUNET_break (0);
2144     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2145     return;
2146   }
2147
2148   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2149   /* Sanity check for message size */
2150   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2151   {
2152     GNUNET_break (0);
2153     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2154     return;
2155   }
2156
2157   /* Tunnel exists? */
2158   tid = ntohl (peer_msg->tunnel_id);
2159   t = tunnel_get_by_local_id (c, tid);
2160   if (NULL == t)
2161   {
2162     GNUNET_break (0);
2163     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2164     return;
2165   }
2166
2167   /* Does client own tunnel? */
2168   if (t->client->handle != client)
2169   {
2170     GNUNET_break (0);
2171     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2172     return;
2173   }
2174
2175   t->peers_total++;
2176   peer_info = peer_info_get (&peer_msg->peer);
2177
2178   /* Start DHT search if needed FIXME: if not already connected */
2179   if (NULL == peer_info->dhtget)
2180   {
2181     peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_TEST, &peer_msg->peer.hashPubKey, 4,  /* replication level */
2182                                               GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
2183                                               0,        /* mutator */
2184                                               NULL,     /* xquery */
2185                                               0,        /* xquery bits */
2186                                               dht_get_id_handler,
2187                                               (void *) peer_info);
2188   }
2189
2190   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2191   return;
2192 }
2193
2194
2195 /**
2196  * Handler for disconnection requests of peers in a tunnel
2197  *
2198  * @param cls closure
2199  * @param client identification of the client
2200  * @param message the actual message (PeerControl)
2201  */
2202 static void
2203 handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
2204                           const struct GNUNET_MessageHeader *message)
2205 {
2206   struct GNUNET_MESH_PeerControl *peer_msg;
2207   struct MeshClient *c;
2208   struct MeshTunnel *t;
2209   MESH_TunnelNumber tid;
2210
2211   /* Sanity check for client registration */
2212   if (NULL == (c = client_get (client)))
2213   {
2214     GNUNET_break (0);
2215     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2216     return;
2217   }
2218   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2219   /* Sanity check for message size */
2220   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2221   {
2222     GNUNET_break (0);
2223     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2224     return;
2225   }
2226
2227   /* Tunnel exists? */
2228   tid = ntohl (peer_msg->tunnel_id);
2229   t = tunnel_get_by_local_id (c, tid);
2230   if (NULL == t)
2231   {
2232     GNUNET_break (0);
2233     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2234     return;
2235   }
2236
2237   /* Does client own tunnel? */
2238   if (t->client->handle != client)
2239   {
2240     GNUNET_break (0);
2241     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2242     return;
2243   }
2244
2245   /* Ok, delete peer from tunnel */
2246   GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
2247                                             &peer_msg->peer.hashPubKey);
2248
2249   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2250   return;
2251 }
2252
2253
2254 /**
2255  * Handler for connection requests to new peers by type
2256  *
2257  * @param cls closure
2258  * @param client identification of the client
2259  * @param message the actual message (ConnectPeerByType)
2260  */
2261 static void
2262 handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
2263                               const struct GNUNET_MessageHeader *message)
2264 {
2265   struct GNUNET_MESH_ConnectPeerByType *connect_msg;
2266   struct MeshClient *c;
2267   struct MeshTunnel *t;
2268   GNUNET_HashCode hash;
2269   GNUNET_MESH_ApplicationType type;
2270   MESH_TunnelNumber tid;
2271
2272   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got connect by type request\n");
2273   /* Sanity check for client registration */
2274   if (NULL == (c = client_get (client)))
2275   {
2276     GNUNET_break (0);
2277     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2278     return;
2279   }
2280
2281   connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
2282   /* Sanity check for message size */
2283   if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
2284       ntohs (connect_msg->header.size))
2285   {
2286     GNUNET_break (0);
2287     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2288     return;
2289   }
2290
2291   /* Tunnel exists? */
2292   tid = ntohl (connect_msg->tunnel_id);
2293   t = tunnel_get_by_local_id (c, tid);
2294   if (NULL == t)
2295   {
2296     GNUNET_break (0);
2297     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2298     return;
2299   }
2300
2301   /* Does client own tunnel? */
2302   if (t->client->handle != client)
2303   {
2304     GNUNET_break (0);
2305     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2306     return;
2307   }
2308
2309   /* Do WE have the service? */
2310   type = ntohl (connect_msg->type);
2311   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  type requested: %u\n", type);
2312   GNUNET_CRYPTO_hash (&type, sizeof (GNUNET_MESH_ApplicationType), &hash);
2313   if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
2314       GNUNET_YES)
2315   {
2316     /* Yes! Fast forward, add ourselves to the tunnel and send the
2317      * good news to the client
2318      */
2319     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  available locally\n");
2320     GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey,
2321                                        peer_info_get (&my_full_id),
2322                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2323
2324     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  notifying client\n");
2325     send_client_peer_connected(t, myid);
2326     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  Done\n");
2327     GNUNET_SERVER_receive_done (client, GNUNET_OK);
2328     return;
2329   }
2330   /* Ok, lets find a peer offering the service */
2331   if (c->dht_get_type)
2332   {
2333     GNUNET_DHT_get_stop (c->dht_get_type);
2334   }
2335   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  looking in DHT for %s\n",
2336               GNUNET_h2s_full (&hash));
2337   c->dht_get_type =
2338       GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL,
2339                             GNUNET_BLOCK_TYPE_TEST, &hash, 10U,
2340                             GNUNET_DHT_RO_RECORD_ROUTE, NULL, 0, NULL, 0,
2341                             &dht_get_type_handler, t);
2342
2343   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2344   return;
2345 }
2346
2347
2348 /**
2349  * Handler for client traffic directed to one peer
2350  *
2351  * @param cls closure
2352  * @param client identification of the client
2353  * @param message the actual message
2354  */
2355 static void
2356 handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
2357                       const struct GNUNET_MessageHeader *message)
2358 {
2359   struct MeshClient *c;
2360   struct MeshTunnel *t;
2361   struct MeshPeerInfo *pi;
2362   struct GNUNET_MESH_Unicast *data_msg;
2363   struct MeshDataDescriptor *info;
2364   MESH_TunnelNumber tid;
2365   size_t data_size;
2366
2367   /* Sanity check for client registration */
2368   if (NULL == (c = client_get (client)))
2369   {
2370     GNUNET_break (0);
2371     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2372     return;
2373   }
2374   data_msg = (struct GNUNET_MESH_Unicast *) message;
2375   /* Sanity check for message size */
2376   if (sizeof (struct GNUNET_MESH_Unicast) +
2377       sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
2378   {
2379     GNUNET_break (0);
2380     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2381     return;
2382   }
2383
2384   /* Tunnel exists? */
2385   tid = ntohl (data_msg->tid);
2386   t = tunnel_get_by_local_id (c, tid);
2387   if (NULL == t)
2388   {
2389     GNUNET_break (0);
2390     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2391     return;
2392   }
2393
2394   /*  Is it a local tunnel? Then, does client own the tunnel? */
2395   if (t->client->handle != NULL && t->client->handle != client)
2396   {
2397     GNUNET_break (0);
2398     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2399     return;
2400   }
2401
2402   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
2403                                           &data_msg->destination.hashPubKey);
2404   /* Is the selected peer in the tunnel? */
2405   if (NULL == pi)
2406   {
2407     GNUNET_break (0);
2408     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2409     return;
2410   }
2411   if (pi->id == myid)
2412   {
2413     struct GNUNET_MESH_Unicast copy;
2414
2415     /* Work around const limitation */
2416     memcpy (&copy, data_msg, sizeof (struct GNUNET_MESH_Unicast));
2417     copy.oid = my_full_id;
2418     copy.tid = htonl (t->id.tid);
2419     handle_mesh_data_unicast (NULL, &my_full_id, &copy.header, NULL);
2420     return;
2421   }
2422   data_size = ntohs (message->size) - sizeof (struct GNUNET_MESH_Unicast);
2423   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + data_size);
2424   memcpy (&info[1], &data_msg[1], data_size);
2425   info->destination = pi->id;
2426   info->origin = &t->id;
2427   info->size = data_size;
2428   info->client = client;
2429   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2430                                      GNUNET_TIME_UNIT_FOREVER_REL,
2431                                      path_get_first_hop (t, pi),
2432                                      /* FIXME re-check types */
2433                                      data_size +
2434                                      sizeof (struct GNUNET_MESH_Unicast),
2435                                      &send_core_data_unicast, info);
2436   return;
2437 }
2438
2439 /**
2440  * Handler for client traffic directed to all peers in a tunnel
2441  *
2442  * @param cls closure
2443  * @param client identification of the client
2444  * @param message the actual message
2445  */
2446 static void
2447 handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
2448                         const struct GNUNET_MessageHeader *message)
2449 {
2450   struct MeshClient *c;
2451   struct MeshTunnel *t;
2452   struct GNUNET_MESH_Multicast *data_msg;
2453   MESH_TunnelNumber tid;
2454
2455   /* Sanity check for client registration */
2456   if (NULL == (c = client_get (client)))
2457   {
2458     GNUNET_break (0);
2459     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2460     return;
2461   }
2462   data_msg = (struct GNUNET_MESH_Multicast *) message;
2463   /* Sanity check for message size */
2464   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (data_msg->header.size))
2465   {
2466     GNUNET_break (0);
2467     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2468     return;
2469   }
2470
2471   /* Tunnel exists? */
2472   tid = ntohl (data_msg->tid);
2473   t = tunnel_get_by_local_id (c, tid);
2474   if (NULL == t)
2475   {
2476     GNUNET_break (0);
2477     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2478     return;
2479   }
2480
2481   /* Does client own tunnel? */
2482   if (t->client->handle != client)
2483   {
2484     GNUNET_break (0);
2485     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2486     return;
2487   }
2488
2489   /*  TODO */
2490
2491   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2492   return;
2493 }
2494
2495 /**
2496  * Functions to handle messages from clients
2497  */
2498 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
2499   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2500   {&handle_local_tunnel_create, NULL,
2501    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2502    sizeof (struct GNUNET_MESH_TunnelMessage)},
2503   {&handle_local_tunnel_destroy, NULL,
2504    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2505    sizeof (struct GNUNET_MESH_TunnelMessage)},
2506   {&handle_local_connect_add, NULL,
2507    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
2508    sizeof (struct GNUNET_MESH_PeerControl)},
2509   {&handle_local_connect_del, NULL,
2510    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
2511    sizeof (struct GNUNET_MESH_PeerControl)},
2512   {&handle_local_connect_by_type, NULL,
2513    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
2514    sizeof (struct GNUNET_MESH_ConnectPeerByType)},
2515   {&handle_local_unicast, NULL,
2516    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2517   {&handle_local_unicast, NULL,
2518    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2519   {&handle_local_multicast, NULL,
2520    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
2521   {NULL, NULL, 0, 0}
2522 };
2523
2524
2525 /**
2526  * To be called on core init/fail.
2527  *
2528  * @param cls service closure
2529  * @param server handle to the server for this service
2530  * @param identity the public identity of this peer
2531  * @param publicKey the public key of this peer
2532  */
2533 static void
2534 core_init (void *cls, struct GNUNET_CORE_Handle *server,
2535            const struct GNUNET_PeerIdentity *identity,
2536            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
2537 {
2538   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Core init\n");
2539   core_handle = server;
2540   if (0 != memcmp(identity, &my_full_id, sizeof(my_full_id)) || NULL == server)
2541   {
2542     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, _("MESH: Wrong CORE service\n"));
2543     GNUNET_SCHEDULER_shutdown();   
2544   }
2545   return;
2546 }
2547
2548 /**
2549  * Method called whenever a given peer connects.
2550  *
2551  * @param cls closure
2552  * @param peer peer identity this notification is about
2553  * @param atsi performance data for the connection
2554  */
2555 static void
2556 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
2557               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2558 {
2559 //     GNUNET_PEER_Id              pid;
2560   struct MeshPeerInfo *peer_info;
2561   struct MeshPeerPath *path;
2562
2563   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n");
2564   peer_info = peer_info_get (peer);
2565   if (myid == peer_info->id)
2566   {
2567     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
2568     return;
2569   }
2570   path = GNUNET_malloc (sizeof (struct MeshPeerPath));
2571   path->length = 2;
2572   path->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id) * 2);
2573   path->peers[0] = myid;
2574   path->peers[1] = peer_info->id;
2575   path_add_to_peer (peer_info, path);
2576   return;
2577 }
2578
2579 /**
2580  * Method called whenever a peer disconnects.
2581  *
2582  * @param cls closure
2583  * @param peer peer identity this notification is about
2584  */
2585 static void
2586 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
2587 {
2588   struct MeshPeerInfo *pi;
2589   unsigned int i;
2590
2591   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer disconnected\n");
2592   pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
2593   if (!pi)
2594   {
2595     GNUNET_break (0);
2596     return;
2597   }
2598   for (i = 0; i < CORE_QUEUE_SIZE; i++)
2599   {
2600     if (pi->core_transmit[i])
2601     {
2602       GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit[i]);
2603       /* TODO: notify that tranmission has failed */
2604       GNUNET_free (pi->infos[i]);
2605     }
2606   }
2607   path_remove_from_peer (pi, pi->id, myid);
2608   if (myid == pi->id)
2609   {
2610     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
2611   }
2612   return;
2613 }
2614
2615
2616 /******************************************************************************/
2617 /************************      MAIN FUNCTIONS      ****************************/
2618 /******************************************************************************/
2619
2620 /**
2621  * Task run during shutdown.
2622  *
2623  * @param cls unused
2624  * @param tc unused
2625  */
2626 static void
2627 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2628 {
2629   struct MeshClient *c;
2630
2631   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shutting down\n");
2632   if (core_handle != NULL)
2633   {
2634     GNUNET_CORE_disconnect (core_handle);
2635     core_handle = NULL;
2636   }
2637   if (dht_handle != NULL)
2638   {
2639     for (c = clients; NULL != c; c = c->next)
2640       if (NULL != c->dht_get_type)
2641         GNUNET_DHT_get_stop (c->dht_get_type);
2642     GNUNET_DHT_disconnect (dht_handle);
2643     dht_handle = NULL;
2644   }
2645   if (nc != NULL)
2646   {
2647     GNUNET_SERVER_notification_context_destroy (nc);
2648     nc = NULL;
2649   }
2650   if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
2651   {
2652     GNUNET_SCHEDULER_cancel (announce_id_task);
2653     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
2654   }
2655   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shut down\n");
2656 }
2657
2658 /**
2659  * Process mesh requests.
2660  *
2661  * @param cls closure
2662  * @param server the initialized server
2663  * @param c configuration to use
2664  */
2665 static void
2666 run (void *cls, struct GNUNET_SERVER_Handle *server,
2667      const struct GNUNET_CONFIGURATION_Handle *c)
2668 {
2669   struct MeshPeerInfo *peer;
2670   struct MeshPeerPath *p;
2671   char *keyfile;
2672
2673   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: starting to run\n");
2674   server_handle = server;
2675   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
2676                                      CORE_QUEUE_SIZE,   /* queue size */
2677                                      NULL,      /* Closure passed to MESH functions */
2678                                      &core_init,        /* Call core_init once connected */
2679                                      &core_connect,     /* Handle connects */
2680                                      &core_disconnect,  /* remove peers on disconnects */
2681                                      NULL,      /* Do we care about "status" updates? */
2682                                      NULL,      /* Don't notify about all incoming messages */
2683                                      GNUNET_NO, /* For header only in notification */
2684                                      NULL,      /* Don't notify about all outbound messages */
2685                                      GNUNET_NO, /* For header-only out notification */
2686                                      core_handlers);    /* Register these handlers */
2687   if (core_handle == NULL)
2688   {
2689     GNUNET_break (0);
2690     GNUNET_SCHEDULER_shutdown ();
2691     return;
2692   }
2693
2694   if (GNUNET_OK !=
2695        GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
2696                                                 &keyfile))
2697   {
2698     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2699                 _
2700                 ("Mesh service is lacking key configuration settings.  Exiting.\n"));
2701     GNUNET_SCHEDULER_shutdown ();
2702     return;
2703   }
2704   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
2705   GNUNET_free (keyfile);
2706   if (my_private_key == NULL)
2707   {
2708     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
2709                 _("Mesh service could not access hostkey.  Exiting.\n"));
2710     GNUNET_SCHEDULER_shutdown ();
2711     return;
2712   }
2713   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
2714   GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
2715                       &my_full_id.hashPubKey);
2716   myid = GNUNET_PEER_intern (&my_full_id);
2717
2718   dht_handle = GNUNET_DHT_connect (c, 64);
2719   if (dht_handle == NULL)
2720   {
2721     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error connecting to DHT.\
2722                    Running without DHT has a severe\
2723                    impact in MESH capabilities.\n\
2724                    Plase check your configuretion and enable DHT.\n");
2725     GNUNET_break (0);
2726   }
2727
2728   next_tid = 0;
2729
2730   tunnels = GNUNET_CONTAINER_multihashmap_create (32);
2731   peers = GNUNET_CONTAINER_multihashmap_create (32);
2732   applications = GNUNET_CONTAINER_multihashmap_create (32);
2733   types = GNUNET_CONTAINER_multihashmap_create (32);
2734
2735   GNUNET_SERVER_add_handlers (server_handle, client_handlers);
2736   nc = GNUNET_SERVER_notification_context_create (server_handle,
2737                                                   LOCAL_QUEUE_SIZE);
2738   GNUNET_SERVER_disconnect_notify (server_handle,
2739                                    &handle_local_client_disconnect,
2740                                    NULL);
2741
2742
2743   clients = NULL;
2744   clients_tail = NULL;
2745 #if MESH_DEBUG
2746   next_client_id = 0;
2747 #endif
2748
2749   announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
2750   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
2751
2752   /* Create a peer_info for the local peer */
2753   peer = peer_info_get(&my_full_id);
2754   p = GNUNET_malloc (sizeof (struct MeshPeerPath));
2755   p->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id));
2756   p->length = 1;
2757   p->peers[0] = myid;
2758   path_add_to_peer(peer, p);
2759
2760   /* Scheduled the task to clean up when shutdown is called */
2761   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
2762                                 NULL);
2763
2764   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: end of run()\n");
2765 }
2766
2767 /**
2768  * The main function for the mesh service.
2769  *
2770  * @param argc number of arguments from the command line
2771  * @param argv command line arguments
2772  * @return 0 ok, 1 on error
2773  */
2774 int
2775 main (int argc, char *const *argv)
2776 {
2777   int ret;
2778
2779 #if MESH_DEBUG
2780   fprintf (stderr, "main ()\n");
2781 #endif
2782   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main()\n");
2783   ret =
2784       (GNUNET_OK ==
2785        GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
2786                            NULL)) ? 0 : 1;
2787   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main() END\n");
2788 #if MESH_DEBUG
2789   fprintf (stderr, "main () END\n");
2790 #endif
2791   return ret;
2792 }