Fixed client shutdown case, various minor fixes
[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  * - relay corking down to core
44  * - set ttl relative to tree depth
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 #define UNACKNOWLEDGED_WAIT     GNUNET_TIME_relative_multiply(\
70                                     GNUNET_TIME_UNIT_SECONDS,\
71                                     2)
72 #define DEFAULT_TTL     64
73
74 #define MESH_DEBUG_DHT GNUNET_NO
75
76
77
78 /******************************************************************************/
79 /************************      DATA STRUCTURES     ****************************/
80 /******************************************************************************/
81
82 /** FWD declaration */
83 struct MeshPeerInfo;
84
85
86 /**
87  * Struct representing a piece of data being sent to other peers
88  */
89 struct MeshData
90 {
91   /** Tunnel it belongs to. */
92   struct MeshTunnel *t;
93
94   /** In case of a multicast, task to allow a client to send more data if
95    * some neighbor is too slow. */
96   GNUNET_SCHEDULER_TaskIdentifier *task;
97
98   /** How many remaining neighbors we need to send this to. */
99   unsigned int *reference_counter;
100
101   /** Size of the data. */
102   size_t data_len;
103
104   /** Data itself */
105   void *data;
106 };
107
108
109 /**
110  * Struct containing all info possibly needed to build a package when called
111  * back by core.
112  */
113 struct MeshTransmissionDescriptor
114 {
115     /** ID of the tunnel this packet travels in */
116   struct MESH_TunnelID *origin;
117
118     /** Who was this message being sent to */
119   struct MeshPeerInfo *peer;
120
121     /** Ultimate destination of the packet */
122   GNUNET_PEER_Id destination;
123
124     /** Which handler was used to request the transmission */
125   unsigned int handler_n;
126
127     /** Data descriptor */
128   struct MeshData* mesh_data;
129 };
130
131
132 /**
133  * Struct containing all information regarding a given peer
134  */
135 struct MeshPeerInfo
136 {
137     /**
138      * ID of the peer
139      */
140   GNUNET_PEER_Id id;
141
142     /**
143      * Last time we heard from this peer
144      */
145   struct GNUNET_TIME_Absolute last_contact;
146
147     /**
148      * Number of attempts to reconnect so far
149      */
150   int n_reconnect_attempts;
151
152     /**
153      * Paths to reach the peer, ordered by ascending hop count
154      */
155   struct MeshPeerPath *path_head;
156
157     /**
158      * Paths to reach the peer, ordered by ascending hop count
159      */
160   struct MeshPeerPath *path_tail;
161
162     /**
163      * Handle to stop the DHT search for a path to this peer
164      */
165   struct GNUNET_DHT_GetHandle *dhtget;
166
167     /**
168      * Closure given to the DHT GET
169      */
170   struct MeshPathInfo *dhtgetcls;
171
172     /**
173      * Handles to stop queued transmissions for this peer
174      */
175   struct GNUNET_CORE_TransmitHandle *core_transmit[CORE_QUEUE_SIZE];
176
177     /**
178      * Pointer to info stuctures used as cls for queued transmissions
179      */
180   void *infos[CORE_QUEUE_SIZE];
181
182     /**
183      * Type of message being in each transmission
184      */
185   uint16_t types[CORE_QUEUE_SIZE];
186
187     /**
188      * Array of tunnels this peer participates in
189      * (most probably a small amount, therefore not a hashmap)
190      * When the path to the peer changes, notify these tunnels to let them
191      * re-adjust their path trees.
192      */
193   struct MeshTunnel **tunnels;
194
195     /**
196      * Number of tunnels this peers participates in
197      */
198   unsigned int ntunnels;
199 };
200
201
202 /**
203  * Data scheduled to transmit (to local client or remote peer)
204  */
205 struct MeshQueue
206 {
207     /**
208      * Double linked list
209      */
210   struct MeshQueue *next;
211   struct MeshQueue *prev;
212
213     /**
214      * Target of the data (NULL if target is client)
215      */
216   struct MeshPeerInfo *peer;
217
218     /**
219      * Client to send the data to (NULL if target is peer)
220      */
221   struct MeshClient *client;
222
223     /**
224      * Size of the message to transmit
225      */
226   unsigned int size;
227
228     /**
229      * How old is the data?
230      */
231   struct GNUNET_TIME_Absolute timestamp;
232
233     /**
234      * Data itself
235      */
236   struct GNUNET_MessageHeader *data;
237 };
238
239 /**
240  * Globally unique tunnel identification (owner + number)
241  * DO NOT USE OVER THE NETWORK
242  */
243 struct MESH_TunnelID
244 {
245     /**
246      * Node that owns the tunnel
247      */
248   GNUNET_PEER_Id oid;
249
250     /**
251      * Tunnel number to differentiate all the tunnels owned by the node oid
252      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_CLI )
253      */
254   MESH_TunnelNumber tid;
255 };
256
257
258 struct MeshClient;              /* FWD declaration */
259
260 /**
261  * Struct containing all information regarding a tunnel
262  * For an intermediate node the improtant info used will be:
263  * - id        Tunnel unique identification
264  * - paths[0]  To know where to send it next
265  * - metainfo: ready, speeds, accounting
266  */
267 struct MeshTunnel
268 {
269     /**
270      * Tunnel ID
271      */
272   struct MESH_TunnelID id;
273
274     /**
275      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI or 0 )
276      */
277   MESH_TunnelNumber local_tid;
278
279       /**
280      * Local tunnel number for local destination clients
281      */
282   MESH_TunnelNumber local_tid_dest;
283
284     /**
285      * ID of the last multicast packet seen/sent.
286      */
287   uint32_t mid;
288
289     /**
290      * Last time the tunnel was used
291      */
292   struct GNUNET_TIME_Absolute timestamp;
293
294     /**
295      * Peers in the tunnel, indexed by PeerIdentity -> (MeshPeerInfo)
296      * containing peers added by id or by type, not intermediate peers.
297      */
298   struct GNUNET_CONTAINER_MultiHashMap *peers;
299
300     /**
301      * Number of peers that are connected and potentially ready to receive data
302      */
303   unsigned int peers_ready;
304
305     /**
306      * Number of peers that have been added to the tunnel
307      */
308   unsigned int peers_total;
309
310     /**
311      * Client owner of the tunnel, if any
312      */
313   struct MeshClient *client;
314
315     /**
316      * Client destination of the tunnel, if any
317      */
318   struct MeshClient *client_dest;
319
320     /**
321      * Messages ready to transmit
322      */
323   struct MeshQueue *queue_head;
324   struct MeshQueue *queue_tail;
325
326   /**
327    * Tunnel paths
328    */
329   struct MeshTunnelTree *tree;
330
331   /**
332    * Application type we are looking for in this tunnel
333    */
334   GNUNET_MESH_ApplicationType type;
335
336     /**
337      * Used to search peers offering a service
338      */
339   struct GNUNET_DHT_GetHandle *dht_get_type;
340
341   /**
342    * Task to keep the used paths alive
343    */
344   GNUNET_SCHEDULER_TaskIdentifier path_refresh_task;
345
346   /**
347    * Task to destroy the tunnel after timeout
348    *
349    * FIXME: merge the two? a tunnel will have either
350    * a path refresh OR a timeout, never both!
351    */
352   GNUNET_SCHEDULER_TaskIdentifier timeout_task;
353 };
354
355
356 /**
357  * Info needed to work with tunnel paths and peers
358  */
359 struct MeshPathInfo
360 {
361   /**
362    * Tunnel
363    */
364   struct MeshTunnel *t;
365
366   /**
367    * Neighbouring peer to whom we send the packet to
368    */
369   struct MeshPeerInfo *peer;
370
371   /**
372    * Path itself
373    */
374   struct MeshPeerPath *path;
375
376   /**
377    * Position in peer's transmit queue
378    */
379   unsigned int pos;
380 };
381
382
383 /**
384  * Struct containing information about a client of the service
385  */
386 struct MeshClient
387 {
388     /**
389      * Linked list
390      */
391   struct MeshClient *next;
392   struct MeshClient *prev;
393
394     /**
395      * Tunnels that belong to this client, indexed by local id
396      */
397   struct GNUNET_CONTAINER_MultiHashMap *tunnels;
398
399     /**
400      * Handle to communicate with the client
401      */
402   struct GNUNET_SERVER_Client *handle;
403
404     /**
405      * Applications that this client has claimed to provide
406      */
407   struct GNUNET_CONTAINER_MultiHashMap *apps;
408
409     /**
410      * Messages that this client has declared interest in
411      */
412   struct GNUNET_CONTAINER_MultiHashMap *types;
413
414 #if MESH_DEBUG
415     /**
416      * ID of the client, for debug messages
417      */
418   unsigned int id;
419 #endif
420
421 };
422
423
424
425 /******************************************************************************/
426 /************************      DEBUG FUNCTIONS     ****************************/
427 /******************************************************************************/
428
429 #if MESH_DEBUG
430 /**
431  * GNUNET_SCHEDULER_Task for printing a message after some operation is done
432  * @param cls string to print
433  * @param tc task context
434  */
435 static void
436 mesh_debug (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
437 {
438   char *s = cls;
439
440   if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason)
441   {
442     return;
443   }
444   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: %s\n", s);
445 }
446 #endif
447
448 /******************************************************************************/
449 /***********************      GLOBAL VARIABLES     ****************************/
450 /******************************************************************************/
451
452 /**
453  * All the clients
454  */
455 static struct MeshClient *clients;
456 static struct MeshClient *clients_tail;
457
458 /**
459  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
460  */
461 static struct GNUNET_CONTAINER_MultiHashMap *tunnels;
462
463 /**
464  * Tunnels incoming, indexed by MESH_TunnelNumber
465  * (which is greater than GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
466  */
467 static struct GNUNET_CONTAINER_MultiHashMap *incoming_tunnels;
468
469 /**
470  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
471  */
472 static struct GNUNET_CONTAINER_MultiHashMap *peers;
473
474 /**
475  * Handle to communicate with core
476  */
477 static struct GNUNET_CORE_Handle *core_handle;
478
479 /**
480  * Handle to communicate with transport
481  */
482 // static struct GNUNET_TRANSPORT_Handle *transport_handle;
483
484 /**
485  * Handle to use DHT
486  */
487 static struct GNUNET_DHT_Handle *dht_handle;
488
489 /**
490  * Handle to server
491  */
492 static struct GNUNET_SERVER_Handle *server_handle;
493
494 /**
495  * Notification context, to send messages to local clients
496  */
497 static struct GNUNET_SERVER_NotificationContext *nc;
498
499 /**
500  * Local peer own ID (memory efficient handle)
501  */
502 static GNUNET_PEER_Id myid;
503
504 /**
505  * Local peer own ID (full value)
506  */
507 static struct GNUNET_PeerIdentity my_full_id;
508
509 /**
510  * Own private key
511  */
512 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
513
514 /**
515  * Own public key.
516  */
517 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
518
519 /**
520  * Tunnel ID for the next created tunnel (global tunnel number)
521  */
522 static MESH_TunnelNumber next_tid;
523
524 /**
525  * Tunnel ID for the next incoming tunnel (local tunnel number)
526  */
527 static MESH_TunnelNumber next_local_tid;
528
529 /**
530  * All application types provided by this peer
531  */
532 static struct GNUNET_CONTAINER_MultiHashMap *applications;
533
534 /**
535  * All message types clients of this peer are interested in
536  */
537 static struct GNUNET_CONTAINER_MultiHashMap *types;
538
539 /**
540  * Task to periodically announce provided applications
541  */
542 GNUNET_SCHEDULER_TaskIdentifier announce_applications_task;
543
544 /**
545  * Task to periodically announce itself in the network
546  */
547 GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
548
549 #if MESH_DEBUG
550 unsigned int next_client_id;
551 #endif
552
553
554 /******************************************************************************/
555 /************************         ITERATORS        ****************************/
556 /******************************************************************************/
557
558 /* FIXME move iterators here */
559
560
561 /******************************************************************************/
562 /************************    PERIODIC FUNCTIONS    ****************************/
563 /******************************************************************************/
564
565 /**
566  * Announce iterator over for each application provided by the peer
567  *
568  * @param cls closure
569  * @param key current key code
570  * @param value value in the hash map
571  * @return GNUNET_YES if we should continue to
572  *         iterate,
573  *         GNUNET_NO if not.
574  */
575 static int
576 announce_application (void *cls, const GNUNET_HashCode * key, void *value)
577 {
578   /* FIXME are hashes in multihash map equal on all aquitectures? */
579   GNUNET_DHT_put (dht_handle, key, 10U,
580                   GNUNET_DHT_RO_RECORD_ROUTE |
581                   GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, GNUNET_BLOCK_TYPE_TEST,
582                   sizeof (struct GNUNET_PeerIdentity),
583                   (const char *) &my_full_id,
584 #if MESH_DEBUG
585                   GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_FOREVER_REL,
586                   &mesh_debug, "DHT_put for app completed");
587 #else
588                   GNUNET_TIME_absolute_add (GNUNET_TIME_absolute_get (),
589                                             APP_ANNOUNCE_TIME),
590                   APP_ANNOUNCE_TIME, NULL, NULL);
591 #endif
592   return GNUNET_OK;
593 }
594
595
596 /**
597  * Periodically announce what applications are provided by local clients
598  *
599  * @param cls closure
600  * @param tc task context
601  */
602 static void
603 announce_applications (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
604 {
605   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
606   {
607     announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
608     return;
609   }
610 #if MESH_DEBUG_DHT
611   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Starting PUT for apps\n");
612 #endif
613   GNUNET_CONTAINER_multihashmap_iterate (applications, &announce_application,
614                                          NULL);
615   announce_applications_task =
616       GNUNET_SCHEDULER_add_delayed (APP_ANNOUNCE_TIME, &announce_applications,
617                                     cls);
618 #if MESH_DEBUG_DHT
619   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Finished PUT for apps\n");
620 #endif
621   return;
622 }
623
624
625 /**
626  * Periodically announce self id in the DHT
627  *
628  * @param cls closure
629  * @param tc task context
630  */
631 static void
632 announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
633 {
634   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
635   {
636     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
637     return;
638   }
639   /* TODO
640    * - Set data expiration in function of X
641    * - Adapt X to churn
642    */
643 #if MESH_DEBUG_DHT
644   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: DHT_put for ID %s started.\n",
645               GNUNET_i2s (&my_full_id));
646 #endif
647   GNUNET_DHT_put (dht_handle,   /* DHT handle */
648                   &my_full_id.hashPubKey,       /* Key to use */
649                   10U,          /* Replication level */
650                   GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,    /* DHT options */
651                   GNUNET_BLOCK_TYPE_TEST,       /* Block type */
652                   sizeof (my_full_id),  /* Size of the data */
653                   (char *) &my_full_id, /* Data itself */
654                   GNUNET_TIME_absolute_get_forever (),  /* Data expiration */
655                   GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
656 #if MESH_DEBUG_DHT
657                   &mesh_debug, "DHT_put for id completed");
658 #else
659                   NULL,         /* Continuation */
660                   NULL);        /* Continuation closure */
661 #endif
662   announce_id_task =
663       GNUNET_SCHEDULER_add_delayed (ID_ANNOUNCE_TIME, &announce_id, cls);
664 }
665
666
667 /**
668  * Function to process paths received for a new peer addition. The recorded
669  * paths form the initial tunnel, which can be optimized later.
670  * Called on each result obtained for the DHT search.
671  *
672  * @param cls closure
673  * @param exp when will this value expire
674  * @param key key of the result
675  * @param type type of the result
676  * @param size number of bytes in data
677  * @param data pointer to the result data
678  */
679 static void
680 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
681                     const GNUNET_HashCode * key,
682                     const struct GNUNET_PeerIdentity *get_path,
683                     unsigned int get_path_length,
684                     const struct GNUNET_PeerIdentity *put_path,
685                     unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
686                     size_t size, const void *data);
687
688
689 /******************************************************************************/
690 /******************      GENERAL HELPER FUNCTIONS      ************************/
691 /******************************************************************************/
692
693 /**
694  * Check if client has registered with the service and has not disconnected
695  *
696  * @param client the client to check
697  *
698  * @return non-NULL if client exists in the global DLL
699  */
700 static struct MeshClient *
701 client_get (struct GNUNET_SERVER_Client *client)
702 {
703   struct MeshClient *c;
704
705   c = clients;
706   while (NULL != c)
707   {
708     if (c->handle == client)
709       return c;
710     c = c->next;
711   }
712   return NULL;
713 }
714
715
716 /**
717  * Checks if a given client has subscribed to certain message type
718  *
719  * @param message_type Type of message to check
720  * @param c Client to check
721  *
722  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
723  *
724  * TODO inline?
725  */
726 static int
727 client_is_subscribed (uint16_t message_type, struct MeshClient *c)
728 {
729   GNUNET_HashCode hc;
730
731   GNUNET_CRYPTO_hash (&message_type, sizeof (uint16_t), &hc);
732   return GNUNET_CONTAINER_multihashmap_contains (c->types, &hc);
733 }
734
735
736 /**
737  * Allow a client to send more data after transmitting a multicast message
738  * which some neighbor has not yet accepted altough a reasonable time has
739  * passed.
740  *
741  * @param cls Closure (DataDescriptor containing the task identifier)
742  * @param tc Task Context
743  */
744 static void
745 client_allow_send (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
746 {
747   struct MeshData *mdata = cls;
748
749   if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason)
750     return;
751 #if MESH_DEBUG
752   GNUNET_assert (NULL != mdata->reference_counter);
753   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
754               "MESH: CLIENT ALLOW SEND DESPITE %u COPIES PENDING\n",
755               mdata->reference_counter);
756 #endif
757   *(mdata->task) = GNUNET_SCHEDULER_NO_TASK;
758   GNUNET_SERVER_receive_done (mdata->t->client->handle, GNUNET_OK);
759 }
760
761
762 /**
763  * Search for a tunnel by global ID using full PeerIdentities
764  *
765  * @param oid owner of the tunnel
766  * @param tid global tunnel number
767  *
768  * @return tunnel handler, NULL if doesn't exist
769  */
770 static struct MeshTunnel *
771 tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid);
772
773
774 /**
775  * Notify a tunnel that a connection has broken that affects at least
776  * some of its peers.
777  *
778  * @param t Tunnel affected.
779  * @param p1 Peer that got disconnected from p2.
780  * @param p2 Peer that got disconnected from p1.
781  *
782  * @return Short ID of the peer disconnected (either p1 or p2).
783  *         0 if the tunnel remained unaffected.
784  */
785 static GNUNET_PEER_Id
786 tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
787                                  GNUNET_PEER_Id p2);
788
789
790 /**
791  * Send the message to all clients that have subscribed to its type
792  *
793  * @param msg Pointer to the message itself
794  * @param payload Pointer to the payload of the message.
795  * @return number of clients this message was sent to
796  */
797 static unsigned int
798 send_subscribed_clients (const struct GNUNET_MessageHeader *msg,
799                          const struct GNUNET_MessageHeader *payload)
800 {
801   struct GNUNET_PeerIdentity *oid;
802   struct MeshClient *c;
803   struct MeshTunnel *t;
804   MESH_TunnelNumber *tid;
805   unsigned int count;
806   uint16_t type;
807   char cbuf[htons (msg->size)];
808
809 #if MESH_DEBUG
810   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Sending to clients...\n");
811   type = ntohs (payload->type);
812   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: message of type %u\n", type);
813 #endif
814
815   memcpy (cbuf, msg, sizeof (cbuf));
816   switch (htons (msg->type))
817   {
818     struct GNUNET_MESH_Unicast *uc;
819     struct GNUNET_MESH_Multicast *mc;
820     struct GNUNET_MESH_ToOrigin *to;
821
822   case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
823     uc = (struct GNUNET_MESH_Unicast *) cbuf;
824     tid = &uc->tid;
825     oid = &uc->oid;
826     break;
827   case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
828     mc = (struct GNUNET_MESH_Multicast *) cbuf;
829     tid = &mc->tid;
830     oid = &mc->oid;
831     break;
832   case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
833     to = (struct GNUNET_MESH_ToOrigin *) cbuf;
834     tid = &to->tid;
835     oid = &to->oid;
836     break;
837   default:
838     GNUNET_break (0);
839     return 0;
840   }
841   t = tunnel_get (oid, ntohl (*tid));
842   if (NULL == t)
843   {
844     GNUNET_break (0);
845     return 0;
846   }
847   // FIXME proper client differentiation mechanism required
848   if (htons (msg->type) == GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN)
849     *tid = htonl (t->local_tid);
850   else
851     *tid = htonl (t->local_tid_dest != 0 ? t->local_tid_dest : t->local_tid);
852   for (count = 0, c = clients; c != NULL; c = c->next)
853   {
854 #if MESH_DEBUG
855     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    client %u\n", c->id);
856 #endif
857     if (client_is_subscribed (type, c))
858     {
859       count++;
860       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      sending\n");
861       GNUNET_SERVER_notification_context_unicast (nc, c->handle,
862                                                   (struct GNUNET_MessageHeader
863                                                    *) cbuf, GNUNET_YES);
864     }
865   }
866   return count;
867 }
868
869
870 /**
871  * Notify the client that owns the tunnel that a peer has connected to it
872  * (the requested path to it has been confirmed).
873  *
874  * @param t Tunnel whose owner to notify
875  * @param id Short id of the peer that has connected
876  */
877 static void
878 send_client_peer_connected (const struct MeshTunnel *t, const GNUNET_PEER_Id id)
879 {
880   struct GNUNET_MESH_PeerControl pc;
881
882   pc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
883   pc.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
884   pc.tunnel_id = htonl (t->local_tid);
885   GNUNET_PEER_resolve (id, &pc.peer);
886   GNUNET_SERVER_notification_context_unicast (nc, t->client->handle, &pc.header,
887                                               GNUNET_NO);
888 }
889
890
891 /**
892  * Notify all clients (not depending on registration status) that the incoming
893  * tunnel is no longer valid.
894  *
895  * @param t Tunnel that was destroyed.
896  */
897 static void
898 send_clients_tunnel_destroy (struct MeshTunnel *t)
899 {
900   struct GNUNET_MESH_TunnelMessage msg;
901
902   msg.header.size = htons (sizeof (msg));
903   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
904   msg.tunnel_id = htonl (t->local_tid);
905   GNUNET_SERVER_notification_context_broadcast (nc, &msg.header, GNUNET_NO);
906 }
907
908
909 /**
910  * Notify a client that the other local client disconnected, if needed.
911  * In case the origin disconnects, the destination get a tunnel destroy
912  * notification. Otherwise, the origin gets a (local ID) peer disconnected.
913  *
914  * @param t Tunnel that was destroyed.
915  * @param c Client that disconnected
916  */
917 static void
918 send_client_tunnel_disconnect (struct MeshTunnel *t, struct MeshClient *c)
919 {
920   if (c == t->client_dest)
921   {
922     struct GNUNET_MESH_PeerControl msg;
923
924     msg.header.size = htons (sizeof (msg));
925     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
926     msg.tunnel_id = htonl (t->local_tid);
927     msg.peer = my_full_id;
928     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
929                                                 &msg.header, GNUNET_NO);
930   }
931   else if (NULL != t->client_dest && c == t->client)
932   {
933     struct GNUNET_MESH_TunnelMessage msg;
934
935     msg.header.size = htons (sizeof (msg));
936     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
937     msg.tunnel_id = htonl (t->local_tid_dest);
938     GNUNET_SERVER_notification_context_unicast (nc, t->client_dest->handle,
939                                                 &msg.header, GNUNET_NO);
940   }
941 }
942
943
944 /**
945  * Function called to notify a client about the socket
946  * being ready to queue more data.  "buf" will be
947  * NULL and "size" zero if the socket was closed for
948  * writing in the meantime.
949  *
950  * @param cls closure
951  * @param size number of bytes available in buf
952  * @param buf where the callee should write the message
953  * @return number of bytes written to buf
954  */
955 static size_t
956 send_core_create_path (void *cls, size_t size, void *buf);
957
958
959 /**
960  * Function called to notify a client about the socket
961  * being ready to queue more data.  "buf" will be
962  * NULL and "size" zero if the socket was closed for
963  * writing in the meantime.
964  *
965  * @param cls closure (data itself)
966  * @param size number of bytes available in buf
967  * @param buf where the callee should write the message
968  *
969  * @return number of bytes written to buf
970  */
971 static size_t
972 send_core_data_multicast (void *cls, size_t size, void *buf);
973
974
975 /**
976  * Decrements the reference counter and frees all resources if needed
977  *
978  * @param dd Data Descriptor used in a multicast message. Freed if needed.
979  */
980 static void
981 data_descriptor_decrement_multicast (struct MeshData *mesh_data)
982 {
983   /* Make sure it's a multicast packet */
984   GNUNET_assert (NULL != mesh_data->reference_counter);
985
986   if (0 == --(*(mesh_data->reference_counter)))
987   {
988     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Last copy!\n");
989     if (NULL != mesh_data->task)
990     {
991       if (GNUNET_SCHEDULER_NO_TASK != *(mesh_data->task))
992       {
993         GNUNET_SCHEDULER_cancel (*(mesh_data->task));
994         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  notifying client...\n");
995         GNUNET_SERVER_receive_done (mesh_data->t->client->handle, GNUNET_OK);
996       }
997       GNUNET_free (mesh_data->task);
998     }
999     GNUNET_free (mesh_data->reference_counter);
1000     GNUNET_free (mesh_data->data);
1001     GNUNET_free (mesh_data);
1002   }
1003 }
1004
1005
1006 /**
1007  * Cancel a core transmission that was already requested and free all resources
1008  * associated to the request.
1009  *
1010  * @param peer PeeInfo of the peer whose transmission is cancelled.
1011  * @param i Position of the transmission to be cancelled.
1012  */
1013 static void
1014 peer_info_cancel_transmission (struct MeshPeerInfo *peer, unsigned int i)
1015 {
1016   if (NULL != peer->core_transmit[i])
1017   {
1018     struct MeshTransmissionDescriptor *dd;
1019     struct MeshPathInfo *path_info;
1020
1021 #if MESH_DEBUG
1022     {
1023       struct GNUNET_PeerIdentity id;
1024
1025       GNUNET_PEER_resolve (peer->id, &id);
1026       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1027                   "MESH:   Cancelling data transmission at %s [%u]\n",
1028                   GNUNET_i2s (&id), i);
1029       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    message type %u\n",
1030                   peer->types[i]);
1031     }
1032 #endif
1033     /* TODO: notify that tranmission has failed */
1034     switch (peer->types[i])
1035     {
1036     case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1037     case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1038     case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1039       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    type payload\n");
1040       dd = peer->infos[i];
1041       data_descriptor_decrement_multicast (dd->mesh_data);
1042       break;
1043     case GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE:
1044       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    type create path\n");
1045       path_info = peer->infos[i];
1046       path_destroy (path_info->path);
1047       break;
1048     default:
1049       GNUNET_break (0);
1050       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    type unknown!\n");
1051     }
1052     GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit[i]);
1053     peer->core_transmit[i] = NULL;
1054     GNUNET_free (peer->infos[i]);
1055   }
1056 }
1057
1058
1059 /**
1060  * Get a unused CORE slot to transmit a message to a peer. If all the slots
1061  * are used, cancel one and return it's position.
1062  *
1063  * @param peer PeerInfo of the neighbor we want to transmit to.
1064  *
1065  * @return The index of an available slot to transmit to the neighbor.
1066  */
1067 static unsigned int
1068 peer_info_transmit_slot (struct MeshPeerInfo *peer)
1069 {
1070   unsigned int i;
1071
1072   for (i = 0; peer->core_transmit[i]; i++)
1073   {
1074     if (i == (CORE_QUEUE_SIZE - 1))
1075     {
1076       /* All positions are taken! Overwriting! */
1077       GNUNET_break (0);
1078       peer_info_cancel_transmission (peer, 0);
1079       return 0;
1080     }
1081   }
1082   return i;
1083 }
1084
1085
1086 /**
1087  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1088  * and insert it in the appropiate structures if the peer is not known yet.
1089  *
1090  * @param peer Full identity of the peer.
1091  *
1092  * @return Existing or newly created peer info.
1093  */
1094 static struct MeshPeerInfo *
1095 peer_info_get (const struct GNUNET_PeerIdentity *peer)
1096 {
1097   struct MeshPeerInfo *peer_info;
1098
1099   peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
1100   if (NULL == peer_info)
1101   {
1102     peer_info =
1103         (struct MeshPeerInfo *) GNUNET_malloc (sizeof (struct MeshPeerInfo));
1104     GNUNET_CONTAINER_multihashmap_put (peers, &peer->hashPubKey, peer_info,
1105                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1106     peer_info->id = GNUNET_PEER_intern (peer);
1107   }
1108
1109   return peer_info;
1110 }
1111
1112
1113 /**
1114  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
1115  * and insert it in the appropiate structures if the peer is not known yet.
1116  *
1117  * @param peer Short identity of the peer.
1118  *
1119  * @return Existing or newly created peer info.
1120  */
1121 static struct MeshPeerInfo *
1122 peer_info_get_short (const GNUNET_PEER_Id peer)
1123 {
1124   struct GNUNET_PeerIdentity id;
1125
1126   GNUNET_PEER_resolve (peer, &id);
1127   return peer_info_get (&id);
1128 }
1129
1130
1131 /**
1132  * Iterator to remove the tunnel from the list of tunnels a peer participates
1133  * in.
1134  *
1135  * @param cls Closure (tunnel info)
1136  * @param key GNUNET_PeerIdentity of the peer (unused)
1137  * @param value PeerInfo of the peer
1138  *
1139  * @return always GNUNET_YES, to keep iterating
1140  */
1141 static int
1142 peer_info_delete_tunnel (void *cls, const GNUNET_HashCode * key, void *value)
1143 {
1144   struct MeshTunnel *t = cls;
1145   struct MeshPeerInfo *peer = value;
1146   unsigned int i;
1147
1148   for (i = 0; i < peer->ntunnels; i++)
1149   {
1150     if (0 ==
1151         memcmp (&peer->tunnels[i]->id, &t->id, sizeof (struct MESH_TunnelID)))
1152     {
1153       peer->ntunnels--;
1154       peer->tunnels[i] = peer->tunnels[peer->ntunnels];
1155       peer->tunnels = GNUNET_realloc (peer->tunnels, peer->ntunnels);
1156       return GNUNET_YES;
1157     }
1158   }
1159   return GNUNET_YES;
1160 }
1161
1162
1163 /**
1164   * Core callback to write a
1165   *
1166   * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
1167   * @param size Number of bytes available in buf.
1168   * @param buf Where the to write the message.
1169   *
1170   * @return number of bytes written to buf
1171   */
1172 static size_t
1173 send_core_data_raw (void *cls, size_t size, void *buf)
1174 {
1175   struct MeshTransmissionDescriptor *info = cls;
1176   struct GNUNET_MessageHeader *msg;
1177   size_t total_size;
1178
1179   GNUNET_assert (NULL != info);
1180   GNUNET_assert (NULL != info->mesh_data);
1181   msg = (struct GNUNET_MessageHeader *) info->mesh_data->data;
1182   total_size = ntohs (msg->size);
1183
1184   if (total_size > size)
1185   {
1186     struct GNUNET_PeerIdentity id;
1187
1188     GNUNET_PEER_resolve (info->peer->id, &id);
1189     info->peer->core_transmit[info->handler_n] =
1190         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
1191                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
1192                                            size, &send_core_data_raw, info);
1193     return 0;
1194   }
1195   info->peer->core_transmit[info->handler_n] = NULL;
1196   memcpy (buf, msg, total_size);
1197   GNUNET_free (info->mesh_data);
1198   GNUNET_free (info);
1199   return total_size;
1200 }
1201
1202
1203 /**
1204  * Sends an already built message to a peer, properly registrating
1205  * all used resources.
1206  *
1207  * @param message Message to send. Fucntion makes a copy of it.
1208  * @param peer Short ID of the neighbor whom to send the message.
1209  *
1210  * FIXME tunnel?
1211  */
1212 static void
1213 send_message (const struct GNUNET_MessageHeader *message,
1214               const struct GNUNET_PeerIdentity *peer)
1215 {
1216   struct MeshTransmissionDescriptor *info;
1217   struct MeshPeerInfo *neighbor;
1218   struct MeshPeerPath *p;
1219   unsigned int i;
1220   size_t size;
1221
1222 //   GNUNET_TRANSPORT_try_connect();
1223
1224   size = ntohs (message->size);
1225   info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
1226   info->mesh_data = GNUNET_malloc (sizeof (struct MeshData));
1227   info->mesh_data->data = GNUNET_malloc (size);
1228   memcpy (info->mesh_data->data, message, size);
1229   info->mesh_data->data_len = size;
1230   neighbor = peer_info_get (peer);
1231   for (p = neighbor->path_head; NULL != p; p = p->next)
1232   {
1233     if (2 == p->length)
1234     {
1235       break;
1236     }
1237   }
1238   if (NULL == p)
1239   {
1240     GNUNET_break (0);
1241     GNUNET_free (info->mesh_data->data);
1242     GNUNET_free (info->mesh_data);
1243     GNUNET_free (info);
1244     return;
1245   }
1246   i = peer_info_transmit_slot (neighbor);
1247   info->handler_n = i;
1248   info->peer = neighbor;
1249   neighbor->types[i] = GNUNET_MESSAGE_TYPE_MESH_UNICAST;
1250   neighbor->infos[i] = info;
1251   neighbor->core_transmit[i] =
1252       GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
1253                                          GNUNET_TIME_UNIT_FOREVER_REL, peer,
1254                                          size, &send_core_data_raw, info);
1255
1256 }
1257
1258
1259 /**
1260  * Sends a CREATE PATH message for a path to a peer, properly registrating
1261  * all used resources.
1262  *
1263  * @param peer PeerInfo of the final peer for whom this path is being created.
1264  * @param p Path itself.
1265  * @param t Tunnel for which the path is created.
1266  */
1267 static void
1268 send_create_path (struct MeshPeerInfo *peer, struct MeshPeerPath *p,
1269                   struct MeshTunnel *t)
1270 {
1271   struct GNUNET_PeerIdentity id;
1272   struct MeshPathInfo *path_info;
1273   struct MeshPeerInfo *neighbor;
1274   unsigned int i;
1275
1276   if (NULL == p)
1277   {
1278     p = tree_get_path_to_peer (t->tree, peer->id);
1279     if (NULL == p)
1280     {
1281       GNUNET_break (0);
1282       return;
1283     }
1284   }
1285   for (i = 0; i < p->length; i++)
1286   {
1287     if (p->peers[i] == myid)
1288       break;
1289   }
1290   if (i >= p->length - 1)
1291   {
1292     path_destroy (p);
1293     GNUNET_break (0);
1294     return;
1295   }
1296   GNUNET_PEER_resolve (p->peers[i + 1], &id);
1297
1298   path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
1299   path_info->path = p;
1300   path_info->t = t;
1301   neighbor = peer_info_get (&id);
1302   path_info->peer = neighbor;
1303   path_info->pos = peer_info_transmit_slot (neighbor);
1304   neighbor->types[path_info->pos] = GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE;
1305   neighbor->infos[path_info->pos] = path_info;
1306   neighbor->core_transmit[path_info->pos] = GNUNET_CORE_notify_transmit_ready (core_handle,     /* handle */
1307                                                                                0,       /* cork */
1308                                                                                0,       /* priority */
1309                                                                                GNUNET_TIME_UNIT_FOREVER_REL,    /* timeout */
1310                                                                                &id,     /* target */
1311                                                                                sizeof (struct GNUNET_MESH_ManipulatePath) + (p->length * sizeof (struct GNUNET_PeerIdentity)),  /*size */
1312                                                                                &send_core_create_path,  /* callback */
1313                                                                                path_info);      /* cls */
1314 }
1315
1316
1317 /**
1318  * Sends a DESTROY PATH message to free resources for a path in a tunnel
1319  *
1320  * @param t Tunnel whose path to destroy.
1321  * @param destination Short ID of the peer to whom the path to destroy.
1322  */
1323 static void
1324 send_destroy_path (struct MeshTunnel *t, GNUNET_PEER_Id destination)
1325 {
1326   struct MeshPeerPath *p;
1327   size_t size;
1328
1329   p = tree_get_path_to_peer (t->tree, destination);
1330   if (NULL == p)
1331   {
1332     GNUNET_break (0);
1333     return;
1334   }
1335   size = sizeof (struct GNUNET_MESH_ManipulatePath);
1336   size += p->length * sizeof (struct GNUNET_PeerIdentity);
1337   {
1338     struct GNUNET_MESH_ManipulatePath *msg;
1339     struct GNUNET_PeerIdentity *pi;
1340     char cbuf[size];
1341     unsigned int i;
1342
1343     msg = (struct GNUNET_MESH_ManipulatePath *) cbuf;
1344     msg->header.size = htons (size);
1345     msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY);
1346     msg->tid = htonl (t->id.tid);
1347     pi = (struct GNUNET_PeerIdentity *) &msg[1];
1348     for (i = 0; i < p->length; i++)
1349     {
1350       GNUNET_PEER_resolve (p->peers[i], &pi[i]);
1351     }
1352     send_message (&msg->header, tree_get_first_hop (t->tree, destination));
1353   }
1354   path_destroy (p);
1355 }
1356
1357
1358 /**
1359  * Try to establish a new connection to this peer.
1360  * Use the best path for the given tunnel.
1361  * If the peer doesn't have any path to it yet, try to get one.
1362  * If the peer already has some path, send a CREATE PATH towards it.
1363  *
1364  * @param peer PeerInfo of the peer.
1365  * @param t Tunnel for which to create the path, if possible.
1366  */
1367 static void
1368 peer_info_connect (struct MeshPeerInfo *peer, struct MeshTunnel *t)
1369 {
1370   struct MeshPeerPath *p;
1371   struct MeshPathInfo *path_info;
1372
1373   if (NULL != peer->path_head)
1374   {
1375     p = tree_get_path_to_peer (t->tree, peer->id);
1376     if (NULL == p)
1377     {
1378       GNUNET_break (0);
1379       return;
1380     }
1381
1382     if (p->length > 1)
1383     {
1384       send_create_path (peer, p, t);
1385     }
1386     else
1387     {
1388       path_destroy (p);
1389       send_client_peer_connected (t, myid);
1390     }
1391   }
1392   else if (NULL == peer->dhtget)
1393   {
1394     struct GNUNET_PeerIdentity id;
1395
1396     GNUNET_PEER_resolve (peer->id, &id);
1397     path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
1398     path_info->peer = peer;
1399     path_info->t = t;
1400     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1401                 "MESH:   Starting DHT GET for peer %s\n", GNUNET_i2s (&id));
1402     peer->dhtgetcls = path_info;
1403     peer->dhtget = GNUNET_DHT_get_start (dht_handle,    /* handle */
1404                                          GNUNET_TIME_UNIT_FOREVER_REL,  /* timeout */
1405                                          GNUNET_BLOCK_TYPE_TEST,        /* type */
1406                                          &id.hashPubKey,        /* key to search */
1407                                          4,     /* replication level */
1408                                          GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL,       /* xquery */
1409                                          0,     /* xquery bits */
1410                                          &dht_get_id_handler, path_info);
1411   }
1412   /* Otherwise, there is no path but the DHT get is already started. */
1413 }
1414
1415
1416 /**
1417  * Task to delay the connection of a peer
1418  *
1419  * @param cls Closure (path info with tunnel and peer to connect).
1420  *            Will be free'd on exection.
1421  * @param tc TaskContext
1422  */
1423 static void
1424 peer_info_connect_task (void *cls,
1425                         const struct GNUNET_SCHEDULER_TaskContext *tc)
1426 {
1427   struct MeshPathInfo *path_info = cls;
1428
1429   if (0 != (GNUNET_SCHEDULER_REASON_SHUTDOWN & tc->reason))
1430   {
1431     GNUNET_free (cls);
1432     return;
1433   }
1434   peer_info_connect (path_info->peer, path_info->t);
1435   GNUNET_free (cls);
1436 }
1437
1438
1439 /**
1440  * Destroy the peer_info and free any allocated resources linked to it
1441  *
1442  * @param pi The peer_info to destroy.
1443  *
1444  * @return GNUNET_OK on success
1445  */
1446 static int
1447 peer_info_destroy (struct MeshPeerInfo *pi)
1448 {
1449   struct GNUNET_PeerIdentity id;
1450   struct MeshPeerPath *p;
1451   struct MeshPeerPath *nextp;
1452   unsigned int i;
1453
1454   GNUNET_PEER_resolve (pi->id, &id);
1455   GNUNET_PEER_change_rc (pi->id, -1);
1456
1457   if (GNUNET_YES !=
1458       GNUNET_CONTAINER_multihashmap_remove (peers, &id.hashPubKey, pi))
1459   {
1460     GNUNET_break (0);
1461     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1462                 "MESH: removing peer %s, not in hashmap\n", GNUNET_i2s (&id));
1463   }
1464   if (NULL != pi->dhtget)
1465   {
1466     GNUNET_DHT_get_stop (pi->dhtget);
1467     GNUNET_free (pi->dhtgetcls);
1468   }
1469   for (i = 0; i < CORE_QUEUE_SIZE; i++)
1470   {
1471     peer_info_cancel_transmission (pi, i);
1472   }
1473   p = pi->path_head;
1474   while (NULL != p)
1475   {
1476     nextp = p->next;
1477     GNUNET_CONTAINER_DLL_remove (pi->path_head, pi->path_tail, p);
1478     path_destroy (p);
1479     p = nextp;
1480   }
1481   GNUNET_free (pi);
1482   return GNUNET_OK;
1483 }
1484
1485
1486 /**
1487  * Remove all paths that rely on a direct connection between p1 and p2
1488  * from the peer itself and notify all tunnels about it.
1489  *
1490  * @param peer PeerInfo of affected peer.
1491  * @param p1 GNUNET_PEER_Id of one peer.
1492  * @param p2 GNUNET_PEER_Id of another peer that was connected to the first and
1493  *           no longer is.
1494  *
1495  * TODO: optimize (see below)
1496  */
1497 static void
1498 peer_info_remove_path (struct MeshPeerInfo *peer, GNUNET_PEER_Id p1,
1499                        GNUNET_PEER_Id p2)
1500 {
1501   struct MeshPeerPath *p;
1502   struct MeshPeerPath *aux;
1503   struct MeshPeerInfo *peer_d;
1504   GNUNET_PEER_Id d;
1505   unsigned int destroyed;
1506   unsigned int best;
1507   unsigned int cost;
1508   unsigned int i;
1509
1510   destroyed = 0;
1511   p = peer->path_head;
1512   while (NULL != p)
1513   {
1514     aux = p->next;
1515     for (i = 0; i < (p->length - 1); i++)
1516     {
1517       if ((p->peers[i] == p1 && p->peers[i + 1] == p2) ||
1518           (p->peers[i] == p2 && p->peers[i + 1] == p1))
1519       {
1520         GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
1521         path_destroy (p);
1522         destroyed++;
1523         break;
1524       }
1525     }
1526     p = aux;
1527   }
1528   if (0 == destroyed)
1529     return;
1530
1531   for (i = 0; i < peer->ntunnels; i++)
1532   {
1533     d = tunnel_notify_connection_broken (peer->tunnels[i], p1, p2);
1534     if (0 == d)
1535       continue;
1536     /* TODO
1537      * Problem: one or more peers have been deleted from the tunnel tree.
1538      * We don't know who they are to try to add them again.
1539      * We need to try to find a new path for each of the disconnected peers.
1540      * Some of them might already have a path to reach them that does not
1541      * involve p1 and p2. Adding all anew might render in a better tree than
1542      * the trivial immediate fix.
1543      *
1544      * Trivial immiediate fix: try to reconnect to the disconnected node. All
1545      * its children will be reachable trough him.
1546      */
1547     peer_d = peer_info_get_short (d);
1548     best = UINT_MAX;
1549     aux = NULL;
1550     for (p = peer_d->path_head; NULL != p; p = p->next)
1551     {
1552       if ((cost = tree_get_path_cost (peer->tunnels[i]->tree, p)) < best)
1553       {
1554         best = cost;
1555         aux = p;
1556       }
1557     }
1558     if (NULL != aux)
1559     {
1560       /* No callback, as peer will be already disconnected and a connection
1561        * scheduled by tunnel_notify_connection_broken.
1562        */
1563       tree_add_path (peer->tunnels[i]->tree, aux, NULL, NULL);
1564     }
1565     else
1566     {
1567       peer_info_connect (peer_d, peer->tunnels[i]);
1568     }
1569   }
1570 }
1571
1572
1573 /**
1574  * Add the path to the peer and update the path used to reach it in case this
1575  * is the shortest.
1576  *
1577  * @param peer_info Destination peer to add the path to.
1578  * @param path New path to add. Last peer must be the peer in arg 1.
1579  *             Path will be either used of freed if already known.
1580  * @param trusted Do we trust that this path is real?
1581  */
1582 void
1583 peer_info_add_path (struct MeshPeerInfo *peer_info, struct MeshPeerPath *path,
1584                     int trusted)
1585 {
1586   struct MeshPeerPath *aux;
1587   unsigned int l;
1588   unsigned int l2;
1589
1590   if ((NULL == peer_info) || (NULL == path))
1591   {
1592     GNUNET_break (0);
1593     path_destroy (path);
1594     return;
1595   }
1596   if (path->peers[path->length - 1] != peer_info->id)
1597   {
1598     GNUNET_break (0);
1599     path_destroy (path);
1600     return;
1601   }
1602   if (path->length <= 2 && GNUNET_NO == trusted)
1603   {
1604     /* Only allow CORE to tell us about direct paths */
1605     path_destroy (path);
1606     return;
1607   }
1608   GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
1609   for (l = 1; l < path->length; l++)
1610   {
1611     if (path->peers[l] == myid)
1612     {
1613       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shortening path by %u\n", l);
1614       for (l2 = 0; l2 < path->length - l; l2++)
1615       {
1616         path->peers[l2] = path->peers[l + l2];
1617       }
1618       path->length -= l;
1619       l = 1;
1620       path->peers =
1621           GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
1622     }
1623   }
1624 #if MESH_DEBUG
1625   {
1626     struct GNUNET_PeerIdentity id;
1627
1628     GNUNET_PEER_resolve (peer_info->id, &id);
1629     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: adding path [%u] to peer %s\n",
1630                 path->length, GNUNET_i2s (&id));
1631   }
1632 #endif
1633   l = path_get_length (path);
1634   if (0 == l)
1635   {
1636     GNUNET_free (path);
1637     return;
1638   }
1639
1640   GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
1641   for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
1642   {
1643     l2 = path_get_length (aux);
1644     if (l2 > l)
1645     {
1646       GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
1647                                           peer_info->path_tail, aux, path);
1648       return;
1649     }
1650     else
1651     {
1652       if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
1653       {
1654         path_destroy (path);
1655         return;
1656       }
1657     }
1658   }
1659   GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
1660                                     path);
1661   return;
1662 }
1663
1664
1665 /**
1666  * Add the path to the origin peer and update the path used to reach it in case
1667  * this is the shortest.
1668  * The path is given in peer_info -> destination, therefore we turn the path
1669  * upside down first.
1670  *
1671  * @param peer_info Peer to add the path to, being the origin of the path.
1672  * @param path New path to add after being inversed.
1673  * @param trusted Do we trust that this path is real?
1674  */
1675 static void
1676 peer_info_add_path_to_origin (struct MeshPeerInfo *peer_info,
1677                               struct MeshPeerPath *path, int trusted)
1678 {
1679   path_invert (path);
1680   peer_info_add_path (peer_info, path, trusted);
1681 }
1682
1683
1684 /**
1685  * Build a PeerPath from the paths returned from the DHT, reversing the paths
1686  * to obtain a local peer -> destination path and interning the peer ids.
1687  *
1688  * @return Newly allocated and created path
1689  */
1690 static struct MeshPeerPath *
1691 path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
1692                      unsigned int get_path_length,
1693                      const struct GNUNET_PeerIdentity *put_path,
1694                      unsigned int put_path_length)
1695 {
1696   struct MeshPeerPath *p;
1697   GNUNET_PEER_Id id;
1698   int i;
1699
1700   p = path_new (1);
1701   p->peers[0] = myid;
1702   GNUNET_PEER_change_rc (myid, 1);
1703   i = get_path_length;
1704   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    GET has %d hops.\n", i);
1705   for (i--; i >= 0; i--)
1706   {
1707     id = GNUNET_PEER_intern (&get_path[i]);
1708     if (p->length > 0 && id == p->peers[p->length - 1])
1709     {
1710       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    Optimizing 1 hop out.\n");
1711       GNUNET_PEER_change_rc (id, -1);
1712     }
1713     else
1714     {
1715       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    Adding from GET: %s.\n",
1716                   GNUNET_i2s (&get_path[i]));
1717       p->length++;
1718       p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
1719       p->peers[p->length - 1] = id;
1720     }
1721   }
1722   i = put_path_length;
1723   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    PUT has %d hops.\n", i);
1724   for (i--; i >= 0; i--)
1725   {
1726     id = GNUNET_PEER_intern (&put_path[i]);
1727     if (id == myid)
1728     {
1729       /* PUT path went through us, so discard the path up until now and start
1730        * from here to get a much shorter (and loop-free) path.
1731        */
1732       path_destroy (p);
1733       p = path_new (0);
1734     }
1735     if (p->length > 0 && id == p->peers[p->length - 1])
1736     {
1737       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    Optimizing 1 hop out.\n");
1738       GNUNET_PEER_change_rc (id, -1);
1739     }
1740     else
1741     {
1742       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    Adding from PUT: %s.\n",
1743                   GNUNET_i2s (&put_path[i]));
1744       p->length++;
1745       p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
1746       p->peers[p->length - 1] = id;
1747     }
1748   }
1749 #if MESH_DEBUG
1750   if (get_path_length > 0)
1751     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    (first of GET: %s)\n",
1752                 GNUNET_i2s (&get_path[0]));
1753   if (put_path_length > 0)
1754     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    (first of PUT: %s)\n",
1755                 GNUNET_i2s (&put_path[0]));
1756   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    In total: %d hops\n",
1757               p->length);
1758   for (i = 0; i < p->length; i++)
1759   {
1760     struct GNUNET_PeerIdentity peer_id;
1761
1762     GNUNET_PEER_resolve (p->peers[i], &peer_id);
1763     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:        %u: %s\n", p->peers[i],
1764                 GNUNET_i2s (&peer_id));
1765   }
1766 #endif
1767   return p;
1768 }
1769
1770
1771 /**
1772  * Adds a path to the peer_infos of all the peers in the path
1773  *
1774  * @param p Path to process.
1775  * @param confirmed Whether we know if the path works or not. FIXME use
1776  */
1777 static void
1778 path_add_to_peers (struct MeshPeerPath *p, int confirmed)
1779 {
1780   unsigned int i;
1781
1782   /* TODO: invert and add */
1783   for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
1784   for (i++; i < p->length; i++)
1785   {
1786     struct MeshPeerInfo *aux;
1787     struct MeshPeerPath *copy;
1788
1789     aux = peer_info_get_short (p->peers[i]);
1790     copy = path_duplicate (p);
1791     copy->length = i + 1;
1792     peer_info_add_path (aux, copy, GNUNET_NO);
1793   }
1794 }
1795
1796
1797 /**
1798  * Send keepalive packets for a peer
1799  *
1800  * @param cls Closure (tunnel for which to send the keepalive).
1801  * @param tc Notification context.
1802  *
1803  * TODO: implement explicit multicast keepalive?
1804  */
1805 static void
1806 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1807
1808
1809 /**
1810  * Search for a tunnel among the incoming tunnels
1811  *
1812  * @param tid the local id of the tunnel
1813  *
1814  * @return tunnel handler, NULL if doesn't exist
1815  */
1816 static struct MeshTunnel *
1817 tunnel_get_incoming (MESH_TunnelNumber tid)
1818 {
1819   GNUNET_HashCode hash;
1820
1821   GNUNET_assert (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV);
1822   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
1823   return GNUNET_CONTAINER_multihashmap_get (incoming_tunnels, &hash);
1824 }
1825
1826
1827 /**
1828  * Search for a tunnel among the tunnels for a client
1829  *
1830  * @param c the client whose tunnels to search in
1831  * @param tid the local id of the tunnel
1832  *
1833  * @return tunnel handler, NULL if doesn't exist
1834  */
1835 static struct MeshTunnel *
1836 tunnel_get_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
1837 {
1838   if (tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1839   {
1840     return tunnel_get_incoming (tid);
1841   }
1842   else
1843   {
1844     GNUNET_HashCode hash;
1845
1846     GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
1847     return GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
1848   }
1849 }
1850
1851
1852 /**
1853  * Search for a tunnel by global ID using PEER_ID
1854  *
1855  * @param pi owner of the tunnel
1856  * @param tid global tunnel number
1857  *
1858  * @return tunnel handler, NULL if doesn't exist
1859  */
1860 static struct MeshTunnel *
1861 tunnel_get_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
1862 {
1863   struct MESH_TunnelID id;
1864   GNUNET_HashCode hash;
1865
1866   id.oid = pi;
1867   id.tid = tid;
1868
1869   GNUNET_CRYPTO_hash (&id, sizeof (struct MESH_TunnelID), &hash);
1870   return GNUNET_CONTAINER_multihashmap_get (tunnels, &hash);
1871 }
1872
1873
1874 /**
1875  * Search for a tunnel by global ID using full PeerIdentities
1876  *
1877  * @param oid owner of the tunnel
1878  * @param tid global tunnel number
1879  *
1880  * @return tunnel handler, NULL if doesn't exist
1881  */
1882 static struct MeshTunnel *
1883 tunnel_get (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
1884 {
1885   return tunnel_get_by_pi (GNUNET_PEER_search (oid), tid);
1886 }
1887
1888
1889 /**
1890  * Callback used to notify a client owner of a tunnel that a peer has
1891  * disconnected, most likely because of a path change.
1892  *
1893  * @param cls Closure (tunnel this notification is about).
1894  * @param peer_id Short ID of disconnected peer.
1895  */
1896 void
1897 notify_peer_disconnected (void *cls, GNUNET_PEER_Id peer_id)
1898 {
1899   struct MeshTunnel *t = cls;
1900   struct MeshPeerInfo *peer;
1901   struct MeshPathInfo *path_info;
1902
1903   if (NULL != t->client && NULL != nc)
1904   {
1905     struct GNUNET_MESH_PeerControl msg;
1906
1907     msg.header.size = htons (sizeof (msg));
1908     msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
1909     msg.tunnel_id = htonl (t->local_tid);
1910     GNUNET_PEER_resolve (peer_id, &msg.peer);
1911     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
1912                                                 &msg.header, GNUNET_NO);
1913   }
1914   peer = peer_info_get_short (peer_id);
1915   path_info = GNUNET_malloc (sizeof (struct MeshPathInfo));
1916   path_info->peer = peer;
1917   path_info->t = t;
1918   GNUNET_SCHEDULER_add_now (&peer_info_connect_task, path_info);
1919 }
1920
1921
1922 /**
1923  * Add a peer to a tunnel, accomodating paths accordingly and initializing all
1924  * needed rescources.
1925  * If peer already exists, reevaluate shortest path and change if different.
1926  *
1927  * @param t Tunnel we want to add a new peer to
1928  * @param peer PeerInfo of the peer being added
1929  *
1930  */
1931 static void
1932 tunnel_add_peer (struct MeshTunnel *t, struct MeshPeerInfo *peer)
1933 {
1934   struct GNUNET_PeerIdentity id;
1935   struct MeshPeerPath *best_p;
1936   struct MeshPeerPath *p;
1937   unsigned int best_cost;
1938   unsigned int cost;
1939
1940   GNUNET_PEER_resolve (peer->id, &id);
1941   if (GNUNET_NO ==
1942       GNUNET_CONTAINER_multihashmap_contains (t->peers, &id.hashPubKey))
1943   {
1944     t->peers_total++;
1945     GNUNET_array_append (peer->tunnels, peer->ntunnels, t);
1946     GNUNET_assert (GNUNET_OK ==
1947                    GNUNET_CONTAINER_multihashmap_put (t->peers, &id.hashPubKey,
1948                                                       peer,
1949                                                       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
1950   }
1951
1952   if (NULL != (p = peer->path_head))
1953   {
1954     best_p = p;
1955     best_cost = tree_get_path_cost (t->tree, p);
1956     while (NULL != p)
1957     {
1958       if ((cost = tree_get_path_cost (t->tree, p)) < best_cost)
1959       {
1960         best_cost = cost;
1961         best_p = p;
1962       }
1963       p = p->next;
1964     }
1965     tree_add_path (t->tree, best_p, &notify_peer_disconnected, t);
1966     if (GNUNET_SCHEDULER_NO_TASK == t->path_refresh_task)
1967       t->path_refresh_task =
1968           GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
1969   }
1970   else
1971   {
1972     /* Start a DHT get */
1973     peer_info_connect (peer, t);
1974   }
1975 }
1976
1977 /**
1978  * Add a path to a tunnel which we don't own, just to remember the next hop.
1979  * If destination node was already in the tunnel, the first hop information
1980  * will be replaced with the new path.
1981  *
1982  * @param t Tunnel we want to add a new peer to
1983  * @param p Path to add
1984  * @param own_pos Position of local node in path.
1985  *
1986  */
1987 static void
1988 tunnel_add_path (struct MeshTunnel *t, struct MeshPeerPath *p,
1989                  unsigned int own_pos)
1990 {
1991   struct GNUNET_PeerIdentity id;
1992
1993   GNUNET_assert (0 != own_pos);
1994   tree_add_path (t->tree, p, NULL, NULL);
1995   if (own_pos < p->length - 1)
1996   {
1997     GNUNET_PEER_resolve (p->peers[own_pos + 1], &id);
1998     tree_update_first_hops (t->tree, myid, &id);
1999   }
2000 }
2001
2002
2003 /**
2004  * Notifies a tunnel that a connection has broken that affects at least
2005  * some of its peers. Sends a notification towards the root of the tree.
2006  * In case the peer is the owner of the tree, notifies the client that owns
2007  * the tunnel and tries to reconnect.
2008  *
2009  * @param t Tunnel affected.
2010  * @param p1 Peer that got disconnected from p2.
2011  * @param p2 Peer that got disconnected from p1.
2012  *
2013  * @return Short ID of the peer disconnected (either p1 or p2).
2014  *         0 if the tunnel remained unaffected.
2015  */
2016 static GNUNET_PEER_Id
2017 tunnel_notify_connection_broken (struct MeshTunnel *t, GNUNET_PEER_Id p1,
2018                                  GNUNET_PEER_Id p2)
2019 {
2020   GNUNET_PEER_Id pid;
2021
2022   pid =
2023       tree_notify_connection_broken (t->tree, p1, p2, &notify_peer_disconnected,
2024                                      t);
2025   if (myid != p1 && myid != p2)
2026   {
2027     return pid;
2028   }
2029   if (pid != myid)
2030   {
2031     if (tree_get_predecessor (t->tree) != 0)
2032     {
2033       /* We are the peer still connected, notify owner of the disconnection. */
2034       struct GNUNET_MESH_PathBroken msg;
2035       struct GNUNET_PeerIdentity neighbor;
2036
2037       msg.header.size = htons (sizeof (msg));
2038       msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
2039       GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2040       msg.tid = htonl (t->id.tid);
2041       msg.peer1 = my_full_id;
2042       GNUNET_PEER_resolve (pid, &msg.peer2);
2043       GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
2044       send_message (&msg.header, &neighbor);
2045     }
2046   }
2047   return pid;
2048 }
2049
2050
2051 /**
2052  * Send a multicast packet to a neighbor.
2053  *
2054  * @param cls Closure (Info about the multicast packet)
2055  * @param neighbor_id Short ID of the neighbor to send the packet to.
2056  */
2057 static void
2058 tunnel_send_multicast_iterator (void *cls, GNUNET_PEER_Id neighbor_id)
2059 {
2060   struct MeshData *mdata = cls;
2061   struct MeshTransmissionDescriptor *info;
2062   struct GNUNET_PeerIdentity neighbor;
2063   unsigned int i;
2064
2065   info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
2066
2067   info->mesh_data = mdata;
2068   (*(mdata->reference_counter)) ++;
2069   info->destination = neighbor_id;
2070   GNUNET_PEER_resolve (neighbor_id, &neighbor);
2071 #if MESH_DEBUG
2072   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    sending to %s...\n",
2073               GNUNET_i2s (&neighbor));
2074 #endif
2075   info->peer = peer_info_get (&neighbor);
2076   GNUNET_assert (NULL != info->peer);
2077   i = peer_info_transmit_slot (info->peer);
2078   info->handler_n = i;
2079   info->peer->infos[i] = info;
2080   info->peer->types[i] = GNUNET_MESSAGE_TYPE_MESH_MULTICAST;
2081   info->peer->core_transmit[i] =
2082       GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2083                                          GNUNET_TIME_UNIT_FOREVER_REL,
2084                                          &neighbor, info->mesh_data->data_len,
2085                                          &send_core_data_multicast, info);
2086 }
2087
2088 /**
2089  * Send a message in a tunnel in multicast, sending a copy to each child node
2090  * down the local one in the tunnel tree.
2091  *
2092  * @param t Tunnel in which to send the data.
2093  * @param msg Message to be sent
2094  */
2095 static void
2096 tunnel_send_multicast (struct MeshTunnel *t,
2097                        const struct GNUNET_MessageHeader *msg)
2098 {
2099   struct MeshData *mdata;
2100
2101 #if MESH_DEBUG
2102   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2103               "MESH:  sending a multicast packet...\n");
2104 #endif
2105   mdata = GNUNET_malloc (sizeof (struct MeshData));
2106   mdata->data_len = ntohs (msg->size);
2107   mdata->reference_counter = GNUNET_malloc (sizeof (unsigned int));
2108   mdata->t = t;
2109   mdata->data = GNUNET_malloc (mdata->data_len);
2110   memcpy (mdata->data, msg, mdata->data_len);
2111   if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
2112   {
2113     struct GNUNET_MESH_Multicast *mcast;
2114
2115     mcast = (struct GNUNET_MESH_Multicast *) mdata->data;
2116     mcast->ttl = htonl (ntohl (mcast->ttl) - 1);
2117 #if MESH_DEBUG
2118     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   data packet, ttl: %u\n",
2119                 ntohl (mcast->ttl));
2120   }
2121   else
2122   {
2123     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   not a data packet, no ttl\n");
2124 #endif
2125   }
2126   if (NULL != t->client)
2127   {
2128     mdata->task = GNUNET_malloc (sizeof (GNUNET_SCHEDULER_TaskIdentifier));
2129     (*(mdata->task)) =
2130         GNUNET_SCHEDULER_add_delayed (UNACKNOWLEDGED_WAIT, &client_allow_send,
2131                                       mdata);
2132     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: timeout task %u\n",
2133                 *(mdata->task));
2134   }
2135
2136   tree_iterate_children (t->tree, &tunnel_send_multicast_iterator, mdata);
2137   if (*(mdata->reference_counter) == 0)
2138   {
2139     GNUNET_free (mdata->data);
2140     GNUNET_free (mdata->reference_counter);
2141     if (NULL != mdata->task)
2142     {
2143       GNUNET_SCHEDULER_cancel(*(mdata->task));
2144       GNUNET_free (mdata->task);
2145       GNUNET_SERVER_receive_done(t->client->handle, GNUNET_OK);
2146     }
2147     // FIXME change order?
2148     GNUNET_free (mdata);
2149   }
2150 #if MESH_DEBUG
2151   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2152               "MESH:  sending a multicast packet done\n");
2153 #endif
2154   return;
2155 }
2156
2157
2158 /**
2159  * Send a message to all peers in this tunnel that the tunnel is no longer
2160  * valid.
2161  *
2162  * @param t The tunnel whose peers to notify.
2163  */
2164 static void
2165 tunnel_send_destroy (struct MeshTunnel *t)
2166 {
2167   struct GNUNET_MESH_TunnelDestroy msg;
2168
2169   msg.header.size = htons (sizeof (msg));
2170   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);
2171   GNUNET_PEER_resolve (t->id.oid, &msg.oid);
2172   msg.tid = htonl (t->id.tid);
2173   tunnel_send_multicast (t, &msg.header);
2174 }
2175
2176
2177
2178 /**
2179  * Destroy the tunnel and free any allocated resources linked to it
2180  *
2181  * @param t the tunnel to destroy
2182  *
2183  * @return GNUNET_OK on success
2184  */
2185 static int
2186 tunnel_destroy (struct MeshTunnel *t)
2187 {
2188   struct MeshClient *c;
2189   struct MeshQueue *q;
2190   struct MeshQueue *qn;
2191   GNUNET_HashCode hash;
2192   int r;
2193
2194   if (NULL == t)
2195     return GNUNET_OK;
2196
2197   c = t->client;
2198 #if MESH_DEBUG
2199   {
2200     struct GNUNET_PeerIdentity id;
2201
2202     GNUNET_PEER_resolve (t->id.oid, &id);
2203     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: destroying tunnel %s [%x]\n",
2204                 GNUNET_i2s (&id), t->id.tid);
2205     if (NULL != c)
2206       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
2207   }
2208 #endif
2209
2210   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2211   if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &hash, t))
2212   {
2213     r = GNUNET_SYSERR;
2214   }
2215
2216   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2217   if (NULL != c &&
2218       GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t))
2219   {
2220     r = GNUNET_SYSERR;
2221   }
2222   if (t->local_tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2223   {
2224     GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2225     GNUNET_break (GNUNET_YES ==
2226                   GNUNET_CONTAINER_multihashmap_remove (incoming_tunnels, &hash,
2227                                                         t));
2228   }
2229   if (NULL != t->peers)
2230   {
2231     GNUNET_CONTAINER_multihashmap_iterate (t->peers, &peer_info_delete_tunnel,
2232                                            t);
2233     GNUNET_CONTAINER_multihashmap_destroy (t->peers);
2234   }
2235   q = t->queue_head;
2236   while (NULL != q)
2237   {
2238     if (NULL != q->data)
2239       GNUNET_free (q->data);
2240     qn = q->next;
2241     GNUNET_free (q);
2242     q = qn;
2243     /* TODO cancel core transmit ready in case it was active */
2244   }
2245   tree_destroy (t->tree);
2246   if (NULL != t->dht_get_type)
2247     GNUNET_DHT_get_stop (t->dht_get_type);
2248   if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
2249     GNUNET_SCHEDULER_cancel (t->timeout_task);
2250   if (GNUNET_SCHEDULER_NO_TASK != t->path_refresh_task)
2251     GNUNET_SCHEDULER_cancel (t->path_refresh_task);
2252   GNUNET_free (t);
2253   return r;
2254 }
2255
2256
2257 /**
2258  * Removes an explicit path from a tunnel, freeing all intermediate nodes
2259  * that are no longer needed, as well as nodes of no longer reachable peers.
2260  * The tunnel itself is also destoyed if results in a remote empty tunnel.
2261  *
2262  * @param t Tunnel from which to remove the path.
2263  * @param peer Short id of the peer which should be removed.
2264  */
2265 static void
2266 tunnel_delete_peer (struct MeshTunnel *t, GNUNET_PEER_Id peer)
2267 {
2268   if (GNUNET_NO == tree_del_peer (t->tree, peer, NULL, NULL))
2269     tunnel_destroy (t);
2270 }
2271
2272
2273 /**
2274  * tunnel_destroy_iterator: iterator for deleting each tunnel that belongs to a
2275  * client when the client disconnects.
2276  *
2277  * @param cls closure (client that is disconnecting)
2278  * @param key the hash of the local tunnel id (used to access the hashmap)
2279  * @param value the value stored at the key (tunnel to destroy)
2280  *
2281  * @return GNUNET_OK on success
2282  */
2283 static int
2284 tunnel_destroy_iterator (void *cls, const GNUNET_HashCode * key, void *value)
2285 {
2286   struct MeshTunnel *t = value;
2287   struct MeshClient *c = cls;
2288   int r;
2289
2290   send_client_tunnel_disconnect(t, c);
2291   if (c == t->client_dest)
2292   {
2293     t->client_dest = NULL;
2294     t->local_tid_dest = 0;
2295     return GNUNET_OK;
2296   }
2297   tunnel_send_destroy(t);
2298   r = tunnel_destroy (t);
2299   return r;
2300 }
2301
2302
2303 /**
2304  * Timeout function, destroys tunnel if called
2305  *
2306  * @param cls Closure (tunnel to destroy).
2307  * @param tc TaskContext
2308  */
2309 static void
2310 tunnel_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2311 {
2312   struct MeshTunnel *t = cls;
2313
2314   if (GNUNET_SCHEDULER_REASON_SHUTDOWN == tc->reason)
2315     return;
2316   t->timeout_task = GNUNET_SCHEDULER_NO_TASK;
2317   tunnel_destroy (t);
2318 }
2319
2320 /**
2321  * Resets the tunnel timeout. Starts it if no timeout was running.
2322  *
2323  * @param t Tunnel whose timeout to reset.
2324  */
2325 static void
2326 tunnel_reset_timeout (struct MeshTunnel *t)
2327 {
2328   if (GNUNET_SCHEDULER_NO_TASK != t->timeout_task)
2329     GNUNET_SCHEDULER_cancel (t->timeout_task);
2330   t->timeout_task =
2331       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
2332                                     (REFRESH_PATH_TIME, 4), &tunnel_timeout, t);
2333 }
2334
2335
2336 /******************************************************************************/
2337 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
2338 /******************************************************************************/
2339
2340 /**
2341  * Function called to notify a client about the socket
2342  * being ready to queue more data.  "buf" will be
2343  * NULL and "size" zero if the socket was closed for
2344  * writing in the meantime.
2345  *
2346  * @param cls closure
2347  * @param size number of bytes available in buf
2348  * @param buf where the callee should write the message
2349  * @return number of bytes written to buf
2350  */
2351 static size_t
2352 send_core_create_path (void *cls, size_t size, void *buf)
2353 {
2354   struct MeshPathInfo *info = cls;
2355   struct GNUNET_MESH_ManipulatePath *msg;
2356   struct GNUNET_PeerIdentity *peer_ptr;
2357   struct MeshPeerInfo *peer = info->peer;
2358   struct MeshTunnel *t = info->t;
2359   struct MeshPeerPath *p = info->path;
2360   size_t size_needed;
2361   int i;
2362
2363   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATE PATH sending...\n");
2364   size_needed =
2365       sizeof (struct GNUNET_MESH_ManipulatePath) +
2366       p->length * sizeof (struct GNUNET_PeerIdentity);
2367
2368   if (size < size_needed || NULL == buf)
2369   {
2370     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: create path retransmit!\n");
2371     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   buf:  %p\n", buf);
2372     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   size: (%u/%u)\n", size,
2373                 size_needed);
2374     info->peer->core_transmit[info->pos] =
2375         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2376                                            GNUNET_TIME_UNIT_FOREVER_REL,
2377                                            tree_get_first_hop (t->tree,
2378                                                                peer->id),
2379                                            size_needed, &send_core_create_path,
2380                                            info);
2381     return 0;
2382   }
2383   info->peer->core_transmit[info->pos] = NULL;
2384 #if MESH_DEBUG
2385   {
2386     struct GNUNET_PeerIdentity id;
2387
2388     GNUNET_PEER_resolve (peer->id, &id);
2389     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2390                 "MESH:   setting core_transmit %s [%u] to NULL\n",
2391                 GNUNET_i2s (&id), info->pos);
2392   }
2393 #endif
2394   msg = (struct GNUNET_MESH_ManipulatePath *) buf;
2395   msg->header.size = htons (size_needed);
2396   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
2397   msg->tid = ntohl (t->id.tid);
2398
2399   peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
2400   for (i = 0; i < p->length; i++)
2401   {
2402     GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
2403   }
2404
2405   path_destroy (p);
2406   GNUNET_free (info);
2407
2408   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2409               "MESH: CREATE PATH (%u bytes long) sent!\n", size_needed);
2410   return size_needed;
2411 }
2412
2413
2414 /**
2415  * Function called to notify a client about the socket
2416  * being ready to queue more data.  "buf" will be
2417  * NULL and "size" zero if the socket was closed for
2418  * writing in the meantime.
2419  *
2420  * @param cls closure (data itself)
2421  * @param size number of bytes available in buf
2422  * @param buf where the callee should write the message
2423  *
2424  * @return number of bytes written to buf
2425  */
2426 static size_t
2427 send_core_data_multicast (void *cls, size_t size, void *buf)
2428 {
2429   struct MeshTransmissionDescriptor *info = cls;
2430   size_t total_size;
2431
2432   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Multicast callback.\n");
2433   GNUNET_assert (NULL != info);
2434   GNUNET_assert (NULL != info->peer);
2435   total_size = info->mesh_data->data_len;
2436   GNUNET_assert (total_size < GNUNET_SERVER_MAX_MESSAGE_SIZE);
2437
2438   if (total_size > size)
2439   {
2440     /* Retry */
2441     struct GNUNET_PeerIdentity id;
2442
2443     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2444                 "MESH: Multicast: retransmitting... (%u/%u)\n", size,
2445                 total_size);
2446     GNUNET_PEER_resolve (info->peer->id, &id);
2447     info->peer->core_transmit[info->handler_n] =
2448         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 0,
2449                                            GNUNET_TIME_UNIT_FOREVER_REL, &id,
2450                                            total_size,
2451                                            &send_core_data_multicast, info);
2452     return 0;
2453   }
2454   info->peer->core_transmit[info->handler_n] = NULL;
2455   info->peer->infos[info->handler_n] = NULL;
2456   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  copying data...\n");
2457   memcpy (buf, info->mesh_data->data, total_size);
2458 #if MESH_DEBUG
2459   {
2460     struct GNUNET_MESH_Multicast *mc;
2461     struct GNUNET_MessageHeader *mh;
2462
2463     mh = buf;
2464     if (ntohs (mh->type) == GNUNET_MESSAGE_TYPE_MESH_MULTICAST)
2465     {
2466       mc = (struct GNUNET_MESH_Multicast *) mh;
2467       mh = (struct GNUNET_MessageHeader *) &mc[1];
2468       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2469                   "MESH:  multicast, payload type %u\n", ntohs (mh->type));
2470       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2471                   "MESH:  multicast, payload size %u\n", ntohs (mh->size));
2472     }
2473     else
2474     {
2475       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  type %u\n",
2476                   ntohs (mh->type));
2477     }
2478   }
2479 #endif
2480   data_descriptor_decrement_multicast (info->mesh_data);
2481   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: freeing info...\n");
2482   GNUNET_free (info);
2483   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: return %u\n", total_size);
2484   return total_size;
2485 }
2486
2487
2488 /**
2489  * Function called to notify a client about the socket
2490  * being ready to queue more data.  "buf" will be
2491  * NULL and "size" zero if the socket was closed for
2492  * writing in the meantime.
2493  *
2494  * @param cls closure (MeshTransmissionDescriptor)
2495  * @param size number of bytes available in buf
2496  * @param buf where the callee should write the message
2497  * @return number of bytes written to buf
2498  */
2499 static size_t
2500 send_core_path_ack (void *cls, size_t size, void *buf)
2501 {
2502   struct MeshTransmissionDescriptor *info = cls;
2503   struct GNUNET_MESH_PathACK *msg = buf;
2504
2505   GNUNET_assert (NULL != info);
2506   if (info->peer)
2507   {
2508     info->peer->core_transmit[info->handler_n] = NULL;
2509   }
2510   if (sizeof (struct GNUNET_MESH_PathACK) > size)
2511   {
2512     GNUNET_break (0);
2513     return 0;
2514   }
2515   msg->header.size = htons (sizeof (struct GNUNET_MESH_PathACK));
2516   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_ACK);
2517   GNUNET_PEER_resolve (info->origin->oid, &msg->oid);
2518   msg->tid = htonl (info->origin->tid);
2519   msg->peer_id = my_full_id;
2520   GNUNET_free (info);
2521   /* TODO add signature */
2522
2523   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: PATH ACK sent!\n");
2524   return sizeof (struct GNUNET_MESH_PathACK);
2525 }
2526
2527
2528 /******************************************************************************/
2529 /********************      MESH NETWORK HANDLERS     **************************/
2530 /******************************************************************************/
2531
2532
2533 /**
2534  * Core handler for path creation
2535  *
2536  * @param cls closure
2537  * @param message message
2538  * @param peer peer identity this notification is about
2539  * @param atsi performance data
2540  * @param atsi_count number of records in 'atsi'
2541  *
2542  * @return GNUNET_OK to keep the connection open,
2543  *         GNUNET_SYSERR to close it (signal serious error)
2544  */
2545 static int
2546 handle_mesh_path_create (void *cls, const struct GNUNET_PeerIdentity *peer,
2547                          const struct GNUNET_MessageHeader *message,
2548                          const struct GNUNET_ATS_Information *atsi,
2549                          unsigned int atsi_count)
2550 {
2551   unsigned int own_pos;
2552   uint16_t size;
2553   uint16_t i;
2554   MESH_TunnelNumber tid;
2555   struct GNUNET_MESH_ManipulatePath *msg;
2556   struct GNUNET_PeerIdentity *pi;
2557   GNUNET_HashCode hash;
2558   struct MeshPeerPath *path;
2559   struct MeshPeerInfo *dest_peer_info;
2560   struct MeshPeerInfo *orig_peer_info;
2561   struct MeshTunnel *t;
2562
2563   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2564               "MESH: Received a path create msg [%s]\n",
2565               GNUNET_i2s (&my_full_id));
2566   size = ntohs (message->size);
2567   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
2568   {
2569     GNUNET_break_op (0);
2570     return GNUNET_OK;
2571   }
2572
2573   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
2574   if (size % sizeof (struct GNUNET_PeerIdentity))
2575   {
2576     GNUNET_break_op (0);
2577     return GNUNET_OK;
2578   }
2579   size /= sizeof (struct GNUNET_PeerIdentity);
2580   if (size < 2)
2581   {
2582     GNUNET_break_op (0);
2583     return GNUNET_OK;
2584   }
2585   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:     path has %u hops.\n", size);
2586   msg = (struct GNUNET_MESH_ManipulatePath *) message;
2587
2588   tid = ntohl (msg->tid);
2589   pi = (struct GNUNET_PeerIdentity *) &msg[1];
2590   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2591               "MESH:     path is for tunnel %s [%X].\n", GNUNET_i2s (pi), tid);
2592   t = tunnel_get (pi, tid);
2593   if (NULL == t)
2594   {
2595     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   Creating tunnel\n");
2596     t = GNUNET_malloc (sizeof (struct MeshTunnel));
2597     t->id.oid = GNUNET_PEER_intern (pi);
2598     t->id.tid = tid;
2599     while (NULL != tunnel_get_incoming (next_local_tid))
2600       next_local_tid = (next_local_tid + 1) | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
2601     t->local_tid = next_local_tid++;
2602     next_local_tid = next_local_tid | GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
2603     t->tree = tree_new (t->id.oid);
2604
2605     GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
2606     if (GNUNET_OK !=
2607         GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
2608                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2609     {
2610       tunnel_destroy (t);
2611       GNUNET_break (0);
2612       return GNUNET_OK;
2613     }
2614     tunnel_reset_timeout (t);
2615     GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
2616     if (GNUNET_OK !=
2617         GNUNET_CONTAINER_multihashmap_put (incoming_tunnels, &hash, t,
2618                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2619     {
2620       tunnel_destroy (t);
2621       GNUNET_break (0);
2622       return GNUNET_OK;
2623     }
2624   }
2625   dest_peer_info =
2626       GNUNET_CONTAINER_multihashmap_get (peers, &pi[size - 1].hashPubKey);
2627   if (NULL == dest_peer_info)
2628   {
2629     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2630                 "MESH:   Creating PeerInfo for destination.\n");
2631     dest_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
2632     dest_peer_info->id = GNUNET_PEER_intern (&pi[size - 1]);
2633     GNUNET_CONTAINER_multihashmap_put (peers, &pi[size - 1].hashPubKey,
2634                                        dest_peer_info,
2635                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2636   }
2637   orig_peer_info = GNUNET_CONTAINER_multihashmap_get (peers, &pi->hashPubKey);
2638   if (NULL == orig_peer_info)
2639   {
2640     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2641                 "MESH:   Creating PeerInfo for origin.\n");
2642     orig_peer_info = GNUNET_malloc (sizeof (struct MeshPeerInfo));
2643     orig_peer_info->id = GNUNET_PEER_intern (pi);
2644     GNUNET_CONTAINER_multihashmap_put (peers, &pi->hashPubKey, orig_peer_info,
2645                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
2646   }
2647   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   Creating path...\n");
2648   path = path_new (size);
2649   own_pos = 0;
2650   for (i = 0; i < size; i++)
2651   {
2652     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   ... adding %s\n",
2653                 GNUNET_i2s (&pi[i]));
2654     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
2655     if (path->peers[i] == myid)
2656       own_pos = i;
2657   }
2658   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   Own position: %u\n", own_pos);
2659   if (own_pos == 0)
2660   {
2661     /* cannot be self, must be 'not found' */
2662     /* create path: self not found in path through self */
2663     GNUNET_break_op (0);
2664     path_destroy (path);
2665     /* FIXME error. destroy tunnel? leave for timeout? */
2666     return 0;
2667   }
2668   path_add_to_peers (path, GNUNET_NO);
2669   tunnel_add_path (t, path, own_pos);
2670   if (own_pos == size - 1)
2671   {
2672     /* It is for us! Send ack. */
2673     struct MeshTransmissionDescriptor *info;
2674     unsigned int j;
2675
2676     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   It's for us!\n");
2677     peer_info_add_path_to_origin (orig_peer_info, path, GNUNET_NO);
2678     if (NULL == t->peers)
2679     {
2680       /* New tunnel! Notify clients! */
2681       struct GNUNET_MESH_TunnelNotification cmsg;
2682
2683       cmsg.header.size = htons (sizeof (cmsg));
2684       cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
2685       GNUNET_PEER_resolve (t->id.oid, &cmsg.peer);
2686       cmsg.tunnel_id = htonl (t->local_tid);
2687       GNUNET_SERVER_notification_context_broadcast (nc, &cmsg.header,
2688                                                     GNUNET_NO);
2689
2690       t->peers = GNUNET_CONTAINER_multihashmap_create (4);
2691     }
2692     GNUNET_break (GNUNET_OK ==
2693                   GNUNET_CONTAINER_multihashmap_put (t->peers,
2694                                                      &my_full_id.hashPubKey,
2695                                                      peer_info_get
2696                                                      (&my_full_id),
2697                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE));
2698     /* FIXME use send_message */
2699     info = GNUNET_malloc (sizeof (struct MeshTransmissionDescriptor));
2700     info->origin = &t->id;
2701     info->peer = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
2702     GNUNET_assert (NULL != info->peer);
2703     j = peer_info_transmit_slot (info->peer);
2704     info->handler_n = j;
2705     info->peer->types[j] = GNUNET_MESSAGE_TYPE_MESH_PATH_ACK;
2706     info->peer->infos[j] = info;
2707     info->peer->core_transmit[j] =
2708         GNUNET_CORE_notify_transmit_ready (core_handle, 0, 100,
2709                                            GNUNET_TIME_UNIT_FOREVER_REL, peer,
2710                                            sizeof (struct GNUNET_MESH_PathACK),
2711                                            &send_core_path_ack, info);
2712   }
2713   else
2714   {
2715     struct MeshPeerPath *path2;
2716
2717     /* It's for somebody else! Retransmit. */
2718     path2 = path_duplicate (path);
2719     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   Retransmitting.\n");
2720     peer_info_add_path (dest_peer_info, path2, GNUNET_NO);
2721     path2 = path_duplicate (path);
2722     peer_info_add_path_to_origin (orig_peer_info, path2, GNUNET_NO);
2723     send_create_path (dest_peer_info, path, t);
2724   }
2725   return GNUNET_OK;
2726 }
2727
2728
2729 /**
2730  * Core handler for path destruction
2731  *
2732  * @param cls closure
2733  * @param message message
2734  * @param peer peer identity this notification is about
2735  * @param atsi performance data
2736  * @param atsi_count number of records in 'atsi'
2737  *
2738  * @return GNUNET_OK to keep the connection open,
2739  *         GNUNET_SYSERR to close it (signal serious error)
2740  */
2741 static int
2742 handle_mesh_path_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
2743                           const struct GNUNET_MessageHeader *message,
2744                           const struct GNUNET_ATS_Information *atsi,
2745                           unsigned int atsi_count)
2746 {
2747   struct GNUNET_MESH_ManipulatePath *msg;
2748   struct GNUNET_PeerIdentity *pi;
2749   struct MeshPeerPath *path;
2750   struct MeshTunnel *t;
2751   unsigned int own_pos;
2752   unsigned int i;
2753   size_t size;
2754
2755   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2756               "MESH: Received a PATH DESTROY msg from %s\n", GNUNET_i2s (peer));
2757   size = ntohs (message->size);
2758   if (size < sizeof (struct GNUNET_MESH_ManipulatePath))
2759   {
2760     GNUNET_break_op (0);
2761     return GNUNET_OK;
2762   }
2763
2764   size -= sizeof (struct GNUNET_MESH_ManipulatePath);
2765   if (size % sizeof (struct GNUNET_PeerIdentity))
2766   {
2767     GNUNET_break_op (0);
2768     return GNUNET_OK;
2769   }
2770   size /= sizeof (struct GNUNET_PeerIdentity);
2771   if (size < 2)
2772   {
2773     GNUNET_break_op (0);
2774     return GNUNET_OK;
2775   }
2776   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:     path has %u hops.\n", size);
2777
2778   msg = (struct GNUNET_MESH_ManipulatePath *) message;
2779   pi = (struct GNUNET_PeerIdentity *) &msg[1];
2780   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2781               "MESH:     path is for tunnel %s [%X].\n", GNUNET_i2s (pi),
2782               msg->tid);
2783   t = tunnel_get (pi, ntohl (msg->tid));
2784   if (NULL == t)
2785   {
2786     /* TODO notify back: we don't know this tunnel */
2787     GNUNET_break_op (0);
2788     return GNUNET_OK;
2789   }
2790   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   Creating path...\n");
2791   path = path_new (size);
2792   own_pos = 0;
2793   for (i = 0; i < size; i++)
2794   {
2795     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   ... adding %s\n",
2796                 GNUNET_i2s (&pi[i]));
2797     path->peers[i] = GNUNET_PEER_intern (&pi[i]);
2798     if (path->peers[i] == myid)
2799       own_pos = i;
2800   }
2801   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   Own position: %u\n", own_pos);
2802   if (own_pos < path->length - 1)
2803     send_message (message, &pi[own_pos + 1]);
2804   tunnel_delete_peer (t, path->peers[path->length - 1]);
2805   path_destroy (path);
2806   return GNUNET_OK;
2807 }
2808
2809
2810 /**
2811  * Core handler for notifications of broken paths
2812  *
2813  * @param cls closure
2814  * @param message message
2815  * @param peer peer identity this notification is about
2816  * @param atsi performance data
2817  * @param atsi_count number of records in 'atsi'
2818  *
2819  * @return GNUNET_OK to keep the connection open,
2820  *         GNUNET_SYSERR to close it (signal serious error)
2821  */
2822 static int
2823 handle_mesh_path_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
2824                          const struct GNUNET_MessageHeader *message,
2825                          const struct GNUNET_ATS_Information *atsi,
2826                          unsigned int atsi_count)
2827 {
2828   struct GNUNET_MESH_PathBroken *msg;
2829   struct MeshTunnel *t;
2830
2831   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2832               "MESH: Received a PATH BROKEN msg from %s\n", GNUNET_i2s (peer));
2833   msg = (struct GNUNET_MESH_PathBroken *) message;
2834   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   regarding %s\n",
2835               GNUNET_i2s (&msg->peer1));
2836   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   regarding %s\n",
2837               GNUNET_i2s (&msg->peer2));
2838   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2839   if (NULL == t)
2840   {
2841     GNUNET_break_op (0);
2842     return GNUNET_OK;
2843   }
2844   tunnel_notify_connection_broken (t, GNUNET_PEER_search (&msg->peer1),
2845                                    GNUNET_PEER_search (&msg->peer2));
2846   return GNUNET_OK;
2847
2848 }
2849
2850
2851 /**
2852  * Core handler for tunnel destruction
2853  *
2854  * @param cls closure
2855  * @param message message
2856  * @param peer peer identity this notification is about
2857  * @param atsi performance data
2858  * @param atsi_count number of records in 'atsi'
2859  *
2860  * @return GNUNET_OK to keep the connection open,
2861  *         GNUNET_SYSERR to close it (signal serious error)
2862  */
2863 static int
2864 handle_mesh_tunnel_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
2865                             const struct GNUNET_MessageHeader *message,
2866                             const struct GNUNET_ATS_Information *atsi,
2867                             unsigned int atsi_count)
2868 {
2869   struct GNUNET_MESH_TunnelDestroy *msg;
2870   struct MeshTunnel *t;
2871
2872   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2873               "MESH: Got a TUNNEL DESTROY packet from %s\n", GNUNET_i2s (peer));
2874   msg = (struct GNUNET_MESH_TunnelDestroy *) message;
2875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   for tunnel %s [%u]\n",
2876               GNUNET_i2s (&msg->oid), ntohl (msg->tid));
2877   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2878   if (NULL == t)
2879   {
2880     /* Probably already got the message from another path,
2881      * destroyed the tunnel and retransmitted to children.
2882      * Safe to ignore.
2883      */
2884     return GNUNET_OK;
2885   }
2886   if (t->id.oid == myid)
2887   {
2888     GNUNET_break_op (0);
2889     return GNUNET_OK;
2890   }
2891   if (t->local_tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2892   {
2893     /* Tunnel was incoming, notify clients */
2894     send_clients_tunnel_destroy (t);
2895   }
2896   tunnel_send_destroy (t);
2897   tunnel_destroy (t);
2898   return GNUNET_OK;
2899 }
2900
2901
2902 /**
2903  * Core handler for mesh network traffic going from the origin to a peer
2904  *
2905  * @param cls closure
2906  * @param peer peer identity this notification is about
2907  * @param message message
2908  * @param atsi performance data
2909  * @param atsi_count number of records in 'atsi'
2910  * @return GNUNET_OK to keep the connection open,
2911  *         GNUNET_SYSERR to close it (signal serious error)
2912  */
2913 static int
2914 handle_mesh_data_unicast (void *cls, const struct GNUNET_PeerIdentity *peer,
2915                           const struct GNUNET_MessageHeader *message,
2916                           const struct GNUNET_ATS_Information *atsi,
2917                           unsigned int atsi_count)
2918 {
2919   struct GNUNET_MESH_Unicast *msg;
2920   struct MeshTunnel *t;
2921   GNUNET_PEER_Id pid;
2922   size_t size;
2923
2924   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got a unicast packet from %s\n",
2925               GNUNET_i2s (peer));
2926   size = ntohs (message->size);
2927   if (size <
2928       sizeof (struct GNUNET_MESH_Unicast) +
2929       sizeof (struct GNUNET_MessageHeader))
2930   {
2931     GNUNET_break (0);
2932     return GNUNET_OK;
2933   }
2934   msg = (struct GNUNET_MESH_Unicast *) message;
2935   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  of type %u\n",
2936               ntohs (msg[1].header.type));
2937   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2938   if (NULL == t)
2939   {
2940     /* TODO notify back: we don't know this tunnel */
2941     GNUNET_break_op (0);
2942     return GNUNET_OK;
2943   }
2944   tunnel_reset_timeout (t);
2945   pid = GNUNET_PEER_search (&msg->destination);
2946   if (pid == myid)
2947   {
2948     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2949                 "MESH:   it's for us! sending to clients...\n");
2950     send_subscribed_clients (message, (struct GNUNET_MessageHeader *) &msg[1]);
2951     return GNUNET_OK;
2952   }
2953   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2954               "MESH:   not for us, retransmitting...\n");
2955   send_message (message, tree_get_first_hop (t->tree, pid));
2956   return GNUNET_OK;
2957 }
2958
2959
2960 /**
2961  * Core handler for mesh network traffic going from the origin to all peers
2962  *
2963  * @param cls closure
2964  * @param message message
2965  * @param peer peer identity this notification is about
2966  * @param atsi performance data
2967  * @param atsi_count number of records in 'atsi'
2968  * @return GNUNET_OK to keep the connection open,
2969  *         GNUNET_SYSERR to close it (signal serious error)
2970  *
2971  * TODO: Check who we got this from, to validate route.
2972  */
2973 static int
2974 handle_mesh_data_multicast (void *cls, const struct GNUNET_PeerIdentity *peer,
2975                             const struct GNUNET_MessageHeader *message,
2976                             const struct GNUNET_ATS_Information *atsi,
2977                             unsigned int atsi_count)
2978 {
2979   struct GNUNET_MESH_Multicast *msg;
2980   struct MeshTunnel *t;
2981   size_t size;
2982
2983   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got a multicast packet from %s\n",
2984               GNUNET_i2s (peer));
2985   size = ntohs (message->size);
2986   if (sizeof (struct GNUNET_MESH_Multicast) +
2987       sizeof (struct GNUNET_MessageHeader) > size)
2988   {
2989     GNUNET_break_op (0);
2990     return GNUNET_OK;
2991   }
2992   msg = (struct GNUNET_MESH_Multicast *) message;
2993   t = tunnel_get (&msg->oid, ntohl (msg->tid));
2994
2995   if (NULL == t)
2996   {
2997     /* TODO notify that we dont know that tunnel */
2998     GNUNET_break_op (0);
2999     return GNUNET_OK;
3000   }
3001   if (t->mid == ntohl (msg->mid))
3002   {
3003     /* FIXME: already seen this packet, log dropping */
3004     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3005                 "MESH:  Already seen mid %u, DROPPING!\n", t->mid);
3006     return GNUNET_OK;
3007   }
3008 #if MESH_DEBUG
3009   else
3010   {
3011     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3012                 "MESH:  mid %u not seen yet, forwarding\n", ntohl (msg->mid));
3013   }
3014 #endif
3015   t->mid = ntohl (msg->mid);
3016   tunnel_reset_timeout (t);
3017
3018   /* Transmit to locally interested clients */
3019   if (NULL != t->peers &&
3020       GNUNET_CONTAINER_multihashmap_contains (t->peers, &my_full_id.hashPubKey))
3021   {
3022     send_subscribed_clients (message, &msg[1].header);
3023   }
3024 #if MESH_DEBUG
3025   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    ttl: %u\n", ntohl (msg->ttl));
3026 #endif
3027   if (ntohl (msg->ttl) == 0)
3028   {
3029     /* FIXME: ttl is 0, log dropping */
3030     GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "MESH:  TTL is 0, DROPPING!\n");
3031     return GNUNET_OK;
3032   }
3033   tunnel_send_multicast (t, message);
3034   return GNUNET_OK;
3035 }
3036
3037
3038 /**
3039  * Core handler for mesh network traffic toward the owner of a tunnel
3040  *
3041  * @param cls closure
3042  * @param message message
3043  * @param peer peer identity this notification is about
3044  * @param atsi performance data
3045  * @param atsi_count number of records in 'atsi'
3046  *
3047  * @return GNUNET_OK to keep the connection open,
3048  *         GNUNET_SYSERR to close it (signal serious error)
3049  */
3050 static int
3051 handle_mesh_data_to_orig (void *cls, const struct GNUNET_PeerIdentity *peer,
3052                           const struct GNUNET_MessageHeader *message,
3053                           const struct GNUNET_ATS_Information *atsi,
3054                           unsigned int atsi_count)
3055 {
3056   struct GNUNET_MESH_ToOrigin *msg;
3057   struct GNUNET_PeerIdentity id;
3058   struct MeshPeerInfo *peer_info;
3059   struct MeshTunnel *t;
3060   size_t size;
3061
3062   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got a ToOrigin packet from %s\n",
3063               GNUNET_i2s (peer));
3064   size = ntohs (message->size);
3065   if (size < sizeof (struct GNUNET_MESH_ToOrigin) +     /* Payload must be */
3066       sizeof (struct GNUNET_MessageHeader))     /* at least a header */
3067   {
3068     GNUNET_break_op (0);
3069     return GNUNET_OK;
3070   }
3071   msg = (struct GNUNET_MESH_ToOrigin *) message;
3072   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  of type %u\n",
3073               ntohs (msg[1].header.type));
3074   t = tunnel_get (&msg->oid, ntohl (msg->tid));
3075
3076   if (NULL == t)
3077   {
3078     /* TODO notify that we dont know this tunnel (whom)? */
3079     GNUNET_break_op (0);
3080     return GNUNET_OK;
3081   }
3082
3083   if (t->id.oid == myid)
3084   {
3085     char cbuf[size];
3086     struct GNUNET_MESH_ToOrigin *copy;
3087
3088     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3089                 "MESH:   it's for us! sending to clients...\n");
3090     if (NULL == t->client)
3091     {
3092       /* got data packet for ownerless tunnel */
3093       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   no clients!\n");
3094       GNUNET_break_op (0);
3095       return GNUNET_OK;
3096     }
3097     /* TODO signature verification */
3098     memcpy (cbuf, message, size);
3099     copy = (struct GNUNET_MESH_ToOrigin *) cbuf;
3100     copy->tid = htonl (t->local_tid);
3101     GNUNET_SERVER_notification_context_unicast (nc, t->client->handle,
3102                                                 &copy->header, GNUNET_YES);
3103     return GNUNET_OK;
3104   }
3105   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3106               "MESH:   not for us, retransmitting...\n");
3107
3108   peer_info = peer_info_get (&msg->oid);
3109   if (NULL == peer_info)
3110   {
3111     /* unknown origin of tunnel */
3112     GNUNET_break (0);
3113     return GNUNET_OK;
3114   }
3115   GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
3116   send_message (message, &id);
3117
3118   return GNUNET_OK;
3119 }
3120
3121
3122 /**
3123  * Core handler for path ACKs
3124  *
3125  * @param cls closure
3126  * @param message message
3127  * @param peer peer identity this notification is about
3128  * @param atsi performance data
3129  * @param atsi_count number of records in 'atsi'
3130  *
3131  * @return GNUNET_OK to keep the connection open,
3132  *         GNUNET_SYSERR to close it (signal serious error)
3133  */
3134 static int
3135 handle_mesh_path_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3136                       const struct GNUNET_MessageHeader *message,
3137                       const struct GNUNET_ATS_Information *atsi,
3138                       unsigned int atsi_count)
3139 {
3140   struct GNUNET_MESH_PathACK *msg;
3141   struct GNUNET_PeerIdentity id;
3142   struct MeshPeerInfo *peer_info;
3143   struct MeshPeerPath *p;
3144   struct MeshTunnel *t;
3145
3146   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Received a path ACK msg [%s]\n",
3147               GNUNET_i2s (&my_full_id));
3148   msg = (struct GNUNET_MESH_PathACK *) message;
3149   t = tunnel_get (&msg->oid, msg->tid);
3150   if (NULL == t)
3151   {
3152     /* TODO notify that we don't know the tunnel */
3153     return GNUNET_OK;
3154   }
3155
3156   peer_info = peer_info_get (&msg->peer_id);
3157
3158   /* Add paths to peers? */
3159   p = tree_get_path_to_peer (t->tree, peer_info->id);
3160   if (NULL != p)
3161   {
3162     path_add_to_peers (p, GNUNET_YES);
3163     path_destroy (p);
3164   }
3165   else
3166   {
3167     GNUNET_break (0);
3168   }
3169
3170   /* Message for us? */
3171   if (0 == memcmp (&msg->oid, &my_full_id, sizeof (struct GNUNET_PeerIdentity)))
3172   {
3173     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   It's for us!\n");
3174     if (NULL == t->client)
3175     {
3176       GNUNET_break_op (0);
3177       return GNUNET_OK;
3178     }
3179     if (NULL != t->dht_get_type)
3180     {
3181       GNUNET_DHT_get_stop (t->dht_get_type);
3182       t->dht_get_type = NULL;
3183     }
3184     if (tree_get_status (t->tree, peer_info->id) != MESH_PEER_READY)
3185     {
3186       tree_set_status (t->tree, peer_info->id, MESH_PEER_READY);
3187       send_client_peer_connected (t, peer_info->id);
3188     }
3189     return GNUNET_OK;
3190   }
3191
3192   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3193               "MESH:   not for us, retransmitting...\n");
3194   GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &id);
3195   peer_info = peer_info_get (&msg->oid);
3196   if (NULL == peer_info)
3197   {
3198     /* If we know the tunnel, we should DEFINITELY know the peer */
3199     GNUNET_break (0);
3200     return GNUNET_OK;
3201   }
3202   send_message (message, &id);
3203   return GNUNET_OK;
3204 }
3205
3206
3207 /**
3208  * Functions to handle messages from core
3209  */
3210 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3211   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
3212   {&handle_mesh_path_destroy, GNUNET_MESSAGE_TYPE_MESH_PATH_DESTROY, 0},
3213   {&handle_mesh_path_broken, GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN,
3214    sizeof (struct GNUNET_MESH_PathBroken)},
3215   {&handle_mesh_tunnel_destroy, GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY, 0},
3216   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
3217   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
3218   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
3219   {&handle_mesh_path_ack, GNUNET_MESSAGE_TYPE_MESH_PATH_ACK,
3220    sizeof (struct GNUNET_MESH_PathACK)},
3221   {NULL, 0, 0}
3222 };
3223
3224
3225
3226 /******************************************************************************/
3227 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
3228 /******************************************************************************/
3229
3230 /**
3231  * deregister_app: iterator for removing each application registered by a client
3232  *
3233  * @param cls closure
3234  * @param key the hash of the application id (used to access the hashmap)
3235  * @param value the value stored at the key (client)
3236  *
3237  * @return GNUNET_OK on success
3238  */
3239 static int
3240 deregister_app (void *cls, const GNUNET_HashCode * key, void *value)
3241 {
3242   GNUNET_break (GNUNET_YES ==
3243                 GNUNET_CONTAINER_multihashmap_remove (applications, key,
3244                                                       value));
3245   return GNUNET_OK;
3246 }
3247
3248 #if LATER
3249 /**
3250  * notify_client_connection_failure: notify a client that the connection to the
3251  * requested remote peer is not possible (for instance, no route found)
3252  * Function called when the socket is ready to queue more data. "buf" will be
3253  * NULL and "size" zero if the socket was closed for writing in the meantime.
3254  *
3255  * @param cls closure
3256  * @param size number of bytes available in buf
3257  * @param buf where the callee should write the message
3258  * @return number of bytes written to buf
3259  */
3260 static size_t
3261 notify_client_connection_failure (void *cls, size_t size, void *buf)
3262 {
3263   int size_needed;
3264   struct MeshPeerInfo *peer_info;
3265   struct GNUNET_MESH_PeerControl *msg;
3266   struct GNUNET_PeerIdentity id;
3267
3268   if (0 == size && NULL == buf)
3269   {
3270     // TODO retry? cancel?
3271     return 0;
3272   }
3273
3274   size_needed = sizeof (struct GNUNET_MESH_PeerControl);
3275   peer_info = (struct MeshPeerInfo *) cls;
3276   msg = (struct GNUNET_MESH_PeerControl *) buf;
3277   msg->header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
3278   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
3279 //     msg->tunnel_id = htonl(peer_info->t->tid);
3280   GNUNET_PEER_resolve (peer_info->id, &id);
3281   memcpy (&msg->peer, &id, sizeof (struct GNUNET_PeerIdentity));
3282
3283   return size_needed;
3284 }
3285 #endif
3286
3287
3288 /**
3289  * Send keepalive packets for a peer
3290  *
3291  * @param cls Closure (tunnel for which to send the keepalive).
3292  * @param tc Notification context.
3293  *
3294  * TODO: implement explicit multicast keepalive?
3295  */
3296 static void
3297 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3298 {
3299   struct MeshTunnel *t = cls;
3300   struct GNUNET_MessageHeader *payload;
3301   struct GNUNET_MESH_Multicast *msg;
3302   size_t size =
3303       sizeof (struct GNUNET_MESH_Multicast) +
3304       sizeof (struct GNUNET_MessageHeader);
3305   char cbuf[size];
3306
3307   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
3308   {
3309     return;
3310   }
3311   t->path_refresh_task = GNUNET_SCHEDULER_NO_TASK;
3312
3313   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3314               "MESH: sending keepalive for tunnel %d\n", t->id.tid);
3315
3316   msg = (struct GNUNET_MESH_Multicast *) cbuf;
3317   msg->header.size = htons (size);
3318   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
3319   msg->oid = my_full_id;
3320   msg->tid = htonl (t->id.tid);
3321   payload = (struct GNUNET_MessageHeader *) &msg[1];
3322   payload->size = htons (sizeof (struct GNUNET_MessageHeader));
3323   payload->type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_KEEPALIVE);
3324   tunnel_send_multicast (t, &msg->header);
3325
3326   t->path_refresh_task =
3327       GNUNET_SCHEDULER_add_delayed (REFRESH_PATH_TIME, &path_refresh, t);
3328   return;
3329 }
3330
3331
3332 /**
3333  * Function to process paths received for a new peer addition. The recorded
3334  * paths form the initial tunnel, which can be optimized later.
3335  * Called on each result obtained for the DHT search.
3336  *
3337  * @param cls closure
3338  * @param exp when will this value expire
3339  * @param key key of the result
3340  * @param get_path path of the get request
3341  * @param get_path_length lenght of get_path
3342  * @param put_path path of the put request
3343  * @param put_path_length length of the put_path
3344  * @param type type of the result
3345  * @param size number of bytes in data
3346  * @param data pointer to the result data
3347  *
3348  * TODO: re-issue the request after certain time? cancel after X results?
3349  */
3350 static void
3351 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
3352                     const GNUNET_HashCode * key,
3353                     const struct GNUNET_PeerIdentity *get_path,
3354                     unsigned int get_path_length,
3355                     const struct GNUNET_PeerIdentity *put_path,
3356                     unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
3357                     size_t size, const void *data)
3358 {
3359   struct MeshPathInfo *path_info = cls;
3360   struct MeshPeerPath *p;
3361   struct GNUNET_PeerIdentity pi;
3362   int i;
3363
3364   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Got results from DHT!\n");
3365   GNUNET_PEER_resolve (path_info->peer->id, &pi);
3366   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   for %s\n", GNUNET_i2s (&pi));
3367
3368   p = path_build_from_dht (get_path, get_path_length, put_path,
3369                            put_path_length);
3370   path_add_to_peers (p, GNUNET_NO);
3371   path_destroy(p);
3372   for (i = 0; i < path_info->peer->ntunnels; i++)
3373   {
3374     tunnel_add_peer (path_info->peer->tunnels[i], path_info->peer);
3375     peer_info_connect (path_info->peer, path_info->t);
3376   }
3377
3378   return;
3379 }
3380
3381
3382 /**
3383  * Function to process paths received for a new peer addition. The recorded
3384  * paths form the initial tunnel, which can be optimized later.
3385  * Called on each result obtained for the DHT search.
3386  *
3387  * @param cls closure
3388  * @param exp when will this value expire
3389  * @param key key of the result
3390  * @param get_path path of the get request
3391  * @param get_path_length lenght of get_path
3392  * @param put_path path of the put request
3393  * @param put_path_length length of the put_path
3394  * @param type type of the result
3395  * @param size number of bytes in data
3396  * @param data pointer to the result data
3397  */
3398 static void
3399 dht_get_type_handler (void *cls, struct GNUNET_TIME_Absolute exp,
3400                       const GNUNET_HashCode * key,
3401                       const struct GNUNET_PeerIdentity *get_path,
3402                       unsigned int get_path_length,
3403                       const struct GNUNET_PeerIdentity *put_path,
3404                       unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
3405                       size_t size, const void *data)
3406 {
3407   const struct GNUNET_PeerIdentity *pi = data;
3408   struct MeshTunnel *t = cls;
3409   struct MeshPeerInfo *peer_info;
3410   struct MeshPeerPath *p;
3411
3412   if (size != sizeof (struct GNUNET_PeerIdentity))
3413   {
3414     GNUNET_break_op (0);
3415     return;
3416   }
3417   GNUNET_assert (NULL != t->client);
3418   peer_info = peer_info_get (pi);
3419   (void) GNUNET_CONTAINER_multihashmap_put (t->peers, &pi->hashPubKey,
3420                                             peer_info,
3421                                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
3422
3423   p = path_build_from_dht (get_path, get_path_length, put_path,
3424                            put_path_length);
3425   path_add_to_peers (p, GNUNET_NO);
3426   path_destroy(p);
3427   tunnel_add_peer (t, peer_info);
3428   peer_info_connect (peer_info, t);
3429 }
3430
3431
3432 /******************************************************************************/
3433 /*********************       MESH LOCAL HANDLES      **************************/
3434 /******************************************************************************/
3435
3436
3437 /**
3438  * Handler for client disconnection
3439  *
3440  * @param cls closure
3441  * @param client identification of the client; NULL
3442  *        for the last call when the server is destroyed
3443  */
3444 static void
3445 handle_local_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
3446 {
3447   struct MeshClient *c;
3448   struct MeshClient *next;
3449
3450   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: client disconnected\n");
3451   if (client == NULL)
3452   {
3453     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    (SERVER DOWN)\n");
3454     return;
3455   }
3456   c = clients;
3457   while (NULL != c)
3458   {
3459     if (c->handle != client)
3460     {
3461       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    ... searching\n");
3462       c = c->next;
3463       continue;
3464     }
3465 #if MESH_DEBUG
3466     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: matching client found (%u)\n",
3467                 c->id);
3468 #endif
3469     GNUNET_SERVER_client_drop (c->handle);
3470     if (NULL != c->tunnels)
3471     {
3472       GNUNET_CONTAINER_multihashmap_iterate (c->tunnels,
3473                                              &tunnel_destroy_iterator, c);
3474       GNUNET_CONTAINER_multihashmap_destroy (c->tunnels);
3475     }
3476
3477     /* deregister clients applications */
3478     if (NULL != c->apps)
3479     {
3480       GNUNET_CONTAINER_multihashmap_iterate (c->apps, &deregister_app, NULL);
3481       GNUNET_CONTAINER_multihashmap_destroy (c->apps);
3482     }
3483     if (0 == GNUNET_CONTAINER_multihashmap_size (applications) &&
3484         GNUNET_SCHEDULER_NO_TASK != announce_applications_task)
3485     {
3486       GNUNET_SCHEDULER_cancel (announce_applications_task);
3487       announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
3488     }
3489     if (NULL != c->types)
3490       GNUNET_CONTAINER_multihashmap_destroy (c->types);
3491     next = c->next;
3492     GNUNET_CONTAINER_DLL_remove (clients, clients_tail, c);
3493     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   CLIENT FREE at %p\n", c);
3494     GNUNET_free (c);
3495     c = next;
3496   }
3497
3498   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:    done!\n");
3499   return;
3500 }
3501
3502
3503 /**
3504  * Handler for new clients
3505  *
3506  * @param cls closure
3507  * @param client identification of the client
3508  * @param message the actual message, which includes messages the client wants
3509  */
3510 static void
3511 handle_local_new_client (void *cls, struct GNUNET_SERVER_Client *client,
3512                          const struct GNUNET_MessageHeader *message)
3513 {
3514   struct GNUNET_MESH_ClientConnect *cc_msg;
3515   struct MeshClient *c;
3516   GNUNET_MESH_ApplicationType *a;
3517   unsigned int size;
3518   uint16_t ntypes;
3519   uint16_t *t;
3520   uint16_t napps;
3521   uint16_t i;
3522
3523   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n");
3524   /* Check data sanity */
3525   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
3526   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
3527   ntypes = ntohs (cc_msg->types);
3528   napps = ntohs (cc_msg->applications);
3529   if (size !=
3530       ntypes * sizeof (uint16_t) + napps * sizeof (GNUNET_MESH_ApplicationType))
3531   {
3532     GNUNET_break (0);
3533     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3534     return;
3535   }
3536
3537   /* Create new client structure */
3538   c = GNUNET_malloc (sizeof (struct MeshClient));
3539 #if MESH_DEBUG
3540   c->id = next_client_id++;
3541   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   CLIENT NEW %u at %p\n", c->id,
3542               c);
3543 #endif
3544   c->handle = client;
3545   GNUNET_SERVER_client_keep (client);
3546   a = (GNUNET_MESH_ApplicationType *) &cc_msg[1];
3547   if (napps > 0)
3548   {
3549     GNUNET_MESH_ApplicationType at;
3550     GNUNET_HashCode hc;
3551
3552     c->apps = GNUNET_CONTAINER_multihashmap_create (napps);
3553     for (i = 0; i < napps; i++)
3554     {
3555       at = ntohl (a[i]);
3556       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   app type: %u\n", at);
3557       GNUNET_CRYPTO_hash (&at, sizeof (at), &hc);
3558       /* store in clients hashmap */
3559       GNUNET_CONTAINER_multihashmap_put (c->apps, &hc, c,
3560                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3561       /* store in global hashmap, for announcements */
3562       GNUNET_CONTAINER_multihashmap_put (applications, &hc, c,
3563                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3564     }
3565     if (GNUNET_SCHEDULER_NO_TASK == announce_applications_task)
3566       announce_applications_task =
3567           GNUNET_SCHEDULER_add_now (&announce_applications, NULL);
3568
3569   }
3570   if (ntypes > 0)
3571   {
3572     uint16_t u16;
3573     GNUNET_HashCode hc;
3574
3575     t = (uint16_t *) & a[napps];
3576     c->types = GNUNET_CONTAINER_multihashmap_create (ntypes);
3577     for (i = 0; i < ntypes; i++)
3578     {
3579       u16 = ntohs (t[i]);
3580       GNUNET_CRYPTO_hash (&u16, sizeof (u16), &hc);
3581
3582       /* store in clients hashmap */
3583       GNUNET_CONTAINER_multihashmap_put (c->types, &hc, c,
3584                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3585       /* store in global hashmap */
3586       GNUNET_CONTAINER_multihashmap_put (types, &hc, c,
3587                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
3588     }
3589   }
3590   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3591               "MESH:  client has %u+%u subscriptions\n", napps, ntypes);
3592
3593   GNUNET_CONTAINER_DLL_insert (clients, clients_tail, c);
3594   c->tunnels = GNUNET_CONTAINER_multihashmap_create (32);
3595   GNUNET_SERVER_notification_context_add (nc, client);
3596
3597   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3598 #if MESH_DEBUG
3599   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new client processed\n");
3600 #endif
3601 }
3602
3603
3604 /**
3605  * Handler for requests of new tunnels
3606  *
3607  * @param cls closure
3608  * @param client identification of the client
3609  * @param message the actual message
3610  */
3611 static void
3612 handle_local_tunnel_create (void *cls, struct GNUNET_SERVER_Client *client,
3613                             const struct GNUNET_MessageHeader *message)
3614 {
3615   struct GNUNET_MESH_TunnelMessage *t_msg;
3616   struct MeshTunnel *t;
3617   struct MeshClient *c;
3618   GNUNET_HashCode hash;
3619
3620   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: new tunnel requested\n");
3621
3622   /* Sanity check for client registration */
3623   if (NULL == (c = client_get (client)))
3624   {
3625     GNUNET_break (0);
3626     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3627     return;
3628   }
3629 #if MESH_DEBUG
3630   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
3631 #endif
3632
3633   /* Message sanity check */
3634   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
3635   {
3636     GNUNET_break (0);
3637     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3638     return;
3639   }
3640
3641   t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
3642   /* Sanity check for tunnel numbering */
3643   if (0 == (ntohl (t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_CLI))
3644   {
3645     GNUNET_break (0);
3646     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3647     return;
3648   }
3649   /* Sanity check for duplicate tunnel IDs */
3650   if (NULL != tunnel_get_by_local_id (c, ntohl (t_msg->tunnel_id)))
3651   {
3652     GNUNET_break (0);
3653     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3654     return;
3655   }
3656
3657   t = GNUNET_malloc (sizeof (struct MeshTunnel));
3658   while (NULL != tunnel_get_by_pi (myid, next_tid))
3659     next_tid = (next_tid + 1) & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
3660   t->id.tid = next_tid++;
3661   next_tid = next_tid & ~GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
3662   t->id.oid = myid;
3663   t->local_tid = ntohl (t_msg->tunnel_id);
3664 #if MESH_DEBUG
3665   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: CREATED TUNNEL %s [%x] (%x)\n",
3666               GNUNET_i2s (&my_full_id), t->id.tid, t->local_tid);
3667 #endif
3668   t->client = c;
3669   t->peers = GNUNET_CONTAINER_multihashmap_create (32);
3670
3671   GNUNET_CRYPTO_hash (&t->local_tid, sizeof (MESH_TunnelNumber), &hash);
3672   if (GNUNET_OK !=
3673       GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
3674                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
3675   {
3676     GNUNET_break (0);
3677     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3678     return;
3679   }
3680
3681   GNUNET_CRYPTO_hash (&t->id, sizeof (struct MESH_TunnelID), &hash);
3682   if (GNUNET_OK !=
3683       GNUNET_CONTAINER_multihashmap_put (tunnels, &hash, t,
3684                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
3685   {
3686     GNUNET_break (0);
3687     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3688     return;
3689   }
3690   t->tree = tree_new (myid);
3691
3692   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3693   return;
3694 }
3695
3696
3697 /**
3698  * Handler for requests of deleting tunnels
3699  *
3700  * @param cls closure
3701  * @param client identification of the client
3702  * @param message the actual message
3703  */
3704 static void
3705 handle_local_tunnel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
3706                              const struct GNUNET_MessageHeader *message)
3707 {
3708   struct GNUNET_MESH_TunnelMessage *tunnel_msg;
3709   struct MeshClient *c;
3710   struct MeshTunnel *t;
3711   MESH_TunnelNumber tid;
3712   GNUNET_HashCode hash;
3713
3714   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
3715               "MESH: Got a DESTROY TUNNEL from client!\n");
3716
3717   /* Sanity check for client registration */
3718   if (NULL == (c = client_get (client)))
3719   {
3720     GNUNET_break (0);
3721     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3722     return;
3723   }
3724   /* Message sanity check */
3725   if (sizeof (struct GNUNET_MESH_TunnelMessage) != ntohs (message->size))
3726   {
3727     GNUNET_break (0);
3728     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3729     return;
3730   }
3731 #if MESH_DEBUG
3732   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   by client %u\n", c->id);
3733 #endif
3734   tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
3735
3736   /* Retrieve tunnel */
3737   tid = ntohl (tunnel_msg->tunnel_id);
3738
3739   /* Remove from local id hashmap */
3740   GNUNET_CRYPTO_hash (&tid, sizeof (MESH_TunnelNumber), &hash);
3741   t = GNUNET_CONTAINER_multihashmap_get (c->tunnels, &hash);
3742   send_client_tunnel_disconnect(t, c);
3743   GNUNET_assert (GNUNET_YES ==
3744                  GNUNET_CONTAINER_multihashmap_remove (c->tunnels, &hash, t));
3745
3746   t->client = NULL;
3747   tunnel_send_destroy (t);
3748   tunnel_destroy (t);
3749   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3750   return;
3751 }
3752
3753
3754 /**
3755  * Handler for connection requests to new peers
3756  *
3757  * @param cls closure
3758  * @param client identification of the client
3759  * @param message the actual message (PeerControl)
3760  */
3761 static void
3762 handle_local_connect_add (void *cls, struct GNUNET_SERVER_Client *client,
3763                           const struct GNUNET_MessageHeader *message)
3764 {
3765   struct GNUNET_MESH_PeerControl *peer_msg;
3766   struct MeshPeerInfo *peer_info;
3767   struct MeshClient *c;
3768   struct MeshTunnel *t;
3769   MESH_TunnelNumber tid;
3770
3771   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Got connection request\n");
3772   /* Sanity check for client registration */
3773   if (NULL == (c = client_get (client)))
3774   {
3775     GNUNET_break (0);
3776     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3777     return;
3778   }
3779
3780   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
3781   /* Sanity check for message size */
3782   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
3783   {
3784     GNUNET_break (0);
3785     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3786     return;
3787   }
3788
3789   /* Tunnel exists? */
3790   tid = ntohl (peer_msg->tunnel_id);
3791   t = tunnel_get_by_local_id (c, tid);
3792   if (NULL == t)
3793   {
3794     GNUNET_break (0);
3795     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3796     return;
3797   }
3798
3799   /* Does client own tunnel? */
3800   if (t->client->handle != client)
3801   {
3802     GNUNET_break (0);
3803     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3804     return;
3805   }
3806   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      for %s\n",
3807               GNUNET_i2s (&peer_msg->peer));
3808   peer_info = peer_info_get (&peer_msg->peer);
3809
3810   tunnel_add_peer (t, peer_info);
3811   peer_info_connect (peer_info, t);
3812
3813   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3814   return;
3815 }
3816
3817
3818 /**
3819  * Handler for disconnection requests of peers in a tunnel
3820  *
3821  * @param cls closure
3822  * @param client identification of the client
3823  * @param message the actual message (PeerControl)
3824  */
3825 static void
3826 handle_local_connect_del (void *cls, struct GNUNET_SERVER_Client *client,
3827                           const struct GNUNET_MessageHeader *message)
3828 {
3829   struct GNUNET_MESH_PeerControl *peer_msg;
3830   struct MeshPeerInfo *peer_info;
3831   struct MeshClient *c;
3832   struct MeshTunnel *t;
3833   MESH_TunnelNumber tid;
3834
3835   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Got a PEER DEL request\n");
3836   /* Sanity check for client registration */
3837   if (NULL == (c = client_get (client)))
3838   {
3839     GNUNET_break (0);
3840     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3841     return;
3842   }
3843   peer_msg = (struct GNUNET_MESH_PeerControl *) message;
3844   /* Sanity check for message size */
3845   if (sizeof (struct GNUNET_MESH_PeerControl) != ntohs (peer_msg->header.size))
3846   {
3847     GNUNET_break (0);
3848     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3849     return;
3850   }
3851
3852   /* Tunnel exists? */
3853   tid = ntohl (peer_msg->tunnel_id);
3854   t = tunnel_get_by_local_id (c, tid);
3855   if (NULL == t)
3856   {
3857     GNUNET_break (0);
3858     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3859     return;
3860   }
3861   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   on tunnel %X\n", t->id.tid);
3862
3863   /* Does client own tunnel? */
3864   if (t->client->handle != client)
3865   {
3866     GNUNET_break (0);
3867     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3868     return;
3869   }
3870
3871   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:   for peer %s\n",
3872               GNUNET_i2s (&peer_msg->peer));
3873   /* Is the peer in the tunnel? */
3874   peer_info =
3875       GNUNET_CONTAINER_multihashmap_get (t->peers, &peer_msg->peer.hashPubKey);
3876   if (NULL == peer_info)
3877   {
3878     GNUNET_break (0);
3879     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3880     return;
3881   }
3882
3883   /* Ok, delete peer from tunnel */
3884   GNUNET_CONTAINER_multihashmap_remove_all (t->peers,
3885                                             &peer_msg->peer.hashPubKey);
3886
3887   send_destroy_path (t, peer_info->id);
3888   tunnel_delete_peer (t, peer_info->id);
3889   GNUNET_SERVER_receive_done (client, GNUNET_OK);
3890   return;
3891 }
3892
3893
3894 /**
3895  * Handler for connection requests to new peers by type
3896  *
3897  * @param cls closure
3898  * @param client identification of the client
3899  * @param message the actual message (ConnectPeerByType)
3900  */
3901 static void
3902 handle_local_connect_by_type (void *cls, struct GNUNET_SERVER_Client *client,
3903                               const struct GNUNET_MessageHeader *message)
3904 {
3905   struct GNUNET_MESH_ConnectPeerByType *connect_msg;
3906   struct MeshClient *c;
3907   struct MeshTunnel *t;
3908   GNUNET_HashCode hash;
3909   MESH_TunnelNumber tid;
3910
3911   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: got connect by type request\n");
3912   /* Sanity check for client registration */
3913   if (NULL == (c = client_get (client)))
3914   {
3915     GNUNET_break (0);
3916     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3917     return;
3918   }
3919
3920   connect_msg = (struct GNUNET_MESH_ConnectPeerByType *) message;
3921   /* Sanity check for message size */
3922   if (sizeof (struct GNUNET_MESH_ConnectPeerByType) !=
3923       ntohs (connect_msg->header.size))
3924   {
3925     GNUNET_break (0);
3926     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3927     return;
3928   }
3929
3930   /* Tunnel exists? */
3931   tid = ntohl (connect_msg->tunnel_id);
3932   t = tunnel_get_by_local_id (c, tid);
3933   if (NULL == t)
3934   {
3935     GNUNET_break (0);
3936     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3937     return;
3938   }
3939
3940   /* Does client own tunnel? */
3941   if (t->client->handle != client)
3942   {
3943     GNUNET_break (0);
3944     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
3945     return;
3946   }
3947
3948   /* Do WE have the service? */
3949   t->type = ntohl (connect_msg->type);
3950   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  type requested: %u\n", t->type);
3951   GNUNET_CRYPTO_hash (&t->type, sizeof (GNUNET_MESH_ApplicationType), &hash);
3952   if (GNUNET_CONTAINER_multihashmap_contains (applications, &hash) ==
3953       GNUNET_YES)
3954   {
3955     /* Yes! Fast forward, add ourselves to the tunnel and send the
3956      * good news to the client, and alert the destination client of
3957      * an incoming tunnel.
3958      */
3959     struct GNUNET_MESH_TunnelNotification cmsg;
3960     struct MeshClient *c;
3961
3962     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  available locally\n");
3963     GNUNET_CONTAINER_multihashmap_put (t->peers, &my_full_id.hashPubKey,
3964                                        peer_info_get (&my_full_id),
3965                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
3966
3967     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  notifying client\n");
3968     send_client_peer_connected (t, myid);
3969     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  Done\n");
3970     GNUNET_SERVER_receive_done (client, GNUNET_OK);
3971
3972     /* FIXME implement a proper handling of this case,
3973        a client differentiation mechanism */
3974     cmsg.header.size = htons (sizeof (cmsg));
3975     cmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
3976     cmsg.peer = my_full_id;
3977     t->local_tid_dest = next_local_tid++;
3978     cmsg.tunnel_id = htonl (t->local_tid_dest);
3979     c = (struct MeshClient *) GNUNET_CONTAINER_multihashmap_get(applications,
3980                                                                 &hash);
3981     t->client_dest = c;
3982     GNUNET_CRYPTO_hash (&t->local_tid_dest, sizeof (MESH_TunnelNumber), &hash);
3983     GNUNET_CONTAINER_multihashmap_put (c->tunnels, &hash, t,
3984                                        GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
3985     GNUNET_SERVER_notification_context_unicast (nc, c->handle, &cmsg.header,
3986                                                 GNUNET_NO);
3987     
3988
3989     return;
3990   }
3991   /* Ok, lets find a peer offering the service */
3992   if (NULL != t->dht_get_type)
3993   {
3994     GNUNET_DHT_get_stop (t->dht_get_type);
3995   }
3996   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:  looking in DHT for %s\n",
3997               GNUNET_h2s (&hash));
3998   t->dht_get_type =
3999       GNUNET_DHT_get_start (dht_handle, GNUNET_TIME_UNIT_FOREVER_REL,
4000                             GNUNET_BLOCK_TYPE_TEST, &hash, 10U,
4001                             GNUNET_DHT_RO_RECORD_ROUTE |
4002                             GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, NULL, 0,
4003                             &dht_get_type_handler, t);
4004
4005   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4006   return;
4007 }
4008
4009
4010 /**
4011  * Handler for client traffic directed to one peer
4012  *
4013  * @param cls closure
4014  * @param client identification of the client
4015  * @param message the actual message
4016  */
4017 static void
4018 handle_local_unicast (void *cls, struct GNUNET_SERVER_Client *client,
4019                       const struct GNUNET_MessageHeader *message)
4020 {
4021   struct MeshClient *c;
4022   struct MeshTunnel *t;
4023   struct MeshPeerInfo *pi;
4024   struct GNUNET_MESH_Unicast *data_msg;
4025   MESH_TunnelNumber tid;
4026   size_t size;
4027
4028   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4029               "MESH: Got a unicast request from a client!\n");
4030
4031   /* Sanity check for client registration */
4032   if (NULL == (c = client_get (client)))
4033   {
4034     GNUNET_break (0);
4035     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4036     return;
4037   }
4038   data_msg = (struct GNUNET_MESH_Unicast *) message;
4039   /* Sanity check for message size */
4040   size = ntohs (message->size);
4041   if (sizeof (struct GNUNET_MESH_Unicast) +
4042       sizeof (struct GNUNET_MessageHeader) > size)
4043   {
4044     GNUNET_break (0);
4045     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4046     return;
4047   }
4048
4049   /* Tunnel exists? */
4050   tid = ntohl (data_msg->tid);
4051   t = tunnel_get_by_local_id (c, tid);
4052   if (NULL == t)
4053   {
4054     GNUNET_break (0);
4055     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4056     return;
4057   }
4058
4059   /*  Is it a local tunnel? Then, does client own the tunnel? */
4060   if (NULL != t->client && NULL != t->client->handle &&
4061       t->client->handle != client)
4062   {
4063     GNUNET_break (0);
4064     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4065     return;
4066   }
4067
4068   pi = GNUNET_CONTAINER_multihashmap_get (t->peers,
4069                                           &data_msg->destination.hashPubKey);
4070   /* Is the selected peer in the tunnel? */
4071   if (NULL == pi)
4072   {
4073     GNUNET_break (0);
4074     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4075     return;
4076   }
4077
4078   /* Ok, everything is correct, send the message
4079    * (pretend we got it from a mesh peer)
4080    */
4081   {
4082     char buf[ntohs (message->size)];
4083     struct GNUNET_MESH_Unicast *copy;
4084
4085     /* Work around const limitation */
4086     copy = (struct GNUNET_MESH_Unicast *) buf;
4087     memcpy (buf, data_msg, size);
4088     copy->oid = my_full_id;
4089     copy->tid = htonl (t->id.tid);
4090     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4091                 "MESH:   calling generic handler...\n");
4092     handle_mesh_data_unicast (NULL, &my_full_id, &copy->header, NULL, 0);
4093   }
4094   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4095   return;
4096 }
4097
4098
4099 /**
4100  * Handler for client traffic directed to the origin
4101  *
4102  * @param cls closure
4103  * @param client identification of the client
4104  * @param message the actual message
4105  */
4106 static void
4107 handle_local_to_origin (void *cls, struct GNUNET_SERVER_Client *client,
4108                         const struct GNUNET_MessageHeader *message)
4109 {
4110   struct GNUNET_MESH_ToOrigin *data_msg;
4111   struct GNUNET_PeerIdentity id;
4112   struct MeshClient *c;
4113   struct MeshTunnel *t;
4114   MESH_TunnelNumber tid;
4115   size_t size;
4116
4117   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4118               "MESH: Got a ToOrigin request from a client!\n");
4119
4120   /* Sanity check for client registration */
4121   if (NULL == (c = client_get (client)))
4122   {
4123     GNUNET_break (0);
4124     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4125     return;
4126   }
4127   data_msg = (struct GNUNET_MESH_ToOrigin *) message;
4128   /* Sanity check for message size */
4129   size = ntohs (message->size);
4130   if (sizeof (struct GNUNET_MESH_ToOrigin) +
4131       sizeof (struct GNUNET_MessageHeader) > size)
4132   {
4133     GNUNET_break (0);
4134     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4135     return;
4136   }
4137
4138   /* Tunnel exists? */
4139   tid = ntohl (data_msg->tid);
4140   if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
4141   {
4142     GNUNET_break (0);
4143     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4144     return;
4145   }
4146   t = tunnel_get_by_local_id (c, tid);
4147   if (NULL == t)
4148   {
4149     GNUNET_break (0);
4150     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4151     return;
4152   }
4153
4154   /*  It shouldn't be a local tunnel.  */
4155   if (NULL != t->client)
4156   {
4157     GNUNET_break (0);
4158     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4159     return;
4160   }
4161   GNUNET_PEER_resolve (t->id.oid, &id);
4162
4163   /* Ok, everything is correct, send the message
4164    * (pretend we got it from a mesh peer)
4165    */
4166   {
4167     char buf[ntohs (message->size)];
4168     struct GNUNET_MESH_ToOrigin *copy;
4169
4170     /* Work around const limitation */
4171     copy = (struct GNUNET_MESH_ToOrigin *) buf;
4172     memcpy (buf, data_msg, size);
4173     copy->oid = id;
4174     copy->tid = htonl (t->id.tid);
4175     copy->sender = my_full_id;
4176     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4177                 "MESH:   calling generic handler...\n");
4178     handle_mesh_data_to_orig (NULL, &my_full_id, &copy->header, NULL, 0);
4179   }
4180   GNUNET_SERVER_receive_done (client, GNUNET_OK);
4181   return;
4182 }
4183
4184
4185 /**
4186  * Handler for client traffic directed to all peers in a tunnel
4187  *
4188  * @param cls closure
4189  * @param client identification of the client
4190  * @param message the actual message
4191  */
4192 static void
4193 handle_local_multicast (void *cls, struct GNUNET_SERVER_Client *client,
4194                         const struct GNUNET_MessageHeader *message)
4195 {
4196   struct MeshClient *c;
4197   struct MeshTunnel *t;
4198   struct GNUNET_MESH_Multicast *data_msg;
4199   MESH_TunnelNumber tid;
4200
4201   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4202               "MESH: Got a multicast request from a client!\n");
4203
4204   /* Sanity check for client registration */
4205   if (NULL == (c = client_get (client)))
4206   {
4207     GNUNET_break (0);
4208     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4209     return;
4210   }
4211   data_msg = (struct GNUNET_MESH_Multicast *) message;
4212   /* Sanity check for message size */
4213   if (sizeof (struct GNUNET_MESH_Multicast) +
4214       sizeof (struct GNUNET_MessageHeader) > ntohs (data_msg->header.size))
4215   {
4216     GNUNET_break (0);
4217     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4218     return;
4219   }
4220
4221   /* Tunnel exists? */
4222   tid = ntohl (data_msg->tid);
4223   t = tunnel_get_by_local_id (c, tid);
4224   if (NULL == t)
4225   {
4226     GNUNET_break (0);
4227     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4228     return;
4229   }
4230
4231   /* Does client own tunnel? */
4232   if (t->client->handle != client)
4233   {
4234     GNUNET_break (0);
4235     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
4236     return;
4237   }
4238
4239   {
4240     char buf[ntohs (message->size)];
4241     struct GNUNET_MESH_Multicast *copy;
4242
4243     copy = (struct GNUNET_MESH_Multicast *) buf;
4244     memcpy (buf, message, ntohs (message->size));
4245     copy->oid = my_full_id;
4246     copy->tid = htonl (t->id.tid);
4247     copy->ttl = htonl (DEFAULT_TTL);
4248     copy->mid = htonl (t->mid + 1);
4249     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
4250                 "MESH:   calling generic handler...\n");
4251     handle_mesh_data_multicast (client, &my_full_id, &copy->header, NULL, 0);
4252   }
4253
4254   /* receive done gets called when last copy is sent to a neighbor */
4255   return;
4256 }
4257
4258 /**
4259  * Functions to handle messages from clients
4260  */
4261 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
4262   {&handle_local_new_client, NULL,
4263    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
4264   {&handle_local_tunnel_create, NULL,
4265    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
4266    sizeof (struct GNUNET_MESH_TunnelMessage)},
4267   {&handle_local_tunnel_destroy, NULL,
4268    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
4269    sizeof (struct GNUNET_MESH_TunnelMessage)},
4270   {&handle_local_connect_add, NULL,
4271    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD,
4272    sizeof (struct GNUNET_MESH_PeerControl)},
4273   {&handle_local_connect_del, NULL,
4274    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL,
4275    sizeof (struct GNUNET_MESH_PeerControl)},
4276   {&handle_local_connect_by_type, NULL,
4277    GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE,
4278    sizeof (struct GNUNET_MESH_ConnectPeerByType)},
4279   {&handle_local_unicast, NULL,
4280    GNUNET_MESSAGE_TYPE_MESH_UNICAST, 0},
4281   {&handle_local_to_origin, NULL,
4282    GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN, 0},
4283   {&handle_local_multicast, NULL,
4284    GNUNET_MESSAGE_TYPE_MESH_MULTICAST, 0},
4285   {NULL, NULL, 0, 0}
4286 };
4287
4288
4289 /**
4290  * To be called on core init/fail.
4291  *
4292  * @param cls service closure
4293  * @param server handle to the server for this service
4294  * @param identity the public identity of this peer
4295  */
4296 static void
4297 core_init (void *cls, struct GNUNET_CORE_Handle *server,
4298            const struct GNUNET_PeerIdentity *identity)
4299 {
4300   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Core init\n");
4301   core_handle = server;
4302   if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)) ||
4303       NULL == server)
4304   {
4305     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("MESH: Wrong CORE service\n"));
4306     GNUNET_SCHEDULER_shutdown ();
4307   }
4308   return;
4309 }
4310
4311 /**
4312  * Method called whenever a given peer connects.
4313  *
4314  * @param cls closure
4315  * @param peer peer identity this notification is about
4316  * @param atsi performance data for the connection
4317  * @param atsi_count number of records in 'atsi'
4318  */
4319 static void
4320 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer,
4321               const struct GNUNET_ATS_Information *atsi,
4322               unsigned int atsi_count)
4323 {
4324   struct MeshPeerInfo *peer_info;
4325   struct MeshPeerPath *path;
4326
4327 #if MESH_DEBUG_CONNECTION
4328   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer connected\n");
4329   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      %s\n",
4330               GNUNET_i2s (&my_full_id));
4331 #endif
4332   peer_info = peer_info_get (peer);
4333   if (myid == peer_info->id)
4334   {
4335 #if MESH_DEBUG_CONNECTION
4336     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
4337 #endif
4338     return;
4339   }
4340 #if MESH_DEBUG_CONNECTION
4341   else
4342   {
4343     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      %s\n", GNUNET_i2s (peer));
4344   }
4345 #endif
4346   path = path_new (2);
4347   path->peers[0] = myid;
4348   path->peers[1] = peer_info->id;
4349   GNUNET_PEER_change_rc (myid, 1);
4350   GNUNET_PEER_change_rc (peer_info->id, 1);
4351   peer_info_add_path (peer_info, path, GNUNET_YES);
4352   return;
4353 }
4354
4355 /**
4356  * Method called whenever a peer disconnects.
4357  *
4358  * @param cls closure
4359  * @param peer peer identity this notification is about
4360  */
4361 static void
4362 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
4363 {
4364   struct MeshPeerInfo *pi;
4365   unsigned int i;
4366
4367 #if MESH_DEBUG_CONNECTION
4368   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: Peer disconnected\n");
4369 #endif
4370   pi = GNUNET_CONTAINER_multihashmap_get (peers, &peer->hashPubKey);
4371   if (NULL == pi)
4372   {
4373     GNUNET_break (0);
4374     return;
4375   }
4376   for (i = 0; i < CORE_QUEUE_SIZE; i++)
4377   {
4378     /* TODO: notify that the transmission failed */
4379     peer_info_cancel_transmission (pi, i);
4380   }
4381   peer_info_remove_path (pi, pi->id, myid);
4382 #if MESH_DEBUG_CONNECTION
4383   if (myid == pi->id)
4384   {
4385     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH:      (self)\n");
4386   }
4387 #endif
4388   return;
4389 }
4390
4391
4392 /******************************************************************************/
4393 /************************      MAIN FUNCTIONS      ****************************/
4394 /******************************************************************************/
4395
4396 /**
4397  * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
4398  *
4399  * @param cls closure
4400  * @param key current key code
4401  * @param value value in the hash map
4402  * @return GNUNET_YES if we should continue to iterate,
4403  *         GNUNET_NO if not.
4404  */
4405 static int
4406 shutdown_tunnel (void *cls, const GNUNET_HashCode * key, void *value)
4407 {
4408   struct MeshTunnel *t = value;
4409
4410   tunnel_destroy (t);
4411   return GNUNET_YES;
4412 }
4413
4414 /**
4415  * Iterator over peer hash map entries to destroy the tunnel during shutdown.
4416  *
4417  * @param cls closure
4418  * @param key current key code
4419  * @param value value in the hash map
4420  * @return GNUNET_YES if we should continue to iterate,
4421  *         GNUNET_NO if not.
4422  */
4423 static int
4424 shutdown_peer (void *cls, const GNUNET_HashCode * key, void *value)
4425 {
4426   struct MeshPeerInfo *p = value;
4427
4428   peer_info_destroy (p);
4429   return GNUNET_YES;
4430 }
4431
4432 /**
4433  * Task run during shutdown.
4434  *
4435  * @param cls unused
4436  * @param tc unused
4437  */
4438 static void
4439 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
4440 {
4441   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shutting down\n");
4442
4443   if (core_handle != NULL)
4444   {
4445     GNUNET_CORE_disconnect (core_handle);
4446     core_handle = NULL;
4447   }
4448   GNUNET_CONTAINER_multihashmap_iterate (tunnels, &shutdown_tunnel, NULL);
4449   GNUNET_CONTAINER_multihashmap_iterate (peers, &shutdown_peer, NULL);
4450   if (dht_handle != NULL)
4451   {
4452     GNUNET_DHT_disconnect (dht_handle);
4453     dht_handle = NULL;
4454   }
4455   if (nc != NULL)
4456   {
4457     GNUNET_SERVER_notification_context_destroy (nc);
4458     nc = NULL;
4459   }
4460   if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
4461   {
4462     GNUNET_SCHEDULER_cancel (announce_id_task);
4463     announce_id_task = GNUNET_SCHEDULER_NO_TASK;
4464   }
4465   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: shut down\n");
4466 }
4467
4468 /**
4469  * Process mesh requests.
4470  *
4471  * @param cls closure
4472  * @param server the initialized server
4473  * @param c configuration to use
4474  */
4475 static void
4476 run (void *cls, struct GNUNET_SERVER_Handle *server,
4477      const struct GNUNET_CONFIGURATION_Handle *c)
4478 {
4479   struct MeshPeerInfo *peer;
4480   struct MeshPeerPath *p;
4481   char *keyfile;
4482
4483   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: starting to run\n");
4484   server_handle = server;
4485   core_handle = GNUNET_CORE_connect (c, /* Main configuration */
4486                                      CORE_QUEUE_SIZE,   /* queue size */
4487                                      NULL,      /* Closure passed to MESH functions */
4488                                      &core_init,        /* Call core_init once connected */
4489                                      &core_connect,     /* Handle connects */
4490                                      &core_disconnect,  /* remove peers on disconnects */
4491                                      NULL,      /* Don't notify about all incoming messages */
4492                                      GNUNET_NO, /* For header only in notification */
4493                                      NULL,      /* Don't notify about all outbound messages */
4494                                      GNUNET_NO, /* For header-only out notification */
4495                                      core_handlers);    /* Register these handlers */
4496
4497   if (core_handle == NULL)
4498   {
4499     GNUNET_break (0);
4500     GNUNET_SCHEDULER_shutdown ();
4501     return;
4502   }
4503
4504   if (GNUNET_OK !=
4505       GNUNET_CONFIGURATION_get_value_filename (c, "GNUNETD", "HOSTKEY",
4506                                                &keyfile))
4507   {
4508     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4509                 _
4510                 ("Mesh service is lacking key configuration settings.  Exiting.\n"));
4511     GNUNET_SCHEDULER_shutdown ();
4512     return;
4513   }
4514   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
4515   GNUNET_free (keyfile);
4516   if (my_private_key == NULL)
4517   {
4518     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
4519                 _("Mesh service could not access hostkey.  Exiting.\n"));
4520     GNUNET_SCHEDULER_shutdown ();
4521     return;
4522   }
4523   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
4524   GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
4525                       &my_full_id.hashPubKey);
4526   myid = GNUNET_PEER_intern (&my_full_id);
4527
4528 // //   transport_handle = GNUNET_TRANSPORT_connect(c,
4529 // //                                               &my_full_id,
4530 // //                                               NULL,
4531 // //                                               NULL,
4532 // //                                               NULL,
4533 // //                                               NULL);
4534
4535   dht_handle = GNUNET_DHT_connect (c, 64);
4536   if (dht_handle == NULL)
4537   {
4538     GNUNET_break (0);
4539   }
4540
4541   next_tid = 0;
4542   next_local_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
4543
4544   tunnels = GNUNET_CONTAINER_multihashmap_create (32);
4545   incoming_tunnels = GNUNET_CONTAINER_multihashmap_create (32);
4546   peers = GNUNET_CONTAINER_multihashmap_create (32);
4547   applications = GNUNET_CONTAINER_multihashmap_create (32);
4548   types = GNUNET_CONTAINER_multihashmap_create (32);
4549
4550   GNUNET_SERVER_add_handlers (server_handle, client_handlers);
4551   nc = GNUNET_SERVER_notification_context_create (server_handle,
4552                                                   LOCAL_QUEUE_SIZE);
4553   GNUNET_SERVER_disconnect_notify (server_handle,
4554                                    &handle_local_client_disconnect, NULL);
4555
4556
4557   clients = NULL;
4558   clients_tail = NULL;
4559 #if MESH_DEBUG
4560   next_client_id = 0;
4561 #endif
4562
4563   announce_applications_task = GNUNET_SCHEDULER_NO_TASK;
4564   announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
4565
4566   /* Create a peer_info for the local peer */
4567   peer = peer_info_get (&my_full_id);
4568   p = path_new (1);
4569   p->peers[0] = myid;
4570   GNUNET_PEER_change_rc (myid, 1);
4571   peer_info_add_path (peer, p, GNUNET_YES);
4572
4573   /* Scheduled the task to clean up when shutdown is called */
4574   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
4575                                 NULL);
4576
4577   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: end of run()\n");
4578 }
4579
4580 /**
4581  * The main function for the mesh service.
4582  *
4583  * @param argc number of arguments from the command line
4584  * @param argv command line arguments
4585  * @return 0 ok, 1 on error
4586  */
4587 int
4588 main (int argc, char *const *argv)
4589 {
4590   int ret;
4591
4592   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main()\n");
4593   ret =
4594       (GNUNET_OK ==
4595        GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
4596                            NULL)) ? 0 : 1;
4597   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "MESH: main() END\n");
4598
4599   return ret;
4600 }