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