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