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