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