Added code to create siglne paths from trees
[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  * @param cls string to print
64  * @param tc task context
65  */
66 static void
67 mesh_debug (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
68 {
69   char *s = cls;
70
71   if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason)
72   {
73     return;
74   }
75   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: %s\n", s);
76 }
77 #endif
78
79 /* TODO: move into configuration file */
80 #define CORE_QUEUE_SIZE         10
81 #define LOCAL_QUEUE_SIZE        100
82 #define REFRESH_PATH_TIME       GNUNET_TIME_relative_multiply(\
83                                     GNUNET_TIME_UNIT_SECONDS,\
84                                     300)
85 #define APP_ANNOUNCE_TIME       GNUNET_TIME_relative_multiply(\
86                                     GNUNET_TIME_UNIT_SECONDS,\
87                                     5)
88
89 #define ID_ANNOUNCE_TIME        GNUNET_TIME_relative_multiply(\
90                                     GNUNET_TIME_UNIT_SECONDS,\
91                                     5)
92
93 /******************************************************************************/
94 /************************        ENUMERATIONS      ****************************/
95 /******************************************************************************/
96
97 /**
98  * All the states a peer participating in a tunnel can be in.
99  */
100 enum MeshPeerState
101 {
102     /**
103      * Peer only retransmits traffic, is not a final destination
104      */
105   MESH_PEER_RELAY,
106
107     /**
108      * Path to the peer not known yet
109      */
110   MESH_PEER_SEARCHING,
111
112     /**
113      * Request sent, not yet answered.
114      */
115   MESH_PEER_WAITING,
116
117     /**
118      * Peer connected and ready to accept data
119      */
120   MESH_PEER_READY,
121
122     /**
123      * Peer connected previosly but not responding
124      */
125   MESH_PEER_RECONNECTING
126 };
127
128
129 /******************************************************************************/
130 /************************      DATA STRUCTURES     ****************************/
131 /******************************************************************************/
132
133 /**
134  * Information regarding a possible path to reach a single peer
135  */
136 struct MeshPeerPath
137 {
138
139     /**
140      * Linked list
141      */
142   struct MeshPeerPath *next;
143   struct MeshPeerPath *prev;
144
145     /**
146      * List of all the peers that form the path from origin to target.
147      */
148   GNUNET_PEER_Id *peers;
149
150     /**
151      * Number of peers (hops) in the path
152      */
153   unsigned int length;
154
155 };
156
157
158 /**
159  * Node of path tree for a tunnel
160  */
161 struct MeshTunnelPathNode
162 {
163   /**
164    * Tunnel this node belongs to (and therefore tree)
165    */
166   struct MeshTunnel *t;
167
168   /**
169    * Peer this node describes
170    */
171   struct MeshPeerInfo *peer;
172
173   /**
174    * Parent node in the tree
175    */
176   struct MeshTunnelPathNode *parent;
177
178   /**
179    * Array of children
180    */
181   struct MeshTunnelPathNode *children;
182
183   /**
184    * Number of children
185    */
186   unsigned int nchildren;
187
188     /**
189      * Status of the peer in the tunnel
190      */
191   enum MeshPeerState status;
192 };
193
194
195 /**
196  * Tree to reach all peers in the tunnel
197  */
198 struct MeshTunnelPath
199 {
200   /**
201    * Tunnel this path belongs to
202    */
203   struct MeshTunnel *t;
204
205   /**
206    * Root node of peer tree
207    */
208   struct MeshTunnelPathNode *root;
209
210   /**
211    * Node that represents our position in the tree (for non local tunnels)
212    */
213   struct MeshTunnelPathNode *me;
214
215   /**
216    * Cache of all peers and the first hop to them.
217    * Indexed by Peer_Identity, contains a pointer to the PeerInfo of 1st hop.
218    */
219   struct GNUNET_CONTAINER_MultiHashMap *first_hops;
220
221 };
222
223
224 /** FWD declaration */
225 struct MeshPeerInfo;
226
227 /**
228  * Struct containing all info possibly needed to build a package when called
229  * back by core.
230  */
231 struct MeshDataDescriptor
232 {
233     /** ID of the tunnel this packet travels in */
234   struct MESH_TunnelID *origin;
235
236     /** Ultimate destination of the packet */
237   GNUNET_PEER_Id destination;
238
239     /** Number of identical messages sent to different hops (multicast) */
240   unsigned int copies;
241
242     /** Size of the data */
243   size_t size;
244
245     /** Client that asked for the transmission, if any */
246   struct GNUNET_SERVER_Client *client;
247
248     /** Who was is message being sent to */
249   struct MeshPeerInfo *peer;
250
251     /** Which handler was used to request the transmission */
252   unsigned int handler_n;
253
254   /* Data at the end */
255 };
256
257
258 /**
259  * Struct containing all information regarding a given peer
260  */
261 struct MeshPeerInfo
262 {
263     /**
264      * ID of the peer
265      */
266   GNUNET_PEER_Id id;
267
268     /**
269      * Last time we heard from this peer
270      */
271   struct GNUNET_TIME_Absolute last_contact;
272
273     /**
274      * Number of attempts to reconnect so far
275      */
276   int n_reconnect_attempts;
277
278     /**
279      * Paths to reach the peer, ordered by ascending hop count
280      */
281   struct MeshPeerPath *path_head;
282
283     /**
284      * Paths to reach the peer, ordered by ascending hop count
285      */
286   struct MeshPeerPath *path_tail;
287
288     /**
289      * Handle to stop the DHT search for a path to this peer
290      */
291   struct GNUNET_DHT_GetHandle *dhtget;
292
293     /**
294      * Handles to stop queued transmissions for this peer
295      */
296   struct GNUNET_CORE_TransmitHandle *core_transmit[CORE_QUEUE_SIZE];
297
298     /**
299      * Pointer to info stuctures used as cls for queued transmissions
300      */
301   struct MeshDataDescriptor *infos[CORE_QUEUE_SIZE];
302
303     /**
304      * Array of tunnels this peer participates in
305      * (most probably a small amount, therefore not a hashmap)
306      * When the path to the peer changes, notify these tunnels to let them
307      * re-adjust their path trees.
308      */
309   struct MeshTunnel **tunnels;
310
311     /**
312      * Number of tunnels above
313      */
314   unsigned int ntunnels;
315 };
316
317
318 /**
319  * Data scheduled to transmit (to local client or remote peer)
320  */
321 struct MeshQueue
322 {
323     /**
324      * Double linked list
325      */
326   struct MeshQueue *next;
327   struct MeshQueue *prev;
328
329     /**
330      * Target of the data (NULL if target is client)
331      */
332   struct MeshPeerInfo *peer;
333
334     /**
335      * Client to send the data to (NULL if target is peer)
336      */
337   struct MeshClient *client;
338
339     /**
340      * Size of the message to transmit
341      */
342   unsigned int size;
343
344     /**
345      * How old is the data?
346      */
347   struct GNUNET_TIME_Absolute timestamp;
348
349     /**
350      * Data itself
351      */
352   struct GNUNET_MessageHeader *data;
353 };
354
355 /**
356  * Globally unique tunnel identification (owner + number)
357  * DO NOT USE OVER THE NETWORK
358  */
359 struct MESH_TunnelID
360 {
361     /**
362      * Node that owns the tunnel
363      */
364   GNUNET_PEER_Id oid;
365
366     /**
367      * Tunnel number to differentiate all the tunnels owned by the node oid
368      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
369      */
370   MESH_TunnelNumber tid;
371 };
372
373
374 struct MeshClient;              /* FWD declaration */
375
376 /**
377  * Struct containing all information regarding a tunnel
378  * For an intermediate node the improtant info used will be:
379  * - id        Tunnel unique identification
380  * - paths[0]  To know where to send it next
381  * - metainfo: ready, speeds, accounting
382  */
383 struct MeshTunnel
384 {
385     /**
386      * Tunnel ID
387      */
388   struct MESH_TunnelID id;
389
390     /**
391      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
392      */
393   MESH_TunnelNumber local_tid;
394
395     /**
396      * Last time the tunnel was used
397      */
398   struct GNUNET_TIME_Absolute timestamp;
399
400     /**
401      * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo)
402      */
403   struct GNUNET_CONTAINER_MultiHashMap *peers;
404
405     /**
406      * Number of peers that are connected and potentially ready to receive data
407      */
408   unsigned int peers_ready;
409
410     /**
411      * Number of peers that have been added to the tunnel
412      */
413   unsigned int peers_total;
414
415     /**
416      * Client owner of the tunnel, if any
417      */
418   struct MeshClient *client;
419
420     /**
421      * Messages ready to transmit
422      */
423   struct MeshQueue *queue_head;
424   struct MeshQueue *queue_tail;
425
426   /**
427    * Tunnel paths
428    */
429   struct MeshTunnelPath *paths;
430
431   /**
432    * Task to keep the used paths alive
433    */
434   GNUNET_SCHEDULER_TaskIdentifier path_refresh_task;
435 };
436
437
438 /**
439  * Info needed to work with tunnel paths and peers
440  */
441 struct MeshPathInfo
442 {
443   /**
444    * Tunnel
445    */
446   struct MeshTunnel *t;
447
448   /**
449    * Destination peer
450    */
451   struct MeshPeerInfo *peer;
452
453   /**
454    * Path itself
455    */
456   struct MeshPeerPath *path;
457 };
458
459
460 /**
461  * Struct containing information about a client of the service
462  */
463 struct MeshClient
464 {
465     /**
466      * Linked list
467      */
468   struct MeshClient *next;
469   struct MeshClient *prev;
470
471     /**
472      * Tunnels that belong to this client, indexed by local id
473      */
474   struct GNUNET_CONTAINER_MultiHashMap *tunnels;
475
476     /**
477      * Handle to communicate with the client
478      */
479   struct GNUNET_SERVER_Client *handle;
480
481     /**
482      * Applications that this client has claimed to provide
483      */
484   struct GNUNET_CONTAINER_MultiHashMap *apps;
485
486     /**
487      * Messages that this client has declared interest in
488      */
489   struct GNUNET_CONTAINER_MultiHashMap *types;
490
491     /**
492      * Used to search peers offering a service
493      */
494   struct GNUNET_DHT_GetHandle *dht_get_type;
495
496 #if MESH_DEBUG
497     /**
498      * ID of the client, for debug messages
499      */
500   unsigned int id;
501 #endif
502
503 };
504
505 /******************************************************************************/
506 /***********************      GLOBAL VARIABLES     ****************************/
507 /******************************************************************************/
508
509 /**
510  * All the clients
511  */
512 static struct MeshClient *clients;
513 static struct MeshClient *clients_tail;
514
515 /**
516  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
517  */
518 static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
519
520 /**
521  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
522  */
523 static struct GNUNET_CONTAINER_MultiHashMap *peers;
524
525 /**
526  * Handle to communicate with core
527  */
528 static struct GNUNET_CORE_Handle *core_handle;
529
530 /**
531  * Handle to use DHT
532  */
533 static struct GNUNET_DHT_Handle *dht_handle;
534
535 /**
536  * Handle to server
537  */
538 static struct GNUNET_SERVER_Handle *server_handle;
539
540 /**
541  * Notification context, to send messages to local clients
542  */
543 static struct GNUNET_SERVER_NotificationContext *nc;
544
545 /**
546  * Local peer own ID (memory efficient handle)
547  */
548 static GNUNET_PEER_Id myid;
549
550 /**
551  * Local peer own ID (full value)
552  */
553 static struct GNUNET_PeerIdentity my_full_id;
554
555 /**
556  * Tunnel ID for the next created tunnel (global tunnel number)
557  */
558 static MESH_TunnelNumber next_tid;
559
560 /**
561  * All application types provided by this peer
562  */
563 static struct GNUNET_CONTAINER_MultiHashMap *applications;
564
565 /**
566  * All message types clients of this peer are interested in
567  */
568 static struct GNUNET_CONTAINER_MultiHashMap *types;
569
570 /**
571  * Task to periodically announce provided applications
572  */
573 GNUNET_SCHEDULER_TaskIdentifier announce_applications_task;
574
575 /**
576  * Task to periodically announce itself in the network
577  */
578 GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
579
580 #if MESH_DEBUG
581 unsigned int next_client_id;
582 #endif
583
584
585 /******************************************************************************/
586 /************************    PERIODIC FUNCTIONS    ****************************/
587 /******************************************************************************/
588
589 /**
590  * Announce iterator over for each application provided by the peer
591  *
592  * @param cls closure
593  * @param key current key code
594  * @param value value in the hash map
595  * @return GNUNET_YES if we should continue to
596  *         iterate,
597  *         GNUNET_NO if not.
598  */
599 static int
600 announce_application (void *cls, const GNUNET_HashCode * key, void *value)
601 {
602   /* FIXME are hashes in multihash map equal on all aquitectures? */
603   GNUNET_DHT_put (dht_handle, key, 10U, GNUNET_DHT_RO_RECORD_ROUTE,
604                   GNUNET_BLOCK_TYPE_TEST, sizeof (struct GNUNET_PeerIdentity),
605                   (const char *) &my_full_id,
606 #if MESH_DEBUG
607                   GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL,
608                   &mesh_debug, "DHT_put for app completed");
609 #else
610                   GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
611                                             APP_ANNOUNCE_TIME),
612                   APP_ANNOUNCE_TIME, NULL, NULL);
613 #endif
614   return GNUNET_OK;
615 }
616
617
618 /**
619  * Periodically announce what applications are provided by local clients
620  *
621  * @param cls closure
622  * @param tc task context
623  */
624 static void
625 announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
626 {
627   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
628   {
629     announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
630     return;
631   }
632   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Starting PUT for apps\n");
633   GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application,
634                                          NULL);
635   announce_applications_task =
636       GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_applications,
637                                     cls);
638   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Finished PUT for apps\n");
639   return;
640 }
641
642
643 /**
644  * Periodically announce self id in the DHT
645  *
646  * @param cls closure
647  * @param tc task context
648  */
649 static void
650 announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
651 {
652   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
653   {
654     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
655     return;
656   }
657   /* TODO
658    * - Set data expiration in function of X
659    * - Adapt X to churn
660    */
661   GNUNET_DHT_put (dht_handle,   /* DHT handle */
662                   &my_full_id.hashPubKey,       /* Key to use */
663                   10U,          /* Replication level */
664                   GNUNET_DHT_RO_RECORD_ROUTE,   /* DHT options */
665                   GNUNET_BLOCK_TYPE_TEST,       /* Block type */
666                   0,            /* Size of the data */
667                   NULL,         /* Data itself */
668                   GNUNET_TIME_absolute_get_forever (),  /* Data expiration */
669                   GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
670 #if MESH_DEBUG
671                   &mesh_debug, "DHT_put for id completed");
672 #else
673                   NULL,         /* Continuation */
674                   NULL);        /* Continuation closure */
675 #endif
676   announce_id_task =
677       GNUNET_SCHEDULER_add_delayed (ID_ANNOUNCE_TIME, &announce_id, cls);
678 }
679
680
681 /**
682  * Send keepalive packets for a peer
683  *
684  * @param cls unused
685  * @param tc unused
686  *
687  * FIXME path
688  */
689 static void
690 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
691 {
692   struct MeshTunnel *t = cls;
693
694 //   struct GNUNET_PeerIdentity id;
695
696   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
697   {
698     return;
699   }
700   /* FIXME implement multicast keepalive. Just an empty multicast packet? */
701 //   GNUNET_PEER_resolve (path_get_first_hop (path->t, path->peer)->id, &id);
702 //   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
703 //                                      GNUNET_TIME_UNIT_FOREVER_REL, &id,
704 //                                      sizeof (struct GNUNET_MESH_ManipulatePath)
705 //                                      +
706 //                                      (path->path->length *
707 //                                       sizeof (struct GNUNET_PeerIdentity)),
708 //                                      &send_core_create_path,
709 //                                      t);
710   t->path_refresh_task =
711       GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
712   return;
713 }
714
715
716 /******************************************************************************/
717 /******************      GENERAL HELPER FUNCTIONS      ************************/
718 /******************************************************************************/
719
720 /**
721  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
722  * and insert it in the appropiate structures if the peer is not known yet.
723  *
724  * @param peer Identity of the peer
725  *
726  * @return Existing or newly created peer info
727  */
728 static struct MeshPeerInfo *
729 peer_info_get (const struct GNUNET_PeerIdentity *peer)
730 {
731   struct MeshPeerInfo *peer_info;
732
733   peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
734   if (NULL == peer_info)
735   {
736     peer_info =
737         (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
738     GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
739                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
740     peer_info->id = GNUNET_PEER_intern (peer);
741   }
742
743   return peer_info;
744 }
745
746
747 #if LATER
748 /**
749  * Destroy the peer_info and free any allocated resources linked to it
750  * @param t tunnel the path belongs to
751  * @param pi the peer_info to destroy
752  * @return GNUNET_OK on success
753  */
754 static int
755 peer_info_destroy (struct MeshPeerInfo *pi)
756 {
757   GNUNET_HashCode hash;
758   struct GNUNET_PeerIdentity id;
759
760   GNUNET_PEER_resolve (pi->id, &id);
761   GNUNET_PEER_change_rc (pi->id, -1);
762   GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &hash);
763
764   GNUNET_CONTAINER_multihashmap_remove (peers, &hash, pi);
765   GNUNET_SCHEDULER_cancel (pi->path_refresh_task);
766   GNUNET_free (pi);
767   return GNUNET_OK;
768 }
769 #endif
770
771
772 /**
773  * Destroy the path and free any allocated resources linked to it
774  *
775  * @param p the path to destroy
776  *
777  * @return GNUNET_OK on success
778  */
779 static int
780 path_destroy (struct MeshPeerPath *p)
781 {
782   GNUNET_PEER_decrement_rcs (p->peers, p->length);
783   GNUNET_free (p->peers);
784   GNUNET_free (p);
785   return GNUNET_OK;
786 }
787
788
789 /**
790  * Invert the path
791  *
792  * @param p the path to invert
793  */
794 static void
795 path_invert (struct MeshPeerPath *path)
796 {
797   GNUNET_PEER_Id aux;
798   unsigned int i;
799
800   for (i = 0; i < path->length / 2; i++)
801   {
802     aux = path->peers[i];
803     path->peers[i] = path->peers[path->length - i - 1];
804     path->peers[path->length - i - 1] = aux;
805   }
806 }
807
808
809 /**
810  * Find the first peer whom to send a packet to go down this path
811  *
812  * @param t The tunnel to use
813  * @param peer The peerinfo of the peer we are trying to reach
814  *
815  * @return peerinfo of the peer who is the first hop in the tunnel
816  *         NULL on error
817  */
818 static struct MeshPeerInfo *
819 path_get_first_hop (struct MeshTunnel *t, struct MeshPeerInfo *peer)
820 {
821   struct GNUNET_PeerIdentity id;
822
823   GNUNET_PEER_resolve (peer->id, &id);
824   return GNUNET_CONTAINER_multihashmap_get (t->paths->first_hops,
825                                             &id.hashPubKey);
826 }
827
828
829 /**
830  * Get the length of a path
831  *
832  * @param path The path to measure, with the local peer at any point of it
833  *
834  * @return Number of hops to reach destination
835  *         UINT_MAX in case the peer is not in the path
836  */
837 static unsigned int
838 path_get_length (struct MeshPeerPath *path)
839 {
840   unsigned int i;
841
842   if (NULL == path)
843     return UINT_MAX;
844   for (i = 0; i < path->length; i++)
845   {
846     if (path->peers[i] == myid)
847     {
848       return path->length - i;
849     }
850   }
851   return UINT_MAX;
852 }
853
854
855 /**
856  * Get the cost of the path relative to the already built tunnel tree
857  *
858  * @param t The tunnel to which compare
859  * @param path The individual path to reach a peer
860  *
861  * @return Number of hops to reach destination, UINT_MAX in case the peer is not
862  * in the path
863  *
864  * TODO: remove dummy implementation, look into the tunnel tree
865  */
866 static unsigned int
867 path_get_cost (struct MeshTunnel *t, struct MeshPeerPath *path)
868 {
869   return path_get_length (path);
870 }
871
872
873 /**
874  * Add the path to the peer and update the path used to reach it in case this
875  * is the shortest.
876  *
877  * @param peer_info Destination peer to add the path to.
878  * @param path New path to add. Last peer must be the peer in arg 1.
879  *
880  * TODO: trim the part from origin to us? Add it as path to origin?
881  */
882 static void
883 path_add_to_peer (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path)
884 {
885   unsigned int l;
886   struct MeshPeerPath *aux;
887
888   if (NULL == peer_info || NULL == path)
889   {
890     GNUNET_break (0);
891     return;
892   }
893
894   l = path_get_length (path);
895
896   for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
897   {
898     if (path_get_length (aux) > l)
899     {
900       GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
901                                           peer_info->path_tail, aux, path);
902     }
903   }
904   GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
905                                     path);
906   return;
907 }
908
909
910 /**
911  * Notify a tunnel that a connection has broken that affects at least
912  * some of its peers.
913  *
914  * @param t Tunnel affected
915  * @param peer Peer that (at least) has been affected by the disconnection
916  * @param p1 Peer that got disconnected from p2
917  * @param p2 Peer that got disconnected from p1
918  */
919 static void
920 tunnel_notify_connection_broken (struct MeshTunnel *t,
921                                  struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
922                                  GNUNET_PEER_Id p2);
923
924
925 /**
926  * Remove all paths that rely on a direct connection between p1 and p2
927  * from the peer itself and notify all tunnels about it.
928  *
929  * @param pi PeerInfo of affected peer
930  * @param p1 GNUNET_PEER_Id of one peer.
931  * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
932  *           no longer is.
933  */
934 static void
935 path_remove_from_peer (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
936                        GNUNET_PEER_Id p2)
937 {
938   struct MeshPeerPath *p;
939   struct MeshPeerPath *aux;
940   unsigned int destroyed;
941   unsigned int i;
942
943   destroyed = 0;
944   p = peer->path_head;
945   while (NULL != p)
946   {
947     aux = p->next;
948     for (i = 0; i < (p->length - 1); i++)
949     {
950       if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
951           (p->peers[i] == p2 && p->peers[i + 1] == p1))
952       {
953         path_destroy (p);
954         destroyed++;
955         break;
956       }
957     }
958     p = aux;
959   }
960   if (0 == destroyed)
961     return;
962
963   for (i = 0; i < peer->ntunnels; i++)
964   {
965     tunnel_notify_connection_broken (peer->tunnels[i], peer, p1, p2);
966   }
967 }
968
969
970 /**
971  * Add the path to the origin peer and update the path used to reach it in case
972  * this is the shortest.
973  * The path is given in peer_info -> destination, therefore we turn the path
974  * upside down first.
975  *
976  * @param peer_info Peer to add the path to, being the origin of the path.
977  * @param path New path to add after being inversed.
978  */
979 static void
980 path_add_to_origin (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path)
981 {
982   path_invert(path);
983   path_add_to_peer (peer_info, path);
984 }
985
986
987 /**
988  * Build a PeerPath from the paths returned from the DHT, reversing the paths
989  * to obtain a local peer -> destination path and interning the peer ids.
990  *
991  * @param get_path NULL-terminated array of pointers
992  *                 to the peers on reverse GET path (or NULL if not recorded)
993  * @param put_path NULL-terminated array of pointers
994  *                 to the peers on the PUT path (or NULL if not recorded)
995  *
996  * @return Newly allocated and created path
997  */
998 static struct MeshPeerPath *
999 path_build_from_dht (const struct GNUNET_PeerIdentity *const *get_path,
1000                      const struct GNUNET_PeerIdentity *const *put_path)
1001 {
1002   struct MeshPeerPath *p;
1003   int i;
1004
1005   p = GNUNET_malloc (sizeof (struct MeshPeerPath));
1006   for (i = 0; get_path[i] != NULL; i++) ;
1007   for (i--; i >= 0; i--)
1008   {
1009     p->peers =
1010         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
1011     p->peers[p->length] = GNUNET_PEER_intern (get_path[i]);
1012     p->length++;
1013   }
1014   for (i = 0; put_path[i] != NULL; i++) ;
1015   for (i--; i >= 0; i--)
1016   {
1017     p->peers =
1018         GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * (p->length + 1));
1019     p->peers[p->length] = GNUNET_PEER_intern (put_path[i]);
1020     p->length++;
1021   }
1022   return p;
1023 }
1024
1025
1026 /**
1027  * Check if client has registered with the service and has not disconnected
1028  *
1029  * @param client the client to check
1030  *
1031  * @return non-NULL if client exists in the global DLL
1032  */
1033 static struct MeshClient *
1034 client_get (struct GNUNET_SERVER_Client *client)
1035 {
1036   struct MeshClient *c;
1037
1038   c = clients;
1039   while (NULL != c)
1040   {
1041     if (c->handle == client)
1042       return c;
1043     c = c->next;
1044   }
1045   return NULL;
1046 }
1047
1048
1049 /**
1050  * Checks if a given client has subscribed to certain message type
1051  *
1052  * @param message_type Type of message to check
1053  * @param c Client to check
1054  *
1055  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
1056  *
1057  * TODO inline?
1058  */
1059 static int
1060 client_is_subscribed (uint16_t message_type, struct MeshClient *c)
1061 {
1062   GNUNET_HashCode hc;
1063
1064   GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc);
1065   return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc);
1066 }
1067
1068
1069 /**
1070  * Search for a tunnel among the tunnels for a client
1071  *
1072  * @param c the client whose tunnels to search in
1073  * @param tid the local id of the tunnel
1074  *
1075  * @return tunnel handler, NULL if doesn't exist
1076  */
1077 static struct MeshTunnel *
1078 tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
1079 {
1080   GNUNET_HashCode hash;
1081
1082   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
1083   return GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
1084 }
1085
1086
1087 /**
1088  * Search for a tunnel by global ID using PEER_ID
1089  *
1090  * @param pi owner of the tunnel
1091  * @param tid global tunnel number
1092  *
1093  * @return tunnel handler, NULL if doesn't exist
1094  */
1095 static struct MeshTunnel *
1096 tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
1097 {
1098   struct MESH_TunnelID id;
1099   GNUNET_HashCode hash;
1100
1101   id.oid = pi;
1102   id.tid = tid;
1103
1104   GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
1105   return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
1106 }
1107
1108
1109
1110 /**
1111  * Search for a tunnel by global ID using full PeerIdentities
1112  *
1113  * @param oid owner of the tunnel
1114  * @param tid global tunnel number
1115  *
1116  * @return tunnel handler, NULL if doesn't exist
1117  */
1118 static struct MeshTunnel *
1119 tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
1120 {
1121   return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
1122 }
1123
1124
1125 /**
1126  * Recursively find the given peer in the tree.
1127  *
1128  * @param t Tunnel where to add the new path.
1129  * @param p Path to look for.
1130  *
1131  * @return Pointer to the node of the peer. NULL if not found.
1132  */
1133 static struct MeshTunnelPathNode *
1134 tunnel_find_peer (struct MeshTunnelPathNode *root, struct MeshPeerInfo *peer)
1135 {
1136   struct MeshTunnelPathNode *n;
1137   unsigned int i;
1138
1139   if (root->peer == peer)
1140     return root;
1141   for (i = 0; i < root->nchildren; i++)
1142   {
1143     n = tunnel_find_peer (&root->children[i], peer);
1144     if (NULL != n)
1145       return n;
1146   }
1147   return NULL;
1148 }
1149
1150
1151 /**
1152  * Recusively mark peer and children as disconnected, notify client
1153  *
1154  * @param parent Node to be clean, potentially with children
1155  */
1156 static void
1157 tunnel_mark_peers_disconnected (struct MeshTunnelPathNode *parent)
1158 {
1159   struct GNUNET_MESH_PeerControl msg;
1160   unsigned int i;
1161
1162   parent->status = MESH_PEER_RECONNECTING;
1163   for (i = 0; i < parent->nchildren; i++)
1164   {
1165     tunnel_mark_peers_disconnected (&parent->children[i]);
1166   }
1167   if (NULL == parent->t->client)
1168     return;
1169   msg.header.size = htons (sizeof (msg));
1170   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1171   msg.tunnel_id = htonl (parent->t->local_tid);
1172   GNUNET_PEER_resolve (parent->peer->id, &msg.peer);
1173   GNUNET_SERVER_notification_context_unicast (nc, parent->t->client->handle,
1174                                               &msg.header, GNUNET_NO);
1175 }
1176
1177 /**
1178  * Delete the current path to the peer, including all now unused relays.
1179  *
1180  * @param t Tunnel where to add the new path.
1181  * @param p Path to be integrated.
1182  *
1183  * @return pointer to the pathless node, NULL on error
1184  *
1185  * TODO: notify peers of deletion
1186  */
1187 static struct MeshTunnelPathNode *
1188 tunnel_del_path (struct MeshTunnel *t, struct MeshPeerInfo *peer)
1189 {
1190   struct MeshTunnelPathNode *parent;
1191   struct MeshTunnelPathNode *node;
1192   struct MeshTunnelPathNode *n;
1193
1194   node = n = tunnel_find_peer (t->paths->me, peer);
1195   if (NULL == n)
1196     return NULL;
1197   parent = n->parent;
1198   n->parent = NULL;
1199   while (NULL != parent && MESH_PEER_RELAY == parent->status &&
1200          1 == parent->nchildren)
1201   {
1202     n = parent;
1203     GNUNET_free (parent->children);
1204     parent = parent->parent;
1205   }
1206   if (NULL == parent)
1207     return node;
1208   *n = parent->children[parent->nchildren - 1];
1209   parent->nchildren--;
1210   parent->children = GNUNET_realloc (parent->children, parent->nchildren);
1211
1212   tunnel_mark_peers_disconnected (node);
1213
1214   return node;
1215 }
1216
1217
1218 /**
1219  * Return a newly allocated individual path to reach a peer from the local peer,
1220  * according to the path tree of some tunnel.
1221  * 
1222  * @param t Tunnel from which to read the path tree
1223  * @param peer_info Destination peer to whom we want a path
1224  * 
1225  * @return A newly allocated individual path to reach the destination peer.
1226  *         Path must be destroyed afterwards.
1227  */
1228 static struct MeshPeerPath *
1229 tunnel_get_path_to_peer(struct MeshTunnel *t, struct MeshPeerInfo *peer_info)
1230 {
1231   struct MeshTunnelPathNode *n;
1232   struct MeshPeerPath *p;
1233
1234   n = tunnel_find_peer(t->paths->me, peer_info);
1235   p = GNUNET_malloc(sizeof(struct MeshPeerPath));
1236
1237   /* Building the path (inverted!) */
1238   while (n->peer->id != myid)
1239   {
1240     GNUNET_array_append(p->peers, p->length, n->peer->id);
1241     GNUNET_PEER_change_rc(n->peer->id, 1);
1242     n = n->parent;
1243     GNUNET_assert(NULL != n);
1244   }
1245   GNUNET_array_append(p->peers, p->length, myid);
1246   GNUNET_PEER_change_rc(myid, 1);
1247
1248   path_invert(p);
1249
1250   return p;
1251 }
1252
1253
1254 /**
1255  * Integrate a stand alone path into the tunnel tree.
1256  *
1257  * @param t Tunnel where to add the new path.
1258  * @param p Path to be integrated.
1259  *
1260  * @return GNUNET_OK in case of success.
1261  *         GNUNET_SYSERR in case of error.
1262  *
1263  * TODO: optimize
1264  * - go backwards on path looking for each peer in the present tree
1265  */
1266 static int
1267 tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p)
1268 {
1269   struct MeshTunnelPathNode *parent;
1270   struct MeshTunnelPathNode *oldnode;
1271   struct MeshTunnelPathNode *n;
1272   struct GNUNET_PeerIdentity id;
1273   struct GNUNET_PeerIdentity hop;
1274   int me;
1275   unsigned int i;
1276   unsigned int j;
1277
1278   n = t->paths->root;
1279   if (n->peer->id != p->peers[0])
1280   {
1281     GNUNET_break (0);
1282     return GNUNET_SYSERR;
1283   }
1284   /* Ignore return value, if not found it's ok. */
1285   GNUNET_PEER_resolve (p->peers[p->length - 1], &id);
1286   oldnode = tunnel_del_path (t, peer_info_get (&id));
1287   /* Look for the first node that is not already present in the tree
1288    *
1289    * Assuming that the tree is somewhat balanced, O(log n * log N).
1290    * - Length of the path is expected to be log N (size of whole network).
1291    * - Each level of the tree is expected to have log n children (size of tree).
1292    */
1293   for (i = 1, me = -1; i < p->length; i++)
1294   {
1295     parent = n;
1296     if (p->peers[i] == myid)
1297       me = i;
1298     for (j = 0; j < n->nchildren; j++)
1299     {
1300       if (n->children[j].peer->id == p->peers[i])
1301       {
1302         n = &n->children[j];
1303         break;
1304       }
1305     }
1306     /*  If we couldn't find a child equal to path[i], we have reached the end
1307      * of the common path. */
1308     if (parent == n)
1309       break;
1310   }
1311   if (-1 == me)
1312   {
1313     /* New path deviates from tree before reaching us. What happened? */
1314     GNUNET_break (0);
1315     return GNUNET_SYSERR;
1316   }
1317   /* Add the rest of the path as a branch from parent. */
1318   while (i < p->length)
1319   {
1320     parent->nchildren++;
1321     parent->children = GNUNET_realloc (parent->children, parent->nchildren);
1322     n = &parent->children[parent->nchildren - 1];
1323     if (i == p->length - 1)
1324     {
1325       if (NULL != oldnode)
1326       {
1327         /* Assignation and free can be misleading, using explicit mempcy */
1328         memcpy (n, oldnode, sizeof (struct MeshTunnelPathNode));
1329         GNUNET_free (oldnode);
1330       }
1331     }
1332     else
1333     {
1334       n->t = t;
1335       n->status = MESH_PEER_RELAY;
1336       GNUNET_PEER_resolve (p->peers[i], &id);
1337       n->peer = peer_info_get (&id);
1338     }
1339     n->parent = parent;
1340     i++;
1341     parent = n;
1342   }
1343
1344   /* Add info about first hop into hashmap. */
1345   if (me < p->length - 1)
1346   {
1347     GNUNET_PEER_resolve (p->peers[p->length - 1], &id);
1348     GNUNET_PEER_resolve (p->peers[me + 1], &hop);
1349     GNUNET_CONTAINER_multihashmap_put (t->paths->first_hops, &id.hashPubKey,
1350                                        peer_info_get (&hop),
1351                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1352   }
1353   return GNUNET_OK;
1354 }
1355
1356
1357 /**
1358  * Add a peer to a tunnel, accomodating paths accordingly and initializing all
1359  * needed rescources.
1360  *
1361  * @param t Tunnel we want to add a new peer to
1362  * @param peer PeerInfo of the peer being added
1363  *
1364  */
1365 static void
1366 tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer)
1367 {
1368   struct MeshPeerPath *p;
1369   struct MeshPeerPath *best_p;
1370   unsigned int best_cost;
1371   unsigned int cost;
1372
1373   GNUNET_array_append (peer->tunnels, peer->ntunnels, t);
1374   if (NULL == (p = peer->path_head))
1375     return;
1376
1377   best_p = p;
1378   best_cost = UINT_MAX;
1379   while (NULL != p)
1380   {
1381     if ((cost = path_get_cost (t, p)) < best_cost)
1382     {
1383       best_cost = cost;
1384       best_p = p;
1385     }
1386     p = p->next;
1387   }
1388   tunnel_add_path (t, best_p);
1389   if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task)
1390     t->path_refresh_task =
1391         GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
1392 }
1393
1394
1395 /**
1396  * Notify a tunnel that a connection has broken that affects at least
1397  * some of its peers.
1398  *
1399  * @param t Tunnel affected
1400  * @param peer Peer that (at least) has been affected by the disconnection
1401  * @param p1 Peer that got disconnected from p2
1402  * @param p2 Peer that got disconnected from p1
1403  * 
1404  * FIXME path
1405  */
1406 static void
1407 tunnel_notify_connection_broken (struct MeshTunnel *t,
1408                                  struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
1409                                  GNUNET_PEER_Id p2)
1410 {
1411 }
1412
1413
1414 /**
1415  * Destroy the tunnel and free any allocated resources linked to it
1416  *
1417  * @param t the tunnel to destroy
1418  *
1419  * @return GNUNET_OK on success
1420  */
1421 static int
1422 tunnel_destroy (struct MeshTunnel *t)
1423 {
1424   struct MeshClient *c;
1425   struct MeshQueue *q;
1426   struct MeshQueue *qn;
1427   GNUNET_HashCode hash;
1428   int r;
1429
1430   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: DESTROYING TUNNEL at %p\n", t);
1431   if (NULL == t)
1432     return GNUNET_OK;
1433
1434   c = t->client;
1435 #if MESH_DEBUG
1436   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
1437 #endif
1438
1439   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
1440   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
1441   {
1442     r = GNUNET_SYSERR;
1443   }
1444
1445   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
1446   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t))
1447   {
1448     r = GNUNET_SYSERR;
1449   }
1450   GNUNET_CONTAINER_multihashmap_destroy (t->peers);
1451   q = t->queue_head;
1452   while (NULL != q)
1453   {
1454     if (NULL != q->data)
1455       GNUNET_free (q->data);
1456     qn = q->next;
1457     GNUNET_free (q);
1458     q = qn;
1459     /* TODO cancel core transmit ready in case it was active */
1460   }
1461   GNUNET_free (t);
1462   return r;
1463 }
1464
1465
1466 /**
1467  * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
1468  * client when the client disconnects.
1469  * 
1470  * @param cls closure (client that is disconnecting)
1471  * @param key the hash of the local tunnel id (used to access the hashmap)
1472  * @param value the value stored at the key (tunnel to destroy)
1473  * 
1474  * @return GNUNET_OK on success
1475  */
1476 static int
1477 tunnel_destroy_iterator (void *cls, const GNUNET_HashCode * key, void *value)
1478 {
1479   int r;
1480
1481   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: D %p\n", value);
1482   r = tunnel_destroy ((struct MeshTunnel *) value);
1483   return r;
1484 }
1485
1486
1487 /******************************************************************************/
1488 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
1489 /******************************************************************************/
1490
1491
1492 /**
1493  * Function called to notify a client about the socket
1494  * being ready to queue more data.  "buf" will be
1495  * NULL and "size" zero if the socket was closed for
1496  * writing in the meantime.
1497  *
1498  * @param cls closure
1499  * @param size number of bytes available in buf
1500  * @param buf where the callee should write the message
1501  * @return number of bytes written to buf
1502  */
1503 static size_t
1504 send_core_create_path (void *cls, size_t size, void *buf)
1505 {
1506   struct MeshPathInfo *info = cls;
1507   struct GNUNET_MESH_ManipulatePath *msg;
1508   struct GNUNET_PeerIdentity *peer_ptr;
1509   struct GNUNET_PeerIdentity id;
1510   struct MeshPeerInfo *peer = info->peer;
1511   struct MeshTunnel *t = info->t;
1512   struct MeshPeerPath *p = info->path;
1513   size_t size_needed;
1514   int i;
1515
1516   size_needed =
1517       sizeof (struct GNUNET_MESH_ManipulatePath) +
1518       p->length * sizeof (struct GNUNET_PeerIdentity);
1519
1520   if (size < size_needed || NULL == buf)
1521   {
1522     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n");
1523     GNUNET_PEER_resolve (path_get_first_hop (t, peer)->id, &id);
1524     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1525                                        GNUNET_TIME_UNIT_FOREVER_REL, &id,
1526                                        size_needed, &send_core_create_path,
1527                                        info);
1528     return 0;
1529   }
1530
1531   msg = (struct GNUNET_MESH_ManipulatePath *) buf;
1532   msg->header.size = htons (size_needed);
1533   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
1534   msg->tid = ntohl (t->id.tid);
1535
1536   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
1537   for (i = 0; i < p->length; i++)
1538   {
1539     GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
1540   }
1541
1542   path_destroy (p);
1543   GNUNET_free (info);
1544
1545   return size_needed;
1546 }
1547
1548
1549 #if LATER
1550 /**
1551  * Function called to notify a client about the socket
1552  * being ready to queue more data.  "buf" will be
1553  * NULL and "size" zero if the socket was closed for
1554  * writing in the meantime.
1555  *
1556  * @param cls closure (MeshDataDescriptor with all info to build packet)
1557  * @param size number of bytes available in buf
1558  * @param buf where the callee should write the message
1559  * @return number of bytes written to buf
1560  */
1561 static size_t
1562 send_core_data_to_origin (void *cls, size_t size, void *buf)
1563 {
1564   struct MeshDataDescriptor *info = cls;
1565   struct GNUNET_MESH_ToOrigin *msg = buf;
1566   size_t total_size;
1567
1568   GNUNET_assert (NULL != info);
1569   total_size = sizeof (struct GNUNET_MESH_ToOrigin) + info->size;
1570   GNUNET_assert (total_size < 65536);   /* UNIT16_MAX */
1571
1572   if (total_size > size)
1573   {
1574     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1575                 "not enough buffer to send data to origin\n");
1576     return 0;
1577   }
1578   msg->header.size = htons (total_size);
1579   msg->header.type = htons (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
1580   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1581   msg->tid = htonl (info->origin->tid);
1582   if (0 != info->size)
1583   {
1584     memcpy (&msg[1], &info[1], info->size);
1585   }
1586   if (NULL != info->client)
1587   {
1588     GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
1589   }
1590   GNUNET_free (info);
1591   return total_size;
1592 }
1593 #endif
1594
1595 /**
1596  * Function called to notify a client about the socket
1597  * being ready to queue more data.  "buf" will be
1598  * NULL and "size" zero if the socket was closed for
1599  * writing in the meantime.
1600  *
1601  * @param cls closure (data itself)
1602  * @param size number of bytes available in buf
1603  * @param buf where the callee should write the message
1604  * @return number of bytes written to buf
1605  */
1606 static size_t
1607 send_core_data_unicast (void *cls, size_t size, void *buf)
1608 {
1609   struct MeshDataDescriptor *info = cls;
1610   struct GNUNET_MESH_Unicast *msg = buf;
1611   size_t total_size;
1612
1613   GNUNET_assert (NULL != info);
1614   total_size = sizeof (struct GNUNET_MESH_Unicast) + info->size;
1615   GNUNET_assert (total_size < 65536);   /* UNIT16_MAX */
1616
1617   if (total_size > size)
1618   {
1619     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1620                 "not enough buffer to send data to peer\n");
1621     return 0;
1622   }
1623   msg->header.size = htons (total_size);
1624   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1625   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1626   GNUNET_PEER_resolve (info->destination, &msg->destination);
1627   msg->tid = htonl (info->origin->tid);
1628   if (0 != info->size)
1629   {
1630     memcpy (&msg[1], &info[1], info->size);
1631   }
1632   if (NULL != info->client)
1633   {
1634     GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
1635   }
1636   GNUNET_free (info);
1637   return total_size;
1638 }
1639
1640
1641 /**
1642  * Function called to notify a client about the socket
1643  * being ready to queue more data.  "buf" will be
1644  * NULL and "size" zero if the socket was closed for
1645  * writing in the meantime.
1646  *
1647  * @param cls closure (data itself)
1648  * @param size number of bytes available in buf
1649  * @param buf where the callee should write the message
1650  * @return number of bytes written to buf
1651  */
1652 static size_t
1653 send_core_data_multicast (void *cls, size_t size, void *buf)
1654 {
1655   struct MeshDataDescriptor *info = cls;
1656   struct GNUNET_MESH_Multicast *msg = buf;
1657   size_t total_size;
1658
1659   GNUNET_assert (NULL != info);
1660   total_size = info->size + sizeof (struct GNUNET_MESH_Multicast);
1661   GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
1662
1663   if (info->peer)
1664   {
1665     info->peer->core_transmit[info->handler_n] = NULL;
1666   }
1667   if (total_size > size)
1668   {
1669     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1670                 "not enough buffer to send data futher\n");
1671     return 0;
1672   }
1673   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1674   msg->header.size = htons (total_size);
1675   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1676   msg->tid = htonl (info->origin->tid);
1677   memcpy (&msg[1], &info[1], total_size);
1678   if (0 == --info->copies)
1679   {
1680     if (NULL != info->client)
1681     {
1682       GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
1683     }
1684     GNUNET_free (info);
1685   }
1686   return total_size;
1687 }
1688
1689
1690 /**
1691  * Function called to notify a client about the socket
1692  * being ready to queue more data.  "buf" will be
1693  * NULL and "size" zero if the socket was closed for
1694  * writing in the meantime.
1695  *
1696  * @param cls closure (MeshDataDescriptor)
1697  * @param size number of bytes available in buf
1698  * @param buf where the callee should write the message
1699  * @return number of bytes written to buf
1700  */
1701 static size_t
1702 send_core_path_ack (void *cls, size_t size, void *buf)
1703 {
1704   struct MeshDataDescriptor *info = cls;
1705   struct GNUNET_MESH_PathACK *msg = buf;
1706
1707   GNUNET_assert (NULL != info);
1708   if (info->peer)
1709   {
1710     info->peer->core_transmit[info->handler_n] = NULL;
1711   }
1712   if (sizeof (struct GNUNET_MESH_PathACK) > size)
1713   {
1714     GNUNET_break (0);
1715     return 0;
1716   }
1717   msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
1718   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
1719   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1720   msg->tid = htonl (info->origin->tid);
1721   msg->peer_id = my_full_id;
1722   GNUNET_free (info);
1723   /* TODO add signature */
1724
1725   return sizeof (struct GNUNET_MESH_PathACK);
1726 }
1727
1728
1729 /**
1730  * Function called to notify a client about the socket
1731  * being ready to queue more data.  "buf" will be
1732  * NULL and "size" zero if the socket was closed for
1733  * writing in the meantime.
1734  *
1735  * @param cls closure (data itself)
1736  * @param size number of bytes available in buf
1737  * @param buf where the callee should write the message
1738  * @return number of bytes written to buf
1739  */
1740 static size_t
1741 send_core_data_raw (void *cls, size_t size, void *buf)
1742 {
1743   struct GNUNET_MessageHeader *msg = cls;
1744   size_t total_size;
1745
1746   GNUNET_assert (NULL != msg);
1747   total_size = ntohs (msg->size);
1748
1749   if (total_size > size)
1750   {
1751     GNUNET_break (0);
1752     return 0;
1753   }
1754   memcpy (buf, msg, total_size);
1755   GNUNET_free (cls);
1756   return total_size;
1757 }
1758
1759
1760 #if LATER
1761 /**
1762  * Send another peer a notification to destroy a tunnel
1763  * @param cls The tunnel to destroy
1764  * @param size Size in the buffer
1765  * @param buf Memory where to put the data to transmit
1766  * @return Size of data put in buffer
1767  */
1768 static size_t
1769 send_p2p_tunnel_destroy (void *cls, size_t size, void *buf)
1770 {
1771   struct MeshTunnel *t = cls;
1772   struct MeshClient *c;
1773   struct GNUNET_MESH_TunnelMessage *msg;
1774
1775   c = t->client;
1776   msg = buf;
1777   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1778    /*FIXME*/ msg->header.size =
1779       htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1780   msg->tunnel_id = htonl (t->id.tid);
1781
1782   tunnel_destroy (c, t);
1783   return sizeof (struct GNUNET_MESH_TunnelMessage);
1784 }
1785 #endif
1786
1787
1788 /**
1789  * Send the message to all clients that have subscribed to its type
1790  *
1791  * @param msg Pointer to the message itself
1792  * @return number of clients this message was sent to
1793  */
1794 static unsigned int
1795 send_subscribed_clients (struct GNUNET_MessageHeader *msg)
1796 {
1797   struct MeshClient *c;
1798   unsigned int count;
1799   uint16_t type;
1800
1801   type = ntohs (msg->type);
1802   for (count = 0, c = clients; c != NULL; c = c->next)
1803   {
1804     if (client_is_subscribed (type, c))
1805     {
1806       count++;
1807       GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg,
1808                                                   GNUNET_YES);
1809     }
1810   }
1811   return count;
1812 }
1813
1814
1815 /**
1816  * Iterator over hash map peer entries collect all neighbors who to resend the
1817  * data to.
1818  *
1819  * @param cls closure (**GNUNET_PEER_Id to store hops to send packet)
1820  * @param key current key code (peer id hash)
1821  * @param value value in the hash map (peer_info)
1822  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
1823  */
1824 static int
1825 iterate_collect_neighbors (void *cls, const GNUNET_HashCode * key, void *value)
1826 {
1827   struct MeshPeerInfo *peer_info = value;
1828   struct MeshPathInfo *neighbors = cls;
1829   unsigned int i;
1830
1831   if (peer_info->id == myid)
1832   {
1833     return GNUNET_YES;
1834   }
1835   peer_info = path_get_first_hop (neighbors->t, peer_info);
1836   for (i = 0; i < neighbors->path->length; i++)
1837   {
1838     if (neighbors->path->peers[i] == peer_info->id)
1839       return GNUNET_YES;
1840   }
1841   GNUNET_array_append (neighbors->path->peers, neighbors->path->length,
1842                        peer_info->id);
1843
1844   return GNUNET_YES;
1845 }
1846
1847
1848 /******************************************************************************/
1849 /********************      MESH NETWORK HANDLERS     **************************/
1850 /******************************************************************************/
1851
1852
1853 /**
1854  * Core handler for path creation
1855  * struct GNUNET_CORE_MessageHandler
1856  *
1857  * @param cls closure
1858  * @param message message
1859  * @param peer peer identity this notification is about
1860  * @param atsi performance data
1861  * @return GNUNET_OK to keep the connection open,
1862  *         GNUNET_SYSERR to close it (signal serious error)
1863  *
1864  */
1865 static int
1866 handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1867                          const struct GNUNET_MessageHeader *message,
1868                          const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1869 {
1870   unsigned int own_pos;
1871   uint16_t size;
1872   uint16_t i;
1873   MESH_TunnelNumber tid;
1874   struct GNUNET_MESH_ManipulatePath *msg;
1875   struct GNUNET_PeerIdentity *pi;
1876   struct GNUNET_PeerIdentity id;
1877   GNUNET_HashCode hash;
1878   struct MeshPeerPath *path;
1879   struct MeshPeerInfo *dest_peer_info;
1880   struct MeshPeerInfo *orig_peer_info;
1881   struct MeshTunnel *t;
1882
1883   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1884               "MESH: Received a MESH path create msg\n");
1885   size = ntohs (message->size);
1886   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
1887   {
1888     GNUNET_break_op (0);
1889     return GNUNET_OK;
1890   }
1891
1892   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
1893   if (size % sizeof (struct GNUNET_PeerIdentity))
1894   {
1895     GNUNET_break_op (0);
1896     return GNUNET_OK;
1897   }
1898   size /= sizeof (struct GNUNET_PeerIdentity);
1899   if (size < 2)
1900   {
1901     GNUNET_break_op (0);
1902     return GNUNET_OK;
1903   }
1904   msg = (struct GNUNET_MESH_ManipulatePath *) message;
1905
1906   tid = ntohl (msg->tid);
1907   pi = (struct GNUNET_PeerIdentity *) &msg[1];
1908   t = tunnel_get (pi, tid);
1909
1910   if (NULL == t)
1911   {
1912     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Creating tunnel\n");
1913     t = GNUNET_malloc (sizeof (struct MeshTunnel));
1914     t->id.oid = GNUNET_PEER_intern (pi);
1915     t->id.tid = tid;
1916     t->peers = GNUNET_CONTAINER_multihashmap_create (32);
1917
1918     GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
1919     if (GNUNET_OK !=
1920         GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
1921                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1922     {
1923       GNUNET_break (0);
1924       return GNUNET_OK;
1925     }
1926
1927   }
1928   dest_peer_info =
1929       GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
1930   if (NULL == dest_peer_info)
1931   {
1932     dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1933     dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
1934     GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
1935                                        dest_peer_info,
1936                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1937   }
1938   orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
1939   if (NULL == orig_peer_info)
1940   {
1941     orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1942     orig_peer_info->id = GNUNET_PEER_intern (pi);
1943     GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
1944                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1945   }
1946
1947   path = GNUNET_malloc (sizeof (struct MeshPeerPath));
1948   path->length = size;
1949   path->peers = GNUNET_malloc (size * sizeof (GNUNET_PEER_Id));
1950   own_pos = 0;
1951   for (i = 0; i < size; i++)
1952   {
1953     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
1954     if (path->peers[i] == myid)
1955       own_pos = i;
1956   }
1957   if (own_pos == 0)
1958   {                             /* cannot be self, must be 'not found' */
1959     /* create path: self not found in path through self */
1960     GNUNET_break_op (0);
1961     path_destroy (path);
1962     /* FIXME error. destroy tunnel? leave for timeout? */
1963     return 0;
1964   }
1965   if (own_pos == size - 1)
1966   {
1967     /* It is for us! Send ack. */
1968     struct MeshDataDescriptor *info;
1969     unsigned int j;
1970
1971     path_add_to_origin (orig_peer_info, path);  /* inverts path!  */
1972     info = GNUNET_malloc (sizeof (struct MeshDataDescriptor));
1973     info->origin = &t->id;
1974     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
1975     GNUNET_assert (info->peer);
1976     for (j = 0; info->peer->core_transmit[j]; j++)
1977     {
1978       if (j == 9)
1979       {
1980         GNUNET_break (0);
1981         return GNUNET_OK;
1982       }
1983     }
1984     info->handler_n = j;
1985     info->peer->core_transmit[j] =
1986         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
1987                                            GNUNET_TIME_UNIT_FOREVER_REL, peer,
1988                                            sizeof (struct GNUNET_MessageHeader),
1989                                            &send_core_path_ack, info);
1990   }
1991   else
1992   {
1993     /* It's for somebody else! Retransmit. */
1994     struct MeshPathInfo *path_info;
1995
1996     path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
1997     path_info->t = t;
1998     path_info->path = path;
1999     path_info->peer = dest_peer_info;
2000
2001     path_add_to_peer (dest_peer_info, path);
2002     GNUNET_PEER_resolve (path->peers[own_pos + 1], &id);
2003     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2004                                        GNUNET_TIME_UNIT_FOREVER_REL, &id,
2005                                        sizeof (struct GNUNET_MessageHeader),
2006                                        &send_core_create_path, path_info);
2007   }
2008   return GNUNET_OK;
2009 }
2010
2011
2012 /**
2013  * Core handler for mesh network traffic going from the origin to a peer
2014  *
2015  * @param cls closure
2016  * @param peer peer identity this notification is about
2017  * @param message message
2018  * @param atsi performance data
2019  * @return GNUNET_OK to keep the connection open,
2020  *         GNUNET_SYSERR to close it (signal serious error)
2021  */
2022 static int
2023 handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
2024                           const struct GNUNET_MessageHeader *message,
2025                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2026 {
2027   struct GNUNET_MESH_Unicast *msg;
2028   struct GNUNET_PeerIdentity id;
2029   struct MeshTunnel *t;
2030   struct MeshPeerInfo *pi;
2031   size_t size;
2032
2033   size = ntohs (message->size);
2034   if (size <
2035       sizeof (struct GNUNET_MESH_Unicast) +
2036       sizeof (struct GNUNET_MessageHeader))
2037   {
2038     GNUNET_break (0);
2039     return GNUNET_OK;
2040   }
2041   msg = (struct GNUNET_MESH_Unicast *) message;
2042   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2043   if (NULL == t)
2044   {
2045     /* TODO notify back: we don't know this tunnel */
2046     return GNUNET_OK;
2047   }
2048   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
2049                                           &msg->destination.hashPubKey);
2050   if (NULL == pi)
2051   {
2052     /* TODO maybe feedback, log to statistics */
2053     return GNUNET_OK;
2054   }
2055   if (pi->id == myid)
2056   {
2057     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
2058     return GNUNET_OK;
2059   }
2060   GNUNET_PEER_resolve (path_get_first_hop (t, pi)->id, &id);
2061   msg = GNUNET_malloc (size);
2062   memcpy (msg, message, size);
2063   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2064                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
2065                                      &send_core_data_raw, msg);
2066   return GNUNET_OK;
2067 }
2068
2069
2070 /**
2071  * Core handler for mesh network traffic going from the origin to all peers
2072  *
2073  * @param cls closure
2074  * @param message message
2075  * @param peer peer identity this notification is about
2076  * @param atsi performance data
2077  * @return GNUNET_OK to keep the connection open,
2078  *         GNUNET_SYSERR to close it (signal serious error)
2079  */
2080 static int
2081 handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
2082                             const struct GNUNET_MessageHeader *message,
2083                             const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2084 {
2085   struct GNUNET_MESH_Multicast *msg;
2086   struct GNUNET_PeerIdentity id;
2087   struct MeshDataDescriptor *info;
2088   struct MeshPathInfo neighbors;
2089   struct MeshTunnel *t;
2090   size_t size;
2091   uint16_t i;
2092   uint16_t j;
2093
2094
2095   size = ntohs (message->size);
2096   if (size <
2097       sizeof (struct GNUNET_MESH_Multicast) +
2098       sizeof (struct GNUNET_MessageHeader))
2099   {
2100     GNUNET_break_op (0);
2101     return GNUNET_OK;
2102   }
2103   msg = (struct GNUNET_MESH_Multicast *) message;
2104   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2105
2106   if (NULL == t)
2107   {
2108     /* TODO notify that we dont know that tunnel */
2109     return GNUNET_OK;
2110   }
2111
2112   /* Transmit to locally interested clients */
2113   if (GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey))
2114   {
2115     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
2116   }
2117
2118   /* Retransmit to other peers.
2119    * Using path here as just a collection of peers, not a path per se.
2120    */
2121   neighbors.t = t;
2122   neighbors.path = GNUNET_malloc (sizeof (struct MeshPeerPath));
2123   GNUNET_CONTAINER_multihashmap_iterate (t->peers, &iterate_collect_neighbors,
2124                                          &neighbors);
2125   if (0 == neighbors.path->length)
2126   {
2127     GNUNET_free (neighbors.path);
2128     return GNUNET_OK;
2129   }
2130   size -= sizeof (struct GNUNET_MESH_Multicast);
2131   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + size);
2132   info->origin = &t->id;
2133   info->copies = neighbors.path->length;
2134   for (i = 0; i < info->copies; i++)
2135   {
2136     GNUNET_PEER_resolve (neighbors.path->peers[i], &id);
2137     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
2138     GNUNET_assert (NULL != info->peer);
2139     for (j = 0; 0 != info->peer->core_transmit[j]; j++)
2140     {
2141       if (j == (CORE_QUEUE_SIZE - 1))
2142       {
2143         GNUNET_break (0);
2144         return GNUNET_OK;
2145       }
2146     }
2147     info->handler_n = j;
2148     info->peer->infos[j] = info;
2149     info->peer->core_transmit[j] =
2150         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2151                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
2152                                            ntohs (msg->header.size),
2153                                            &send_core_data_multicast, info);
2154   }
2155   GNUNET_free (neighbors.path->peers);
2156   GNUNET_free (neighbors.path);
2157   return GNUNET_OK;
2158 }
2159
2160
2161 /**
2162  * Core handler for mesh network traffic
2163  *
2164  * @param cls closure
2165  * @param message message
2166  * @param peer peer identity this notification is about
2167  * @param atsi performance data
2168  *
2169  * @return GNUNET_OK to keep the connection open,
2170  *         GNUNET_SYSERR to close it (signal serious error)
2171  */
2172 static int
2173 handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
2174                           const struct GNUNET_MessageHeader *message,
2175                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2176 {
2177   struct GNUNET_MESH_ToOrigin *msg;
2178   struct GNUNET_PeerIdentity id;
2179   struct MeshPeerInfo *peer_info;
2180   struct MeshTunnel *t;
2181   size_t size;
2182
2183   size = ntohs (message->size);
2184   if (size < sizeof (struct GNUNET_MESH_ToOrigin) +     /* Payload must be */
2185       sizeof (struct GNUNET_MessageHeader))     /* at least a header */
2186   {
2187     GNUNET_break_op (0);
2188     return GNUNET_OK;
2189   }
2190   msg = (struct GNUNET_MESH_ToOrigin *) message;
2191   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2192
2193   if (NULL == t)
2194   {
2195     /* TODO notify that we dont know this tunnel (whom)? */
2196     return GNUNET_OK;
2197   }
2198
2199   if (t->id.oid == myid)
2200   {
2201     if (NULL == t->client)
2202     {
2203       /* got data packet for ownerless tunnel */
2204       GNUNET_break_op (0);
2205       return GNUNET_OK;
2206     }
2207     /* TODO signature verification */
2208     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, message,
2209                                                 GNUNET_YES);
2210     return GNUNET_OK;
2211   }
2212   peer_info = peer_info_get (&msg->oid);
2213   if (NULL == peer_info)
2214   {
2215     /* unknown origin of tunnel */
2216     GNUNET_break (0);
2217     return GNUNET_OK;
2218   }
2219   GNUNET_PEER_resolve (t->paths->me->parent->peer->id, &id);
2220   msg = GNUNET_malloc (size);
2221   memcpy (msg, message, size);
2222   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2223                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
2224                                      &send_core_data_raw, msg);
2225
2226   return GNUNET_OK;
2227 }
2228
2229
2230 /**
2231  * Core handler for path ACKs
2232  *
2233  * @param cls closure
2234  * @param message message
2235  * @param peer peer identity this notification is about
2236  * @param atsi performance data
2237  *
2238  * @return GNUNET_OK to keep the connection open,
2239  *         GNUNET_SYSERR to close it (signal serious error)
2240  *
2241  * FIXME path change state
2242  */
2243 static int
2244 handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
2245                       const struct GNUNET_MessageHeader *message,
2246                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2247 {
2248   struct GNUNET_MESH_PathACK *msg;
2249   struct GNUNET_PeerIdentity id;
2250   struct MeshTunnel *t;
2251   struct MeshPeerInfo *peer_info;
2252
2253   msg = (struct GNUNET_MESH_PathACK *) message;
2254   t = tunnel_get (&msg->oid, msg->tid);
2255   if (NULL == t)
2256   {
2257     /* TODO notify that we don't know the tunnel */
2258     return GNUNET_OK;
2259   }
2260
2261   /* Message for us? */
2262   if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
2263   {
2264     struct GNUNET_MESH_PeerControl pc;
2265
2266     if (NULL == t->client)
2267     {
2268       GNUNET_break (0);
2269       return GNUNET_OK;
2270     }
2271     peer_info = peer_info_get (&msg->peer_id);
2272     if (NULL == peer_info)
2273     {
2274       GNUNET_break_op (0);
2275       return GNUNET_OK;
2276     }
2277     /* FIXME change state of peer */
2278     pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
2279     pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2280     pc.tunnel_id = htonl (t->local_tid);
2281     GNUNET_PEER_resolve (peer_info->id, &pc.peer);
2282     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
2283                                                 &pc.header, GNUNET_NO);
2284     return GNUNET_OK;
2285   }
2286
2287   peer_info = peer_info_get (&msg->oid);
2288   if (NULL == peer_info)
2289   {
2290     /* If we know the tunnel, we should DEFINITELY know the peer */
2291     GNUNET_break (0);
2292     return GNUNET_OK;
2293   }
2294   GNUNET_PEER_resolve (path_get_first_hop (t, peer_info)->id, &id);
2295   msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PathACK));
2296   memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK));
2297   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2298                                      GNUNET_TIME_UNIT_FOREVER_REL, &id,
2299                                      sizeof (struct GNUNET_MESH_PathACK),
2300                                      &send_core_data_raw, msg);
2301   return GNUNET_OK;
2302 }
2303
2304
2305 /**
2306  * Functions to handle messages from core
2307  */
2308 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
2309   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
2310   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2311   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
2312   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2313   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
2314    sizeof (struct GNUNET_MESH_PathACK)},
2315   {NULL, 0, 0}
2316 };
2317
2318
2319
2320 /******************************************************************************/
2321 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
2322 /******************************************************************************/
2323
2324 /**
2325  * deregister_app: iterator for removing each application registered by a client
2326  * 
2327  * @param cls closure
2328  * @param key the hash of the application id (used to access the hashmap)
2329  * @param value the value stored at the key (client)
2330  * 
2331  * @return GNUNET_OK on success
2332  */
2333 static int
2334 deregister_app (void *cls, const GNUNET_HashCode * key, void *value)
2335 {
2336   GNUNET_CONTAINER_multihashmap_remove (applications, key, value);
2337   return GNUNET_OK;
2338 }
2339
2340 #if LATER
2341 /**
2342  * notify_client_connection_failure: notify a client that the connection to the
2343  * requested remote peer is not possible (for instance, no route found)
2344  * Function called when the socket is ready to queue more data. "buf" will be
2345  * NULL and "size" zero if the socket was closed for writing in the meantime.
2346  *
2347  * @param cls closure
2348  * @param size number of bytes available in buf
2349  * @param buf where the callee should write the message
2350  * @return number of bytes written to buf
2351  */
2352 static size_t
2353 notify_client_connection_failure (void *cls, size_t size, void *buf)
2354 {
2355   int size_needed;
2356   struct MeshPeerInfo *peer_info;
2357   struct GNUNET_MESH_PeerControl *msg;
2358   struct GNUNET_PeerIdentity id;
2359
2360   if (0 == size && NULL == buf)
2361   {
2362     // TODO retry? cancel?
2363     return 0;
2364   }
2365
2366   size_needed = sizeof (struct GNUNET_MESH_PeerControl);
2367   peer_info = (struct MeshPeerInfo *) cls;
2368   msg = (struct GNUNET_MESH_PeerControl *) buf;
2369   msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2370   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
2371 //     msg->tunnel_id = htonl(peer_info->t->tid);
2372   GNUNET_PEER_resolve (peer_info->id, &id);
2373   memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
2374
2375   return size_needed;
2376 }
2377 #endif
2378
2379
2380 /**
2381  * Function to process paths received for a new peer addition. The recorded
2382  * paths form the initial tunnel, which can be optimized later.
2383  * Called on each result obtained for the DHT search.
2384  *
2385  * @param cls closure
2386  * @param exp when will this value expire
2387  * @param key key of the result
2388  * @param get_path NULL-terminated array of pointers
2389  *                 to the peers on reverse GET path (or NULL if not recorded)
2390  * @param put_path NULL-terminated array of pointers
2391  *                 to the peers on the PUT path (or NULL if not recorded)
2392  * @param type type of the result
2393  * @param size number of bytes in data
2394  * @param data pointer to the result data
2395  *
2396  * FIXME path
2397  */
2398 static void
2399 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
2400                     const GNUNET_HashCode * key,
2401                     const struct GNUNET_PeerIdentity *const *get_path,
2402                     const struct GNUNET_PeerIdentity *const *put_path,
2403                     enum GNUNET_BLOCK_Type type, size_t size, const void *data)
2404 {
2405   struct MeshPathInfo *path_info = cls;
2406   struct MeshPeerPath *p;
2407   struct GNUNET_PeerIdentity pi;
2408   int i;
2409
2410   if (NULL == get_path || NULL == put_path)
2411   {
2412     if (NULL == path_info->peer->path_head)
2413     {
2414       // Find ourselves some alternate initial path to the destination: retry
2415       GNUNET_DHT_get_stop (path_info->peer->dhtget);
2416       GNUNET_PEER_resolve (path_info->peer->id, &pi);
2417       path_info->peer->dhtget = GNUNET_DHT_get_start (dht_handle,       /* handle */
2418                                                       GNUNET_TIME_UNIT_FOREVER_REL,     /* timeout */
2419                                                       GNUNET_BLOCK_TYPE_TEST,   /* type */
2420                                                       &pi.hashPubKey,   /*key to search */
2421                                                       4,        /* replication level */
2422                                                       GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
2423                                                       0,        /* mutator */
2424                                                       NULL,     /* xquery */
2425                                                       0,        /* xquery bits */
2426                                                       dht_get_id_handler,
2427                                                       (void *) path_info);
2428       return;
2429     }
2430   }
2431
2432   p = path_build_from_dht (get_path, put_path);
2433   path_add_to_peer (path_info->peer, p);
2434   for (i = 0; i < path_info->peer->ntunnels; i++)
2435   {
2436     tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer);
2437   }
2438   GNUNET_free (path_info);
2439
2440   return;
2441 }
2442
2443
2444 /**
2445  * Function to process paths received for a new peer addition. The recorded
2446  * paths form the initial tunnel, which can be optimized later.
2447  * Called on each result obtained for the DHT search.
2448  *
2449  * @param cls closure
2450  * @param exp when will this value expire
2451  * @param key key of the result
2452  * @param get_path NULL-terminated array of pointers
2453  *                 to the peers on reverse GET path (or NULL if not recorded)
2454  * @param put_path NULL-terminated array of pointers
2455  *                 to the peers on the PUT path (or NULL if not recorded)
2456  * @param type type of the result
2457  * @param size number of bytes in data
2458  * @param data pointer to the result data
2459  */
2460 static void
2461 dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
2462                       const GNUNET_HashCode * key,
2463                       const struct GNUNET_PeerIdentity *const *get_path,
2464                       const struct GNUNET_PeerIdentity *const *put_path,
2465                       enum GNUNET_BLOCK_Type type, size_t size,
2466                       const void *data)
2467 {
2468   const struct GNUNET_PeerIdentity *pi = data;
2469   struct GNUNET_PeerIdentity id;
2470   struct MeshTunnel *t = cls;
2471   struct MeshPeerInfo *peer_info;
2472   struct MeshPathInfo *path_info;
2473   struct MeshPeerPath *p;
2474   int i;
2475
2476   if (size != sizeof (struct GNUNET_PeerIdentity))
2477   {
2478     GNUNET_break_op (0);
2479     return;
2480   }
2481   GNUNET_assert (NULL != t->client);
2482   GNUNET_DHT_get_stop (t->client->dht_get_type);
2483   t->client->dht_get_type = NULL;
2484   peer_info = peer_info_get (pi);
2485   GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, peer_info,
2486                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2487
2488   if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path_head &&
2489       NULL == peer_info->dhtget)
2490   {
2491     /* we don't have a route to the peer, let's try a direct lookup */
2492     peer_info->dhtget = GNUNET_DHT_get_start (dht_handle,
2493                                               /* handle */
2494                                               GNUNET_TIME_UNIT_FOREVER_REL,
2495                                               /* timeout */
2496                                               GNUNET_BLOCK_TYPE_TEST,
2497                                               /* block type */
2498                                               &pi->hashPubKey,
2499                                               /* key to look up */
2500                                               10U,
2501                                               /* replication level */
2502                                               GNUNET_DHT_RO_RECORD_ROUTE,
2503                                               /* option to dht: record route */
2504                                               NULL,     /* bloom filter */
2505                                               0,        /* mutator */
2506                                               NULL,     /* xquery */
2507                                               0,        /* xquery bits */
2508                                               dht_get_id_handler,
2509                                               /* callback */
2510                                               peer_info);       /* closure */
2511   }
2512
2513   p = path_build_from_dht (get_path, put_path);
2514   path_add_to_peer (peer_info, p);
2515   tunnel_add_peer(t, peer_info);
2516   p = tunnel_get_path_to_peer(t, peer_info);
2517   path_info = GNUNET_malloc(sizeof(struct MeshPathInfo));
2518   path_info->t = t;
2519   path_info->peer = peer_info;
2520   path_info->path = p;
2521 #if MESH_DEBUG
2522   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2523               "MESH: new route for tunnel 0x%x found, has %u hops\n",
2524               t->local_tid, p->length);
2525   for (i = 0; i < p->length; i++)
2526   {
2527     GNUNET_PEER_resolve (p->peers[0], &id);
2528     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:\t%d\t%s\n", i,
2529                 GNUNET_h2s_full (&id.hashPubKey));
2530   }
2531 #endif
2532
2533   GNUNET_PEER_resolve (p->peers[1], &id);
2534   GNUNET_CORE_notify_transmit_ready (core_handle,
2535                                      /* handle */
2536                                      0,
2537                                      /* cork */
2538                                      0,
2539                                      /* priority */
2540                                      GNUNET_TIME_UNIT_FOREVER_REL,
2541                                      /* timeout */
2542                                      &id,
2543                                      /* target */
2544                                      sizeof (struct GNUNET_MESH_ManipulatePath)
2545                                      +
2546                                      (p->length *
2547                                       sizeof (struct GNUNET_PeerIdentity)),
2548                                      /*size */
2549                                      &send_core_create_path,
2550                                      /* callback */
2551                                      path_info);        /* cls */
2552 }
2553
2554 /******************************************************************************/
2555 /*********************       MESH LOCAL HANDLES      **************************/
2556 /******************************************************************************/
2557
2558
2559 /**
2560  * Handler for client disconnection
2561  *
2562  * @param cls closure
2563  * @param client identification of the client; NULL
2564  *        for the last call when the server is destroyed
2565  */
2566 static void
2567 handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
2568 {
2569   struct MeshClient *c;
2570   struct MeshClient *next;
2571
2572   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n");
2573   if (client == NULL)
2574      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    (SERVER DOWN)\n");
2575   c = clients;
2576   while (NULL != c)
2577   {
2578     if (c->handle != client && NULL != client)
2579     {
2580       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    ... searching\n");
2581       c = c->next;
2582       continue;
2583     }
2584     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: matching client found\n");
2585     if (NULL != c->tunnels)
2586     {
2587       GNUNET_CONTAINER_multihashmap_iterate (c->tunnels,
2588                                              &tunnel_destroy_iterator,
2589                                              c);
2590       GNUNET_CONTAINER_multihashmap_destroy (c->tunnels);
2591     }
2592
2593     /* deregister clients applications */
2594     if (NULL != c->apps)
2595     {
2596       GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, NULL);
2597       GNUNET_CONTAINER_multihashmap_destroy (c->apps);
2598     }
2599     if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
2600         GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
2601     {
2602       GNUNET_SCHEDULER_cancel (announce_applications_task);
2603       announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
2604     }
2605     if (NULL != c->types)
2606       GNUNET_CONTAINER_multihashmap_destroy (c->types);
2607     if (NULL != c->dht_get_type)
2608       GNUNET_DHT_get_stop (c->dht_get_type);
2609     GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
2610     next = c->next;
2611     GNUNET_free (c);
2612     c = next;
2613   }
2614
2615   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    done!\n");
2616   return;
2617 }
2618
2619
2620 /**
2621  * Handler for new clients
2622  *
2623  * @param cls closure
2624  * @param client identification of the client
2625  * @param message the actual message, which includes messages the client wants
2626  */
2627 static void
2628 handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
2629                          const struct GNUNET_MessageHeader *message)
2630 {
2631   struct GNUNET_MESH_ClientConnect *cc_msg;
2632   struct MeshClient *c;
2633   GNUNET_MESH_ApplicationType *a;
2634   unsigned int size;
2635   uint16_t ntypes;
2636   uint16_t *t;
2637   uint16_t napps;
2638   uint16_t i;
2639
2640   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n");
2641   /* Check data sanity */
2642   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
2643   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
2644   ntypes = ntohs (cc_msg->types);
2645   napps = ntohs (cc_msg->applications);
2646   if (size !=
2647       ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType))
2648   {
2649     GNUNET_break (0);
2650     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2651     return;
2652   }
2653
2654   /* Create new client structure */
2655   c = GNUNET_malloc (sizeof (struct MeshClient));
2656 #if MESH_DEBUG
2657   c->id = next_client_id++;
2658 #endif
2659   c->handle = client;
2660   a = (GNUNET_MESH_ApplicationType *) &cc_msg[1];
2661   if (napps > 0)
2662   {
2663     GNUNET_MESH_ApplicationType at;
2664     GNUNET_HashCode hc;
2665
2666     c->apps = GNUNET_CONTAINER_multihashmap_create (napps);
2667     for (i = 0; i < napps; i++)
2668     {
2669       at = ntohl (a[i]);
2670       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   app type: %u\n", at);
2671       GNUNET_CRYPTO_hash (&at, sizeof (at), &hc);
2672       /* store in clients hashmap */
2673       GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, c,
2674                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2675       /* store in global hashmap, for announcements */
2676       GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
2677                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2678     }
2679     if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
2680       announce_applications_task =
2681           GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
2682
2683   }
2684   if (ntypes > 0)
2685   {
2686     uint16_t u16;
2687     GNUNET_HashCode hc;
2688
2689     t = (uint16_t *) & a[napps];
2690     c->types = GNUNET_CONTAINER_multihashmap_create (ntypes);
2691     for (i = 0; i < ntypes; i++)
2692     {
2693       u16 = ntohs (t[i]);
2694       GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
2695
2696       /* store in clients hashmap */
2697       GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
2698                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2699       /* store in global hashmap */
2700       GNUNET_CONTAINER_multihashmap_put (types, &hc, c,
2701                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2702     }
2703   }
2704   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2705               "MESH:  client has %u+%u subscriptions\n", napps, ntypes);
2706
2707   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
2708   c->tunnels = GNUNET_CONTAINER_multihashmap_create (32);
2709   GNUNET_SERVER_notification_context_add (nc, client);
2710
2711   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2712 #if MESH_DEBUG
2713   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client processed\n");
2714 #endif
2715 }
2716
2717
2718 /**
2719  * Handler for requests of new tunnels
2720  *
2721  * @param cls closure
2722  * @param client identification of the client
2723  * @param message the actual message
2724  */
2725 static void
2726 handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
2727                             const struct GNUNET_MessageHeader *message)
2728 {
2729   struct GNUNET_MESH_TunnelMessage *t_msg;
2730   struct MeshTunnel *t;
2731   struct MeshClient *c;
2732   GNUNET_HashCode hash;
2733
2734   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n");
2735
2736   /* Sanity check for client registration */
2737   if (NULL == (c = client_get (client)))
2738   {
2739     GNUNET_break (0);
2740     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2741     return;
2742   }
2743 #if MESH_DEBUG
2744   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
2745 #endif
2746
2747   /* Message sanity check */
2748   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2749   {
2750     GNUNET_break (0);
2751     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2752     return;
2753   }
2754
2755   t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2756   /* Sanity check for tunnel numbering */
2757   if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
2758   {
2759     GNUNET_break (0);
2760     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2761     return;
2762   }
2763   /* Sanity check for duplicate tunnel IDs */
2764   if (NULL != tunnel_get_by_local_id (c, ntohl (t_msg->tunnel_id)))
2765   {
2766     GNUNET_break (0);
2767     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2768     return;
2769   }
2770
2771   t = GNUNET_malloc (sizeof (struct MeshTunnel));
2772   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL at %p\n", t);
2773   while (NULL != tunnel_get_by_pi (myid, next_tid))
2774     next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
2775   t->id.tid = next_tid++;
2776   t->id.oid = myid;
2777   t->local_tid = ntohl (t_msg->tunnel_id);
2778   t->client = c;
2779   t->peers = GNUNET_CONTAINER_multihashmap_create (32);
2780
2781   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2782   if (GNUNET_OK !=
2783       GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
2784                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2785   {
2786     GNUNET_break (0);
2787     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2788     return;
2789   }
2790
2791   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2792   if (GNUNET_OK !=
2793       GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
2794                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2795   {
2796     GNUNET_break (0);
2797     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2798     return;
2799   }
2800
2801   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2802   return;
2803 }
2804
2805
2806 /**
2807  * Handler for requests of deleting tunnels
2808  *
2809  * @param cls closure
2810  * @param client identification of the client
2811  * @param message the actual message
2812  */
2813 static void
2814 handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2815                              const struct GNUNET_MessageHeader *message)
2816 {
2817   struct GNUNET_MESH_TunnelMessage *tunnel_msg;
2818   struct MeshClient *c;
2819   struct MeshTunnel *t;
2820   MESH_TunnelNumber tid;
2821   GNUNET_HashCode hash;
2822
2823   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel\n");
2824
2825   /* Sanity check for client registration */
2826   if (NULL == (c = client_get (client)))
2827   {
2828     GNUNET_break (0);
2829     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2830     return;
2831   }
2832   /* Message sanity check */
2833   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2834   {
2835     GNUNET_break (0);
2836     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2837     return;
2838   }
2839 #if MESH_DEBUG
2840   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
2841 #endif
2842   tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2843
2844   /* Retrieve tunnel */
2845   tid = ntohl (tunnel_msg->tunnel_id);
2846
2847   /* Remove from local id hashmap */
2848   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
2849   t = GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
2850   GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t);
2851
2852   /* Remove from global id hashmap */
2853   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2854   GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t);
2855
2856 //     notify_tunnel_destroy(t); FIXME
2857   tunnel_destroy(t);
2858   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2859   return;
2860 }
2861
2862
2863 /**
2864  * Handler for connection requests to new peers
2865  *
2866  * @param cls closure
2867  * @param client identification of the client
2868  * @param message the actual message (PeerControl)
2869  *
2870  * FIXME path
2871  */
2872 static void
2873 handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
2874                           const struct GNUNET_MessageHeader *message)
2875 {
2876   struct GNUNET_MESH_PeerControl *peer_msg;
2877   struct MeshClient *c;
2878   struct MeshTunnel *t;
2879   MESH_TunnelNumber tid;
2880   struct MeshPeerInfo *peer_info;
2881
2882
2883   /* Sanity check for client registration */
2884   if (NULL == (c = client_get (client)))
2885   {
2886     GNUNET_break (0);
2887     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2888     return;
2889   }
2890
2891   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2892   /* Sanity check for message size */
2893   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2894   {
2895     GNUNET_break (0);
2896     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2897     return;
2898   }
2899
2900   /* Tunnel exists? */
2901   tid = ntohl (peer_msg->tunnel_id);
2902   t = tunnel_get_by_local_id (c, tid);
2903   if (NULL == t)
2904   {
2905     GNUNET_break (0);
2906     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2907     return;
2908   }
2909
2910   /* Does client own tunnel? */
2911   if (t->client->handle != client)
2912   {
2913     GNUNET_break (0);
2914     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2915     return;
2916   }
2917
2918   t->peers_total++;
2919   peer_info = peer_info_get (&peer_msg->peer);
2920
2921   /* Start DHT search if needed FIXME: if not already connected */
2922   if (NULL == peer_info->dhtget)
2923   {
2924     peer_info->dhtget = GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_BLOCK_TYPE_TEST, &peer_msg->peer.hashPubKey, 4,  /* replication level */
2925                                               GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
2926                                               0,        /* mutator */
2927                                               NULL,     /* xquery */
2928                                               0,        /* xquery bits */
2929                                               dht_get_id_handler,
2930                                               (void *) peer_info);
2931   }
2932
2933   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2934   return;
2935 }
2936
2937
2938 /**
2939  * Handler for disconnection requests of peers in a tunnel
2940  *
2941  * @param cls closure
2942  * @param client identification of the client
2943  * @param message the actual message (PeerControl)
2944  */
2945 static void
2946 handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
2947                           const struct GNUNET_MessageHeader *message)
2948 {
2949   struct GNUNET_MESH_PeerControl *peer_msg;
2950   struct MeshClient *c;
2951   struct MeshTunnel *t;
2952   MESH_TunnelNumber tid;
2953
2954   /* Sanity check for client registration */
2955   if (NULL == (c = client_get (client)))
2956   {
2957     GNUNET_break (0);
2958     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2959     return;
2960   }
2961   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2962   /* Sanity check for message size */
2963   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2964   {
2965     GNUNET_break (0);
2966     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2967     return;
2968   }
2969
2970   /* Tunnel exists? */
2971   tid = ntohl (peer_msg->tunnel_id);
2972   t = tunnel_get_by_local_id (c, tid);
2973   if (NULL == t)
2974   {
2975     GNUNET_break (0);
2976     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2977     return;
2978   }
2979
2980   /* Does client own tunnel? */
2981   if (t->client->handle != client)
2982   {
2983     GNUNET_break (0);
2984     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2985     return;
2986   }
2987
2988   /* Ok, delete peer from tunnel */
2989   GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
2990                                             &peer_msg->peer.hashPubKey);
2991
2992   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2993   return;
2994 }
2995
2996
2997 /**
2998  * Handler for connection requests to new peers by type
2999  *
3000  * @param cls closure
3001  * @param client identification of the client
3002  * @param message the actual message (ConnectPeerByType)
3003  */
3004 static void
3005 handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
3006                               const struct GNUNET_MessageHeader *message)
3007 {
3008   struct GNUNET_MESH_ConnectPeerByType *connect_msg;
3009   struct MeshClient *c;
3010   struct MeshTunnel *t;
3011   GNUNET_HashCode hash;
3012   GNUNET_MESH_ApplicationType type;
3013   MESH_TunnelNumber tid;
3014
3015   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got connect by type request\n");
3016   /* Sanity check for client registration */
3017   if (NULL == (c = client_get (client)))
3018   {
3019     GNUNET_break (0);
3020     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3021     return;
3022   }
3023
3024   connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
3025   /* Sanity check for message size */
3026   if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
3027       ntohs (connect_msg->header.size))
3028   {
3029     GNUNET_break (0);
3030     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3031     return;
3032   }
3033
3034   /* Tunnel exists? */
3035   tid = ntohl (connect_msg->tunnel_id);
3036   t = tunnel_get_by_local_id (c, tid);
3037   if (NULL == t)
3038   {
3039     GNUNET_break (0);
3040     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3041     return;
3042   }
3043
3044   /* Does client own tunnel? */
3045   if (t->client->handle != client)
3046   {
3047     GNUNET_break (0);
3048     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3049     return;
3050   }
3051
3052   /* Do WE have the service? */
3053   type = ntohl (connect_msg->type);
3054   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  type requested: %u\n", type);
3055   GNUNET_CRYPTO_hash (&type, sizeof (GNUNET_MESH_ApplicationType), &hash);
3056   if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
3057       GNUNET_YES)
3058   {
3059     /* Yes! Fast forward, add ourselves to the tunnel and send the
3060      * good news to the client
3061      */
3062     struct GNUNET_MESH_PeerControl pc;
3063
3064     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  available locally\n");
3065     pc.peer = my_full_id;
3066     GNUNET_CONTAINER_multihashmap_put (t->peers, &pc.peer.hashPubKey,
3067                                        peer_info_get (&pc.peer),
3068                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3069     pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
3070     pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
3071     pc.tunnel_id = htonl (t->local_tid);
3072     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  notifying client\n");
3073     GNUNET_SERVER_notification_context_unicast (nc,     /* context */
3074                                                 client, /* dest */
3075                                                 &pc.header,     /* msg */
3076                                                 GNUNET_NO);     /* can drop? */
3077     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  Done\n");
3078     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3079     return;
3080   }
3081   /* Ok, lets find a peer offering the service */
3082   if (c->dht_get_type)
3083   {
3084     GNUNET_DHT_get_stop (c->dht_get_type);
3085   }
3086   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  looking in DHT for %s\n",
3087               GNUNET_h2s_full (&hash));
3088   c->dht_get_type =
3089       GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL,
3090                             GNUNET_BLOCK_TYPE_TEST, &hash, 10U,
3091                             GNUNET_DHT_RO_RECORD_ROUTE, NULL, 0, NULL, 0,
3092                             &dht_get_type_handler, t);
3093
3094   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3095   return;
3096 }
3097
3098
3099 /**
3100  * Handler for client traffic directed to one peer
3101  *
3102  * @param cls closure
3103  * @param client identification of the client
3104  * @param message the actual message
3105  */
3106 static void
3107 handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
3108                       const struct GNUNET_MessageHeader *message)
3109 {
3110   struct MeshClient *c;
3111   struct MeshTunnel *t;
3112   struct MeshPeerInfo *pi;
3113   struct GNUNET_MESH_Unicast *data_msg;
3114   struct GNUNET_PeerIdentity next_hop;
3115   struct MeshDataDescriptor *info;
3116   MESH_TunnelNumber tid;
3117   size_t data_size;
3118
3119   /* Sanity check for client registration */
3120   if (NULL == (c = client_get (client)))
3121   {
3122     GNUNET_break (0);
3123     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3124     return;
3125   }
3126   data_msg = (struct GNUNET_MESH_Unicast *) message;
3127   /* Sanity check for message size */
3128   if (sizeof (struct GNUNET_MESH_Unicast) +
3129       sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
3130   {
3131     GNUNET_break (0);
3132     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3133     return;
3134   }
3135
3136   /* Tunnel exists? */
3137   tid = ntohl (data_msg->tid);
3138   t = tunnel_get_by_local_id (c, tid);
3139   if (NULL == t)
3140   {
3141     GNUNET_break (0);
3142     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3143     return;
3144   }
3145
3146   /*  Is it a local tunnel? Then, does client own the tunnel? */
3147   if (t->client->handle != NULL && t->client->handle != client)
3148   {
3149     GNUNET_break (0);
3150     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3151     return;
3152   }
3153
3154   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
3155                                           &data_msg->destination.hashPubKey);
3156   /* Is the selected peer in the tunnel? */
3157   if (NULL == pi)
3158   {
3159     GNUNET_break (0);
3160     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3161     return;
3162   }
3163   if (pi->id == myid)
3164   {
3165     struct GNUNET_MESH_Unicast copy;
3166
3167     /* Work around const limitation */
3168     memcpy (&copy, data_msg, sizeof (struct GNUNET_MESH_Unicast));
3169     copy.oid = my_full_id;
3170     copy.tid = htonl (t->id.tid);
3171     handle_mesh_data_unicast (NULL, &my_full_id, &copy.header, NULL);
3172     return;
3173   }
3174   GNUNET_PEER_resolve (path_get_first_hop (t, pi)->id, &next_hop);
3175   data_size = ntohs (message->size) - sizeof (struct GNUNET_MESH_Unicast);
3176   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + data_size);
3177   memcpy (&info[1], &data_msg[1], data_size);
3178   info->destination = pi->id;
3179   info->origin = &t->id;
3180   info->size = data_size;
3181   info->client = client;
3182   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
3183                                      GNUNET_TIME_UNIT_FOREVER_REL, &next_hop,
3184                                      /* FIXME re-check types */
3185                                      data_size +
3186                                      sizeof (struct GNUNET_MESH_Unicast),
3187                                      &send_core_data_unicast, info);
3188   return;
3189 }
3190
3191 /**
3192  * Handler for client traffic directed to all peers in a tunnel
3193  *
3194  * @param cls closure
3195  * @param client identification of the client
3196  * @param message the actual message
3197  */
3198 static void
3199 handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
3200                         const struct GNUNET_MessageHeader *message)
3201 {
3202   struct MeshClient *c;
3203   struct MeshTunnel *t;
3204   struct GNUNET_MESH_Multicast *data_msg;
3205   MESH_TunnelNumber tid;
3206
3207   /* Sanity check for client registration */
3208   if (NULL == (c = client_get (client)))
3209   {
3210     GNUNET_break (0);
3211     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3212     return;
3213   }
3214   data_msg = (struct GNUNET_MESH_Multicast *) message;
3215   /* Sanity check for message size */
3216   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (data_msg->header.size))
3217   {
3218     GNUNET_break (0);
3219     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3220     return;
3221   }
3222
3223   /* Tunnel exists? */
3224   tid = ntohl (data_msg->tid);
3225   t = tunnel_get_by_local_id (c, tid);
3226   if (NULL == t)
3227   {
3228     GNUNET_break (0);
3229     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3230     return;
3231   }
3232
3233   /* Does client own tunnel? */
3234   if (t->client->handle != client)
3235   {
3236     GNUNET_break (0);
3237     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3238     return;
3239   }
3240
3241   /*  TODO */
3242
3243   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3244   return;
3245 }
3246
3247 /**
3248  * Functions to handle messages from clients
3249  */
3250 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
3251   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
3252   {&handle_local_tunnel_create, NULL,
3253    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
3254    sizeof (struct GNUNET_MESH_TunnelMessage)},
3255   {&handle_local_tunnel_destroy, NULL,
3256    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
3257    sizeof (struct GNUNET_MESH_TunnelMessage)},
3258   {&handle_local_connect_add, NULL,
3259    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
3260    sizeof (struct GNUNET_MESH_PeerControl)},
3261   {&handle_local_connect_del, NULL,
3262    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
3263    sizeof (struct GNUNET_MESH_PeerControl)},
3264   {&handle_local_connect_by_type, NULL,
3265    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
3266    sizeof (struct GNUNET_MESH_ConnectPeerByType)},
3267   {&handle_local_unicast, NULL,
3268    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
3269   {&handle_local_unicast, NULL,
3270    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
3271   {&handle_local_multicast, NULL,
3272    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
3273   {NULL, NULL, 0, 0}
3274 };
3275
3276
3277 /**
3278  * To be called on core init/fail.
3279  *
3280  * @param cls service closure
3281  * @param server handle to the server for this service
3282  * @param identity the public identity of this peer
3283  * @param publicKey the public key of this peer
3284  */
3285 static void
3286 core_init (void *cls, struct GNUNET_CORE_Handle *server,
3287            const struct GNUNET_PeerIdentity *identity,
3288            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
3289 {
3290   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Core init\n");
3291   core_handle = server;
3292   my_full_id = *identity;
3293   myid = GNUNET_PEER_intern (identity);
3294   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
3295   return;
3296 }
3297
3298 /**
3299  * Method called whenever a given peer connects.
3300  *
3301  * @param cls closure
3302  * @param peer peer identity this notification is about
3303  * @param atsi performance data for the connection
3304  */
3305 static void
3306 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
3307               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
3308 {
3309 //     GNUNET_PEER_Id              pid;
3310   struct MeshPeerInfo *peer_info;
3311   struct MeshPeerPath *path;
3312
3313   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n");
3314   peer_info = peer_info_get (peer);
3315   if (myid == peer_info->id)
3316   {
3317     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
3318   }
3319   path = GNUNET_malloc (sizeof (struct MeshPeerPath));
3320   path->length = 2;
3321   path->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id) * 2);
3322   path->peers[0] = myid;
3323   path->peers[1] = peer_info->id;
3324   path_add_to_peer (peer_info, path);
3325   return;
3326 }
3327
3328 /**
3329  * Method called whenever a peer disconnects.
3330  *
3331  * @param cls closure
3332  * @param peer peer identity this notification is about
3333  */
3334 static void
3335 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
3336 {
3337   struct MeshPeerInfo *pi;
3338   unsigned int i;
3339
3340   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer disconnected\n");
3341   pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
3342   if (!pi)
3343   {
3344     GNUNET_break (0);
3345     return;
3346   }
3347   for (i = 0; i < CORE_QUEUE_SIZE; i++)
3348   {
3349     if (pi->core_transmit[i])
3350     {
3351       GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit[i]);
3352       /* TODO: notify that tranmission has failed */
3353       GNUNET_free (pi->infos[i]);
3354     }
3355   }
3356   path_remove_from_peer (pi, pi->id, myid);
3357   if (myid == pi->id)
3358   {
3359     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
3360   }
3361   return;
3362 }
3363
3364
3365 /******************************************************************************/
3366 /************************      MAIN FUNCTIONS      ****************************/
3367 /******************************************************************************/
3368
3369 /**
3370  * Task run during shutdown.
3371  *
3372  * @param cls unused
3373  * @param tc unused
3374  */
3375 static void
3376 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3377 {
3378   struct MeshClient *c;
3379
3380   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shutting down\n");
3381   if (core_handle != NULL)
3382   {
3383     GNUNET_CORE_disconnect (core_handle);
3384     core_handle = NULL;
3385   }
3386   if (dht_handle != NULL)
3387   {
3388     for (c = clients; NULL != c; c = c->next)
3389       if (NULL != c->dht_get_type)
3390         GNUNET_DHT_get_stop (c->dht_get_type);
3391     GNUNET_DHT_disconnect (dht_handle);
3392     dht_handle = NULL;
3393   }
3394   if (nc != NULL)
3395   {
3396     GNUNET_SERVER_notification_context_destroy (nc);
3397     nc = NULL;
3398   }
3399   if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
3400   {
3401     GNUNET_SCHEDULER_cancel (announce_id_task);
3402     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
3403   }
3404   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shut down\n");
3405 }
3406
3407 /**
3408  * Process mesh requests.
3409  *
3410  * @param cls closure
3411  * @param server the initialized server
3412  * @param c configuration to use
3413  */
3414 static void
3415 run (void *cls, struct GNUNET_SERVER_Handle *server,
3416      const struct GNUNET_CONFIGURATION_Handle *c)
3417 {
3418   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: starting to run\n");
3419   GNUNET_SERVER_add_handlers (server, client_handlers);
3420   GNUNET_SERVER_disconnect_notify (server,
3421                                    &handle_local_client_disconnect,
3422                                    NULL);
3423   server_handle = server;
3424   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
3425                                      CORE_QUEUE_SIZE,   /* queue size */
3426                                      NULL,      /* Closure passed to MESH functions */
3427                                      &core_init,        /* Call core_init once connected */
3428                                      &core_connect,     /* Handle connects */
3429                                      &core_disconnect,  /* remove peers on disconnects */
3430                                      NULL,      /* Do we care about "status" updates? */
3431                                      NULL,      /* Don't notify about all incoming messages */
3432                                      GNUNET_NO, /* For header only in notification */
3433                                      NULL,      /* Don't notify about all outbound messages */
3434                                      GNUNET_NO, /* For header-only out notification */
3435                                      core_handlers);    /* Register these handlers */
3436   if (core_handle == NULL)
3437   {
3438     GNUNET_break (0);
3439   }
3440   dht_handle = GNUNET_DHT_connect (c, 64);
3441   if (dht_handle == NULL)
3442   {
3443     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error connecting to DHT.\
3444                    Running without DHT has a severe\
3445                    impact in MESH capabilities.\n\
3446                    Plase check your configuretion and enable DHT.\n");
3447     GNUNET_break (0);
3448   }
3449
3450   next_tid = 0;
3451
3452   tunnels = GNUNET_CONTAINER_multihashmap_create (32);
3453   peers = GNUNET_CONTAINER_multihashmap_create (32);
3454   applications = GNUNET_CONTAINER_multihashmap_create (32);
3455   types = GNUNET_CONTAINER_multihashmap_create (32);
3456   nc = GNUNET_SERVER_notification_context_create (server_handle,
3457                                                   LOCAL_QUEUE_SIZE);
3458   clients = NULL;
3459   clients_tail = NULL;
3460 #if MESH_DEBUG
3461   next_client_id = 0;
3462 #endif
3463
3464   announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
3465
3466   /* Scheduled the task to clean up when shutdown is called */
3467   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
3468                                 NULL);
3469
3470   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: end of run()\n");
3471 }
3472
3473 /**
3474  * The main function for the mesh service.
3475  *
3476  * @param argc number of arguments from the command line
3477  * @param argv command line arguments
3478  * @return 0 ok, 1 on error
3479  */
3480 int
3481 main (int argc, char *const *argv)
3482 {
3483   int ret;
3484
3485   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main()\n");
3486   ret =
3487       (GNUNET_OK ==
3488        GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
3489                            NULL)) ? 0 : 1;
3490   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main() END\n");
3491   return ret;
3492 }