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