Fixed creation and destrucion of trees with parent tunnel
[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  * Recursively destory the path tree of a tunnel.
1416  * Note: it does not liberate memory for itself, parent must do it!
1417  *
1418  * @param n The node to destroy, along with children.
1419  *
1420  * @return GNUNET_OK on success
1421  */
1422 static void
1423 tunnel_destroy_tree_node (struct MeshTunnelPathNode *n)
1424 {
1425   unsigned int i;
1426
1427   for (i = 0; i < n->nchildren; i++)
1428   {
1429     tunnel_destroy_tree_node(&n->children[i]);
1430   }
1431   GNUNET_free (n->children);
1432 }
1433
1434
1435 /**
1436  * Destroy the tunnel and free any allocated resources linked to it
1437  *
1438  * @param t the tunnel to destroy
1439  *
1440  * @return GNUNET_OK on success
1441  */
1442 static int
1443 tunnel_destroy (struct MeshTunnel *t)
1444 {
1445   struct MeshClient *c;
1446   struct MeshQueue *q;
1447   struct MeshQueue *qn;
1448   GNUNET_HashCode hash;
1449   int r;
1450
1451   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: DESTROYING TUNNEL at %p\n", t);
1452   if (NULL == t)
1453     return GNUNET_OK;
1454
1455   c = t->client;
1456 #if MESH_DEBUG
1457   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
1458 #endif
1459
1460   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
1461   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
1462   {
1463     r = GNUNET_SYSERR;
1464   }
1465
1466   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
1467   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t))
1468   {
1469     r = GNUNET_SYSERR;
1470   }
1471   GNUNET_CONTAINER_multihashmap_destroy (t->peers);
1472   q = t->queue_head;
1473   while (NULL != q)
1474   {
1475     if (NULL != q->data)
1476       GNUNET_free (q->data);
1477     qn = q->next;
1478     GNUNET_free (q);
1479     q = qn;
1480     /* TODO cancel core transmit ready in case it was active */
1481   }
1482
1483   GNUNET_CONTAINER_multihashmap_destroy(t->paths->first_hops);
1484   tunnel_destroy_tree_node(t->paths->root);
1485   GNUNET_free(t->paths->root);
1486   GNUNET_free (t->paths);
1487   GNUNET_free (t);
1488   return r;
1489 }
1490
1491
1492 /**
1493  * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
1494  * client when the client disconnects.
1495  * 
1496  * @param cls closure (client that is disconnecting)
1497  * @param key the hash of the local tunnel id (used to access the hashmap)
1498  * @param value the value stored at the key (tunnel to destroy)
1499  * 
1500  * @return GNUNET_OK on success
1501  */
1502 static int
1503 tunnel_destroy_iterator (void *cls, const GNUNET_HashCode * key, void *value)
1504 {
1505   int r;
1506
1507   r = tunnel_destroy ((struct MeshTunnel *) value);
1508   return r;
1509 }
1510
1511
1512 /******************************************************************************/
1513 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
1514 /******************************************************************************/
1515
1516
1517 /**
1518  * Function called to notify a client about the socket
1519  * being ready to queue more data.  "buf" will be
1520  * NULL and "size" zero if the socket was closed for
1521  * writing in the meantime.
1522  *
1523  * @param cls closure
1524  * @param size number of bytes available in buf
1525  * @param buf where the callee should write the message
1526  * @return number of bytes written to buf
1527  */
1528 static size_t
1529 send_core_create_path (void *cls, size_t size, void *buf)
1530 {
1531   struct MeshPathInfo *info = cls;
1532   struct GNUNET_MESH_ManipulatePath *msg;
1533   struct GNUNET_PeerIdentity *peer_ptr;
1534   struct GNUNET_PeerIdentity id;
1535   struct MeshPeerInfo *peer = info->peer;
1536   struct MeshTunnel *t = info->t;
1537   struct MeshPeerPath *p = info->path;
1538   size_t size_needed;
1539   int i;
1540
1541   size_needed =
1542       sizeof (struct GNUNET_MESH_ManipulatePath) +
1543       p->length * sizeof (struct GNUNET_PeerIdentity);
1544
1545   if (size < size_needed || NULL == buf)
1546   {
1547     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Retransmitting create path\n");
1548     GNUNET_PEER_resolve (path_get_first_hop (t, peer)->id, &id);
1549     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
1550                                        GNUNET_TIME_UNIT_FOREVER_REL, &id,
1551                                        size_needed, &send_core_create_path,
1552                                        info);
1553     return 0;
1554   }
1555
1556   msg = (struct GNUNET_MESH_ManipulatePath *) buf;
1557   msg->header.size = htons (size_needed);
1558   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
1559   msg->tid = ntohl (t->id.tid);
1560
1561   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
1562   for (i = 0; i < p->length; i++)
1563   {
1564     GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
1565   }
1566
1567   path_destroy (p);
1568   GNUNET_free (info);
1569
1570   return size_needed;
1571 }
1572
1573
1574 #if LATER
1575 /**
1576  * Function called to notify a client about the socket
1577  * being ready to queue more data.  "buf" will be
1578  * NULL and "size" zero if the socket was closed for
1579  * writing in the meantime.
1580  *
1581  * @param cls closure (MeshDataDescriptor with all info to build packet)
1582  * @param size number of bytes available in buf
1583  * @param buf where the callee should write the message
1584  * @return number of bytes written to buf
1585  */
1586 static size_t
1587 send_core_data_to_origin (void *cls, size_t size, void *buf)
1588 {
1589   struct MeshDataDescriptor *info = cls;
1590   struct GNUNET_MESH_ToOrigin *msg = buf;
1591   size_t total_size;
1592
1593   GNUNET_assert (NULL != info);
1594   total_size = sizeof (struct GNUNET_MESH_ToOrigin) + info->size;
1595   GNUNET_assert (total_size < 65536);   /* UNIT16_MAX */
1596
1597   if (total_size > size)
1598   {
1599     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1600                 "not enough buffer to send data to origin\n");
1601     return 0;
1602   }
1603   msg->header.size = htons (total_size);
1604   msg->header.type = htons (GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
1605   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1606   msg->tid = htonl (info->origin->tid);
1607   if (0 != info->size)
1608   {
1609     memcpy (&msg[1], &info[1], info->size);
1610   }
1611   if (NULL != info->client)
1612   {
1613     GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
1614   }
1615   GNUNET_free (info);
1616   return total_size;
1617 }
1618 #endif
1619
1620 /**
1621  * Function called to notify a client about the socket
1622  * being ready to queue more data.  "buf" will be
1623  * NULL and "size" zero if the socket was closed for
1624  * writing in the meantime.
1625  *
1626  * @param cls closure (data itself)
1627  * @param size number of bytes available in buf
1628  * @param buf where the callee should write the message
1629  * @return number of bytes written to buf
1630  */
1631 static size_t
1632 send_core_data_unicast (void *cls, size_t size, void *buf)
1633 {
1634   struct MeshDataDescriptor *info = cls;
1635   struct GNUNET_MESH_Unicast *msg = buf;
1636   size_t total_size;
1637
1638   GNUNET_assert (NULL != info);
1639   total_size = sizeof (struct GNUNET_MESH_Unicast) + info->size;
1640   GNUNET_assert (total_size < 65536);   /* UNIT16_MAX */
1641
1642   if (total_size > size)
1643   {
1644     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1645                 "not enough buffer to send data to peer\n");
1646     return 0;
1647   }
1648   msg->header.size = htons (total_size);
1649   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1650   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1651   GNUNET_PEER_resolve (info->destination, &msg->destination);
1652   msg->tid = htonl (info->origin->tid);
1653   if (0 != info->size)
1654   {
1655     memcpy (&msg[1], &info[1], info->size);
1656   }
1657   if (NULL != info->client)
1658   {
1659     GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
1660   }
1661   GNUNET_free (info);
1662   return total_size;
1663 }
1664
1665
1666 /**
1667  * Function called to notify a client about the socket
1668  * being ready to queue more data.  "buf" will be
1669  * NULL and "size" zero if the socket was closed for
1670  * writing in the meantime.
1671  *
1672  * @param cls closure (data itself)
1673  * @param size number of bytes available in buf
1674  * @param buf where the callee should write the message
1675  * @return number of bytes written to buf
1676  */
1677 static size_t
1678 send_core_data_multicast (void *cls, size_t size, void *buf)
1679 {
1680   struct MeshDataDescriptor *info = cls;
1681   struct GNUNET_MESH_Multicast *msg = buf;
1682   size_t total_size;
1683
1684   GNUNET_assert (NULL != info);
1685   total_size = info->size + sizeof (struct GNUNET_MESH_Multicast);
1686   GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
1687
1688   if (info->peer)
1689   {
1690     info->peer->core_transmit[info->handler_n] = NULL;
1691   }
1692   if (total_size > size)
1693   {
1694     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1695                 "not enough buffer to send data futher\n");
1696     return 0;
1697   }
1698   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1699   msg->header.size = htons (total_size);
1700   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1701   msg->tid = htonl (info->origin->tid);
1702   memcpy (&msg[1], &info[1], total_size);
1703   if (0 == --info->copies)
1704   {
1705     if (NULL != info->client)
1706     {
1707       GNUNET_SERVER_receive_done (info->client, GNUNET_OK);
1708     }
1709     GNUNET_free (info);
1710   }
1711   return total_size;
1712 }
1713
1714
1715 /**
1716  * Function called to notify a client about the socket
1717  * being ready to queue more data.  "buf" will be
1718  * NULL and "size" zero if the socket was closed for
1719  * writing in the meantime.
1720  *
1721  * @param cls closure (MeshDataDescriptor)
1722  * @param size number of bytes available in buf
1723  * @param buf where the callee should write the message
1724  * @return number of bytes written to buf
1725  */
1726 static size_t
1727 send_core_path_ack (void *cls, size_t size, void *buf)
1728 {
1729   struct MeshDataDescriptor *info = cls;
1730   struct GNUNET_MESH_PathACK *msg = buf;
1731
1732   GNUNET_assert (NULL != info);
1733   if (info->peer)
1734   {
1735     info->peer->core_transmit[info->handler_n] = NULL;
1736   }
1737   if (sizeof (struct GNUNET_MESH_PathACK) > size)
1738   {
1739     GNUNET_break (0);
1740     return 0;
1741   }
1742   msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
1743   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
1744   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
1745   msg->tid = htonl (info->origin->tid);
1746   msg->peer_id = my_full_id;
1747   GNUNET_free (info);
1748   /* TODO add signature */
1749
1750   return sizeof (struct GNUNET_MESH_PathACK);
1751 }
1752
1753
1754 /**
1755  * Function called to notify a client about the socket
1756  * being ready to queue more data.  "buf" will be
1757  * NULL and "size" zero if the socket was closed for
1758  * writing in the meantime.
1759  *
1760  * @param cls closure (data itself)
1761  * @param size number of bytes available in buf
1762  * @param buf where the callee should write the message
1763  * @return number of bytes written to buf
1764  */
1765 static size_t
1766 send_core_data_raw (void *cls, size_t size, void *buf)
1767 {
1768   struct GNUNET_MessageHeader *msg = cls;
1769   size_t total_size;
1770
1771   GNUNET_assert (NULL != msg);
1772   total_size = ntohs (msg->size);
1773
1774   if (total_size > size)
1775   {
1776     GNUNET_break (0);
1777     return 0;
1778   }
1779   memcpy (buf, msg, total_size);
1780   GNUNET_free (cls);
1781   return total_size;
1782 }
1783
1784
1785 #if LATER
1786 /**
1787  * Send another peer a notification to destroy a tunnel
1788  * @param cls The tunnel to destroy
1789  * @param size Size in the buffer
1790  * @param buf Memory where to put the data to transmit
1791  * @return Size of data put in buffer
1792  */
1793 static size_t
1794 send_p2p_tunnel_destroy (void *cls, size_t size, void *buf)
1795 {
1796   struct MeshTunnel *t = cls;
1797   struct MeshClient *c;
1798   struct GNUNET_MESH_TunnelMessage *msg;
1799
1800   c = t->client;
1801   msg = buf;
1802   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1803    /*FIXME*/ msg->header.size =
1804       htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1805   msg->tunnel_id = htonl (t->id.tid);
1806
1807   tunnel_destroy (c, t);
1808   return sizeof (struct GNUNET_MESH_TunnelMessage);
1809 }
1810 #endif
1811
1812
1813 /**
1814  * Send the message to all clients that have subscribed to its type
1815  *
1816  * @param msg Pointer to the message itself
1817  * @return number of clients this message was sent to
1818  */
1819 static unsigned int
1820 send_subscribed_clients (struct GNUNET_MessageHeader *msg)
1821 {
1822   struct MeshClient *c;
1823   unsigned int count;
1824   uint16_t type;
1825
1826   type = ntohs (msg->type);
1827   for (count = 0, c = clients; c != NULL; c = c->next)
1828   {
1829     if (client_is_subscribed (type, c))
1830     {
1831       count++;
1832       GNUNET_SERVER_notification_context_unicast (nc, c->handle, msg,
1833                                                   GNUNET_YES);
1834     }
1835   }
1836   return count;
1837 }
1838
1839
1840 /**
1841  * Iterator over hash map peer entries collect all neighbors who to resend the
1842  * data to.
1843  *
1844  * @param cls closure (**GNUNET_PEER_Id to store hops to send packet)
1845  * @param key current key code (peer id hash)
1846  * @param value value in the hash map (peer_info)
1847  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
1848  */
1849 static int
1850 iterate_collect_neighbors (void *cls, const GNUNET_HashCode * key, void *value)
1851 {
1852   struct MeshPeerInfo *peer_info = value;
1853   struct MeshPathInfo *neighbors = cls;
1854   unsigned int i;
1855
1856   if (peer_info->id == myid)
1857   {
1858     return GNUNET_YES;
1859   }
1860   peer_info = path_get_first_hop (neighbors->t, peer_info);
1861   for (i = 0; i < neighbors->path->length; i++)
1862   {
1863     if (neighbors->path->peers[i] == peer_info->id)
1864       return GNUNET_YES;
1865   }
1866   GNUNET_array_append (neighbors->path->peers, neighbors->path->length,
1867                        peer_info->id);
1868
1869   return GNUNET_YES;
1870 }
1871
1872
1873 /******************************************************************************/
1874 /********************      MESH NETWORK HANDLERS     **************************/
1875 /******************************************************************************/
1876
1877
1878 /**
1879  * Core handler for path creation
1880  * struct GNUNET_CORE_MessageHandler
1881  *
1882  * @param cls closure
1883  * @param message message
1884  * @param peer peer identity this notification is about
1885  * @param atsi performance data
1886  * @return GNUNET_OK to keep the connection open,
1887  *         GNUNET_SYSERR to close it (signal serious error)
1888  *
1889  */
1890 static int
1891 handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1892                          const struct GNUNET_MessageHeader *message,
1893                          const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1894 {
1895   unsigned int own_pos;
1896   uint16_t size;
1897   uint16_t i;
1898   MESH_TunnelNumber tid;
1899   struct GNUNET_MESH_ManipulatePath *msg;
1900   struct GNUNET_PeerIdentity *pi;
1901   struct GNUNET_PeerIdentity id;
1902   GNUNET_HashCode hash;
1903   struct MeshPeerPath *path;
1904   struct MeshPeerInfo *dest_peer_info;
1905   struct MeshPeerInfo *orig_peer_info;
1906   struct MeshTunnel *t;
1907
1908   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1909               "MESH: Received a MESH path create msg\n");
1910   size = ntohs (message->size);
1911   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
1912   {
1913     GNUNET_break_op (0);
1914     return GNUNET_OK;
1915   }
1916
1917   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
1918   if (size % sizeof (struct GNUNET_PeerIdentity))
1919   {
1920     GNUNET_break_op (0);
1921     return GNUNET_OK;
1922   }
1923   size /= sizeof (struct GNUNET_PeerIdentity);
1924   if (size < 2)
1925   {
1926     GNUNET_break_op (0);
1927     return GNUNET_OK;
1928   }
1929   msg = (struct GNUNET_MESH_ManipulatePath *) message;
1930
1931   tid = ntohl (msg->tid);
1932   pi = (struct GNUNET_PeerIdentity *) &msg[1];
1933   t = tunnel_get (pi, tid);
1934
1935   if (NULL == t)
1936   {
1937     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Creating tunnel\n");
1938     t = GNUNET_malloc (sizeof (struct MeshTunnel));
1939     t->id.oid = GNUNET_PEER_intern (pi);
1940     t->id.tid = tid;
1941     t->peers = GNUNET_CONTAINER_multihashmap_create (32);
1942
1943     GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
1944     if (GNUNET_OK !=
1945         GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
1946                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1947     {
1948       GNUNET_break (0);
1949       return GNUNET_OK;
1950     }
1951
1952   }
1953   dest_peer_info =
1954       GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
1955   if (NULL == dest_peer_info)
1956   {
1957     dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1958     dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
1959     GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
1960                                        dest_peer_info,
1961                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1962   }
1963   orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
1964   if (NULL == orig_peer_info)
1965   {
1966     orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
1967     orig_peer_info->id = GNUNET_PEER_intern (pi);
1968     GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
1969                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1970   }
1971
1972   path = GNUNET_malloc (sizeof (struct MeshPeerPath));
1973   path->length = size;
1974   path->peers = GNUNET_malloc (size * sizeof (GNUNET_PEER_Id));
1975   own_pos = 0;
1976   for (i = 0; i < size; i++)
1977   {
1978     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
1979     if (path->peers[i] == myid)
1980       own_pos = i;
1981   }
1982   if (own_pos == 0)
1983   {                             /* cannot be self, must be 'not found' */
1984     /* create path: self not found in path through self */
1985     GNUNET_break_op (0);
1986     path_destroy (path);
1987     /* FIXME error. destroy tunnel? leave for timeout? */
1988     return 0;
1989   }
1990   if (own_pos == size - 1)
1991   {
1992     /* It is for us! Send ack. */
1993     struct MeshDataDescriptor *info;
1994     unsigned int j;
1995
1996     path_add_to_origin (orig_peer_info, path);  /* inverts path!  */
1997     info = GNUNET_malloc (sizeof (struct MeshDataDescriptor));
1998     info->origin = &t->id;
1999     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
2000     GNUNET_assert (info->peer);
2001     for (j = 0; info->peer->core_transmit[j]; j++)
2002     {
2003       if (j == 9)
2004       {
2005         GNUNET_break (0);
2006         return GNUNET_OK;
2007       }
2008     }
2009     info->handler_n = j;
2010     info->peer->core_transmit[j] =
2011         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
2012                                            GNUNET_TIME_UNIT_FOREVER_REL, peer,
2013                                            sizeof (struct GNUNET_MessageHeader),
2014                                            &send_core_path_ack, info);
2015   }
2016   else
2017   {
2018     /* It's for somebody else! Retransmit. */
2019     struct MeshPathInfo *path_info;
2020
2021     path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
2022     path_info->t = t;
2023     path_info->path = path;
2024     path_info->peer = dest_peer_info;
2025
2026     path_add_to_peer (dest_peer_info, path);
2027     GNUNET_PEER_resolve (path->peers[own_pos + 1], &id);
2028     GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2029                                        GNUNET_TIME_UNIT_FOREVER_REL, &id,
2030                                        sizeof (struct GNUNET_MessageHeader),
2031                                        &send_core_create_path, path_info);
2032   }
2033   return GNUNET_OK;
2034 }
2035
2036
2037 /**
2038  * Core handler for mesh network traffic going from the origin to a peer
2039  *
2040  * @param cls closure
2041  * @param peer peer identity this notification is about
2042  * @param message message
2043  * @param atsi performance data
2044  * @return GNUNET_OK to keep the connection open,
2045  *         GNUNET_SYSERR to close it (signal serious error)
2046  */
2047 static int
2048 handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
2049                           const struct GNUNET_MessageHeader *message,
2050                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2051 {
2052   struct GNUNET_MESH_Unicast *msg;
2053   struct GNUNET_PeerIdentity id;
2054   struct MeshTunnel *t;
2055   struct MeshPeerInfo *pi;
2056   size_t size;
2057
2058   size = ntohs (message->size);
2059   if (size <
2060       sizeof (struct GNUNET_MESH_Unicast) +
2061       sizeof (struct GNUNET_MessageHeader))
2062   {
2063     GNUNET_break (0);
2064     return GNUNET_OK;
2065   }
2066   msg = (struct GNUNET_MESH_Unicast *) message;
2067   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2068   if (NULL == t)
2069   {
2070     /* TODO notify back: we don't know this tunnel */
2071     return GNUNET_OK;
2072   }
2073   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
2074                                           &msg->destination.hashPubKey);
2075   if (NULL == pi)
2076   {
2077     /* TODO maybe feedback, log to statistics */
2078     return GNUNET_OK;
2079   }
2080   if (pi->id == myid)
2081   {
2082     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
2083     return GNUNET_OK;
2084   }
2085   GNUNET_PEER_resolve (path_get_first_hop (t, pi)->id, &id);
2086   msg = GNUNET_malloc (size);
2087   memcpy (msg, message, size);
2088   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2089                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
2090                                      &send_core_data_raw, msg);
2091   return GNUNET_OK;
2092 }
2093
2094
2095 /**
2096  * Core handler for mesh network traffic going from the origin to all peers
2097  *
2098  * @param cls closure
2099  * @param message message
2100  * @param peer peer identity this notification is about
2101  * @param atsi performance data
2102  * @return GNUNET_OK to keep the connection open,
2103  *         GNUNET_SYSERR to close it (signal serious error)
2104  */
2105 static int
2106 handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
2107                             const struct GNUNET_MessageHeader *message,
2108                             const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2109 {
2110   struct GNUNET_MESH_Multicast *msg;
2111   struct GNUNET_PeerIdentity id;
2112   struct MeshDataDescriptor *info;
2113   struct MeshPathInfo neighbors;
2114   struct MeshTunnel *t;
2115   size_t size;
2116   uint16_t i;
2117   uint16_t j;
2118
2119
2120   size = ntohs (message->size);
2121   if (size <
2122       sizeof (struct GNUNET_MESH_Multicast) +
2123       sizeof (struct GNUNET_MessageHeader))
2124   {
2125     GNUNET_break_op (0);
2126     return GNUNET_OK;
2127   }
2128   msg = (struct GNUNET_MESH_Multicast *) message;
2129   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2130
2131   if (NULL == t)
2132   {
2133     /* TODO notify that we dont know that tunnel */
2134     return GNUNET_OK;
2135   }
2136
2137   /* Transmit to locally interested clients */
2138   if (GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey))
2139   {
2140     send_subscribed_clients ((struct GNUNET_MessageHeader *) &msg[1]);
2141   }
2142
2143   /* Retransmit to other peers.
2144    * Using path here as just a collection of peers, not a path per se.
2145    */
2146   neighbors.t = t;
2147   neighbors.path = GNUNET_malloc (sizeof (struct MeshPeerPath));
2148   GNUNET_CONTAINER_multihashmap_iterate (t->peers, &iterate_collect_neighbors,
2149                                          &neighbors);
2150   if (0 == neighbors.path->length)
2151   {
2152     GNUNET_free (neighbors.path);
2153     return GNUNET_OK;
2154   }
2155   size -= sizeof (struct GNUNET_MESH_Multicast);
2156   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + size);
2157   info->origin = &t->id;
2158   info->copies = neighbors.path->length;
2159   for (i = 0; i < info->copies; i++)
2160   {
2161     GNUNET_PEER_resolve (neighbors.path->peers[i], &id);
2162     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &id.hashPubKey);
2163     GNUNET_assert (NULL != info->peer);
2164     for (j = 0; 0 != info->peer->core_transmit[j]; j++)
2165     {
2166       if (j == (CORE_QUEUE_SIZE - 1))
2167       {
2168         GNUNET_break (0);
2169         return GNUNET_OK;
2170       }
2171     }
2172     info->handler_n = j;
2173     info->peer->infos[j] = info;
2174     info->peer->core_transmit[j] =
2175         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2176                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
2177                                            ntohs (msg->header.size),
2178                                            &send_core_data_multicast, info);
2179   }
2180   GNUNET_free (neighbors.path->peers);
2181   GNUNET_free (neighbors.path);
2182   return GNUNET_OK;
2183 }
2184
2185
2186 /**
2187  * Core handler for mesh network traffic
2188  *
2189  * @param cls closure
2190  * @param message message
2191  * @param peer peer identity this notification is about
2192  * @param atsi performance data
2193  *
2194  * @return GNUNET_OK to keep the connection open,
2195  *         GNUNET_SYSERR to close it (signal serious error)
2196  */
2197 static int
2198 handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
2199                           const struct GNUNET_MessageHeader *message,
2200                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2201 {
2202   struct GNUNET_MESH_ToOrigin *msg;
2203   struct GNUNET_PeerIdentity id;
2204   struct MeshPeerInfo *peer_info;
2205   struct MeshTunnel *t;
2206   size_t size;
2207
2208   size = ntohs (message->size);
2209   if (size < sizeof (struct GNUNET_MESH_ToOrigin) +     /* Payload must be */
2210       sizeof (struct GNUNET_MessageHeader))     /* at least a header */
2211   {
2212     GNUNET_break_op (0);
2213     return GNUNET_OK;
2214   }
2215   msg = (struct GNUNET_MESH_ToOrigin *) message;
2216   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2217
2218   if (NULL == t)
2219   {
2220     /* TODO notify that we dont know this tunnel (whom)? */
2221     return GNUNET_OK;
2222   }
2223
2224   if (t->id.oid == myid)
2225   {
2226     if (NULL == t->client)
2227     {
2228       /* got data packet for ownerless tunnel */
2229       GNUNET_break_op (0);
2230       return GNUNET_OK;
2231     }
2232     /* TODO signature verification */
2233     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, message,
2234                                                 GNUNET_YES);
2235     return GNUNET_OK;
2236   }
2237   peer_info = peer_info_get (&msg->oid);
2238   if (NULL == peer_info)
2239   {
2240     /* unknown origin of tunnel */
2241     GNUNET_break (0);
2242     return GNUNET_OK;
2243   }
2244   GNUNET_PEER_resolve (t->paths->me->parent->peer->id, &id);
2245   msg = GNUNET_malloc (size);
2246   memcpy (msg, message, size);
2247   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2248                                      GNUNET_TIME_UNIT_FOREVER_REL, &id, size,
2249                                      &send_core_data_raw, msg);
2250
2251   return GNUNET_OK;
2252 }
2253
2254
2255 /**
2256  * Core handler for path ACKs
2257  *
2258  * @param cls closure
2259  * @param message message
2260  * @param peer peer identity this notification is about
2261  * @param atsi performance data
2262  *
2263  * @return GNUNET_OK to keep the connection open,
2264  *         GNUNET_SYSERR to close it (signal serious error)
2265  *
2266  * FIXME path change state
2267  */
2268 static int
2269 handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
2270                       const struct GNUNET_MessageHeader *message,
2271                       const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2272 {
2273   struct GNUNET_MESH_PathACK *msg;
2274   struct GNUNET_PeerIdentity id;
2275   struct MeshTunnel *t;
2276   struct MeshPeerInfo *peer_info;
2277
2278   msg = (struct GNUNET_MESH_PathACK *) message;
2279   t = tunnel_get (&msg->oid, msg->tid);
2280   if (NULL == t)
2281   {
2282     /* TODO notify that we don't know the tunnel */
2283     return GNUNET_OK;
2284   }
2285
2286   /* Message for us? */
2287   if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
2288   {
2289     struct GNUNET_MESH_PeerControl pc;
2290
2291     if (NULL == t->client)
2292     {
2293       GNUNET_break (0);
2294       return GNUNET_OK;
2295     }
2296     peer_info = peer_info_get (&msg->peer_id);
2297     if (NULL == peer_info)
2298     {
2299       GNUNET_break_op (0);
2300       return GNUNET_OK;
2301     }
2302     /* FIXME change state of peer */
2303     pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
2304     pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2305     pc.tunnel_id = htonl (t->local_tid);
2306     GNUNET_PEER_resolve (peer_info->id, &pc.peer);
2307     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
2308                                                 &pc.header, GNUNET_NO);
2309     return GNUNET_OK;
2310   }
2311
2312   peer_info = peer_info_get (&msg->oid);
2313   if (NULL == peer_info)
2314   {
2315     /* If we know the tunnel, we should DEFINITELY know the peer */
2316     GNUNET_break (0);
2317     return GNUNET_OK;
2318   }
2319   GNUNET_PEER_resolve (path_get_first_hop (t, peer_info)->id, &id);
2320   msg = GNUNET_malloc (sizeof (struct GNUNET_MESH_PathACK));
2321   memcpy (msg, message, sizeof (struct GNUNET_MESH_PathACK));
2322   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2323                                      GNUNET_TIME_UNIT_FOREVER_REL, &id,
2324                                      sizeof (struct GNUNET_MESH_PathACK),
2325                                      &send_core_data_raw, msg);
2326   return GNUNET_OK;
2327 }
2328
2329
2330 /**
2331  * Functions to handle messages from core
2332  */
2333 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
2334   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
2335   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
2336   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
2337   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
2338   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
2339    sizeof (struct GNUNET_MESH_PathACK)},
2340   {NULL, 0, 0}
2341 };
2342
2343
2344
2345 /******************************************************************************/
2346 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
2347 /******************************************************************************/
2348
2349 /**
2350  * deregister_app: iterator for removing each application registered by a client
2351  * 
2352  * @param cls closure
2353  * @param key the hash of the application id (used to access the hashmap)
2354  * @param value the value stored at the key (client)
2355  * 
2356  * @return GNUNET_OK on success
2357  */
2358 static int
2359 deregister_app (void *cls, const GNUNET_HashCode * key, void *value)
2360 {
2361   GNUNET_CONTAINER_multihashmap_remove (applications, key, value);
2362   return GNUNET_OK;
2363 }
2364
2365 #if LATER
2366 /**
2367  * notify_client_connection_failure: notify a client that the connection to the
2368  * requested remote peer is not possible (for instance, no route found)
2369  * Function called when the socket is ready to queue more data. "buf" will be
2370  * NULL and "size" zero if the socket was closed for writing in the meantime.
2371  *
2372  * @param cls closure
2373  * @param size number of bytes available in buf
2374  * @param buf where the callee should write the message
2375  * @return number of bytes written to buf
2376  */
2377 static size_t
2378 notify_client_connection_failure (void *cls, size_t size, void *buf)
2379 {
2380   int size_needed;
2381   struct MeshPeerInfo *peer_info;
2382   struct GNUNET_MESH_PeerControl *msg;
2383   struct GNUNET_PeerIdentity id;
2384
2385   if (0 == size && NULL == buf)
2386   {
2387     // TODO retry? cancel?
2388     return 0;
2389   }
2390
2391   size_needed = sizeof (struct GNUNET_MESH_PeerControl);
2392   peer_info = (struct MeshPeerInfo *) cls;
2393   msg = (struct GNUNET_MESH_PeerControl *) buf;
2394   msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2395   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
2396 //     msg->tunnel_id = htonl(peer_info->t->tid);
2397   GNUNET_PEER_resolve (peer_info->id, &id);
2398   memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
2399
2400   return size_needed;
2401 }
2402 #endif
2403
2404
2405 /**
2406  * Function to process paths received for a new peer addition. The recorded
2407  * paths form the initial tunnel, which can be optimized later.
2408  * Called on each result obtained for the DHT search.
2409  *
2410  * @param cls closure
2411  * @param exp when will this value expire
2412  * @param key key of the result
2413  * @param get_path NULL-terminated array of pointers
2414  *                 to the peers on reverse GET path (or NULL if not recorded)
2415  * @param put_path NULL-terminated array of pointers
2416  *                 to the peers on the PUT path (or NULL if not recorded)
2417  * @param type type of the result
2418  * @param size number of bytes in data
2419  * @param data pointer to the result data
2420  *
2421  * FIXME path
2422  */
2423 static void
2424 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
2425                     const GNUNET_HashCode * key,
2426                     const struct GNUNET_PeerIdentity *const *get_path,
2427                     const struct GNUNET_PeerIdentity *const *put_path,
2428                     enum GNUNET_BLOCK_Type type, size_t size, const void *data)
2429 {
2430   struct MeshPathInfo *path_info = cls;
2431   struct MeshPeerPath *p;
2432   struct GNUNET_PeerIdentity pi;
2433   int i;
2434
2435   if (NULL == get_path || NULL == put_path)
2436   {
2437     if (NULL == path_info->peer->path_head)
2438     {
2439       // Find ourselves some alternate initial path to the destination: retry
2440       GNUNET_DHT_get_stop (path_info->peer->dhtget);
2441       GNUNET_PEER_resolve (path_info->peer->id, &pi);
2442       path_info->peer->dhtget = GNUNET_DHT_get_start (dht_handle,       /* handle */
2443                                                       GNUNET_TIME_UNIT_FOREVER_REL,     /* timeout */
2444                                                       GNUNET_BLOCK_TYPE_TEST,   /* type */
2445                                                       &pi.hashPubKey,   /*key to search */
2446                                                       4,        /* replication level */
2447                                                       GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
2448                                                       0,        /* mutator */
2449                                                       NULL,     /* xquery */
2450                                                       0,        /* xquery bits */
2451                                                       dht_get_id_handler,
2452                                                       (void *) path_info);
2453       return;
2454     }
2455   }
2456
2457   p = path_build_from_dht (get_path, put_path);
2458   path_add_to_peer (path_info->peer, p);
2459   for (i = 0; i < path_info->peer->ntunnels; i++)
2460   {
2461     tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer);
2462   }
2463   GNUNET_free (path_info);
2464
2465   return;
2466 }
2467
2468
2469 /**
2470  * Function to process paths received for a new peer addition. The recorded
2471  * paths form the initial tunnel, which can be optimized later.
2472  * Called on each result obtained for the DHT search.
2473  *
2474  * @param cls closure
2475  * @param exp when will this value expire
2476  * @param key key of the result
2477  * @param get_path NULL-terminated array of pointers
2478  *                 to the peers on reverse GET path (or NULL if not recorded)
2479  * @param put_path NULL-terminated array of pointers
2480  *                 to the peers on the PUT path (or NULL if not recorded)
2481  * @param type type of the result
2482  * @param size number of bytes in data
2483  * @param data pointer to the result data
2484  */
2485 static void
2486 dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
2487                       const GNUNET_HashCode * key,
2488                       const struct GNUNET_PeerIdentity *const *get_path,
2489                       const struct GNUNET_PeerIdentity *const *put_path,
2490                       enum GNUNET_BLOCK_Type type, size_t size,
2491                       const void *data)
2492 {
2493   const struct GNUNET_PeerIdentity *pi = data;
2494   struct GNUNET_PeerIdentity id;
2495   struct MeshTunnel *t = cls;
2496   struct MeshPeerInfo *peer_info;
2497   struct MeshPathInfo *path_info;
2498   struct MeshPeerPath *p;
2499   int i;
2500
2501   if (size != sizeof (struct GNUNET_PeerIdentity))
2502   {
2503     GNUNET_break_op (0);
2504     return;
2505   }
2506   GNUNET_assert (NULL != t->client);
2507   GNUNET_DHT_get_stop (t->client->dht_get_type);
2508   t->client->dht_get_type = NULL;
2509   peer_info = peer_info_get (pi);
2510   GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey, peer_info,
2511                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2512
2513   if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path_head &&
2514       NULL == peer_info->dhtget)
2515   {
2516     /* we don't have a route to the peer, let's try a direct lookup */
2517     peer_info->dhtget = GNUNET_DHT_get_start (dht_handle,
2518                                               /* handle */
2519                                               GNUNET_TIME_UNIT_FOREVER_REL,
2520                                               /* timeout */
2521                                               GNUNET_BLOCK_TYPE_TEST,
2522                                               /* block type */
2523                                               &pi->hashPubKey,
2524                                               /* key to look up */
2525                                               10U,
2526                                               /* replication level */
2527                                               GNUNET_DHT_RO_RECORD_ROUTE,
2528                                               /* option to dht: record route */
2529                                               NULL,     /* bloom filter */
2530                                               0,        /* mutator */
2531                                               NULL,     /* xquery */
2532                                               0,        /* xquery bits */
2533                                               dht_get_id_handler,
2534                                               /* callback */
2535                                               peer_info);       /* closure */
2536   }
2537
2538   p = path_build_from_dht (get_path, put_path);
2539   path_add_to_peer (peer_info, p);
2540   tunnel_add_peer(t, peer_info);
2541   p = tunnel_get_path_to_peer(t, peer_info);
2542   path_info = GNUNET_malloc(sizeof(struct MeshPathInfo));
2543   path_info->t = t;
2544   path_info->peer = peer_info;
2545   path_info->path = p;
2546 #if MESH_DEBUG
2547   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2548               "MESH: new route for tunnel 0x%x found, has %u hops\n",
2549               t->local_tid, p->length);
2550   for (i = 0; i < p->length; i++)
2551   {
2552     GNUNET_PEER_resolve (p->peers[0], &id);
2553     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:\t%d\t%s\n", i,
2554                 GNUNET_h2s_full (&id.hashPubKey));
2555   }
2556 #endif
2557
2558   GNUNET_PEER_resolve (p->peers[1], &id);
2559   GNUNET_CORE_notify_transmit_ready (core_handle,
2560                                      /* handle */
2561                                      0,
2562                                      /* cork */
2563                                      0,
2564                                      /* priority */
2565                                      GNUNET_TIME_UNIT_FOREVER_REL,
2566                                      /* timeout */
2567                                      &id,
2568                                      /* target */
2569                                      sizeof (struct GNUNET_MESH_ManipulatePath)
2570                                      +
2571                                      (p->length *
2572                                       sizeof (struct GNUNET_PeerIdentity)),
2573                                      /*size */
2574                                      &send_core_create_path,
2575                                      /* callback */
2576                                      path_info);        /* cls */
2577 }
2578
2579 /******************************************************************************/
2580 /*********************       MESH LOCAL HANDLES      **************************/
2581 /******************************************************************************/
2582
2583
2584 /**
2585  * Handler for client disconnection
2586  *
2587  * @param cls closure
2588  * @param client identification of the client; NULL
2589  *        for the last call when the server is destroyed
2590  */
2591 static void
2592 handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
2593 {
2594   struct MeshClient *c;
2595   struct MeshClient *next;
2596
2597   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n");
2598   if (client == NULL)
2599      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    (SERVER DOWN)\n");
2600   c = clients;
2601   while (NULL != c)
2602   {
2603     if (c->handle != client && NULL != client)
2604     {
2605       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    ... searching\n");
2606       c = c->next;
2607       continue;
2608     }
2609     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: matching client found\n");
2610     if (NULL != c->tunnels)
2611     {
2612       GNUNET_CONTAINER_multihashmap_iterate (c->tunnels,
2613                                              &tunnel_destroy_iterator,
2614                                              c);
2615       GNUNET_CONTAINER_multihashmap_destroy (c->tunnels);
2616     }
2617
2618     /* deregister clients applications */
2619     if (NULL != c->apps)
2620     {
2621       GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, NULL);
2622       GNUNET_CONTAINER_multihashmap_destroy (c->apps);
2623     }
2624     if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
2625         GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
2626     {
2627       GNUNET_SCHEDULER_cancel (announce_applications_task);
2628       announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
2629     }
2630     if (NULL != c->types)
2631       GNUNET_CONTAINER_multihashmap_destroy (c->types);
2632     if (NULL != c->dht_get_type)
2633       GNUNET_DHT_get_stop (c->dht_get_type);
2634     GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
2635     next = c->next;
2636     GNUNET_free (c);
2637     c = next;
2638   }
2639
2640   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    done!\n");
2641   return;
2642 }
2643
2644
2645 /**
2646  * Handler for new clients
2647  *
2648  * @param cls closure
2649  * @param client identification of the client
2650  * @param message the actual message, which includes messages the client wants
2651  */
2652 static void
2653 handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
2654                          const struct GNUNET_MessageHeader *message)
2655 {
2656   struct GNUNET_MESH_ClientConnect *cc_msg;
2657   struct MeshClient *c;
2658   GNUNET_MESH_ApplicationType *a;
2659   unsigned int size;
2660   uint16_t ntypes;
2661   uint16_t *t;
2662   uint16_t napps;
2663   uint16_t i;
2664
2665   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n");
2666   /* Check data sanity */
2667   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
2668   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
2669   ntypes = ntohs (cc_msg->types);
2670   napps = ntohs (cc_msg->applications);
2671   if (size !=
2672       ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType))
2673   {
2674     GNUNET_break (0);
2675     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2676     return;
2677   }
2678
2679   /* Create new client structure */
2680   c = GNUNET_malloc (sizeof (struct MeshClient));
2681 #if MESH_DEBUG
2682   c->id = next_client_id++;
2683 #endif
2684   c->handle = client;
2685   a = (GNUNET_MESH_ApplicationType *) &cc_msg[1];
2686   if (napps > 0)
2687   {
2688     GNUNET_MESH_ApplicationType at;
2689     GNUNET_HashCode hc;
2690
2691     c->apps = GNUNET_CONTAINER_multihashmap_create (napps);
2692     for (i = 0; i < napps; i++)
2693     {
2694       at = ntohl (a[i]);
2695       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   app type: %u\n", at);
2696       GNUNET_CRYPTO_hash (&at, sizeof (at), &hc);
2697       /* store in clients hashmap */
2698       GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, c,
2699                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2700       /* store in global hashmap, for announcements */
2701       GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
2702                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2703     }
2704     if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
2705       announce_applications_task =
2706           GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
2707
2708   }
2709   if (ntypes > 0)
2710   {
2711     uint16_t u16;
2712     GNUNET_HashCode hc;
2713
2714     t = (uint16_t *) & a[napps];
2715     c->types = GNUNET_CONTAINER_multihashmap_create (ntypes);
2716     for (i = 0; i < ntypes; i++)
2717     {
2718       u16 = ntohs (t[i]);
2719       GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
2720
2721       /* store in clients hashmap */
2722       GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
2723                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2724       /* store in global hashmap */
2725       GNUNET_CONTAINER_multihashmap_put (types, &hc, c,
2726                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
2727     }
2728   }
2729   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2730               "MESH:  client has %u+%u subscriptions\n", napps, ntypes);
2731
2732   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
2733   c->tunnels = GNUNET_CONTAINER_multihashmap_create (32);
2734   GNUNET_SERVER_notification_context_add (nc, client);
2735
2736   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2737 #if MESH_DEBUG
2738   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client processed\n");
2739 #endif
2740 }
2741
2742
2743 /**
2744  * Handler for requests of new tunnels
2745  *
2746  * @param cls closure
2747  * @param client identification of the client
2748  * @param message the actual message
2749  */
2750 static void
2751 handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
2752                             const struct GNUNET_MessageHeader *message)
2753 {
2754   struct GNUNET_MESH_TunnelMessage *t_msg;
2755   struct MeshTunnel *t;
2756   struct MeshClient *c;
2757   GNUNET_HashCode hash;
2758
2759   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n");
2760
2761   /* Sanity check for client registration */
2762   if (NULL == (c = client_get (client)))
2763   {
2764     GNUNET_break (0);
2765     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2766     return;
2767   }
2768 #if MESH_DEBUG
2769   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
2770 #endif
2771
2772   /* Message sanity check */
2773   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2774   {
2775     GNUNET_break (0);
2776     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2777     return;
2778   }
2779
2780   t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2781   /* Sanity check for tunnel numbering */
2782   if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
2783   {
2784     GNUNET_break (0);
2785     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2786     return;
2787   }
2788   /* Sanity check for duplicate tunnel IDs */
2789   if (NULL != tunnel_get_by_local_id (c, ntohl (t_msg->tunnel_id)))
2790   {
2791     GNUNET_break (0);
2792     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2793     return;
2794   }
2795
2796   t = GNUNET_malloc (sizeof (struct MeshTunnel));
2797   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL at %p\n", t);
2798   while (NULL != tunnel_get_by_pi (myid, next_tid))
2799     next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
2800   t->id.tid = next_tid++;
2801   t->id.oid = myid;
2802   t->local_tid = ntohl (t_msg->tunnel_id);
2803   t->client = c;
2804   t->peers = GNUNET_CONTAINER_multihashmap_create (32);
2805
2806   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2807   if (GNUNET_OK !=
2808       GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
2809                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2810   {
2811     GNUNET_break (0);
2812     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2813     return;
2814   }
2815
2816   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2817   if (GNUNET_OK !=
2818       GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
2819                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
2820   {
2821     GNUNET_break (0);
2822     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2823     return;
2824   }
2825   t->paths = GNUNET_malloc (sizeof(struct MeshTunnelPath));
2826   t->paths->first_hops = GNUNET_CONTAINER_multihashmap_create(32);
2827   t->paths->t = t;
2828   t->paths->root = GNUNET_malloc(sizeof(struct MeshTunnelPathNode));
2829   t->paths->root->status = MESH_PEER_READY;
2830   t->paths->root->t = t;
2831   t->paths->root->peer = peer_info_get(&my_full_id);
2832   t->paths->me = t->paths->root;
2833
2834   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2835   return;
2836 }
2837
2838
2839 /**
2840  * Handler for requests of deleting tunnels
2841  *
2842  * @param cls closure
2843  * @param client identification of the client
2844  * @param message the actual message
2845  */
2846 static void
2847 handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
2848                              const struct GNUNET_MessageHeader *message)
2849 {
2850   struct GNUNET_MESH_TunnelMessage *tunnel_msg;
2851   struct MeshClient *c;
2852   struct MeshTunnel *t;
2853   MESH_TunnelNumber tid;
2854   GNUNET_HashCode hash;
2855
2856   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel\n");
2857
2858   /* Sanity check for client registration */
2859   if (NULL == (c = client_get (client)))
2860   {
2861     GNUNET_break (0);
2862     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2863     return;
2864   }
2865   /* Message sanity check */
2866   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
2867   {
2868     GNUNET_break (0);
2869     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2870     return;
2871   }
2872 #if MESH_DEBUG
2873   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
2874 #endif
2875   tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
2876
2877   /* Retrieve tunnel */
2878   tid = ntohl (tunnel_msg->tunnel_id);
2879
2880   /* Remove from local id hashmap */
2881   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
2882   t = GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
2883   GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t);
2884
2885   /* Remove from global id hashmap */
2886   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2887   GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t);
2888
2889 //     notify_tunnel_destroy(t); FIXME
2890   tunnel_destroy(t);
2891   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2892   return;
2893 }
2894
2895
2896 /**
2897  * Handler for connection requests to new peers
2898  *
2899  * @param cls closure
2900  * @param client identification of the client
2901  * @param message the actual message (PeerControl)
2902  *
2903  * FIXME path
2904  */
2905 static void
2906 handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
2907                           const struct GNUNET_MessageHeader *message)
2908 {
2909   struct GNUNET_MESH_PeerControl *peer_msg;
2910   struct MeshClient *c;
2911   struct MeshTunnel *t;
2912   MESH_TunnelNumber tid;
2913   struct MeshPeerInfo *peer_info;
2914
2915
2916   /* Sanity check for client registration */
2917   if (NULL == (c = client_get (client)))
2918   {
2919     GNUNET_break (0);
2920     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2921     return;
2922   }
2923
2924   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2925   /* Sanity check for message size */
2926   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2927   {
2928     GNUNET_break (0);
2929     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2930     return;
2931   }
2932
2933   /* Tunnel exists? */
2934   tid = ntohl (peer_msg->tunnel_id);
2935   t = tunnel_get_by_local_id (c, tid);
2936   if (NULL == t)
2937   {
2938     GNUNET_break (0);
2939     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2940     return;
2941   }
2942
2943   /* Does client own tunnel? */
2944   if (t->client->handle != client)
2945   {
2946     GNUNET_break (0);
2947     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2948     return;
2949   }
2950
2951   t->peers_total++;
2952   peer_info = peer_info_get (&peer_msg->peer);
2953
2954   /* Start DHT search if needed FIXME: if not already connected */
2955   if (NULL == peer_info->dhtget)
2956   {
2957     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 */
2958                                               GNUNET_DHT_RO_RECORD_ROUTE, NULL, /* bloom filter */
2959                                               0,        /* mutator */
2960                                               NULL,     /* xquery */
2961                                               0,        /* xquery bits */
2962                                               dht_get_id_handler,
2963                                               (void *) peer_info);
2964   }
2965
2966   GNUNET_SERVER_receive_done (client, GNUNET_OK);
2967   return;
2968 }
2969
2970
2971 /**
2972  * Handler for disconnection requests of peers in a tunnel
2973  *
2974  * @param cls closure
2975  * @param client identification of the client
2976  * @param message the actual message (PeerControl)
2977  */
2978 static void
2979 handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
2980                           const struct GNUNET_MessageHeader *message)
2981 {
2982   struct GNUNET_MESH_PeerControl *peer_msg;
2983   struct MeshClient *c;
2984   struct MeshTunnel *t;
2985   MESH_TunnelNumber tid;
2986
2987   /* Sanity check for client registration */
2988   if (NULL == (c = client_get (client)))
2989   {
2990     GNUNET_break (0);
2991     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
2992     return;
2993   }
2994   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
2995   /* Sanity check for message size */
2996   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
2997   {
2998     GNUNET_break (0);
2999     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3000     return;
3001   }
3002
3003   /* Tunnel exists? */
3004   tid = ntohl (peer_msg->tunnel_id);
3005   t = tunnel_get_by_local_id (c, tid);
3006   if (NULL == t)
3007   {
3008     GNUNET_break (0);
3009     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3010     return;
3011   }
3012
3013   /* Does client own tunnel? */
3014   if (t->client->handle != client)
3015   {
3016     GNUNET_break (0);
3017     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3018     return;
3019   }
3020
3021   /* Ok, delete peer from tunnel */
3022   GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
3023                                             &peer_msg->peer.hashPubKey);
3024
3025   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3026   return;
3027 }
3028
3029
3030 /**
3031  * Handler for connection requests to new peers by type
3032  *
3033  * @param cls closure
3034  * @param client identification of the client
3035  * @param message the actual message (ConnectPeerByType)
3036  */
3037 static void
3038 handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
3039                               const struct GNUNET_MessageHeader *message)
3040 {
3041   struct GNUNET_MESH_ConnectPeerByType *connect_msg;
3042   struct MeshClient *c;
3043   struct MeshTunnel *t;
3044   GNUNET_HashCode hash;
3045   GNUNET_MESH_ApplicationType type;
3046   MESH_TunnelNumber tid;
3047
3048   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got connect by type request\n");
3049   /* Sanity check for client registration */
3050   if (NULL == (c = client_get (client)))
3051   {
3052     GNUNET_break (0);
3053     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3054     return;
3055   }
3056
3057   connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
3058   /* Sanity check for message size */
3059   if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
3060       ntohs (connect_msg->header.size))
3061   {
3062     GNUNET_break (0);
3063     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3064     return;
3065   }
3066
3067   /* Tunnel exists? */
3068   tid = ntohl (connect_msg->tunnel_id);
3069   t = tunnel_get_by_local_id (c, tid);
3070   if (NULL == t)
3071   {
3072     GNUNET_break (0);
3073     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3074     return;
3075   }
3076
3077   /* Does client own tunnel? */
3078   if (t->client->handle != client)
3079   {
3080     GNUNET_break (0);
3081     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3082     return;
3083   }
3084
3085   /* Do WE have the service? */
3086   type = ntohl (connect_msg->type);
3087   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  type requested: %u\n", type);
3088   GNUNET_CRYPTO_hash (&type, sizeof (GNUNET_MESH_ApplicationType), &hash);
3089   if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
3090       GNUNET_YES)
3091   {
3092     /* Yes! Fast forward, add ourselves to the tunnel and send the
3093      * good news to the client
3094      */
3095     struct GNUNET_MESH_PeerControl pc;
3096
3097     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  available locally\n");
3098     pc.peer = my_full_id;
3099     GNUNET_CONTAINER_multihashmap_put (t->peers, &pc.peer.hashPubKey,
3100                                        peer_info_get (&pc.peer),
3101                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3102     pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
3103     pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
3104     pc.tunnel_id = htonl (t->local_tid);
3105     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  notifying client\n");
3106     GNUNET_SERVER_notification_context_unicast (nc,     /* context */
3107                                                 client, /* dest */
3108                                                 &pc.header,     /* msg */
3109                                                 GNUNET_NO);     /* can drop? */
3110     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  Done\n");
3111     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3112     return;
3113   }
3114   /* Ok, lets find a peer offering the service */
3115   if (c->dht_get_type)
3116   {
3117     GNUNET_DHT_get_stop (c->dht_get_type);
3118   }
3119   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  looking in DHT for %s\n",
3120               GNUNET_h2s_full (&hash));
3121   c->dht_get_type =
3122       GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL,
3123                             GNUNET_BLOCK_TYPE_TEST, &hash, 10U,
3124                             GNUNET_DHT_RO_RECORD_ROUTE, NULL, 0, NULL, 0,
3125                             &dht_get_type_handler, t);
3126
3127   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3128   return;
3129 }
3130
3131
3132 /**
3133  * Handler for client traffic directed to one peer
3134  *
3135  * @param cls closure
3136  * @param client identification of the client
3137  * @param message the actual message
3138  */
3139 static void
3140 handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
3141                       const struct GNUNET_MessageHeader *message)
3142 {
3143   struct MeshClient *c;
3144   struct MeshTunnel *t;
3145   struct MeshPeerInfo *pi;
3146   struct GNUNET_MESH_Unicast *data_msg;
3147   struct GNUNET_PeerIdentity next_hop;
3148   struct MeshDataDescriptor *info;
3149   MESH_TunnelNumber tid;
3150   size_t data_size;
3151
3152   /* Sanity check for client registration */
3153   if (NULL == (c = client_get (client)))
3154   {
3155     GNUNET_break (0);
3156     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3157     return;
3158   }
3159   data_msg = (struct GNUNET_MESH_Unicast *) message;
3160   /* Sanity check for message size */
3161   if (sizeof (struct GNUNET_MESH_Unicast) +
3162       sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
3163   {
3164     GNUNET_break (0);
3165     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3166     return;
3167   }
3168
3169   /* Tunnel exists? */
3170   tid = ntohl (data_msg->tid);
3171   t = tunnel_get_by_local_id (c, tid);
3172   if (NULL == t)
3173   {
3174     GNUNET_break (0);
3175     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3176     return;
3177   }
3178
3179   /*  Is it a local tunnel? Then, does client own the tunnel? */
3180   if (t->client->handle != NULL && t->client->handle != client)
3181   {
3182     GNUNET_break (0);
3183     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3184     return;
3185   }
3186
3187   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
3188                                           &data_msg->destination.hashPubKey);
3189   /* Is the selected peer in the tunnel? */
3190   if (NULL == pi)
3191   {
3192     GNUNET_break (0);
3193     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3194     return;
3195   }
3196   if (pi->id == myid)
3197   {
3198     struct GNUNET_MESH_Unicast copy;
3199
3200     /* Work around const limitation */
3201     memcpy (&copy, data_msg, sizeof (struct GNUNET_MESH_Unicast));
3202     copy.oid = my_full_id;
3203     copy.tid = htonl (t->id.tid);
3204     handle_mesh_data_unicast (NULL, &my_full_id, &copy.header, NULL);
3205     return;
3206   }
3207   GNUNET_PEER_resolve (path_get_first_hop (t, pi)->id, &next_hop);
3208   data_size = ntohs (message->size) - sizeof (struct GNUNET_MESH_Unicast);
3209   info = GNUNET_malloc (sizeof (struct MeshDataDescriptor) + data_size);
3210   memcpy (&info[1], &data_msg[1], data_size);
3211   info->destination = pi->id;
3212   info->origin = &t->id;
3213   info->size = data_size;
3214   info->client = client;
3215   GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
3216                                      GNUNET_TIME_UNIT_FOREVER_REL, &next_hop,
3217                                      /* FIXME re-check types */
3218                                      data_size +
3219                                      sizeof (struct GNUNET_MESH_Unicast),
3220                                      &send_core_data_unicast, info);
3221   return;
3222 }
3223
3224 /**
3225  * Handler for client traffic directed to all peers in a tunnel
3226  *
3227  * @param cls closure
3228  * @param client identification of the client
3229  * @param message the actual message
3230  */
3231 static void
3232 handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
3233                         const struct GNUNET_MessageHeader *message)
3234 {
3235   struct MeshClient *c;
3236   struct MeshTunnel *t;
3237   struct GNUNET_MESH_Multicast *data_msg;
3238   MESH_TunnelNumber tid;
3239
3240   /* Sanity check for client registration */
3241   if (NULL == (c = client_get (client)))
3242   {
3243     GNUNET_break (0);
3244     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3245     return;
3246   }
3247   data_msg = (struct GNUNET_MESH_Multicast *) message;
3248   /* Sanity check for message size */
3249   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (data_msg->header.size))
3250   {
3251     GNUNET_break (0);
3252     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3253     return;
3254   }
3255
3256   /* Tunnel exists? */
3257   tid = ntohl (data_msg->tid);
3258   t = tunnel_get_by_local_id (c, tid);
3259   if (NULL == t)
3260   {
3261     GNUNET_break (0);
3262     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3263     return;
3264   }
3265
3266   /* Does client own tunnel? */
3267   if (t->client->handle != client)
3268   {
3269     GNUNET_break (0);
3270     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3271     return;
3272   }
3273
3274   /*  TODO */
3275
3276   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3277   return;
3278 }
3279
3280 /**
3281  * Functions to handle messages from clients
3282  */
3283 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
3284   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
3285   {&handle_local_tunnel_create, NULL,
3286    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
3287    sizeof (struct GNUNET_MESH_TunnelMessage)},
3288   {&handle_local_tunnel_destroy, NULL,
3289    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
3290    sizeof (struct GNUNET_MESH_TunnelMessage)},
3291   {&handle_local_connect_add, NULL,
3292    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
3293    sizeof (struct GNUNET_MESH_PeerControl)},
3294   {&handle_local_connect_del, NULL,
3295    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
3296    sizeof (struct GNUNET_MESH_PeerControl)},
3297   {&handle_local_connect_by_type, NULL,
3298    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
3299    sizeof (struct GNUNET_MESH_ConnectPeerByType)},
3300   {&handle_local_unicast, NULL,
3301    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
3302   {&handle_local_unicast, NULL,
3303    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
3304   {&handle_local_multicast, NULL,
3305    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
3306   {NULL, NULL, 0, 0}
3307 };
3308
3309
3310 /**
3311  * To be called on core init/fail.
3312  *
3313  * @param cls service closure
3314  * @param server handle to the server for this service
3315  * @param identity the public identity of this peer
3316  * @param publicKey the public key of this peer
3317  */
3318 static void
3319 core_init (void *cls, struct GNUNET_CORE_Handle *server,
3320            const struct GNUNET_PeerIdentity *identity,
3321            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
3322 {
3323   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Core init\n");
3324   core_handle = server;
3325   my_full_id = *identity;
3326   myid = GNUNET_PEER_intern (identity);
3327   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
3328   return;
3329 }
3330
3331 /**
3332  * Method called whenever a given peer connects.
3333  *
3334  * @param cls closure
3335  * @param peer peer identity this notification is about
3336  * @param atsi performance data for the connection
3337  */
3338 static void
3339 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
3340               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
3341 {
3342 //     GNUNET_PEER_Id              pid;
3343   struct MeshPeerInfo *peer_info;
3344   struct MeshPeerPath *path;
3345
3346   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n");
3347   peer_info = peer_info_get (peer);
3348   if (myid == peer_info->id)
3349   {
3350     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
3351   }
3352   path = GNUNET_malloc (sizeof (struct MeshPeerPath));
3353   path->length = 2;
3354   path->peers = GNUNET_malloc (sizeof (GNUNET_PEER_Id) * 2);
3355   path->peers[0] = myid;
3356   path->peers[1] = peer_info->id;
3357   path_add_to_peer (peer_info, path);
3358   return;
3359 }
3360
3361 /**
3362  * Method called whenever a peer disconnects.
3363  *
3364  * @param cls closure
3365  * @param peer peer identity this notification is about
3366  */
3367 static void
3368 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
3369 {
3370   struct MeshPeerInfo *pi;
3371   unsigned int i;
3372
3373   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer disconnected\n");
3374   pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
3375   if (!pi)
3376   {
3377     GNUNET_break (0);
3378     return;
3379   }
3380   for (i = 0; i < CORE_QUEUE_SIZE; i++)
3381   {
3382     if (pi->core_transmit[i])
3383     {
3384       GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit[i]);
3385       /* TODO: notify that tranmission has failed */
3386       GNUNET_free (pi->infos[i]);
3387     }
3388   }
3389   path_remove_from_peer (pi, pi->id, myid);
3390   if (myid == pi->id)
3391   {
3392     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
3393   }
3394   return;
3395 }
3396
3397
3398 /******************************************************************************/
3399 /************************      MAIN FUNCTIONS      ****************************/
3400 /******************************************************************************/
3401
3402 /**
3403  * Task run during shutdown.
3404  *
3405  * @param cls unused
3406  * @param tc unused
3407  */
3408 static void
3409 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3410 {
3411   struct MeshClient *c;
3412
3413   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shutting down\n");
3414   if (core_handle != NULL)
3415   {
3416     GNUNET_CORE_disconnect (core_handle);
3417     core_handle = NULL;
3418   }
3419   if (dht_handle != NULL)
3420   {
3421     for (c = clients; NULL != c; c = c->next)
3422       if (NULL != c->dht_get_type)
3423         GNUNET_DHT_get_stop (c->dht_get_type);
3424     GNUNET_DHT_disconnect (dht_handle);
3425     dht_handle = NULL;
3426   }
3427   if (nc != NULL)
3428   {
3429     GNUNET_SERVER_notification_context_destroy (nc);
3430     nc = NULL;
3431   }
3432   if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
3433   {
3434     GNUNET_SCHEDULER_cancel (announce_id_task);
3435     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
3436   }
3437   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shut down\n");
3438 }
3439
3440 /**
3441  * Process mesh requests.
3442  *
3443  * @param cls closure
3444  * @param server the initialized server
3445  * @param c configuration to use
3446  */
3447 static void
3448 run (void *cls, struct GNUNET_SERVER_Handle *server,
3449      const struct GNUNET_CONFIGURATION_Handle *c)
3450 {
3451   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: starting to run\n");
3452   GNUNET_SERVER_add_handlers (server, client_handlers);
3453   GNUNET_SERVER_disconnect_notify (server,
3454                                    &handle_local_client_disconnect,
3455                                    NULL);
3456   server_handle = server;
3457   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
3458                                      CORE_QUEUE_SIZE,   /* queue size */
3459                                      NULL,      /* Closure passed to MESH functions */
3460                                      &core_init,        /* Call core_init once connected */
3461                                      &core_connect,     /* Handle connects */
3462                                      &core_disconnect,  /* remove peers on disconnects */
3463                                      NULL,      /* Do we care about "status" updates? */
3464                                      NULL,      /* Don't notify about all incoming messages */
3465                                      GNUNET_NO, /* For header only in notification */
3466                                      NULL,      /* Don't notify about all outbound messages */
3467                                      GNUNET_NO, /* For header-only out notification */
3468                                      core_handlers);    /* Register these handlers */
3469   if (core_handle == NULL)
3470   {
3471     GNUNET_break (0);
3472   }
3473   dht_handle = GNUNET_DHT_connect (c, 64);
3474   if (dht_handle == NULL)
3475   {
3476     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error connecting to DHT.\
3477                    Running without DHT has a severe\
3478                    impact in MESH capabilities.\n\
3479                    Plase check your configuretion and enable DHT.\n");
3480     GNUNET_break (0);
3481   }
3482
3483   next_tid = 0;
3484
3485   tunnels = GNUNET_CONTAINER_multihashmap_create (32);
3486   peers = GNUNET_CONTAINER_multihashmap_create (32);
3487   applications = GNUNET_CONTAINER_multihashmap_create (32);
3488   types = GNUNET_CONTAINER_multihashmap_create (32);
3489   nc = GNUNET_SERVER_notification_context_create (server_handle,
3490                                                   LOCAL_QUEUE_SIZE);
3491   clients = NULL;
3492   clients_tail = NULL;
3493 #if MESH_DEBUG
3494   next_client_id = 0;
3495 #endif
3496
3497   announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
3498
3499   /* Scheduled the task to clean up when shutdown is called */
3500   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
3501                                 NULL);
3502
3503   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: end of run()\n");
3504 }
3505
3506 /**
3507  * The main function for the mesh service.
3508  *
3509  * @param argc number of arguments from the command line
3510  * @param argv command line arguments
3511  * @return 0 ok, 1 on error
3512  */
3513 int
3514 main (int argc, char *const *argv)
3515 {
3516   int ret;
3517
3518   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main()\n");
3519   ret =
3520       (GNUNET_OK ==
3521        GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
3522                            NULL)) ? 0 : 1;
3523   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main() END\n");
3524   return ret;
3525 }