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