fixes
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh.c
1 /*
2      This file is part of GNUnet.
3      (C) 2001 - 2011 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file mesh/gnunet-service-mesh.c
23  * @brief GNUnet MESH service
24  * @author Bartlomiej Polot
25  *
26  * STRUCTURE:
27  * - DATA STRUCTURES
28  * - GLOBAL VARIABLES
29  * - MESH NETWORK HANDLER HELPERS
30  * - MESH NETWORK HANDLES
31  * - MESH LOCAL HANDLER HELPERS
32  * - MESH LOCAL HANDLES
33  * - PERIODIC FUNCTIONS
34  * - MAIN FUNCTIONS (main & run)
35  * 
36  * TODO:
37  * - error reporting (CREATE/CHANGE/ADD/DEL?) -- new message!
38  * - partial disconnect reporting -- same as error reporting?
39  * - add vs create? change vs. keep-alive? same msg or different ones? -- thinking...
40  * - speed requirement specification (change?) in mesh API -- API call
41  * - add ping message (connection confirmation, others?)
42  */
43
44 #include "platform.h"
45 #include "gnunet_common.h"
46 #include "gnunet_util_lib.h"
47 #include "gnunet_peer_lib.h"
48 #include "gnunet_core_service.h"
49 #include "gnunet_protocols.h"
50
51 #include "mesh.h"
52 #include "mesh_protocol.h"
53 #include "gnunet_dht_service.h"
54
55 #define REFRESH_PATH_TIME GNUNET_TIME_relative_multiply(\
56                                     GNUNET_TIME_UNIT_SECONDS,\
57                                     300)
58
59
60 /******************************************************************************/
61 /************************      DATA STRUCTURES     ****************************/
62 /******************************************************************************/
63
64 /**
65  * Information regarding a path
66  */
67 struct MeshPath
68 {
69
70     /**
71      * Linked list
72      */
73     struct MeshPath             *next;
74     struct MeshPath             *prev;
75
76     /**
77      * Whether the path is serving traffic in a tunnel or is a backup
78      */
79     int                         in_use;
80
81     /**
82      * List of all the peers that form the path from origin to target
83      */
84     GNUNET_PEER_Id              *peers;
85
86     /**
87      * Number of peers (hops) in the path
88      */
89     unsigned int                length;
90 };
91
92
93 /**
94  * All the states a peer participating in a tunnel can be in.
95  */
96 enum MeshPeerState
97 {
98     /**
99      * Path to the peer not known yet
100      */
101     MESH_PEER_SEARCHING,
102
103     /**
104      * Request sent, not yet answered.
105      */
106     MESH_PEER_WAITING,
107
108     /**
109      * Peer connected and ready to accept data
110      */
111     MESH_PEER_READY,
112
113     /**
114      * Peer connected previosly but not responding
115      */
116     MESH_PEER_RECONNECTING
117 };
118
119
120 /**
121  * Struct containing all information regarding a given peer
122  */
123 struct MeshPeerInfo
124 {
125     /**
126      * ID of the peer
127      */
128     GNUNET_PEER_Id              id;
129
130     /**
131      * Is the peer reachable? Is the peer even connected?
132      */
133     enum MeshPeerState          state;
134
135     /**
136      * Last time we heard from this peer
137      */
138     struct GNUNET_TIME_Absolute last_contact;
139
140     /**
141      * Number of attempts to reconnect so far
142      */
143     int                         n_reconnect_attempts;
144
145     /**
146      * Paths to reach the peer
147      */
148     struct MeshPath             *path;
149     struct MeshPath             *path_tail;
150
151     /**
152      * Handle to stop the DHT search for a path to this peer
153      */
154     struct GNUNET_DHT_GetHandle *dhtget;
155 };
156
157
158 /**
159  * Data scheduled to transmit (to local client or remote peer)
160  */
161 struct MeshQueue
162 {
163     /**
164      * Double linked list
165      */
166     struct MeshQueue            *next;
167     struct MeshQueue            *prev;
168
169     /**
170      * Target of the data (NULL if target is client)
171      */
172     struct MeshPeerInfo         *peer;
173
174     /**
175      * Client to send the data to (NULL if target is peer)
176      */
177     struct MeshClient           *client;
178
179     /**
180      * Size of the message to transmit
181      */
182     unsigned int                size;
183
184     /**
185      * How old is the data?
186      */
187     struct GNUNET_TIME_Absolute timestamp;
188
189     /**
190      * Data itself
191      */
192     struct GNUNET_MessageHeader *data;
193 };
194
195 /**
196  * Globally unique tunnel identification (owner + number)
197  * DO NOT USE OVER THE NETWORK
198  */
199 struct MESH_TunnelID {
200     /**
201      * Node that owns the tunnel
202      */
203     GNUNET_PEER_Id      oid;
204
205     /**
206      * Tunnel number to differentiate all the tunnels owned by the node oid
207      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
208      */
209     MESH_TunnelNumber   tid;
210 };
211
212
213 struct MeshClient; /* FWD declaration */
214 /**
215  * Struct containing all information regarding a tunnel
216  * For an intermediate node the improtant info used will be:
217  * - id        Tunnel unique identification
218  * - paths[0]  To know where to send it next
219  * - metainfo: ready, speeds, accounting
220  */
221 struct MeshTunnel
222 {
223     /**
224      * Tunnel ID
225      */
226     struct MESH_TunnelID        id;
227
228     /**
229      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
230      */
231     MESH_TunnelNumber           local_tid;
232
233     /**
234      * Last time the tunnel was used
235      */
236     struct GNUNET_TIME_Absolute timestamp;
237
238     /**
239      * Peers in the tunnelindexed by PeerIdentity (MeshPeerInfo)
240      */
241     struct GNUNET_CONTAINER_MultiHashMap* peers;
242
243     /**
244      * Number of peers that are connected and potentially ready to receive data
245      */
246     unsigned int                peers_ready;
247
248     /**
249      * Number of peers that have been added to the tunnel
250      */
251     unsigned int                peers_total;
252
253
254     /**
255      * Client owner of the tunnel, if any
256      */
257     struct MeshClient           *client;
258
259     /**
260      * Messages ready to transmit
261      */
262     struct MeshQueue            *queue_head;
263     struct MeshQueue            *queue_tail;
264
265 };
266
267 /**
268  * Struct containing information about a client of the service
269  */
270 struct MeshClient
271 {
272     /**
273      * Linked list
274      */
275     struct MeshClient           *next;
276     struct MeshClient           *prev;
277
278     /**
279      * Tunnels that belong to this client, indexed by local id
280      */
281     struct GNUNET_CONTAINER_MultiHashMap* tunnels;
282
283     /**
284      * Handle to communicate with the client
285      */
286     struct GNUNET_SERVER_Client *handle;
287
288     /**
289      * Applications that this client has claimed to provide
290      */
291     GNUNET_MESH_ApplicationType *apps;
292     unsigned int                app_counter;
293
294     /**
295      * Messages that this client has declared interest in
296      */
297     uint16_t                    *types;
298     unsigned int                type_counter;
299
300 };
301
302 /******************************************************************************/
303 /***********************      GLOBAL VARIABLES     ****************************/
304 /******************************************************************************/
305
306 /**
307  * All the clients
308  */
309 static struct MeshClient                *clients;
310 static struct MeshClient                *clients_tail;
311
312 /**
313  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
314  */
315 static struct GNUNET_CONTAINER_MultiHashMap     *tunnels;
316
317 /**
318  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
319  */
320 static struct GNUNET_CONTAINER_MultiHashMap     *peers;
321
322 /**
323  * Handle to communicate with core
324  */
325 static struct GNUNET_CORE_Handle        *core_handle;
326
327 /**
328  * Handle to use DHT
329  */
330 static struct GNUNET_DHT_Handle         *dht_handle;
331
332 /**
333  * Local peer own ID (memory efficient handle)
334  */
335 static GNUNET_PEER_Id                   myid;
336
337 /**
338  * Tunnel ID for the next created tunnel (global tunnel number)
339  */
340 static MESH_TunnelNumber                next_tid;
341
342 /******************************************************************************/
343 /******************      GENERAL HELPER FUNCTIONS      ************************/
344 /******************************************************************************/
345
346 /**
347  * Retrieve the MeshPeerInfo stucture associated with the peer, create one
348  * and inster it in the appropiate structures if the peer is not known yet.
349  * @param peer Identity of the peer
350  * @return Existing or newly created peer info
351  */
352 static struct MeshPeerInfo *
353 get_peer_info (const struct GNUNET_PeerIdentity *peer)
354 {
355     struct MeshPeerInfo *       peer_info;
356
357     peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
358                                                   &peer->hashPubKey);
359     if (NULL == peer_info) {
360         peer_info = (struct MeshPeerInfo *)
361                     GNUNET_malloc(sizeof(struct MeshPeerInfo));
362         GNUNET_CONTAINER_multihashmap_put(peers,
363                             &peer->hashPubKey,
364                             peer_info,
365                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
366         peer_info->id = GNUNET_PEER_intern(peer);
367         peer_info->state = MESH_PEER_SEARCHING;
368     }
369
370     return peer_info;
371 }
372
373 /**
374  * Find the first peer whom to send a packet to go down this path
375  * @param path The path to use
376  * @return short id of the next peer, myid in case of local delivery,
377  * or 0 in case of error
378  */
379 static GNUNET_PEER_Id
380 get_first_hop (struct MeshPath *path)
381 {
382     unsigned int        i;
383
384     while (NULL != path) {
385         if (path->in_use) break;
386         path = path->next;
387     }
388     if (NULL == path) {
389         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
390                    "tried to get the next hop from an invalid path\n");
391         return 0;
392     }
393
394     for (i = 0; i < path->length; i++) {
395         if (path->peers[i] == myid) {
396             if (i < path->length - 1) {
397                 return path->peers[i+1];
398             } else {
399                 return myid;
400             }
401         }
402     }
403     return 0;
404 }
405
406
407 /**
408  * Get the cost of the path.
409  * @param path The path to analyze
410  * @return Number of hops to reach destination, UINT_MAX in case the peer is not
411  * in the path
412  */
413 static unsigned int
414 get_path_cost(struct MeshPath *path)
415 {
416     unsigned int        i;
417
418     if (NULL == path) return UINT_MAX;
419     for (i = 0; i < path->length; i++) {
420         if (path->peers[i] == myid) {
421             return path->length - i;
422         }
423     }
424     return UINT_MAX;
425 }
426
427
428 /**
429  * Add the path to the peer and update the path used to reach it in case this
430  * is the shortest.
431  * @param peer_info Destination peer to add the path to.
432  * @param path New path to add. Last peer must be the peer in arg 1.
433  */
434 static void
435 add_path_to_peer(struct MeshPeerInfo *peer_info, struct MeshPath *path)
436 {
437     unsigned int        i;
438     unsigned int        new_cost;
439     unsigned int        best_cost;
440     struct MeshPath     *aux;
441     struct MeshPath     *best;
442
443     if (NULL == peer_info || NULL == path) return;
444
445     new_cost = get_path_cost(path);
446     best_cost = UINT_MAX;
447     best = NULL;
448     for (aux = peer_info->path; aux != NULL; aux = aux->next) {
449         if ((i = get_path_cost(aux)) < best_cost) {
450             best = aux;
451             best_cost = i;
452         }
453     }
454     if (best_cost < new_cost) {
455         path->in_use = 0;
456         GNUNET_CONTAINER_DLL_insert_tail(peer_info->path,
457                                          peer_info->path_tail,
458                                          path);
459     } else {
460         if (NULL != best) best->in_use = 0;
461         path->in_use = 1;
462         GNUNET_CONTAINER_DLL_insert(peer_info->path,
463                                     peer_info->path_tail,
464                                     path);
465     }
466     return;
467 }
468
469
470 /**
471  * Add the path to the peer and update the path used to reach it in case this
472  * is the shortest. The path is given in reverse, the destination peer is
473  * path[0]. The function modifies the path, inverting it to use the origin as
474  * destination.
475  * @param peer_info Destination peer to add the path to.
476  * @param path New path to add. First peer must be the peer in arg 1.
477  */
478 static void
479 add_path_to_origin(struct MeshPeerInfo *peer_info, struct MeshPath *path)
480 {
481     GNUNET_PEER_Id      aux;
482     unsigned int        i;
483
484     for (i = 0; i < path->length/2; i++) {
485         aux = path->peers[i];
486         path->peers[i] = path->peers[path->length - i - 1];
487         path->peers[path->length - i - 1] = aux;
488     }
489     add_path_to_peer(peer_info, path);
490 }
491
492
493 /**
494  * Check if client has registered with the service and has not disconnected
495  * @param client the client to check
496  * @return non-NULL if client exists in the global DLL
497  */
498 static struct MeshClient *
499 retrieve_client (struct GNUNET_SERVER_Client *client)
500 {
501     struct MeshClient       *c;
502
503     c = clients; 
504     while (NULL != c) {
505         if (c->handle == client) return c;
506         c = c->next;
507     }
508     return NULL;
509 }
510
511
512 /**
513  * Checks if a given client has subscribed to certain message type
514  * @param message_type Type of message to check
515  * @param c Client to check
516  * @return GNUNET_YES or GNUNET_NO, depending on subscription status
517  */
518 static int
519 is_client_subscribed(uint16_t message_type, struct MeshClient *c)
520 {
521     unsigned int        i;
522
523     for (i = 0; i < c->type_counter; i++) {
524         if (c->types[i] == message_type) return GNUNET_YES;
525     }
526     return GNUNET_NO;
527 }
528
529
530 /**
531  * Search for a tunnel among the tunnels for a client
532  * @param client the client whose tunnels to search in
533  * @param tid the local id of the tunnel
534  * @return tunnel handler, NULL if doesn't exist
535  */
536 static struct MeshTunnel *
537 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
538 {
539     GNUNET_HashCode hash;
540
541     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
542     return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
543 }
544
545 /**
546  * Search for a tunnel by global ID using PEER_ID
547  * @param pi owner of the tunnel
548  * @param tid global tunnel number
549  * @return tunnel handler, NULL if doesn't exist
550  */
551 static struct MeshTunnel *
552 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
553 {
554     struct MESH_TunnelID        id;
555     GNUNET_HashCode             hash;
556
557     id.oid = pi;
558     id.tid = tid;
559
560     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
561     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
562 }
563
564
565
566 /**
567  * Search for a tunnel by global ID using full PeerIdentities
568  * @param oid owner of the tunnel
569  * @param tid global tunnel number
570  * @return tunnel handler, NULL if doesn't exist
571  */
572 static struct MeshTunnel *
573 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
574 {
575     return retrieve_tunnel_by_pi(GNUNET_PEER_search(oid), tid);
576 }
577
578
579 /**
580  * Destroy the path and free any allocated resources linked to it
581  * @param t tunnel the path belongs to
582  * @param p the path to destroy
583  * @return GNUNET_OK on success
584  */
585 static int
586 destroy_path(struct MeshPath *p)
587 {
588     GNUNET_PEER_decrement_rcs(p->peers, p->length);
589     GNUNET_free(p->peers);
590     GNUNET_free(p);
591     return GNUNET_OK;
592 }
593
594 #if LATER
595 /**
596  * Destroy the peer_info and free any allocated resources linked to it
597  * @param t tunnel the path belongs to
598  * @param pi the peer_info to destroy
599  * @return GNUNET_OK on success
600  */
601 static int
602 destroy_peer_info(struct MeshPeerInfo *pi)
603 {
604     GNUNET_HashCode                     hash;
605     struct GNUNET_PeerIdentity          id;
606
607     GNUNET_PEER_resolve(pi->id, &id);
608     GNUNET_PEER_change_rc(pi->id, -1);
609     GNUNET_CRYPTO_hash(&id, sizeof(struct GNUNET_PeerIdentity), &hash);
610
611     GNUNET_CONTAINER_multihashmap_remove(peers, &hash, pi);
612     GNUNET_free(pi);
613     return GNUNET_OK;
614 }
615 #endif
616
617
618 /**
619  * Destroy the tunnel and free any allocated resources linked to it
620  * @param c client the tunnel belongs to
621  * @param t the tunnel to destroy
622  * @return GNUNET_OK on success
623  */
624 static int
625 destroy_tunnel(struct MeshTunnel  *t)
626 {
627     struct MeshClient           *c;
628     GNUNET_HashCode             hash;
629     int                         r;
630
631     if (NULL == t) return GNUNET_OK;
632
633     c = t->client;
634
635     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
636     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
637         r = GNUNET_SYSERR;
638     }
639
640     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
641     if(GNUNET_YES !=
642         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
643     {
644         r = GNUNET_SYSERR;
645     }
646     GNUNET_free(t);
647     return r;
648 }
649
650 /******************************************************************************/
651 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
652 /******************************************************************************/
653
654 /**
655  * Function called to notify a client about the socket
656  * being ready to queue more data.  "buf" will be
657  * NULL and "size" zero if the socket was closed for
658  * writing in the meantime.
659  *
660  * @param cls closure
661  * @param size number of bytes available in buf
662  * @param buf where the callee should write the message
663  * @return number of bytes written to buf
664  */
665 static size_t
666 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
667 {
668     struct MeshPeerInfo                 *peer_info = cls;
669     struct GNUNET_MESH_ManipulatePath   *msg;
670     struct MeshPath                     *p;
671     struct GNUNET_PeerIdentity          *peer_ptr;
672     struct GNUNET_PeerIdentity          id;
673     size_t                              size_needed;
674     int                                 i;
675
676     if (0 == size && NULL == buf) {
677         GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Retransmitting create path\n");
678         GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
679         GNUNET_CORE_notify_transmit_ready(core_handle,
680                             0,
681                             0,
682                             GNUNET_TIME_UNIT_FOREVER_REL,
683                             &id,
684                             sizeof(struct GNUNET_MESH_ManipulatePath)
685                             + (peer_info->path->length
686                             * sizeof (struct GNUNET_PeerIdentity)),
687                             &send_core_create_path_for_peer,
688                             peer_info);
689         return 0;
690     }
691     p = peer_info->path;
692     while (NULL != p) {
693         if (p->in_use) {
694             break;
695         }
696         p = p->next;
697     }
698     if (p == NULL) return 0; // TODO Notify ERROR Path not found
699
700     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
701                   + p->length * sizeof(struct GNUNET_PeerIdentity);
702     if (size < size_needed) {
703         // TODO retry? cancel?
704         return 0;
705     }
706
707     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
708     msg->header.size = htons(size_needed);
709     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
710
711     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
712     for (i = 0; i < p->length; i++) {
713         GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
714     }
715
716     peer_info->state = MESH_PEER_WAITING;
717
718     return size_needed;
719 }
720
721 /**
722  * FIXME / COMMENT
723  * There are several options to send a "data to origin" or similar packet.
724  * The core callback function needs to know at least: ID of tunnel and the
725  * data itself, so one parameter (cls) is not enough.
726  * 1. Build the message inside the original funtction, call core_ntfy_trnsmt_rdy
727  *    passing the created message as cls
728  *    - # memcpy: 2 (function X: to message struct, callback: from cls to buf)
729  *    - Very messy, original function becomes huge and ugly
730  *      (see "handle_mesh_path_create" for example)
731  * 2. Create a helper function to build the packet, then call
732  *    core_ntfy_trnsmt_rdy with message as cls.
733  *    - # memcpy: 2 (in helper function data->msg and in callback cls->buf)
734  * 3- Define new container, pass container with pointers
735  *    - # memcpy = 1 (in callback, cls->buf)
736  *    - Noise: extra containers defined per type of message
737  */
738 struct info_for_data_to_origin
739 {
740     struct MESH_TunnelID        *origin;
741     void                        *data;
742     size_t                      size;
743 };
744
745 /**
746  * Function called to notify a client about the socket
747  * being ready to queue more data.  "buf" will be
748  * NULL and "size" zero if the socket was closed for
749  * writing in the meantime.
750  *
751  * @param cls closure (info_for_data_to_origin with all info to build packet)
752  * @param size number of bytes available in buf
753  * @param buf where the callee should write the message
754  * @return number of bytes written to buf
755  */
756 static size_t
757 send_core_data_to_origin (void *cls, size_t size, void *buf)
758 {
759     struct info_for_data_to_origin              *info = cls;
760     struct GNUNET_MESH_DataMessageToOrigin      *msg = buf;
761     size_t                                      total_size;
762
763     GNUNET_assert(NULL != info);
764     total_size = sizeof(struct GNUNET_MESH_DataMessageToOrigin) + info->size;
765     GNUNET_assert(total_size < 65536); /* UNIT16_MAX */
766
767     if (total_size > size) {
768         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
769                    "not enough buffer to send data to origin\n");
770         return 0;
771     }
772     msg->header.size = htons(total_size);
773     msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
774     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
775     msg->tid = htonl(info->origin->tid);
776     if (0 != info->size && NULL != info->data) {
777         memcpy(&msg[1], info->data, info->size);
778     }
779     GNUNET_free(info);
780     return total_size;
781 }
782
783 /**
784  * Function called to notify a client about the socket
785  * being ready to queue more data.  "buf" will be
786  * NULL and "size" zero if the socket was closed for
787  * writing in the meantime.
788  *
789  * @param cls closure (data itself)
790  * @param size number of bytes available in buf
791  * @param buf where the callee should write the message
792  * @return number of bytes written to buf
793  */
794 static size_t
795 send_core_data_raw (void *cls, size_t size, void *buf)
796 {
797     struct GNUNET_MessageHeader *msg = cls;
798     size_t                      total_size;
799
800     GNUNET_assert(NULL != msg);
801     total_size = ntohs(msg->size);
802
803     if (total_size > size) {
804         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
805                    "not enough buffer to send data futher\n");
806         return 0;
807     }
808     memcpy(buf, msg, total_size);
809     return total_size;
810 }
811
812
813 #if LATER
814 /**
815  * Function called to notify a client about the socket
816  * being ready to queue more data.  "buf" will be
817  * NULL and "size" zero if the socket was closed for
818  * writing in the meantime.
819  *
820  * @param cls closure (data itself)
821  * @param size number of bytes available in buf
822  * @param buf where the callee should write the message
823  * @return number of bytes written to buf
824  */
825 static size_t
826 send_core_data_multicast (void *cls, size_t size, void *buf)
827 {
828     struct GNUNET_MESH_DataMessageFromOrigin    *msg = cls;
829     size_t                                      total_size;
830
831     GNUNET_assert(NULL != msg);
832     total_size = ntohs(msg->header.size);
833
834     if (total_size > size) {
835         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
836                    "not enough buffer to send data futher\n");
837         return 0;
838     }
839     memcpy(msg, buf, total_size);
840     return total_size;
841 }
842
843
844 /**
845  * Function called to notify a client about the socket
846  * being ready to queue more data.  "buf" will be
847  * NULL and "size" zero if the socket was closed for
848  * writing in the meantime.
849  *
850  * @param cls closure (data itself)
851  * @param size number of bytes available in buf
852  * @param buf where the callee should write the message
853  * @return number of bytes written to buf
854  */
855 static size_t
856 send_core_data_to_peer (void *cls, size_t size, void *buf)
857 {
858     struct info_for_data_to_origin              *info = cls;
859     struct GNUNET_MESH_DataMessageToOrigin      *msg = buf;
860     size_t                                      total_size;
861
862     GNUNET_assert(NULL != info);
863     total_size = sizeof(struct GNUNET_MESH_DataMessageToOrigin) + info->size;
864     /* FIXME better constant? short >= 16 bits, not == 16 bits... */
865     GNUNET_assert(total_size < USHRT_MAX);
866
867     if (total_size > size) {
868         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
869                    "not enough buffer to send data to origin\n");
870         return 0;
871     }
872     msg->header.size = htons(total_size);
873     msg->header.type = htons(GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN);
874     GNUNET_PEER_resolve(info->origin->oid, &msg->oid);
875     msg->tid = htonl(info->origin->tid);
876     if (0 != info->size && NULL != info->data) {
877         memcpy(&msg[1], info->data, info->size);
878     }
879     GNUNET_free(info);
880     return total_size;
881 }
882
883
884 /**
885  * Send another peer a notification to destroy a tunnel
886  * @param cls The tunnel to destroy
887  * @param size Size in the buffer
888  * @param buf Memory where to put the data to transmit
889  * @return Size of data put in buffer
890  */
891 static size_t
892 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
893 {
894     struct MeshTunnel                   *t = cls;
895     struct MeshClient                   *c;
896     struct GNUNET_MESH_TunnelMessage    *msg;
897
898     c = t->client;
899     msg = buf;
900     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
901     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
902     msg->tunnel_id = htonl(t->id.tid);
903
904     destroy_tunnel(c, t);
905     return sizeof(struct GNUNET_MESH_TunnelMessage);
906 }
907 #endif
908
909
910 /**
911  * Function called to notify a client about the socket
912  * begin ready to queue more data.  "buf" will be
913  * NULL and "size" zero if the socket was closed for
914  * writing in the meantime.
915  *
916  * @param cls closure
917  * @param size number of bytes available in buf
918  * @param buf where the callee should write the message
919  * @return number of bytes written to buf
920  */
921 size_t
922 send_client_raw (void *cls, size_t size, void *buf)
923 {
924     struct GNUNET_MessageHeader *msg = cls;
925     size_t                      msg_size;
926
927     msg_size = ntohs(msg->size);
928     if (msg_size > size) {
929         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
930                    "deliver to client failed: buffer too small\n");
931         return 0;
932     }
933     memcpy(buf, cls, msg_size);
934     return msg_size;
935 }
936
937
938 /**
939  * Iterator over hash map peer entries to resend a data packet to all peers
940  * down the tunnel.
941  *
942  * @param cls closure (original message)
943  * @param key current key code (peer id hash)
944  * @param value value in the hash map (peer_info)
945  * @return GNUNET_YES if we should continue to iterate, GNUNET_NO if not.
946  */
947 static int iterate_resend_multicast (void *cls,
948                                      const GNUNET_HashCode * key,
949                                      void *value)
950 {
951     struct GNUNET_MESH_DataMessageMulticast     *msg = cls;
952     struct GNUNET_PeerIdentity                  id;
953     struct MeshPeerInfo                         *peer_info = value;
954
955     if (peer_info->id == myid) {
956 //         TODO retransmit to interested clients
957         return GNUNET_YES;
958     }
959     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
960     GNUNET_CORE_notify_transmit_ready(core_handle,
961                                       0,
962                                       0,
963                                       GNUNET_TIME_UNIT_FOREVER_REL,
964                                       &id,
965                                       ntohs(msg->header.size),
966                                       &send_core_data_raw,
967                                       msg);
968     return GNUNET_YES;
969 }
970
971
972 /******************************************************************************/
973 /********************      MESH NETWORK HANDLERS     **************************/
974 /******************************************************************************/
975
976
977 /**
978  * Core handler for path creation
979  * struct GNUNET_CORE_MessageHandler
980  *
981  * @param cls closure
982  * @param message message
983  * @param peer peer identity this notification is about
984  * @param atsi performance data
985  * @return GNUNET_OK to keep the connection open,
986  *         GNUNET_SYSERR to close it (signal serious error)
987  *
988  */
989 static int
990 handle_mesh_path_create (void *cls,
991                               const struct GNUNET_PeerIdentity *peer,
992                               const struct GNUNET_MessageHeader *message,
993                               const struct GNUNET_TRANSPORT_ATS_Information
994                               *atsi)
995 {
996     unsigned int                        own_pos;
997     uint16_t                            size;
998     uint16_t                            i;
999     MESH_TunnelNumber                   tid;
1000     struct GNUNET_MESH_ManipulatePath   *msg;
1001     struct GNUNET_PeerIdentity          *pi;
1002     struct GNUNET_PeerIdentity          id;
1003     GNUNET_HashCode                     hash;
1004     struct MeshPath                     *path;
1005     struct MeshPeerInfo                 *dest_peer_info;
1006     struct MeshPeerInfo                 *orig_peer_info;
1007     struct MeshTunnel                   *t;
1008
1009
1010     size = ntohs(message->size);
1011     if (size < sizeof(struct GNUNET_MESH_ManipulatePath)) {
1012         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1013                    "received create path message too short\n");
1014         return GNUNET_OK;
1015     }
1016
1017     size -= sizeof(struct GNUNET_MESH_ManipulatePath);
1018     if (size < 2 * sizeof(struct GNUNET_PeerIdentity)) {
1019         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1020                    "create path message lacks enough peers\n");
1021         return GNUNET_OK;
1022     }
1023     if (size % sizeof(struct GNUNET_PeerIdentity)) {
1024         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1025                    "create path message of wrong size\n");
1026         return GNUNET_OK;
1027     }
1028     msg = (struct GNUNET_MESH_ManipulatePath *) message;
1029     size /= sizeof(struct GNUNET_PeerIdentity);
1030
1031     tid = ntohl(msg->tid);
1032     pi = (struct GNUNET_PeerIdentity *) &msg[1];
1033     t = retrieve_tunnel(pi, tid);
1034
1035     if (NULL == t) {
1036         t = GNUNET_malloc(sizeof(struct MeshTunnel));
1037         t->id.oid = GNUNET_PEER_intern(pi);
1038         t->id.tid = tid;
1039         t->local_tid = 0;
1040         t->client = NULL;
1041         t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1042
1043         GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1044         if (GNUNET_OK !=
1045             GNUNET_CONTAINER_multihashmap_put(tunnels,
1046                             &hash,
1047                             t,
1048                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1049         {
1050             GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1051                    "create path: could not store tunnel in hashmap\n");
1052             return GNUNET_OK;
1053         }
1054
1055     }
1056     dest_peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
1057                                                   &pi[size - 1].hashPubKey);
1058     if (NULL == dest_peer_info) {
1059         dest_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1060         dest_peer_info->id = GNUNET_PEER_intern(&pi[size - 1]);
1061         dest_peer_info->state = MESH_PEER_WAITING;
1062         GNUNET_CONTAINER_multihashmap_put(peers,
1063                             &pi[size - 1].hashPubKey,
1064                             dest_peer_info,
1065                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1066     }
1067     orig_peer_info = GNUNET_CONTAINER_multihashmap_get(peers, &pi->hashPubKey);
1068     if (NULL == orig_peer_info) {
1069         orig_peer_info = GNUNET_malloc(sizeof(struct MeshPeerInfo));
1070         orig_peer_info->id = GNUNET_PEER_intern(pi);
1071         orig_peer_info->state = MESH_PEER_WAITING;
1072         GNUNET_CONTAINER_multihashmap_put(peers,
1073                             &pi->hashPubKey,
1074                             orig_peer_info,
1075                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1076     }
1077
1078
1079     path = GNUNET_malloc(sizeof(struct MeshPath));
1080     path->length = size;
1081     path->peers = GNUNET_malloc(size * sizeof(GNUNET_PEER_Id));
1082     own_pos = 0;
1083     for (i = 0; i < size; i++) {
1084         path->peers[i] = GNUNET_PEER_intern(&pi[i]);
1085         if (path->peers[i] == myid) own_pos = i;
1086     }
1087     if (own_pos == 0) { /* cannot be self, must be 'not found' */
1088         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1089                    "create path: self not found in path through self\n");
1090         destroy_path(path);
1091         /* FIXME error. destroy tunnel? leave for timeout? */
1092         return 0;
1093     }
1094     if (own_pos == size - 1) { /* it is for us! */
1095         add_path_to_origin(orig_peer_info, path);           /* inverts path!  */
1096         GNUNET_PEER_resolve(get_first_hop(path), &id); /* path is inverted :) */
1097         /* FIXME / COMMENT 
1098          * is it allowed/desired to declare variables this way?
1099          * (style, best practices, etc)
1100          * This variable is short lived and completely irrelevant for the rest
1101          * of the function
1102          */
1103         struct info_for_data_to_origin *info =
1104             GNUNET_malloc(sizeof(struct info_for_data_to_origin));
1105         info->origin = &t->id;
1106         info->data = NULL;
1107         info->size = 0;
1108         GNUNET_CORE_notify_transmit_ready(core_handle,
1109                                 0,
1110                                 0,
1111                                 GNUNET_TIME_UNIT_FOREVER_REL,
1112                                 &id,
1113                                 sizeof(struct GNUNET_MessageHeader),
1114                                 &send_core_data_to_origin,
1115                                 info);
1116     } else {
1117         add_path_to_peer(dest_peer_info, path);
1118         GNUNET_PEER_resolve(get_first_hop(path), &id);
1119         GNUNET_CORE_notify_transmit_ready(core_handle,
1120                                 0,
1121                                 0,
1122                                 GNUNET_TIME_UNIT_FOREVER_REL,
1123                                 &id,
1124                                 sizeof(struct GNUNET_MessageHeader),
1125                                 &send_core_create_path_for_peer,
1126                                 dest_peer_info);
1127     }
1128     return GNUNET_OK;
1129 }
1130
1131
1132 /**
1133  * Core handler for mesh network traffic going from the origin to a peer
1134  *
1135  * @param cls closure
1136  * @param message message
1137  * @param peer peer identity this notification is about
1138  * @param atsi performance data
1139  * @return GNUNET_OK to keep the connection open,
1140  *         GNUNET_SYSERR to close it (signal serious error)
1141  */
1142 static int
1143 handle_mesh_data_unicast (void *cls,
1144                           const struct GNUNET_PeerIdentity *peer,
1145                           const struct GNUNET_MessageHeader *message,
1146                           const struct GNUNET_TRANSPORT_ATS_Information
1147                           *atsi)
1148 {
1149     struct GNUNET_MESH_DataMessageFromOrigin    *msg;
1150     struct GNUNET_PeerIdentity                  id;
1151     struct MeshTunnel                           *t;
1152     struct MeshPeerInfo                         *pi;
1153     struct MeshClient                           *c;
1154     size_t                                      size;
1155     uint16_t                                    payload_type;
1156
1157     size = ntohs(message->size);
1158     if (size < sizeof(struct GNUNET_MESH_DataMessageFromOrigin)) {
1159         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1160                 "got data from origin packet: too short\n");
1161         return GNUNET_OK; // FIXME maybe SYSERR? peer misbehaving?
1162     }
1163     msg = (struct GNUNET_MESH_DataMessageFromOrigin *) message;
1164     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1165     if (NULL == t) {
1166         /* TODO: are we so nice that we try to send it to OID anyway? We *could*
1167          * know how to reach it, from the global peer hashmap
1168          */
1169         return GNUNET_OK;
1170     }
1171     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
1172                                         &msg->destination.hashPubKey);
1173     if (NULL == pi) {
1174         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1175                    "got invalid data from origin packet: wrong destination\n");
1176         /* TODO are we so nice to try to deliver it anyway? maybe we missed
1177          * a Create_Path packet that added the peer but we have it in the
1178          * _global_ peer pool anyway...
1179          */
1180         return GNUNET_OK;
1181     }
1182     if (pi->id == myid) {
1183         payload_type = ntohs(msg[1].header.type);
1184         for (c = clients; NULL != c; c = c->next) {
1185             if (is_client_subscribed(payload_type, c)) {
1186                 GNUNET_SERVER_notify_transmit_ready(c->handle,
1187                     size - sizeof(struct GNUNET_MESH_DataMessageFromOrigin),
1188                     GNUNET_TIME_UNIT_FOREVER_REL,
1189                     send_client_raw,
1190                     &msg[1]);
1191             }
1192         }
1193         return GNUNET_OK;
1194     }
1195     GNUNET_PEER_resolve(get_first_hop(pi->path), &id);
1196     GNUNET_CORE_notify_transmit_ready(core_handle,
1197         0,
1198         0,
1199         GNUNET_TIME_UNIT_FOREVER_REL,
1200         &id,
1201         size,
1202         &send_core_data_raw,
1203         msg);
1204     return GNUNET_OK;
1205 }
1206
1207
1208 /**
1209  * Core handler for mesh network traffic going from the origin to all peers
1210  *
1211  * @param cls closure
1212  * @param message message
1213  * @param peer peer identity this notification is about
1214  * @param atsi performance data
1215  * @return GNUNET_OK to keep the connection open,
1216  *         GNUNET_SYSERR to close it (signal serious error)
1217  */
1218 static int
1219 handle_mesh_data_multicast (void *cls,
1220                           const struct GNUNET_PeerIdentity *peer,
1221                           const struct GNUNET_MessageHeader *message,
1222                           const struct GNUNET_TRANSPORT_ATS_Information
1223                           *atsi)
1224 {
1225     struct GNUNET_MESH_DataMessageMulticast    *msg;
1226     struct MeshTunnel                           *t;
1227     size_t                                      size;
1228
1229     size = ntohs(message->size);
1230     if (size < sizeof(struct GNUNET_MESH_DataMessageMulticast)) {
1231         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1232                 "got multicast packet: too short\n");
1233         return GNUNET_OK; // FIXME maybe SYSERR? peer misbehaving?
1234     }
1235     msg = (struct GNUNET_MESH_DataMessageMulticast *) message;
1236     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1237
1238     if (NULL == t) {
1239         return GNUNET_OK;
1240     }
1241
1242     GNUNET_CONTAINER_multihashmap_iterate(t->peers,
1243                                           &iterate_resend_multicast,
1244                                           msg);
1245
1246     return GNUNET_OK;
1247 }
1248
1249
1250 /**
1251  * Core handler for mesh network traffic
1252  *
1253  * @param cls closure
1254  * @param message message
1255  * @param peer peer identity this notification is about
1256  * @param atsi performance data
1257  * @return GNUNET_OK to keep the connection open,
1258  *         GNUNET_SYSERR to close it (signal serious error)
1259  */
1260 static int
1261 handle_mesh_data_to_orig (void *cls,
1262                           const struct GNUNET_PeerIdentity *peer,
1263                           const struct GNUNET_MessageHeader *message,
1264                           const struct GNUNET_TRANSPORT_ATS_Information
1265                           *atsi)
1266 {
1267     struct GNUNET_MESH_DataMessageToOrigin      *msg;
1268     struct GNUNET_PeerIdentity                  id;
1269     struct MeshTunnel                           *t;
1270     struct MeshPeerInfo                         *peer_info;
1271     size_t                                      size;
1272
1273     size = ntohs(message->size);
1274     if (size < sizeof(struct GNUNET_MESH_DataMessageToOrigin)) {
1275         GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1276                 "got invalid data to origin packet: too short\n");
1277         return GNUNET_OK; // FIXME maybe SYSERR? peer misbehaving?
1278     }
1279     msg = (struct GNUNET_MESH_DataMessageToOrigin *) message;
1280     t = retrieve_tunnel(&msg->oid, ntohl(msg->tid));
1281
1282     if (NULL == t) {
1283         /* TODO: are we so nice that we try to send it to OID anyway? We *could*
1284          * know how to reach it, from the global peer hashmap
1285          */
1286         return GNUNET_OK;
1287     }
1288
1289     if (t->id.oid == myid) {
1290         if (NULL == t->client) {
1291             GNUNET_log(GNUNET_ERROR_TYPE_WARNING,
1292                 "got data packet for ownerless tunnel\n");
1293             return GNUNET_OK;
1294         }
1295         //         TODO retransmit to client owner
1296         return GNUNET_OK;
1297     }
1298     peer_info = get_peer_info(&msg->oid);
1299     if (NULL == peer_info) {
1300         GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1301                 "unknown origin of tunnel\n");
1302         return GNUNET_OK;
1303     }
1304     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1305     GNUNET_CORE_notify_transmit_ready(core_handle,
1306                                       0,
1307                                       0,
1308                                       GNUNET_TIME_UNIT_FOREVER_REL,
1309                                       &id,
1310                                       size,
1311                                       &send_core_data_raw,
1312                                       msg);
1313
1314     return GNUNET_OK;
1315 }
1316
1317
1318 /**
1319  * Functions to handle messages from core
1320  */
1321 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1322   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
1323   {&handle_mesh_data_unicast, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN, 0},
1324   {&handle_mesh_data_multicast, GNUNET_MESSAGE_TYPE_DATA_MULTICAST, 0},
1325   {&handle_mesh_data_to_orig, GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN, 0},
1326   {NULL, 0, 0}
1327 };
1328
1329
1330
1331 /******************************************************************************/
1332 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
1333 /******************************************************************************/
1334
1335 /**
1336  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
1337  * client when the client disconnects.
1338  * @param cls closure (client that is disconnecting)
1339  * @param key the hash of the local tunnel id (used to access the hashmap)
1340  * @param value the value stored at the key (tunnel to destroy)
1341  * @return GNUNET_OK on success
1342  */
1343 static int
1344 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
1345     int r;
1346     r = destroy_tunnel((struct MeshTunnel *) value);
1347     return r;
1348 }
1349
1350 #if LATER
1351 /**
1352  * notify_client_connection_failure: notify a client that the connection to the
1353  * requested remote peer is not possible (for instance, no route found)
1354  * Function called when the socket is ready to queue more data. "buf" will be
1355  * NULL and "size" zero if the socket was closed for writing in the meantime.
1356  *
1357  * @param cls closure
1358  * @param size number of bytes available in buf
1359  * @param buf where the callee should write the message
1360  * @return number of bytes written to buf
1361  */
1362 static size_t
1363 notify_client_connection_failure (void *cls, size_t size, void *buf)
1364 {
1365     int                                 size_needed;
1366     struct MeshPeerInfo                 *peer_info;
1367     struct GNUNET_MESH_PeerControl      *msg;
1368     struct GNUNET_PeerIdentity          id;
1369
1370     if (0 == size && NULL == buf) {
1371         // TODO retry? cancel?
1372         return 0;
1373     }
1374
1375     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
1376     peer_info = (struct MeshPeerInfo *) cls;
1377     msg = (struct GNUNET_MESH_PeerControl *) buf;
1378     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
1379     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
1380 //     msg->tunnel_id = htonl(peer_info->t->tid);
1381     GNUNET_PEER_resolve(peer_info->id, &id);
1382     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
1383
1384     return size_needed;
1385 }
1386 #endif
1387
1388
1389 /**
1390  * Send keepalive packets for a peer
1391  *
1392  * @param cls unused
1393  * @param tc unused
1394  */
1395 static void
1396 path_refresh (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1397 {
1398     struct MeshPeerInfo         *peer_info = cls;
1399     struct GNUNET_PeerIdentity  id;
1400
1401     if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN) return;
1402     GNUNET_PEER_resolve(get_first_hop(peer_info->path), &id);
1403     GNUNET_CORE_notify_transmit_ready(core_handle,
1404                                 0,
1405                                 0,
1406                                 GNUNET_TIME_UNIT_FOREVER_REL,
1407                                 &id,
1408                                 sizeof(struct GNUNET_MESH_ManipulatePath)
1409                                 + (peer_info->path->length
1410                                 * sizeof (struct GNUNET_PeerIdentity)),
1411                                 &send_core_create_path_for_peer,
1412                                 peer_info);
1413
1414     return;
1415 }
1416
1417
1418 /**
1419  * Function to process paths received for a new peer addition. The recorded
1420  * paths form the initial tunnel, which can be optimized later.
1421  * Called on each result obtained for the DHT search.
1422  *
1423  * @param cls closure
1424  * @param exp when will this value expire
1425  * @param key key of the result
1426  * @param get_path NULL-terminated array of pointers
1427  *                 to the peers on reverse GET path (or NULL if not recorded)
1428  * @param put_path NULL-terminated array of pointers
1429  *                 to the peers on the PUT path (or NULL if not recorded)
1430  * @param type type of the result
1431  * @param size number of bytes in data
1432  * @param data pointer to the result data
1433  */
1434 static void
1435 dht_get_response_handler(void *cls,
1436                         struct GNUNET_TIME_Absolute exp,
1437                         const GNUNET_HashCode * key,
1438                         const struct GNUNET_PeerIdentity * const *get_path,
1439                         const struct GNUNET_PeerIdentity * const *put_path,
1440                         enum GNUNET_BLOCK_Type type,
1441                         size_t size,
1442                         const void *data)
1443 {
1444     struct MeshPeerInfo         *peer_info = cls;
1445     struct MeshPath             *p;
1446     struct GNUNET_PeerIdentity  pi;
1447     int                         i;
1448
1449     if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
1450         // Find ourselves some alternate initial path to the destination: retry
1451         GNUNET_DHT_get_stop(peer_info->dhtget);
1452         GNUNET_PEER_resolve(peer_info->id, &pi);
1453         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1454                                     GNUNET_TIME_UNIT_FOREVER_REL,
1455                                     GNUNET_BLOCK_TYPE_ANY,
1456                                     &pi.hashPubKey,
1457                                     4,    /* replication level */
1458                                     GNUNET_DHT_RO_RECORD_ROUTE,
1459                                     NULL, /* bloom filter */
1460                                     0,    /* mutator */
1461                                     NULL, /* xquery */
1462                                     0,    /* xquery bits */
1463                                     dht_get_response_handler,
1464                                     (void *)peer_info);
1465     }
1466
1467     p = GNUNET_malloc(sizeof(struct MeshPath));
1468     for (i = 0; get_path[i] != NULL; i++);
1469     for (i--; i >= 0; i--) {
1470         p->peers = GNUNET_realloc(p->peers,
1471                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
1472         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
1473         p->length++;
1474     }
1475     for (i = 0; put_path[i] != NULL; i++);
1476     for (i--; i >= 0; i--) {
1477         p->peers = GNUNET_realloc(p->peers,
1478                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
1479         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
1480         p->length++;
1481     }
1482     add_path_to_peer(peer_info, p);
1483     GNUNET_CORE_notify_transmit_ready(core_handle,
1484                                       0,
1485                                       0,
1486                                       GNUNET_TIME_UNIT_FOREVER_REL,
1487                                       get_path[1],
1488                                       sizeof(struct GNUNET_MESH_ManipulatePath)
1489                                         + (p->length
1490                                         * sizeof (struct GNUNET_PeerIdentity)),
1491                                       &send_core_create_path_for_peer,
1492                                       peer_info);
1493     GNUNET_SCHEDULER_add_delayed(REFRESH_PATH_TIME, &path_refresh, peer_info);
1494     return;
1495 }
1496
1497
1498 /******************************************************************************/
1499 /*********************       MESH LOCAL HANDLES      **************************/
1500 /******************************************************************************/
1501
1502
1503 /**
1504  * Handler for client disconnection
1505  *
1506  * @param cls closure
1507  * @param client identification of the client; NULL
1508  *        for the last call when the server is destroyed
1509  */
1510 static void
1511 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
1512 {
1513     struct MeshClient   *c;
1514     struct MeshClient   *next;
1515
1516     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1517                "client disconnected\n");
1518     c = clients;
1519     while (NULL != c) {
1520         if (c->handle == client) {
1521             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1522                " matching client found, cleaning\n");
1523             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
1524                                                   &delete_tunnel_entry,
1525                                                   c);
1526             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
1527             if(0 != c->app_counter) GNUNET_free (c->apps);
1528             if(0 != c->type_counter) GNUNET_free (c->types);
1529             GNUNET_CONTAINER_DLL_remove(clients, clients_tail, c);
1530             next = c->next;
1531             GNUNET_free (c);
1532             c = next;
1533         } else {
1534             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1535                "   ... searching\n");
1536             c = c->next;
1537         }
1538     }
1539     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1540                "   done!\n");
1541     return;
1542 }
1543
1544
1545 /**
1546  * Handler for new clients
1547  * 
1548  * @param cls closure
1549  * @param client identification of the client
1550  * @param message the actual message, which includes messages the client wants
1551  */
1552 static void
1553 handle_local_new_client (void *cls,
1554                          struct GNUNET_SERVER_Client *client,
1555                          const struct GNUNET_MessageHeader *message)
1556 {
1557     struct GNUNET_MESH_ClientConnect    *cc_msg;
1558     struct MeshClient                   *c;
1559     unsigned int                        size;
1560     uint16_t                            types;
1561     uint16_t                            apps;
1562
1563     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "new client connected\n");
1564     /* Check data sanity */
1565     size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
1566     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
1567     types = ntohs(cc_msg->types);
1568     apps = ntohs(cc_msg->applications);
1569     if (size !=
1570         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
1571     {
1572         GNUNET_break(0);
1573         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1574         return;
1575     }
1576
1577     /* Create new client structure */
1578     c = GNUNET_malloc(sizeof(struct MeshClient));
1579     c->handle = client;
1580     if (types != 0) {
1581         c->type_counter = types;
1582         c->types = GNUNET_malloc(types * sizeof(uint16_t));
1583         memcpy(c->types, &message[1], types * sizeof(uint16_t));
1584     }
1585     if (apps != 0) {
1586         c->app_counter = apps;
1587         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
1588         memcpy(c->apps,
1589                &message[1] + types * sizeof(uint16_t),
1590                apps * sizeof(GNUNET_MESH_ApplicationType));
1591     }
1592     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1593                " client has %u+%u subscriptions\n",
1594                c->type_counter,
1595                c->app_counter);
1596
1597     GNUNET_CONTAINER_DLL_insert(clients, clients_tail, c);
1598     c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1599
1600     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1601
1602 }
1603
1604
1605 /**
1606  * Handler for requests of new tunnels
1607  * 
1608  * @param cls closure
1609  * @param client identification of the client
1610  * @param message the actual message
1611  */
1612 static void
1613 handle_local_tunnel_create (void *cls,
1614                             struct GNUNET_SERVER_Client *client,
1615                             const struct GNUNET_MessageHeader *message)
1616 {
1617     struct GNUNET_MESH_TunnelMessage    *t_msg;
1618     struct MeshTunnel                   *t;
1619     struct MeshClient                   *c;
1620     GNUNET_HashCode                     hash;
1621
1622     /* Sanity check for client registration */
1623     if (NULL == (c = retrieve_client(client))) {
1624         GNUNET_break(0);
1625         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1626         return;
1627     }
1628
1629     /* Message sanity check */
1630     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1631         GNUNET_break(0);
1632         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1633         return;
1634     }
1635
1636     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1637     /* Sanity check for tunnel numbering */
1638     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
1639         GNUNET_break(0);
1640         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1641         return;
1642     }
1643     /* Sanity check for duplicate tunnel IDs */
1644     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
1645         GNUNET_break(0);
1646         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1647         return;
1648     }
1649
1650     t = GNUNET_malloc(sizeof(struct MeshTunnel));
1651     while (NULL != retrieve_tunnel_by_pi(myid, next_tid))
1652         next_tid = (next_tid + 1) % GNUNET_MESH_LOCAL_TUNNEL_ID_MARK;
1653     t->id.tid = next_tid++;
1654     t->id.oid = myid;
1655     t->local_tid = ntohl(t_msg->tunnel_id);
1656     t->client = c;
1657     t->peers = GNUNET_CONTAINER_multihashmap_create(32);
1658
1659     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
1660     if (GNUNET_OK !=
1661         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
1662                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1663     {
1664         GNUNET_break(0);
1665         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1666         return;
1667     }
1668
1669     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1670     if (GNUNET_OK !=
1671         GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
1672                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
1673     {
1674         GNUNET_break(0);
1675         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1676         return;
1677     }
1678
1679     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1680     return;
1681 }
1682
1683
1684 /**
1685  * Handler for requests of deleting tunnels
1686  * 
1687  * @param cls closure
1688  * @param client identification of the client
1689  * @param message the actual message
1690  */
1691 static void
1692 handle_local_tunnel_destroy (void *cls,
1693                              struct GNUNET_SERVER_Client *client,
1694                              const struct GNUNET_MessageHeader *message)
1695 {
1696     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
1697     struct MeshClient                   *c;
1698     struct MeshTunnel                   *t;
1699     MESH_TunnelNumber                   tid;
1700     GNUNET_HashCode                     hash;
1701
1702
1703     /* Sanity check for client registration */
1704     if (NULL == (c = retrieve_client(client))) {
1705         GNUNET_break(0);
1706         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1707         return;
1708     }
1709     /* Message sanity check */
1710     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
1711         GNUNET_break(0);
1712         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1713         return;
1714     }
1715
1716     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
1717
1718     /* Retrieve tunnel */
1719     tid = ntohl(tunnel_msg->tunnel_id);
1720
1721     /* Remove from local id hashmap */
1722     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1723     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1724     GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1725
1726     /* Remove from global id hashmap */
1727     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1728     GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1729
1730 //     notify_tunnel_destroy(t);
1731     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1732     return;
1733 }
1734
1735
1736 /**
1737  * Handler for connection requests to new peers
1738  * 
1739  * @param cls closure
1740  * @param client identification of the client
1741  * @param message the actual message (PeerControl)
1742  */
1743 static void
1744 handle_local_connect_add (void *cls,
1745                           struct GNUNET_SERVER_Client *client,
1746                           const struct GNUNET_MessageHeader *message)
1747 {
1748     struct GNUNET_MESH_PeerControl      *peer_msg;
1749     struct MeshClient                   *c;
1750     struct MeshTunnel                   *t;
1751     MESH_TunnelNumber                   tid;
1752     struct MeshPeerInfo                 *peer_info;
1753
1754
1755     /* Sanity check for client registration */
1756     if (NULL == (c = retrieve_client(client))) {
1757         GNUNET_break(0);
1758         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1759         return;
1760     }
1761
1762     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1763     /* Sanity check for message size */
1764     if (sizeof(struct GNUNET_MESH_PeerControl)
1765         != ntohs(peer_msg->header.size))
1766     {
1767         GNUNET_break(0);
1768         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1769         return;
1770     }
1771
1772     /* Tunnel exists? */
1773     tid = ntohl(peer_msg->tunnel_id);
1774     t = retrieve_tunnel_by_local_id(c, tid);
1775     if (NULL == t) {
1776         GNUNET_break(0);
1777         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1778         return;
1779     }
1780
1781     /* Does client own tunnel? */
1782     if (t->client->handle != client) {
1783         GNUNET_break(0);
1784         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1785         return;
1786     }
1787
1788     t->peers_total++;
1789     peer_info = get_peer_info(&peer_msg->peer);
1790
1791     /* Start DHT search if needed */
1792     if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
1793         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1794                                             GNUNET_TIME_UNIT_FOREVER_REL,
1795                                             GNUNET_BLOCK_TYPE_ANY,
1796                                             &peer_msg->peer.hashPubKey,
1797                                             4,    /* replication level */
1798                                             GNUNET_DHT_RO_RECORD_ROUTE,
1799                                             NULL, /* bloom filter */
1800                                             0,    /* mutator */
1801                                             NULL, /* xquery */
1802                                             0,    /* xquery bits */
1803                                             dht_get_response_handler,
1804                                             (void *)peer_info);
1805     }
1806
1807     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1808     return;
1809 }
1810
1811
1812 /**
1813  * Handler for disconnection requests of peers in a tunnel
1814  * 
1815  * @param cls closure
1816  * @param client identification of the client
1817  * @param message the actual message (PeerControl)
1818  */
1819 static void
1820 handle_local_connect_del (void *cls,
1821                           struct GNUNET_SERVER_Client *client,
1822                           const struct GNUNET_MessageHeader *message)
1823 {
1824     struct GNUNET_MESH_PeerControl      *peer_msg;
1825     struct MeshClient                   *c;
1826     struct MeshTunnel                   *t;
1827     MESH_TunnelNumber                   tid;
1828
1829     /* Sanity check for client registration */
1830     if (NULL == (c = retrieve_client(client))) {
1831         GNUNET_break(0);
1832         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1833         return;
1834     }
1835     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1836     /* Sanity check for message size */
1837     if (sizeof(struct GNUNET_MESH_PeerControl)
1838         != ntohs(peer_msg->header.size))
1839     {
1840         GNUNET_break(0);
1841         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1842         return;
1843     }
1844
1845     /* Tunnel exists? */
1846     tid = ntohl(peer_msg->tunnel_id);
1847     t = retrieve_tunnel_by_local_id(c, tid);
1848     if (NULL == t) {
1849             GNUNET_break(0);
1850             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1851             return;
1852         }
1853
1854     /* Does client own tunnel? */
1855     if (t->client->handle != client) {
1856         GNUNET_break(0);
1857         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1858         return;
1859     }
1860
1861     /* Ok, delete peer from tunnel */
1862     GNUNET_CONTAINER_multihashmap_remove_all(t->peers,
1863                                              &peer_msg->peer.hashPubKey);
1864
1865     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1866     return;
1867 }
1868
1869
1870 /**
1871  * Handler for connection requests to new peers by type
1872  * 
1873  * @param cls closure
1874  * @param client identification of the client
1875  * @param message the actual message (ConnectPeerByType)
1876  */
1877 static void
1878 handle_local_connect_by_type (void *cls,
1879                               struct GNUNET_SERVER_Client *client,
1880                               const struct GNUNET_MessageHeader *message)
1881 {
1882     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1883     MESH_TunnelNumber                           tid;
1884     GNUNET_MESH_ApplicationType                 application;
1885     struct MeshClient                           *c;
1886     struct MeshTunnel                           *t;
1887
1888     /* Sanity check for client registration */
1889     if (NULL == (c = retrieve_client(client))) {
1890         GNUNET_break(0);
1891         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1892         return;
1893     }
1894
1895     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1896     /* Sanity check for message size */
1897     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1898             ntohs(connect_msg->header.size))
1899     {
1900         GNUNET_break(0);
1901         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1902         return;
1903     }
1904
1905     /* Tunnel exists? */
1906     tid = ntohl(connect_msg->tunnel_id);
1907     t = retrieve_tunnel_by_local_id(c, tid);
1908     if (NULL == t) {
1909         GNUNET_break(0);
1910         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1911         return;
1912     }
1913
1914     /* Does client own tunnel? */
1915     if (t->client->handle != client) {
1916         GNUNET_break(0);
1917         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1918         return;
1919     }
1920
1921     /* Ok, lets find a peer offering the service */
1922     application = ntohl(connect_msg->type);
1923     application++; // FIXME silence warnings
1924
1925     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1926     return;
1927 }
1928
1929
1930 /**
1931  * Handler for client traffic directed to one peer
1932  * 
1933  * @param cls closure
1934  * @param client identification of the client
1935  * @param message the actual message
1936  */
1937 static void
1938 handle_local_network_traffic (void *cls,
1939                          struct GNUNET_SERVER_Client *client,
1940                          const struct GNUNET_MessageHeader *message)
1941 {
1942     struct MeshClient                           *c;
1943     struct MeshTunnel                           *t;
1944     struct MeshPeerInfo                         *pi;
1945     struct GNUNET_MESH_Data                     *data_msg;
1946     struct GNUNET_PeerIdentity                  next_hop;
1947     MESH_TunnelNumber                           tid;
1948
1949     /* Sanity check for client registration */
1950     if (NULL == (c = retrieve_client(client))) {
1951         GNUNET_break(0);
1952         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1953         return;
1954     }
1955     data_msg = (struct GNUNET_MESH_Data *)message;
1956     /* Sanity check for message size */
1957     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1958             ntohs(data_msg->header.size))
1959     {
1960         GNUNET_break(0);
1961         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1962         return;
1963     }
1964
1965     /* Tunnel exists? */
1966     tid = ntohl(data_msg->tunnel_id);
1967     t = retrieve_tunnel_by_local_id(c, tid);
1968     if (NULL == t) {
1969         GNUNET_break(0);
1970         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1971         return;
1972     }
1973
1974     /*  Is it a local tunnel? Then, does client own the tunnel? */
1975     if (t->client->handle != NULL && t->client->handle != client) {
1976         GNUNET_break(0);
1977         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1978         return;
1979     }
1980
1981     pi = GNUNET_CONTAINER_multihashmap_get(t->peers,
1982                                            &data_msg->peer_id.hashPubKey);
1983     /* Is the selected peer in the tunnel? */
1984     if (NULL == pi) {
1985         /* TODO
1986          * Are we SO nice that we automatically try to add him to the tunnel?
1987          */
1988         GNUNET_break(0);
1989         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1990         return;
1991     }
1992     GNUNET_PEER_resolve(get_first_hop(pi->path), &next_hop);
1993     GNUNET_CORE_notify_transmit_ready(core_handle,
1994                             0,
1995                             0,
1996                             GNUNET_TIME_UNIT_FOREVER_REL,
1997                             &next_hop,
1998                             /* FIXME re-check types */
1999                             message->size - sizeof(struct GNUNET_MESH_Data)
2000                             + sizeof(struct GNUNET_MESH_DataMessageFromOrigin),
2001                             &send_core_data_to_origin, /* FIXME re-check */
2002                             NULL);
2003
2004     GNUNET_SERVER_receive_done(client, GNUNET_OK); /* FIXME not yet */
2005     return;
2006 }
2007
2008 /**
2009  * Handler for client traffic directed to all peers in a tunnel
2010  * 
2011  * @param cls closure
2012  * @param client identification of the client
2013  * @param message the actual message
2014  */
2015 static void
2016 handle_local_network_traffic_bcast (void *cls,
2017                                     struct GNUNET_SERVER_Client *client,
2018                                     const struct GNUNET_MessageHeader *message)
2019 {
2020     struct MeshClient                           *c;
2021     struct MeshTunnel                           *t;
2022     struct GNUNET_MESH_DataBroadcast            *data_msg;
2023     MESH_TunnelNumber                           tid;
2024
2025     /* Sanity check for client registration */
2026     if (NULL == (c = retrieve_client(client))) {
2027         GNUNET_break(0);
2028         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2029         return;
2030     }
2031     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
2032     /* Sanity check for message size */
2033     if (sizeof(struct GNUNET_MESH_PeerControl)
2034         != ntohs(data_msg->header.size))
2035     {
2036         GNUNET_break(0);
2037         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2038         return;
2039     }
2040
2041     /* Tunnel exists? */
2042     tid = ntohl(data_msg->tunnel_id);
2043     t = retrieve_tunnel_by_local_id(c, tid);
2044     if (NULL == t) {
2045         GNUNET_break(0);
2046         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2047         return;
2048     }
2049
2050     /* Does client own tunnel? */
2051     if (t->client->handle != client) {
2052         GNUNET_break(0);
2053         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
2054         return;
2055     }
2056
2057     /*  TODO */
2058
2059     GNUNET_SERVER_receive_done(client, GNUNET_OK);
2060     return;
2061 }
2062
2063 /**
2064  * Functions to handle messages from clients
2065  */
2066 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
2067   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
2068   {&handle_local_tunnel_create, NULL,
2069    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
2070    sizeof(struct GNUNET_MESH_TunnelMessage)},
2071   {&handle_local_tunnel_destroy, NULL,
2072    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
2073    sizeof(struct GNUNET_MESH_TunnelMessage)},
2074   {&handle_local_connect_add, NULL,
2075    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
2076    sizeof(struct GNUNET_MESH_PeerControl)},
2077   {&handle_local_connect_del, NULL,
2078    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
2079    sizeof(struct GNUNET_MESH_PeerControl)},
2080   {&handle_local_connect_by_type, NULL,
2081    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
2082    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
2083   {&handle_local_network_traffic, NULL,
2084    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
2085   {&handle_local_network_traffic_bcast, NULL,
2086    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
2087   {NULL, NULL, 0, 0}
2088 };
2089
2090
2091 /**
2092  * To be called on core init/fail.
2093  *
2094  * @param cls service closure
2095  * @param server handle to the server for this service
2096  * @param identity the public identity of this peer
2097  * @param publicKey the public key of this peer
2098  */
2099 static void
2100 core_init (void *cls,
2101            struct GNUNET_CORE_Handle *server,
2102            const struct GNUNET_PeerIdentity *identity,
2103            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
2104 {
2105     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2106                 "Core init\n");
2107     core_handle = server;
2108     myid = GNUNET_PEER_intern(identity);
2109     return;
2110 }
2111
2112 /**
2113  * Method called whenever a given peer connects.
2114  *
2115  * @param cls closure
2116  * @param peer peer identity this notification is about
2117  * @param atsi performance data for the connection
2118  */
2119 static void
2120 core_connect (void *cls,
2121               const struct GNUNET_PeerIdentity *peer,
2122               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
2123 {
2124 //     GNUNET_PEER_Id              pid;
2125     struct MeshPeerInfo         *peer_info;
2126     struct MeshPath             *path;
2127
2128     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2129                 "Peer connected\n");
2130     peer_info = get_peer_info(peer);
2131     if (myid == peer_info->id) {
2132         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2133                 "     (self)\n");
2134     }
2135     path = GNUNET_malloc(sizeof(struct MeshPath));
2136     path->length = 2;
2137     path->peers = GNUNET_malloc(sizeof(GNUNET_PEER_Id) * 2);
2138     path->peers[0] = myid;
2139     path->peers[1] = peer_info->id;
2140     add_path_to_peer(peer_info, path);
2141     return;
2142 }
2143
2144 /**
2145  * Method called whenever a peer disconnects.
2146  *
2147  * @param cls closure
2148  * @param peer peer identity this notification is about
2149  */
2150 static void
2151 core_disconnect (void *cls,
2152                 const struct
2153                 GNUNET_PeerIdentity *peer)
2154 {
2155     GNUNET_PEER_Id      pid;
2156     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2157                 "Peer disconnected\n");
2158     pid = GNUNET_PEER_search(peer);
2159     if (myid == pid) {
2160         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2161                 "     (self)\n");
2162     }
2163     return;
2164 }
2165
2166
2167 /******************************************************************************/
2168 /************************      MAIN FUNCTIONS      ****************************/
2169 /******************************************************************************/
2170
2171 /**
2172  * Task run during shutdown.
2173  *
2174  * @param cls unused
2175  * @param tc unused
2176  */
2177 static void
2178 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2179 {
2180     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2181                 "shutting down\n");
2182     if (core_handle != NULL) {
2183         GNUNET_CORE_disconnect (core_handle);
2184         core_handle = NULL;
2185     }
2186     if (dht_handle != NULL) {
2187         GNUNET_DHT_disconnect (dht_handle);
2188         dht_handle = NULL;
2189     }
2190     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2191                 "shut down\n");
2192 }
2193
2194 /**
2195  * Process mesh requests.
2196  *
2197  * @param cls closure
2198  * @param server the initialized server
2199  * @param c configuration to use
2200  */
2201 static void
2202 run (void *cls,
2203      struct GNUNET_SERVER_Handle *server,
2204      const struct GNUNET_CONFIGURATION_Handle *c)
2205 {
2206     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2207                 "starting to run\n");
2208     GNUNET_SERVER_add_handlers (server, plugin_handlers);
2209     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
2210     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
2211                             1,                                  /* queue size */
2212                             NULL,         /* Closure passed to MESH functions */
2213                             &core_init,      /* Call core_init once connected */
2214                             &core_connect,                 /* Handle connects */
2215                             &core_disconnect,  /* remove peers on disconnects */
2216                             NULL,       /* Do we care about "status" updates? */
2217                             NULL, /* Don't notify about all incoming messages */
2218                             GNUNET_NO,     /* For header only in notification */
2219                             NULL, /* Don't notify about all outbound messages */
2220                             GNUNET_NO,    /* For header-only out notification */
2221                             core_handlers);        /* Register these handlers */
2222     if (core_handle == NULL) {
2223         GNUNET_break(0);
2224     }
2225     dht_handle = GNUNET_DHT_connect(c, 64);
2226     if (dht_handle == NULL) {
2227         GNUNET_break(0);
2228     }
2229     next_tid = 0;
2230
2231     tunnels = GNUNET_CONTAINER_multihashmap_create(32);
2232     peers = GNUNET_CONTAINER_multihashmap_create(32);
2233     clients = NULL;
2234     clients_tail = NULL;
2235
2236     /* Scheduled the task to clean up when shutdown is called */
2237     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
2238                                   &shutdown_task, NULL);
2239
2240     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2241                 "end if run()\n");
2242 }
2243
2244 /**
2245  * The main function for the mesh service.
2246  *
2247  * @param argc number of arguments from the command line
2248  * @param argv command line arguments
2249  * @return 0 ok, 1 on error
2250  */
2251 int
2252 main (int argc, char *const *argv)
2253 {
2254     int ret;
2255
2256     ret = (GNUNET_OK ==
2257            GNUNET_SERVICE_run (argc,
2258                                argv,
2259                                "mesh",
2260                                GNUNET_SERVICE_OPTION_NONE,
2261                                &run, NULL)) ? 0 : 1;
2262     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2263                 "end of main()\n");
2264     return ret;
2265 }