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