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