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