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