Added timeout & notification code
[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,
1298               "MESH: Received a MESH path create msg\n");
1299   size = ntohs (message->size);
1300   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
1301   {
1302     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1303                 "received create path message too short\n");
1304     return GNUNET_OK;
1305   }
1306
1307   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
1308   if (size < 2 * sizeof (struct GNUNET_PeerIdentity))
1309   {
1310     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1311                 "create path message lacks enough peers\n");
1312     return GNUNET_OK;
1313   }
1314   if (size % sizeof (struct GNUNET_PeerIdentity))
1315   {
1316     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1317                 "create path message of wrong size\n");
1318     return GNUNET_OK;
1319   }
1320   msg = (struct GNUNET_MESH_ManipulatePath *) message;
1321   size /= sizeof (struct GNUNET_PeerIdentity);
1322
1323   tid = ntohl (msg->tid);
1324   pi = (struct GNUNET_PeerIdentity *) &msg[1];
1325   t = retrieve_tunnel (pi, tid);
1326
1327   if (NULL == t)
1328   {
1329     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Creating tunnel\n");
1330     t = GNUNET_malloc (sizeof (struct MeshTunnel));
1331     t->id.oid = GNUNET_PEER_intern (pi);
1332     t->id.tid = tid;
1333     t->peers = GNUNET_CONTAINER_multihashmap_create (32);
1334
1335     GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
1336     if (GNUNET_OK !=
1337         GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
1338                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1339     {
1340       GNUNET_break (0);
1341       return GNUNET_OK;
1342     }
1343
1344   }
1345   dest_peer_info =
1346       GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
1347   if (NULL == dest_peer_info)
1348   {
1349     dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1350     dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
1351     dest_peer_info->state = MESH_PEER_WAITING;
1352     GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
1353                                        dest_peer_info,
1354                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1355   }
1356   orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
1357   if (NULL == orig_peer_info)
1358   {
1359     orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1360     orig_peer_info->id = GNUNET_PEER_intern (pi);
1361     orig_peer_info->state = MESH_PEER_WAITING;
1362     GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
1363                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1364   }
1365
1366
1367   path = GNUNET_malloc (sizeof (struct MeshPath));
1368   path->length = size;
1369   path->peers = GNUNET_malloc (size * sizeof (GNUNET_PEER_Id));
1370   own_pos = 0;
1371   for (i = 0; i < size; i++)
1372   {
1373     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
1374     if (path->peers[i] == myid)
1375       own_pos = i;
1376   }
1377   if (own_pos == 0)
1378   {                             /* cannot be self, must be 'not found' */
1379     /* create path: self not found in path through self */
1380     GNUNET_break_op (0);
1381     destroy_path (path);
1382     /* FIXME error. destroy tunnel? leave for timeout? */
1383     return 0;
1384   }
1385   if (own_pos == size - 1)
1386   {                             /* it is for us! */
1387     struct MeshDataDescriptor *info;
1388     unsigned int j;
1389
1390     add_path_to_origin (orig_peer_info, path);  /* inverts path!  */
1391     GNUNET_PEER_resolve (get_first_hop (path), &id);    /* path is inverted :) */
1392     info = GNUNET_malloc (sizeof (struct MeshDataDescriptor));
1393     info->origin = &t->id;
1394     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
1395     GNUNET_assert (info->peer);
1396     for (j = 0; info->peer->core_transmit[j]; j++)
1397     {
1398       if (j == 9)
1399       {
1400         GNUNET_break (0);
1401         return GNUNET_OK;
1402       }
1403     }
1404     info->handler_n = j;
1405     info->peer->core_transmit[j] =
1406         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
1407                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
1408                                            sizeof (struct GNUNET_MessageHeader),
1409                                            &send_core_path_ack, info);
1410   }
1411   else
1412   {
1413     add_path_to_peer (dest_peer_info, path);
1414     GNUNET_PEER_resolve (get_first_hop (path), &id);
1415     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1416                                        GNUNET_TIME_UNIT_FOREVER_REL, &id,
1417                                        sizeof (struct GNUNET_MessageHeader),
1418                                        &send_core_create_path_for_peer,
1419                                        dest_peer_info);
1420   }
1421   return GNUNET_OK;
1422 }
1423
1424
1425 /**
1426  * Core handler for mesh network traffic going from the origin to a peer
1427  *
1428  * @param cls closure
1429  * @param message message
1430  * @param peer peer identity this notification is about
1431  * @param atsi performance data
1432  * @return GNUNET_OK to keep the connection open,
1433  *         GNUNET_SYSERR to close it (signal serious error)
1434  */
1435 static int
1436 handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
1437                           const struct GNUNET_MessageHeader *message,
1438                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1439 {
1440   struct GNUNET_MESH_Unicast *msg;
1441   struct GNUNET_PeerIdentity id;
1442   struct MeshTunnel *t;
1443   struct MeshPeerInfo *pi;
1444   size_t size;
1445
1446   size = ntohs (message->size);
1447   if (size <
1448       sizeof (struct GNUNET_MESH_Unicast) +
1449       sizeof (struct GNUNET_MessageHeader))
1450   {
1451     GNUNET_break (0);
1452     return GNUNET_OK;
1453   }
1454   msg = (struct GNUNET_MESH_Unicast *) message;
1455   t = retrieve_tunnel (&msg->oid, ntohl (msg->tid));
1456   if (NULL == t)
1457   {
1458     /* TODO notify back: we don't know this tunnel */
1459     return GNUNET_OK;
1460   }
1461   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
1462                                           &msg->destination.hashPubKey);
1463   if (NULL == pi)
1464   {
1465     /* TODO maybe feedback, log to statistics */
1466     return GNUNET_OK;
1467   }
1468   if (pi->id == myid)
1469   {
1470     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
1471     return GNUNET_OK;
1472   }
1473   GNUNET_PEER_resolve (get_first_hop (pi->path), &id);
1474   msg = GNUNET_malloc (size);
1475   memcpy (msg, message, size);
1476   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1477                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
1478                                      &send_core_data_raw, msg);
1479   return GNUNET_OK;
1480 }
1481
1482
1483 /**
1484  * Core handler for mesh network traffic going from the origin to all peers
1485  *
1486  * @param cls closure
1487  * @param message message
1488  * @param peer peer identity this notification is about
1489  * @param atsi performance data
1490  * @return GNUNET_OK to keep the connection open,
1491  *         GNUNET_SYSERR to close it (signal serious error)
1492  */
1493 static int
1494 handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
1495                             const struct GNUNET_MessageHeader *message,
1496                             const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1497 {
1498   struct GNUNET_MESH_Multicast *msg;
1499   struct GNUNET_PeerIdentity id;
1500   struct MeshTunnel *t;
1501   struct MeshDataDescriptor *info;
1502   GNUNET_PEER_Id *neighbors;
1503   size_t size;
1504   uint16_t i;
1505   uint16_t j;
1506
1507
1508   size = ntohs (message->size);
1509   if (size <
1510       sizeof (struct GNUNET_MESH_Multicast) +
1511       sizeof (struct GNUNET_MessageHeader))
1512   {
1513     GNUNET_break_op (0);
1514     return GNUNET_OK;
1515   }
1516   msg = (struct GNUNET_MESH_Multicast *) message;
1517   t = retrieve_tunnel (&msg->oid, ntohl (msg->tid));
1518
1519   if (NULL == t)
1520   {
1521     /* TODO notify that we dont know that tunnel */
1522     return GNUNET_OK;
1523   }
1524
1525   /* Transmit to locally interested clients */
1526   GNUNET_PEER_resolve (myid, &id);
1527   if (GNUNET_CONTAINER_multihashmap_contains (t->peers, &id.hashPubKey))
1528   {
1529     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
1530   }
1531
1532   /* Retransmit to other peers */
1533   neighbors = GNUNET_malloc (sizeof (GNUNET_PEER_Id));
1534   neighbors[0] = 0;
1535   GNUNET_CONTAINER_multihashmap_iterate (t->peers, &iterate_collect_neighbors,
1536                                          &neighbors);
1537   if (!neighbors[0])
1538   {
1539     return GNUNET_OK;
1540   }
1541   size -= sizeof (struct GNUNET_MESH_Multicast);
1542   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + size);
1543   info->origin = &t->id;
1544   info->copies = 0;
1545   for (i = 0; 0 != neighbors[i]; i++)
1546   {
1547     GNUNET_PEER_resolve (neighbors[i], &id);
1548     info->copies++;
1549     info->destination = neighbors[i];
1550     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
1551     GNUNET_assert (info->peer);
1552     for (j = 0; info->peer->core_transmit[j]; j++)
1553     {
1554       if (j == 9)
1555       {
1556         GNUNET_break (0);
1557         return GNUNET_OK;
1558       }
1559     }
1560     info->handler_n = j;
1561     info->peer->infos[j] = info;
1562     info->peer->core_transmit[j] =
1563         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1564                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
1565                                            ntohs (msg->header.size),
1566                                            &send_core_data_multicast, info);
1567   }
1568   return GNUNET_OK;
1569 }
1570
1571
1572 /**
1573  * Core handler for mesh network traffic
1574  *
1575  * @param cls closure
1576  * @param message message
1577  * @param peer peer identity this notification is about
1578  * @param atsi performance data
1579  * @return GNUNET_OK to keep the connection open,
1580  *         GNUNET_SYSERR to close it (signal serious error)
1581  */
1582 static int
1583 handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
1584                           const struct GNUNET_MessageHeader *message,
1585                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1586 {
1587   struct GNUNET_MESH_ToOrigin *msg;
1588   struct GNUNET_PeerIdentity id;
1589   struct MeshTunnel *t;
1590   struct MeshPeerInfo *peer_info;
1591   size_t size;
1592
1593   size = ntohs (message->size);
1594   if (size <
1595       sizeof (struct GNUNET_MESH_ToOrigin) +
1596       sizeof (struct GNUNET_MessageHeader))
1597   {
1598     GNUNET_break_op (0);
1599     return GNUNET_OK;
1600   }
1601   msg = (struct GNUNET_MESH_ToOrigin *) message;
1602   t = retrieve_tunnel (&msg->oid, ntohl (msg->tid));
1603
1604   if (NULL == t)
1605   {
1606     /* TODO notify that we dont know this tunnel (whom)? */
1607     return GNUNET_OK;
1608   }
1609
1610   if (t->id.oid == myid)
1611   {
1612     if (NULL == t->client)
1613     {
1614       /* got data packet for ownerless tunnel */
1615       GNUNET_break_op (0);
1616       return GNUNET_OK;
1617     }
1618     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, message,
1619                                                 GNUNET_YES);
1620     return GNUNET_OK;
1621   }
1622   peer_info = get_peer_info (&msg->oid);
1623   if (NULL == peer_info)
1624   {
1625     /* unknown origin of tunnel */
1626     GNUNET_break (0);
1627     return GNUNET_OK;
1628   }
1629   GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id);
1630   msg = GNUNET_malloc (size);
1631   memcpy (msg, message, size);
1632   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1633                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
1634                                      &send_core_data_raw, msg);
1635
1636   return GNUNET_OK;
1637 }
1638
1639
1640 /**
1641  * Core handler for path ACKs
1642  *
1643  * @param cls closure
1644  * @param message message
1645  * @param peer peer identity this notification is about
1646  * @param atsi performance data
1647  * @return GNUNET_OK to keep the connection open,
1648  *         GNUNET_SYSERR to close it (signal serious error)
1649  */
1650 static int
1651 handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1652                       const struct GNUNET_MessageHeader *message,
1653                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1654 {
1655   struct GNUNET_MESH_PathACK *msg;
1656   struct GNUNET_PeerIdentity id;
1657   struct MeshTunnel *t;
1658   struct MeshPeerInfo *peer_info;
1659
1660   msg = (struct GNUNET_MESH_PathACK *) message;
1661   t = retrieve_tunnel (&msg->oid, msg->tid);
1662   if (NULL == t)
1663   {
1664     /* TODO notify that we don't know the tunnel */
1665     return GNUNET_OK;
1666   }
1667
1668   /* Message for us? */
1669   if (GNUNET_PEER_search (&msg->oid) == myid)
1670   {
1671     struct GNUNET_MESH_PeerControl pc;
1672
1673     if (NULL == t->client)
1674     {
1675       GNUNET_break (0);
1676       return GNUNET_OK;
1677     }
1678     peer_info = get_peer_info (&msg->peer_id);
1679     if (NULL == peer_info)
1680     {
1681       GNUNET_break_op (0);
1682       return GNUNET_OK;
1683     }
1684     peer_info->state = MESH_PEER_READY;
1685     pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED);
1686     pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1687     pc.tunnel_id = htonl (t->local_tid);
1688     GNUNET_PEER_resolve (peer_info->id, &pc.peer);
1689     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
1690                                                 &pc.header, GNUNET_NO);
1691     return GNUNET_OK;
1692   }
1693
1694   peer_info = get_peer_info (&msg->oid);
1695   if (NULL == peer_info)
1696   {
1697     /* If we know the tunnel, we should DEFINITELY know the peer */
1698     GNUNET_break (0);
1699     return GNUNET_OK;
1700   }
1701   GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id);
1702   msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PathACK));
1703   memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK));
1704   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1705                                      GNUNET_TIME_UNIT_FOREVER_REL, &id,
1706                                      sizeof (struct GNUNET_MESH_PathACK),
1707                                      &send_core_data_raw, msg);
1708   return GNUNET_OK;
1709 }
1710
1711
1712 /**
1713  * Functions to handle messages from core
1714  */
1715 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1716   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1717   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
1718   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
1719   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
1720   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
1721    sizeof (struct GNUNET_MESH_PathACK)},
1722   {NULL, 0, 0}
1723 };
1724
1725
1726
1727 /******************************************************************************/
1728 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
1729 /******************************************************************************/
1730
1731 /**
1732  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
1733  * client when the client disconnects.
1734  * @param cls closure (client that is disconnecting)
1735  * @param key the hash of the local tunnel id (used to access the hashmap)
1736  * @param value the value stored at the key (tunnel to destroy)
1737  * @return GNUNET_OK on success
1738  */
1739 static int
1740 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value)
1741 {
1742   int r;
1743
1744   r = destroy_tunnel ((struct MeshTunnel *) value);
1745   return r;
1746 }
1747
1748 #if LATER
1749 /**
1750  * notify_client_connection_failure: notify a client that the connection to the
1751  * requested remote peer is not possible (for instance, no route found)
1752  * Function called when the socket is ready to queue more data. "buf" will be
1753  * NULL and "size" zero if the socket was closed for writing in the meantime.
1754  *
1755  * @param cls closure
1756  * @param size number of bytes available in buf
1757  * @param buf where the callee should write the message
1758  * @return number of bytes written to buf
1759  */
1760 static size_t
1761 notify_client_connection_failure (void *cls, size_t size, void *buf)
1762 {
1763   int size_needed;
1764   struct MeshPeerInfo *peer_info;
1765   struct GNUNET_MESH_PeerControl *msg;
1766   struct GNUNET_PeerIdentity id;
1767
1768   if (0 == size && NULL == buf)
1769   {
1770     // TODO retry? cancel?
1771     return 0;
1772   }
1773
1774   size_needed = sizeof (struct GNUNET_MESH_PeerControl);
1775   peer_info = (struct MeshPeerInfo *) cls;
1776   msg = (struct GNUNET_MESH_PeerControl *) buf;
1777   msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
1778   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1779 //     msg->tunnel_id = htonl(peer_info->t->tid);
1780   GNUNET_PEER_resolve (peer_info->id, &id);
1781   memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
1782
1783   return size_needed;
1784 }
1785 #endif
1786
1787
1788 /**
1789  * Send keepalive packets for a peer
1790  *
1791  * @param cls unused
1792  * @param tc unused
1793  */
1794 static void
1795 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1796 {
1797   struct MeshPeerInfo *peer_info = cls;
1798   struct GNUNET_PeerIdentity id;
1799
1800   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1801     return;
1802   GNUNET_PEER_resolve (get_first_hop (peer_info->path), &id);
1803   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1804                                      GNUNET_TIME_UNIT_FOREVER_REL, &id,
1805                                      sizeof (struct GNUNET_MESH_ManipulatePath)
1806                                      +
1807                                      (peer_info->path->length *
1808                                       sizeof (struct GNUNET_PeerIdentity)),
1809                                      &send_core_create_path_for_peer,
1810                                      peer_info);
1811   peer_info->path_refresh_task =
1812       GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh,
1813                                     peer_info);
1814   return;
1815 }
1816
1817
1818 /**
1819  * Function to process paths received for a new peer addition. The recorded
1820  * paths form the initial tunnel, which can be optimized later.
1821  * Called on each result obtained for the DHT search.
1822  *
1823  * @param cls closure
1824  * @param exp when will this value expire
1825  * @param key key of the result
1826  * @param get_path NULL-terminated array of pointers
1827  *                 to the peers on reverse GET path (or NULL if not recorded)
1828  * @param put_path NULL-terminated array of pointers
1829  *                 to the peers on the PUT path (or NULL if not recorded)
1830  * @param type type of the result
1831  * @param size number of bytes in data
1832  * @param data pointer to the result data
1833  */
1834 static void
1835 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
1836                     const GNUNET_HashCode * key,
1837                     const struct GNUNET_PeerIdentity *const *get_path,
1838                     const struct GNUNET_PeerIdentity *const *put_path,
1839                     enum GNUNET_BLOCK_Type type, size_t size, const void *data)
1840 {
1841   struct MeshPeerInfo *peer_info = cls;
1842   struct MeshPath *p;
1843   struct GNUNET_PeerIdentity pi;
1844   int i;
1845
1846   if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path)
1847   {
1848     // Find ourselves some alternate initial path to the destination: retry
1849     GNUNET_DHT_get_stop (peer_info->dhtget);
1850     GNUNET_PEER_resolve (peer_info->id, &pi);
1851     peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_ANY, &pi.hashPubKey, 4,       /* replication level */
1852                                               GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
1853                                               0,        /* mutator */
1854                                               NULL,     /* xquery */
1855                                               0,        /* xquery bits */
1856                                               dht_get_id_handler,
1857                                               (void *) peer_info);
1858   }
1859
1860   p = GNUNET_malloc (sizeof (struct MeshPath));
1861   for (i = 0; get_path[i] != NULL; i++) ;
1862   for (i--; i >= 0; i--)
1863   {
1864     p->peers =
1865         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
1866     p->peers[p->length] = GNUNET_PEER_intern (get_path[i]);
1867     p->length++;
1868   }
1869   for (i = 0; put_path[i] != NULL; i++) ;
1870   for (i--; i >= 0; i--)
1871   {
1872     p->peers =
1873         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
1874     p->peers[p->length] = GNUNET_PEER_intern (put_path[i]);
1875     p->length++;
1876   }
1877   add_path_to_peer (peer_info, p);
1878   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1879                                      GNUNET_TIME_UNIT_FOREVER_REL, get_path[1],
1880                                      sizeof (struct GNUNET_MESH_ManipulatePath)
1881                                      +
1882                                      (p->length *
1883                                       sizeof (struct GNUNET_PeerIdentity)),
1884                                      &send_core_create_path_for_peer,
1885                                      peer_info);
1886   if (0 == peer_info->path_refresh_task)
1887   {
1888     peer_info->path_refresh_task =
1889         GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh,
1890                                       peer_info);
1891   }
1892   return;
1893 }
1894
1895
1896 /**
1897  * Function to process paths received for a new peer addition. The recorded
1898  * paths form the initial tunnel, which can be optimized later.
1899  * Called on each result obtained for the DHT search.
1900  *
1901  * @param cls closure
1902  * @param exp when will this value expire
1903  * @param key key of the result
1904  * @param get_path NULL-terminated array of pointers
1905  *                 to the peers on reverse GET path (or NULL if not recorded)
1906  * @param put_path NULL-terminated array of pointers
1907  *                 to the peers on the PUT path (or NULL if not recorded)
1908  * @param type type of the result
1909  * @param size number of bytes in data
1910  * @param data pointer to the result data
1911  */
1912 static void
1913 dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
1914                       const GNUNET_HashCode * key,
1915                       const struct GNUNET_PeerIdentity *const *get_path,
1916                       const struct GNUNET_PeerIdentity *const *put_path,
1917                       enum GNUNET_BLOCK_Type type, size_t size,
1918                       const void *data)
1919 {
1920   const struct GNUNET_PeerIdentity *pi = data;
1921   struct MeshTunnel *t = cls;
1922   struct MeshPeerInfo *peer_info;
1923   struct MeshPath *p;
1924   int i;
1925
1926
1927   if (size != sizeof (struct GNUNET_PeerIdentity))
1928   {
1929     GNUNET_break_op (0);
1930     return;
1931   }
1932   peer_info = get_peer_info (pi);
1933   GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, peer_info,
1934                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1935   if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path)
1936   {
1937     /* we don't have a route to the peer, let's try a direct lookup */
1938     if (NULL == peer_info->dhtget)
1939     {
1940       peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_ANY, &pi->hashPubKey, 10U,  /* replication level */
1941                                                 GNUNET_DHT_RO_RECORD_ROUTE, NULL,       /* bloom filter */
1942                                                 0,      /* mutator */
1943                                                 NULL,   /* xquery */
1944                                                 0,      /* xquery bits */
1945                                                 dht_get_id_handler, peer_info);
1946     }
1947   }
1948   /* TODO refactor */
1949   p = GNUNET_malloc (sizeof (struct MeshPath));
1950   for (i = 0; get_path[i] != NULL; i++) ;
1951   for (i--; i >= 0; i--)
1952   {
1953     p->peers =
1954         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
1955     p->peers[p->length] = GNUNET_PEER_intern (get_path[i]);
1956     p->length++;
1957   }
1958   for (i = 0; put_path[i] != NULL; i++) ;
1959   for (i--; i >= 0; i--)
1960   {
1961     p->peers =
1962         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
1963     p->peers[p->length] = GNUNET_PEER_intern (put_path[i]);
1964     p->length++;
1965   }
1966   add_path_to_peer (peer_info, p);
1967   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1968                                      GNUNET_TIME_UNIT_FOREVER_REL, get_path[1],
1969                                      sizeof (struct GNUNET_MESH_ManipulatePath)
1970                                      +
1971                                      (p->length *
1972                                       sizeof (struct GNUNET_PeerIdentity)),
1973                                      &send_core_create_path_for_peer,
1974                                      peer_info);
1975
1976 }
1977
1978 /******************************************************************************/
1979 /*********************       MESH LOCAL HANDLES      **************************/
1980 /******************************************************************************/
1981
1982
1983 /**
1984  * Handler for client disconnection
1985  *
1986  * @param cls closure
1987  * @param client identification of the client; NULL
1988  *        for the last call when the server is destroyed
1989  */
1990 static void
1991 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1992 {
1993   struct MeshClient *c;
1994   struct MeshClient *next;
1995   unsigned int i;
1996   unsigned int j;
1997
1998   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n");
1999   c = clients;
2000   while (NULL != c)
2001   {
2002     if (c->handle == client)
2003     {
2004       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2005                   " matching client found, cleaning\n");
2006       GNUNET_CONTAINER_multihashmap_iterate (c->tunnels, &delete_tunnel_entry,
2007                                              c);
2008       GNUNET_CONTAINER_multihashmap_destroy (c->tunnels);
2009       if (0 != c->app_counter)
2010       {                         /* deregister clients applications */
2011         for (i = 0; i < c->app_counter; i++)
2012         {
2013           for (j = 0; j < n_applications; j++)
2014           {
2015             if (c->apps[i] == applications[j])
2016             {
2017               if (0 == --applications_rc[j])
2018               {
2019                 applications[j] = applications[n_applications - 1];
2020                 applications_rc[j] = applications_rc[n_applications - 1];
2021                 n_applications--;
2022                 applications =
2023                     GNUNET_realloc (applications,
2024                                     n_applications *
2025                                     sizeof (GNUNET_MESH_ApplicationType));
2026                 applications_rc =
2027                     GNUNET_realloc (applications_rc,
2028                                     n_applications * sizeof (unsigned int));
2029               }
2030               break;
2031             }
2032           }
2033         }
2034         GNUNET_free (c->apps);
2035         if (0 == n_applications)
2036         {
2037           GNUNET_SCHEDULER_cancel (announce_applications_task);
2038         }
2039       }
2040       if (0 != c->type_counter)
2041         GNUNET_free (c->types);
2042       GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
2043       next = c->next;
2044       GNUNET_free (c);
2045       c = next;
2046     }
2047     else
2048     {
2049       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    ... searching\n");
2050       c = c->next;
2051     }
2052   }
2053
2054   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    done!\n");
2055   return;
2056 }
2057
2058
2059 /**
2060  * Handler for new clients
2061  *
2062  * @param cls closure
2063  * @param client identification of the client
2064  * @param message the actual message, which includes messages the client wants
2065  */
2066 static void
2067 handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
2068                          const struct GNUNET_MessageHeader *message)
2069 {
2070   struct GNUNET_MESH_ClientConnect *cc_msg;
2071   struct MeshClient *c;
2072   unsigned int size;
2073   uint16_t types;
2074   uint16_t apps;
2075   uint16_t i;
2076   uint16_t j;
2077   int known;
2078
2079   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n");
2080   /* Check data sanity */
2081   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
2082   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
2083   types = ntohs (cc_msg->types);
2084   apps = ntohs (cc_msg->applications);
2085   if (size !=
2086       types * sizeof (uint16_t) + apps * sizeof (GNUNET_MESH_ApplicationType))
2087   {
2088     GNUNET_break (0);
2089     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2090     return;
2091   }
2092
2093   /* Create new client structure */
2094   c = GNUNET_malloc (sizeof (struct MeshClient));
2095   c->handle = client;
2096   if (types != 0)
2097   {
2098     c->type_counter = types;
2099     c->types = GNUNET_malloc (types * sizeof (uint16_t));
2100     memcpy (c->types, &message[1], types * sizeof (uint16_t));
2101   }
2102   if (apps != 0)
2103   {
2104     c->app_counter = apps;
2105     c->apps = GNUNET_malloc (apps * sizeof (GNUNET_MESH_ApplicationType));
2106     memcpy (c->apps, &message[1] + types * sizeof (uint16_t),
2107             apps * sizeof (GNUNET_MESH_ApplicationType));
2108   }
2109   for (i = 0; i < apps; i++)
2110   {
2111     known = GNUNET_NO;
2112     for (j = 0; i < n_applications; j++)
2113     {
2114       if (c->apps[i] == applications[j])
2115       {
2116         known = GNUNET_YES;
2117         applications_rc[j]++;
2118         break;
2119       }
2120     }
2121     if (!known)
2122     {                           /* Register previously unknown application */
2123       n_applications++;
2124       applications =
2125           GNUNET_realloc (applications,
2126                           n_applications *
2127                           sizeof (GNUNET_MESH_ApplicationType));
2128       applications_rc =
2129           GNUNET_realloc (applications_rc,
2130                           n_applications * sizeof (unsigned int));
2131       applications[n_applications - 1] = c->apps[i];
2132       applications_rc[n_applications - 1] = 1;
2133       if (0 == announce_applications_task)
2134       {
2135         announce_applications_task =
2136             GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME,
2137                                           &announce_applications, NULL);
2138       }
2139     }
2140   }
2141   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2142               "MESH:  client has %u+%u subscriptions\n", c->type_counter,
2143               c->app_counter);
2144
2145   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
2146   c->tunnels = GNUNET_CONTAINER_multihashmap_create (32);
2147   GNUNET_SERVER_notification_context_add (nc, client);
2148
2149   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2150
2151 }
2152
2153
2154 /**
2155  * Handler for requests of new tunnels
2156  *
2157  * @param cls closure
2158  * @param client identification of the client
2159  * @param message the actual message
2160  */
2161 static void
2162 handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
2163                             const struct GNUNET_MessageHeader *message)
2164 {
2165   struct GNUNET_MESH_TunnelMessage *t_msg;
2166   struct MeshTunnel *t;
2167   struct MeshClient *c;
2168   GNUNET_HashCode hash;
2169
2170   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n");
2171
2172   /* Sanity check for client registration */
2173   if (NULL == (c = retrieve_client (client)))
2174   {
2175     GNUNET_break (0);
2176     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2177     return;
2178   }
2179
2180   /* Message sanity check */
2181   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2182   {
2183     GNUNET_break (0);
2184     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2185     return;
2186   }
2187
2188   t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2189   /* Sanity check for tunnel numbering */
2190   if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK))
2191   {
2192     GNUNET_break (0);
2193     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2194     return;
2195   }
2196   /* Sanity check for duplicate tunnel IDs */
2197   if (NULL != retrieve_tunnel_by_local_id (c, ntohl (t_msg->tunnel_id)))
2198   {
2199     GNUNET_break (0);
2200     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2201     return;
2202   }
2203
2204   t = GNUNET_malloc (sizeof (struct MeshTunnel));
2205   while (NULL != retrieve_tunnel_by_pi (myid, next_tid))
2206     next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
2207   t->id.tid = next_tid++;
2208   t->id.oid = myid;
2209   t->local_tid = ntohl (t_msg->tunnel_id);
2210   t->client = c;
2211   t->peers = GNUNET_CONTAINER_multihashmap_create (32);
2212
2213   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2214   if (GNUNET_OK !=
2215       GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
2216                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2217   {
2218     GNUNET_break (0);
2219     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2220     return;
2221   }
2222
2223   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2224   if (GNUNET_OK !=
2225       GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
2226                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2227   {
2228     GNUNET_break (0);
2229     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2230     return;
2231   }
2232
2233   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2234   return;
2235 }
2236
2237
2238 /**
2239  * Handler for requests of deleting tunnels
2240  *
2241  * @param cls closure
2242  * @param client identification of the client
2243  * @param message the actual message
2244  */
2245 static void
2246 handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2247                              const struct GNUNET_MessageHeader *message)
2248 {
2249   struct GNUNET_MESH_TunnelMessage *tunnel_msg;
2250   struct MeshClient *c;
2251   struct MeshTunnel *t;
2252   MESH_TunnelNumber tid;
2253   GNUNET_HashCode hash;
2254
2255   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel\n");
2256
2257   /* Sanity check for client registration */
2258   if (NULL == (c = retrieve_client (client)))
2259   {
2260     GNUNET_break (0);
2261     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2262     return;
2263   }
2264   /* Message sanity check */
2265   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2266   {
2267     GNUNET_break (0);
2268     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2269     return;
2270   }
2271
2272   tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2273
2274   /* Retrieve tunnel */
2275   tid = ntohl (tunnel_msg->tunnel_id);
2276
2277   /* Remove from local id hashmap */
2278   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
2279   t = GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
2280   GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t);
2281
2282   /* Remove from global id hashmap */
2283   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2284   GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t);
2285
2286 //     notify_tunnel_destroy(t);
2287   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2288   return;
2289 }
2290
2291
2292 /**
2293  * Handler for connection requests to new peers
2294  *
2295  * @param cls closure
2296  * @param client identification of the client
2297  * @param message the actual message (PeerControl)
2298  */
2299 static void
2300 handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
2301                           const struct GNUNET_MessageHeader *message)
2302 {
2303   struct GNUNET_MESH_PeerControl *peer_msg;
2304   struct MeshClient *c;
2305   struct MeshTunnel *t;
2306   MESH_TunnelNumber tid;
2307   struct MeshPeerInfo *peer_info;
2308
2309
2310   /* Sanity check for client registration */
2311   if (NULL == (c = retrieve_client (client)))
2312   {
2313     GNUNET_break (0);
2314     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2315     return;
2316   }
2317
2318   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2319   /* Sanity check for message size */
2320   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2321   {
2322     GNUNET_break (0);
2323     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2324     return;
2325   }
2326
2327   /* Tunnel exists? */
2328   tid = ntohl (peer_msg->tunnel_id);
2329   t = retrieve_tunnel_by_local_id (c, tid);
2330   if (NULL == t)
2331   {
2332     GNUNET_break (0);
2333     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2334     return;
2335   }
2336
2337   /* Does client own tunnel? */
2338   if (t->client->handle != client)
2339   {
2340     GNUNET_break (0);
2341     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2342     return;
2343   }
2344
2345   t->peers_total++;
2346   peer_info = get_peer_info (&peer_msg->peer);
2347
2348   /* Start DHT search if needed */
2349   if (MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget)
2350   {
2351     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 */
2352                                               GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
2353                                               0,        /* mutator */
2354                                               NULL,     /* xquery */
2355                                               0,        /* xquery bits */
2356                                               dht_get_id_handler,
2357                                               (void *) peer_info);
2358   }
2359
2360   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2361   return;
2362 }
2363
2364
2365 /**
2366  * Handler for disconnection requests of peers in a tunnel
2367  *
2368  * @param cls closure
2369  * @param client identification of the client
2370  * @param message the actual message (PeerControl)
2371  */
2372 static void
2373 handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
2374                           const struct GNUNET_MessageHeader *message)
2375 {
2376   struct GNUNET_MESH_PeerControl *peer_msg;
2377   struct MeshClient *c;
2378   struct MeshTunnel *t;
2379   MESH_TunnelNumber tid;
2380
2381   /* Sanity check for client registration */
2382   if (NULL == (c = retrieve_client (client)))
2383   {
2384     GNUNET_break (0);
2385     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2386     return;
2387   }
2388   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2389   /* Sanity check for message size */
2390   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2391   {
2392     GNUNET_break (0);
2393     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2394     return;
2395   }
2396
2397   /* Tunnel exists? */
2398   tid = ntohl (peer_msg->tunnel_id);
2399   t = retrieve_tunnel_by_local_id (c, tid);
2400   if (NULL == t)
2401   {
2402     GNUNET_break (0);
2403     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2404     return;
2405   }
2406
2407   /* Does client own tunnel? */
2408   if (t->client->handle != client)
2409   {
2410     GNUNET_break (0);
2411     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2412     return;
2413   }
2414
2415   /* Ok, delete peer from tunnel */
2416   GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
2417                                             &peer_msg->peer.hashPubKey);
2418
2419   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2420   return;
2421 }
2422
2423
2424 /**
2425  * Handler for connection requests to new peers by type
2426  *
2427  * @param cls closure
2428  * @param client identification of the client
2429  * @param message the actual message (ConnectPeerByType)
2430  */
2431 static void
2432 handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
2433                               const struct GNUNET_MessageHeader *message)
2434 {
2435   struct GNUNET_MESH_ConnectPeerByType *connect_msg;
2436   struct MeshClient *c;
2437   struct MeshTunnel *t;
2438   GNUNET_HashCode hash;
2439   GNUNET_MESH_ApplicationType type;
2440   MESH_TunnelNumber tid;
2441   uint8_t buffer[12] = "MESH_APP";
2442   uint32_t *p;
2443   unsigned int i;
2444
2445   /* Sanity check for client registration */
2446   if (NULL == (c = retrieve_client (client)))
2447   {
2448     GNUNET_break (0);
2449     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2450     return;
2451   }
2452
2453   connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
2454   /* Sanity check for message size */
2455   if (sizeof (struct GNUNET_MESH_PeerControl) !=
2456       ntohs (connect_msg->header.size))
2457   {
2458     GNUNET_break (0);
2459     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2460     return;
2461   }
2462
2463   /* Tunnel exists? */
2464   tid = ntohl (connect_msg->tunnel_id);
2465   t = retrieve_tunnel_by_local_id (c, tid);
2466   if (NULL == t)
2467   {
2468     GNUNET_break (0);
2469     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2470     return;
2471   }
2472
2473   /* Does client own tunnel? */
2474   if (t->client->handle != client)
2475   {
2476     GNUNET_break (0);
2477     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2478     return;
2479   }
2480
2481   /* Do WE have the service? */
2482   type = ntohl (connect_msg->type);
2483   for (i = 0; i < n_applications; i++)
2484   {
2485     if (applications[i] == type)
2486     {
2487       /* Yes! Fast forward, add ourselves to the tunnel and send the
2488        * good news to the client
2489        */
2490       struct GNUNET_MESH_PeerControl pc;
2491
2492       GNUNET_PEER_resolve (myid, &pc.peer);
2493       GNUNET_CONTAINER_multihashmap_put (t->peers, &pc.peer.hashPubKey,
2494                                          get_peer_info (&pc.peer),
2495                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2496       pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2497       pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_CONNECTED);
2498       pc.tunnel_id = htonl (t->local_tid);
2499       GNUNET_SERVER_notification_context_unicast (nc, client, NULL, GNUNET_NO);
2500     }
2501   }
2502   /* Ok, lets find a peer offering the service */
2503   p = (uint32_t *) & buffer[8];
2504   *p = connect_msg->type;       /* Already in Network Byte Order! */
2505   GNUNET_CRYPTO_hash (buffer, 12, &hash);
2506   if (c->dht_get_type)
2507   {
2508     GNUNET_DHT_get_stop (c->dht_get_type);
2509   }
2510   c->dht_get_type =
2511       GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL,
2512                             GNUNET_BLOCK_TYPE_ANY, &hash, 10U,
2513                             GNUNET_DHT_RO_RECORD_ROUTE, NULL, 0, NULL, 0,
2514                             &dht_get_type_handler, t);
2515
2516   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2517   return;
2518 }
2519
2520
2521 /**
2522  * Handler for client traffic directed to one peer
2523  *
2524  * @param cls closure
2525  * @param client identification of the client
2526  * @param message the actual message
2527  */
2528 static void
2529 handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
2530                       const struct GNUNET_MessageHeader *message)
2531 {
2532   struct MeshClient *c;
2533   struct MeshTunnel *t;
2534   struct MeshPeerInfo *pi;
2535   struct GNUNET_MESH_Unicast *data_msg;
2536   struct GNUNET_PeerIdentity next_hop;
2537   struct MeshDataDescriptor *info;
2538   MESH_TunnelNumber tid;
2539   size_t data_size;
2540
2541   /* Sanity check for client registration */
2542   if (NULL == (c = retrieve_client (client)))
2543   {
2544     GNUNET_break (0);
2545     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2546     return;
2547   }
2548   data_msg = (struct GNUNET_MESH_Unicast *) message;
2549   /* Sanity check for message size */
2550   if (sizeof (struct GNUNET_MESH_Unicast) +
2551       sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
2552   {
2553     GNUNET_break (0);
2554     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2555     return;
2556   }
2557
2558   /* Tunnel exists? */
2559   tid = ntohl (data_msg->tid);
2560   t = retrieve_tunnel_by_local_id (c, tid);
2561   if (NULL == t)
2562   {
2563     GNUNET_break (0);
2564     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2565     return;
2566   }
2567
2568   /*  Is it a local tunnel? Then, does client own the tunnel? */
2569   if (t->client->handle != NULL && t->client->handle != client)
2570   {
2571     GNUNET_break (0);
2572     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2573     return;
2574   }
2575
2576   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
2577                                           &data_msg->destination.hashPubKey);
2578   /* Is the selected peer in the tunnel? */
2579   if (NULL == pi)
2580   {
2581     /* TODO
2582      * Are we SO nice that we automatically try to add him to the tunnel?
2583      */
2584     GNUNET_break (0);
2585     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2586     return;
2587   }
2588   if (pi->id == myid)
2589   {
2590     struct GNUNET_MESH_Unicast copy;
2591
2592     memcpy (&copy, data_msg, sizeof (struct GNUNET_MESH_Unicast));
2593
2594     handle_mesh_data_unicast (NULL, NULL, &copy.header, NULL);
2595     return;
2596   }
2597   GNUNET_PEER_resolve (get_first_hop (pi->path), &next_hop);
2598   data_size = ntohs (message->size) - sizeof (struct GNUNET_MESH_Unicast);
2599   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + data_size);
2600   memcpy (&info[1], &data_msg[1], data_size);
2601   info->destination = pi->id;
2602   info->origin = &t->id;
2603   info->size = data_size;
2604   info->client = client;
2605   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2606                                      GNUNET_TIME_UNIT_FOREVER_REL, &next_hop,
2607                                      /* FIXME re-check types */
2608                                      data_size +
2609                                      sizeof (struct GNUNET_MESH_Unicast),
2610                                      &send_core_data_unicast, info);
2611   return;
2612 }
2613
2614 /**
2615  * Handler for client traffic directed to all peers in a tunnel
2616  *
2617  * @param cls closure
2618  * @param client identification of the client
2619  * @param message the actual message
2620  */
2621 static void
2622 handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
2623                         const struct GNUNET_MessageHeader *message)
2624 {
2625   struct MeshClient *c;
2626   struct MeshTunnel *t;
2627   struct GNUNET_MESH_Multicast *data_msg;
2628   MESH_TunnelNumber tid;
2629
2630   /* Sanity check for client registration */
2631   if (NULL == (c = retrieve_client (client)))
2632   {
2633     GNUNET_break (0);
2634     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2635     return;
2636   }
2637   data_msg = (struct GNUNET_MESH_Multicast *) message;
2638   /* Sanity check for message size */
2639   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (data_msg->header.size))
2640   {
2641     GNUNET_break (0);
2642     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2643     return;
2644   }
2645
2646   /* Tunnel exists? */
2647   tid = ntohl (data_msg->tid);
2648   t = retrieve_tunnel_by_local_id (c, tid);
2649   if (NULL == t)
2650   {
2651     GNUNET_break (0);
2652     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2653     return;
2654   }
2655
2656   /* Does client own tunnel? */
2657   if (t->client->handle != client)
2658   {
2659     GNUNET_break (0);
2660     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2661     return;
2662   }
2663
2664   /*  TODO */
2665
2666   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2667   return;
2668 }
2669
2670 /**
2671  * Functions to handle messages from clients
2672  */
2673 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
2674   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2675   {&handle_local_tunnel_create, NULL,
2676    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2677    sizeof (struct GNUNET_MESH_TunnelMessage)},
2678   {&handle_local_tunnel_destroy, NULL,
2679    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2680    sizeof (struct GNUNET_MESH_TunnelMessage)},
2681   {&handle_local_connect_add, NULL,
2682    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
2683    sizeof (struct GNUNET_MESH_PeerControl)},
2684   {&handle_local_connect_del, NULL,
2685    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
2686    sizeof (struct GNUNET_MESH_PeerControl)},
2687   {&handle_local_connect_by_type, NULL,
2688    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
2689    sizeof (struct GNUNET_MESH_ConnectPeerByType)},
2690   {&handle_local_unicast, NULL,
2691    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2692   {&handle_local_unicast, NULL,
2693    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2694   {&handle_local_multicast, NULL,
2695    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
2696   {NULL, NULL, 0, 0}
2697 };
2698
2699
2700 /**
2701  * To be called on core init/fail.
2702  *
2703  * @param cls service closure
2704  * @param server handle to the server for this service
2705  * @param identity the public identity of this peer
2706  * @param publicKey the public key of this peer
2707  */
2708 static void
2709 core_init (void *cls, struct GNUNET_CORE_Handle *server,
2710            const struct GNUNET_PeerIdentity *identity,
2711            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
2712 {
2713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Core init\n");
2714   core_handle = server;
2715   myid = GNUNET_PEER_intern (identity);
2716   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
2717   return;
2718 }
2719
2720 /**
2721  * Method called whenever a given peer connects.
2722  *
2723  * @param cls closure
2724  * @param peer peer identity this notification is about
2725  * @param atsi performance data for the connection
2726  */
2727 static void
2728 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
2729               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2730 {
2731 //     GNUNET_PEER_Id              pid;
2732   struct MeshPeerInfo *peer_info;
2733   struct MeshPath *path;
2734
2735   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n");
2736   peer_info = get_peer_info (peer);
2737   if (myid == peer_info->id)
2738   {
2739     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
2740   }
2741   path = GNUNET_malloc (sizeof (struct MeshPath));
2742   path->length = 2;
2743   path->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id) * 2);
2744   path->peers[0] = myid;
2745   path->peers[1] = peer_info->id;
2746   add_path_to_peer (peer_info, path);
2747   return;
2748 }
2749
2750 /**
2751  * Method called whenever a peer disconnects.
2752  *
2753  * @param cls closure
2754  * @param peer peer identity this notification is about
2755  */
2756 static void
2757 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
2758 {
2759   struct MeshPeerInfo *pi;
2760   unsigned int i;
2761
2762   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer disconnected\n");
2763   pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
2764   if (!pi)
2765   {
2766     GNUNET_break (0);
2767     return;
2768   }
2769   for (i = 0; i < CORE_QUEUE_SIZE; i++)
2770   {
2771     if (pi->core_transmit[i])
2772     {
2773       GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit[i]);
2774       /* TODO: notify that tranmission has failed */
2775       GNUNET_free (pi->infos[i]);
2776     }
2777   }
2778   if (myid == pi->id)
2779   {
2780     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
2781   }
2782   return;
2783 }
2784
2785
2786 /******************************************************************************/
2787 /************************      MAIN FUNCTIONS      ****************************/
2788 /******************************************************************************/
2789
2790 /**
2791  * Task run during shutdown.
2792  *
2793  * @param cls unused
2794  * @param tc unused
2795  */
2796 static void
2797 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2798 {
2799   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shutting down\n");
2800   if (core_handle != NULL)
2801   {
2802     GNUNET_CORE_disconnect (core_handle);
2803     core_handle = NULL;
2804   }
2805   if (dht_handle != NULL)
2806   {
2807     GNUNET_DHT_disconnect (dht_handle);
2808     dht_handle = NULL;
2809   }
2810   if (nc != NULL)
2811   {
2812     GNUNET_SERVER_notification_context_destroy (nc);
2813     nc = NULL;
2814   }
2815   if (0 != announce_id_task)
2816   {
2817     GNUNET_SCHEDULER_cancel (announce_id_task);
2818     announce_id_task = 0;
2819   }
2820   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shut down\n");
2821 }
2822
2823 /**
2824  * Process mesh requests.
2825  *
2826  * @param cls closure
2827  * @param server the initialized server
2828  * @param c configuration to use
2829  */
2830 static void
2831 run (void *cls, struct GNUNET_SERVER_Handle *server,
2832      const struct GNUNET_CONFIGURATION_Handle *c)
2833 {
2834   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: starting to run\n");
2835   GNUNET_SERVER_add_handlers (server, plugin_handlers);
2836   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
2837   server_handle = server;
2838   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
2839                                      CORE_QUEUE_SIZE,   /* queue size */
2840                                      NULL,      /* Closure passed to MESH functions */
2841                                      &core_init,        /* Call core_init once connected */
2842                                      &core_connect,     /* Handle connects */
2843                                      &core_disconnect,  /* remove peers on disconnects */
2844                                      NULL,      /* Do we care about "status" updates? */
2845                                      NULL,      /* Don't notify about all incoming messages */
2846                                      GNUNET_NO, /* For header only in notification */
2847                                      NULL,      /* Don't notify about all outbound messages */
2848                                      GNUNET_NO, /* For header-only out notification */
2849                                      core_handlers);    /* Register these handlers */
2850   if (core_handle == NULL)
2851   {
2852     GNUNET_break (0);
2853   }
2854   dht_handle = GNUNET_DHT_connect (c, 64);
2855   if (dht_handle == NULL)
2856   {
2857     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error connecting to DHT.\
2858                    Running without DHT has a severe\
2859                    impact in MESH capabilities.\n\
2860                    Plase check your configuretion and enable DHT.\n");
2861     GNUNET_break (0);
2862   }
2863
2864   next_tid = 0;
2865
2866   tunnels = GNUNET_CONTAINER_multihashmap_create (32);
2867   peers = GNUNET_CONTAINER_multihashmap_create (32);
2868   nc = GNUNET_SERVER_notification_context_create (server_handle,
2869                                                   LOCAL_QUEUE_SIZE);
2870   clients = NULL;
2871   clients_tail = NULL;
2872
2873   applications = NULL;
2874   applications_rc = NULL;
2875   n_applications = 0;
2876   announce_applications_task = 0;
2877
2878   /* Scheduled the task to clean up when shutdown is called */
2879   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
2880                                 NULL);
2881
2882   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: end of run()\n");
2883 }
2884
2885 /**
2886  * The main function for the mesh service.
2887  *
2888  * @param argc number of arguments from the command line
2889  * @param argv command line arguments
2890  * @return 0 ok, 1 on error
2891  */
2892 int
2893 main (int argc, char *const *argv)
2894 {
2895   int ret;
2896
2897   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main()\n");
2898   ret =
2899       (GNUNET_OK ==
2900        GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
2901                            NULL)) ? 0 : 1;
2902   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main() END\n");
2903   return ret;
2904 }