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