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