Changed PeerInfo / Path structure
[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  * - MAIN FUNCTIONS (main & run)
34  * 
35  * TODO:
36  * - soft stateing (keep-alive (CHANGE?) / timeout / disconnect) -- not a message issue
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  */
42
43 #include "platform.h"
44 #include "gnunet_common.h"
45 #include "gnunet_util_lib.h"
46 #include "gnunet_peer_lib.h"
47 #include "gnunet_core_service.h"
48 #include "gnunet_protocols.h"
49
50 #include "mesh.h"
51 #include "mesh_protocol.h"
52 #include "gnunet_dht_service.h"
53
54
55 /******************************************************************************/
56 /************************      DATA STRUCTURES     ****************************/
57 /******************************************************************************/
58
59 /**
60  * Information regarding a path
61  */
62 struct MeshPath
63 {
64
65     /**
66      * Linked list
67      */
68     struct MeshPath             *next;
69
70     /**
71      * Whether the path is serving traffic in a tunnel or is a backup
72      */
73     int                         in_use;
74
75     /**
76      * List of all the peers that form the path from origin to target
77      */
78     GNUNET_PEER_Id              *peers;
79
80     /**
81      * Number of peers (hops) in the path
82      */
83     unsigned int                length;
84 };
85
86
87 /**
88  * All the states a peer participating in a tunnel can be in.
89  */
90 enum MeshPeerState
91 {
92     /**
93      * Path to the peer not known yet
94      */
95     MESH_PEER_SEARCHING,
96
97     /**
98      * Request sent, not yet answered.
99      */
100     MESH_PEER_WAITING,
101
102     /**
103      * Peer connected and ready to accept data
104      */
105     MESH_PEER_READY,
106
107     /**
108      * Peer connected previosly but not responding
109      */
110     MESH_PEER_RECONNECTING
111 };
112
113
114 /**
115  * Struct containing all information regarding a given peer
116  */
117 struct MeshPeerInfo
118 {
119     /**
120      * ID of the peer
121      */
122     GNUNET_PEER_Id              id;
123
124     /**
125      * Is the peer reachable? Is the peer even connected?
126      */
127     enum MeshPeerState          state;
128
129     /**
130      * When to try to establish contact again?
131      */
132     struct GNUNET_TIME_Absolute next_reconnect_attempt;
133
134     /**
135      * Number of attempts to reconnect so far
136      */
137     int                         n_reconnect_attempts;
138
139     /**
140      * Paths to reach the peer
141      */
142     struct MeshPath             *path;
143
144     /**
145      * Handle to stop the DHT search for a path to this peer
146      */
147     struct GNUNET_DHT_GetHandle *dhtget;
148 };
149
150
151 /**
152  * Data scheduled to transmit (to local client or remote peer)
153  */
154 struct MeshQueue
155 {
156     /**
157      * Double linked list
158      */
159     struct MeshQueue            *next;
160     struct MeshQueue            *prev;
161
162     /**
163      * Target of the data (NULL if target is client)
164      */
165     struct MeshPeerInfo         *peer;
166
167     /**
168      * Client to send the data to (NULL if target is peer)
169      */
170     struct MeshClient           *client;
171
172     /**
173      * Size of the message to transmit
174      */
175     unsigned int                size;
176
177     /**
178      * How old is the data?
179      */
180     struct GNUNET_TIME_Absolute timestamp;
181
182     /**
183      * Data itself
184      */
185     struct GNUNET_MessageHeader *data;
186 };
187
188 /**
189  * Globally unique tunnel identification (owner + number)
190  * DO NOT USE OVER THE NETWORK
191  */
192 struct MESH_TunnelID {
193     /**
194      * Node that owns the tunnel
195      */
196     GNUNET_PEER_Id      oid;
197
198     /**
199      * Tunnel number to differentiate all the tunnels owned by the node oid
200      * ( tid < GNUNET_MESH_LOCAL_TUNNEL_ID_MARK )
201      */
202     MESH_TunnelNumber   tid;
203 };
204
205
206 struct MeshClient; /* FWD declaration */
207 /**
208  * Struct containing all information regarding a tunnel
209  * For an intermediate node the improtant info used will be:
210  * - id        Tunnel unique identification
211  * - paths[0]  To know where to send it next
212  * - metainfo: ready, speeds, accounting
213  */
214 struct MeshTunnel
215 {
216     /**
217      * Tunnel ID
218      */
219     struct MESH_TunnelID        id;
220
221     /**
222      * Local tunnel number ( >= GNUNET_MESH_LOCAL_TUNNEL_ID_MARK or 0 )
223      */
224     MESH_TunnelNumber           local_tid;
225
226     /**
227      * Last time the tunnel was used
228      */
229     struct GNUNET_TIME_Absolute timestamp;
230
231     /**
232      * Peers in the tunnelindexed by PeerIdentity (MeshPeerInfo)
233      */
234     struct GNUNET_CONTAINER_MultiHashMap* peers;
235
236     /**
237      * Number of peers that are connected and potentially ready to receive data
238      */
239     unsigned int                peers_ready;
240
241     /**
242      * Number of peers that have been added to the tunnel
243      */
244     unsigned int                peers_total;
245
246
247     /**
248      * Client owner of the tunnel, if any
249      */
250     struct MeshClient           *client;
251
252     /**
253      * Messages ready to transmit
254      */
255     struct MeshQueue            *queue_head;
256     struct MeshQueue            *queue_tail;
257
258 };
259
260 /**
261  * Struct containing information about a client of the service
262  */
263 struct MeshClient
264 {
265     /**
266      * Linked list
267      */
268     struct MeshClient           *next;
269
270     /**
271      * Tunnels that belong to this client, indexed by local id
272      */
273     struct GNUNET_CONTAINER_MultiHashMap* tunnels;
274
275     /**
276      * Handle to communicate with the client
277      */
278     struct GNUNET_SERVER_Client *handle;
279
280     /**
281      * Applications that this client has claimed to provide
282      */
283     GNUNET_MESH_ApplicationType *apps;
284     unsigned int                app_counter;
285
286     /**
287      * Messages that this client has declared interest in
288      */
289     uint16_t                    *types;
290     unsigned int                type_counter;
291
292 };
293
294 /******************************************************************************/
295 /***********************      GLOBAL VARIABLES     ****************************/
296 /******************************************************************************/
297
298 /**
299  * All the clients
300  */
301 static struct MeshClient                *clients;
302
303 /**
304  * Tunnels known, indexed by MESH_TunnelID (MeshTunnel)
305  */
306 struct GNUNET_CONTAINER_MultiHashMap    *tunnels;
307
308 /**
309  * Peers known, indexed by PeerIdentity (MeshPeerInfo)
310  */
311 struct GNUNET_CONTAINER_MultiHashMap    *peers;
312
313 /**
314  * Handle to communicate with core
315  */
316 static struct GNUNET_CORE_Handle        *core_handle;
317
318 /**
319  * Handle to use DHT
320  */
321 static struct GNUNET_DHT_Handle         *dht_handle;
322
323 /**
324  * Local peer own ID (memory efficient handle)
325  */
326 static GNUNET_PEER_Id                   myid;
327
328 /**
329  * Tunnel ID for the next created tunnel (global tunnel number)
330  */
331 static MESH_TunnelNumber                next_tid;
332
333 /******************************************************************************/
334 /******************      GENERAL HELPER FUNCTIONS      ************************/
335 /******************************************************************************/
336
337 /**
338  * Check if client has registered with the service and has not disconnected
339  * @param client the client to check
340  * @return non-NULL if client exists in the global DLL
341  */
342 static struct MeshClient *
343 retrieve_client (struct GNUNET_SERVER_Client *client)
344 {
345     struct MeshClient       *c;
346
347     c = clients; 
348     while (NULL != c) {
349         if (c->handle == client) return c;
350         c = c->next;
351     }
352     return NULL;
353 }
354
355
356 /**
357  * Search for a tunnel among the tunnels for a client
358  * @param client the client whose tunnels to search in
359  * @param tid the local id of the tunnel
360  * @return tunnel handler, NULL if doesn't exist
361  */
362 static struct MeshTunnel *
363 retrieve_tunnel_by_local_id (struct MeshClient *c, MESH_TunnelNumber tid)
364 {
365     GNUNET_HashCode hash;
366
367     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
368     return GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
369 }
370
371 /**
372  * Search for a tunnel by global ID using PEER_ID
373  * @param pi owner of the tunnel
374  * @param tid global tunnel number
375  * @return tunnel handler, NULL if doesn't exist
376  */
377 static struct MeshTunnel *
378 retrieve_tunnel_by_pi (GNUNET_PEER_Id pi, MESH_TunnelNumber tid)
379 {
380     struct MESH_TunnelID        id;
381     GNUNET_HashCode             hash;
382
383     id.oid = pi;
384     id.tid = tid;
385
386     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
387     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
388 }
389
390
391 #if LATER
392 /**
393  * Search for a tunnel by global ID using full PeerIdentities
394  * @param oid owner of the tunnel
395  * @param tid global tunnel number
396  * @return tunnel handler, NULL if doesn't exist
397  */
398 static struct MeshTunnel *
399 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
400 {
401     GNUNET_PEER_Id              pi;
402
403     pi = GNUNET_PEER_intern(oid);
404     GNUNET_PEER_change_rc(pi, -1);
405     return retrieve_tunnel_by_pi(pi, tid);
406 }
407
408
409 /**
410  * Destroy the path and free any allocated resources linked to it
411  * @param t tunnel the path belongs to
412  * @param p the path to destroy
413  * @return GNUNET_OK on success
414  */
415 static int
416 destroy_path(struct MeshTunnel  *t, struct MeshPath *p)
417 {
418     GNUNET_PEER_decrement_rcs(p->peers, p->length);
419     GNUNET_free(p->peers);
420     GNUNET_free(p);
421     return GNUNET_OK;
422 }
423
424
425 /**
426  * Destroy the peer_info and free any allocated resources linked to it
427  * @param t tunnel the path belongs to
428  * @param pi the peer_info to destroy
429  * @return GNUNET_OK on success
430  */
431 // static int
432 // destroy_peer_info(struct MeshTunnel  *t, struct MeshPeerInfo *pi)
433 // {
434 //     GNUNET_PEER_change_rc(pi->id, -1);
435 //     /* FIXME delete from list */
436 //     GNUNET_free(pi);
437 //     return GNUNET_OK;
438 // }
439 #endif
440
441
442 /**
443  * Destroy the tunnel and free any allocated resources linked to it
444  * @param c client the tunnel belongs to
445  * @param t the tunnel to destroy
446  * @return GNUNET_OK on success
447  */
448 static int
449 destroy_tunnel(struct MeshClient *c, struct MeshTunnel  *t)
450 {
451 //     struct MeshPath         *path;
452     GNUNET_HashCode         hash;
453     int                     r;
454
455     if (NULL == t) return GNUNET_OK;
456
457     // FIXME
458 //     for (path = t->paths_head; path != NULL; path = t->paths_head) {
459 //         if(GNUNET_OK != destroy_path(t, path)) r = GNUNET_SYSERR;
460 //     }
461
462     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
463     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
464         r = GNUNET_SYSERR;
465     }
466
467     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
468     if(GNUNET_YES !=
469         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
470     {
471         r = GNUNET_SYSERR;
472     }
473     GNUNET_free(t);
474     return r;
475 }
476
477 /******************************************************************************/
478 /****************      MESH NETWORK HANDLER HELPERS     ***********************/
479 /******************************************************************************/
480
481 /**
482  * Function called to notify a client about the socket
483  * being ready to queue more data.  "buf" will be
484  * NULL and "size" zero if the socket was closed for
485  * writing in the meantime.
486  *
487  * @param cls closure
488  * @param size number of bytes available in buf
489  * @param buf where the callee should write the message
490  * @return number of bytes written to buf
491  */
492 static size_t
493 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
494 {
495     struct MeshPeerInfo                 *peer_info = cls;
496     struct GNUNET_MESH_ManipulatePath   *msg;
497     struct MeshPath                     *p;
498     struct GNUNET_PeerIdentity          *peer_ptr;
499     size_t                              size_needed;
500     int                                 i;
501
502     if (0 == size && NULL == buf) {
503         // TODO retry? cancel?
504         return 0;
505     }
506     p = peer_info->path;
507     while (NULL != p) {
508         if (p->in_use) {
509             break;
510         }
511         p = p->next;
512     }
513     if (p == NULL) return 0; // TODO Notify ERROR Path not found
514
515     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
516                   + p->length * sizeof(struct GNUNET_PeerIdentity);
517     if (size < size_needed) {
518         // TODO retry? cancel?
519         return 0;
520     }
521
522     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
523     msg->header.size = htons(size_needed);
524     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
525
526     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
527     for (i = 0; i < p->length; i++) {
528         GNUNET_PEER_resolve(p->peers[i], peer_ptr++);
529     }
530
531     peer_info->state = MESH_PEER_WAITING;
532
533     return size_needed;
534 }
535
536 #if LATER
537 /**
538  * Send another peer a notification to destroy a tunnel
539  * @param cls The tunnel to destroy
540  * @param size Size in the buffer
541  * @param buf Memory where to put the data to transmit
542  * @return Size of data put in buffer
543  */
544 static size_t
545 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
546 {
547     struct MeshTunnel                   *t = cls;
548     struct MeshClient                   *c;
549     struct GNUNET_MESH_TunnelMessage    *msg;
550
551     c = t->client;
552     msg = buf;
553     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
554     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
555     msg->tunnel_id = htonl(t->id.tid);
556
557     destroy_tunnel(c, t);
558     return sizeof(struct GNUNET_MESH_TunnelMessage);
559 }
560 #endif
561
562
563 /******************************************************************************/
564 /********************      MESH NETWORK HANDLERS     **************************/
565 /******************************************************************************/
566
567
568 /**
569  * Core handler for path creation
570  * struct GNUNET_CORE_MessageHandler
571  *
572  * @param cls closure
573  * @param message message
574  * @param peer peer identity this notification is about
575  * @param atsi performance data
576  * @return GNUNET_OK to keep the connection open,
577  *         GNUNET_SYSERR to close it (signal serious error)
578  *
579  */
580 static int
581 handle_mesh_path_create (void *cls,
582                               const struct GNUNET_PeerIdentity *peer,
583                               const struct GNUNET_MessageHeader *message,
584                               const struct GNUNET_TRANSPORT_ATS_Information
585                               *atsi)
586 {
587     /* Extract path */
588     /* Find origin & self */
589     /* Search for origin in local tunnels */
590     /* Create tunnel / add path */
591     /* Retransmit to next link in chain, if any (core_notify + callback) */
592     return GNUNET_OK;
593 }
594
595
596 /**
597  * Core handler for mesh network traffic
598  *
599  * @param cls closure
600  * @param message message
601  * @param peer peer identity this notification is about
602  * @param atsi performance data
603  * @return GNUNET_OK to keep the connection open,
604  *         GNUNET_SYSERR to close it (signal serious error)
605  */
606 static int
607 handle_mesh_network_traffic (void *cls,
608                              const struct GNUNET_PeerIdentity *peer,
609                              const struct GNUNET_MessageHeader *message,
610                              const struct GNUNET_TRANSPORT_ATS_Information
611                              *atsi)
612 {
613     if (GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
614         /* Retransmit to next in path of tunnel identified by message */
615         return GNUNET_OK;
616     } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
617         /* Retransmit to previous in path of tunnel identified by message */
618         return GNUNET_OK;
619     }
620 }
621
622
623 /**
624  * Functions to handle messages from core
625  */
626 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
627   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
628   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
629   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
630   {NULL, 0, 0}
631 };
632
633
634
635 /******************************************************************************/
636 /****************       MESH LOCAL HANDLER HELPERS      ***********************/
637 /******************************************************************************/
638
639 /**
640  * delete_tunnel_entry: iterator for deleting each tunnel that belongs to a
641  * client when the client disconnects.
642  * @param cls closure (client that is disconnecting)
643  * @param key the hash of the local tunnel id (used to access the hashmap)
644  * @param value the value stored at the key (tunnel to destroy)
645  * @return GNUNET_OK on success
646  */
647 static int
648 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
649     int r;
650     r = destroy_tunnel((struct MeshClient *) cls, (struct MeshTunnel *) value);
651     return r;
652 }
653
654 #if LATER
655 /**
656  * notify_client_connection_failure: notify a client that the connection to the
657  * requested remote peer is not possible (for instance, no route found)
658  * Function called when the socket is ready to queue more data."buf" will be
659  * NULL and "size" zero if the socket was closed for writing in the meantime.
660  *
661  * @param cls closure
662  * @param size number of bytes available in buf
663  * @param buf where the callee should write the message
664  * @return number of bytes written to buf
665  */
666 static size_t
667 notify_client_connection_failure (void *cls, size_t size, void *buf)
668 {
669     int                                 size_needed;
670     struct MeshPeerInfo                 *peer_info;
671     struct GNUNET_MESH_PeerControl      *msg;
672     struct GNUNET_PeerIdentity          id;
673
674     if (0 == size && NULL == buf) {
675         // TODO retry? cancel?
676         return 0;
677     }
678
679     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
680     peer_info = (struct MeshPeerInfo *) cls;
681     msg = (struct GNUNET_MESH_PeerControl *) buf;
682     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
683     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
684 //     msg->tunnel_id = htonl(peer_info->t->tid);
685     GNUNET_PEER_resolve(peer_info->id, &id);
686     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
687
688     return size_needed;
689 }
690 #endif
691
692 /**
693  * Function to process paths received for a new peer addition. The recorded
694  * paths form the initial tunnel, which can be optimized later.
695  * Called on each result obtained for the DHT search.
696  *
697  * @param cls closure
698  * @param exp when will this value expire
699  * @param key key of the result
700  * @param get_path NULL-terminated array of pointers
701  *                 to the peers on reverse GET path (or NULL if not recorded)
702  * @param put_path NULL-terminated array of pointers
703  *                 to the peers on the PUT path (or NULL if not recorded)
704  * @param type type of the result
705  * @param size number of bytes in data
706  * @param data pointer to the result data
707  */
708 static void
709 dht_get_response_handler(void *cls,
710                         struct GNUNET_TIME_Absolute exp,
711                         const GNUNET_HashCode * key,
712                         const struct GNUNET_PeerIdentity * const *get_path,
713                         const struct GNUNET_PeerIdentity * const *put_path,
714                         enum GNUNET_BLOCK_Type type,
715                         size_t size,
716                         const void *data)
717 {
718     struct MeshPeerInfo         *peer_info = cls;
719     struct MeshPath             *p;
720     struct MeshPath             *aux;
721     struct GNUNET_PeerIdentity  pi;
722     int                         i;
723
724     if ((NULL == get_path || NULL == put_path) && NULL == peer_info->path) {
725         // Find ourselves some alternate initial path to the destination: retry
726         GNUNET_DHT_get_stop(peer_info->dhtget);
727         GNUNET_PEER_resolve(peer_info->id, &pi);
728         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
729                                     GNUNET_TIME_UNIT_FOREVER_REL,
730                                     GNUNET_BLOCK_TYPE_ANY,
731                                     &pi.hashPubKey,
732                                     4,    /* replication level */
733                                     GNUNET_DHT_RO_RECORD_ROUTE,
734                                     NULL, /* bloom filter */
735                                     0,    /* mutator */
736                                     NULL, /* xquery */
737                                     0,    /* xquery bits */
738                                     dht_get_response_handler,
739                                     (void *)peer_info);
740     }
741
742     p = GNUNET_malloc(sizeof(struct MeshPath));
743     for (i = 0; get_path[i] != NULL; i++);
744     for (i--; i >= 0; i--) {
745         p->peers = GNUNET_realloc(p->peers,
746                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
747         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
748         p->length++;
749     }
750     for (i = 0; put_path[i] != NULL; i++);
751     for (i--; i >= 0; i--) {
752         p->peers = GNUNET_realloc(p->peers,
753                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
754         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
755         p->length++;
756     }
757     if (NULL == peer_info->path) {
758         p->in_use = 1;
759         peer_info->path = p;
760     } else {
761         p->in_use = 0;
762         aux = peer_info->path;
763         while (NULL != aux->next) aux = aux->next;
764         aux->next = p;
765     }
766     GNUNET_CORE_notify_transmit_ready(core_handle,
767                                       0,
768                                       0,
769                                       GNUNET_TIME_UNIT_FOREVER_REL,
770                                       get_path[1],
771                                       sizeof(struct GNUNET_MESH_ManipulatePath)
772                                         + (p->length
773                                         * sizeof (struct GNUNET_PeerIdentity)),
774                                       &send_core_create_path_for_peer,
775                                       peer_info);
776     return;
777 }
778
779
780 /******************************************************************************/
781 /*********************       MESH LOCAL HANDLES      **************************/
782 /******************************************************************************/
783
784
785 /**
786  * Handler for client disconnection
787  *
788  * @param cls closure
789  * @param client identification of the client; NULL
790  *        for the last call when the server is destroyed
791  */
792 static void
793 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
794 {
795     struct MeshClient   *c;
796     struct MeshClient   *next;
797
798     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
799                "MESH: client disconnected\n");
800     c = clients;
801     while (NULL != c) {
802         if (c->handle == client) {
803             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
804                "MESH: matching client found, cleaning\n");
805             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
806                                                   &delete_tunnel_entry,
807                                                   c);
808             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
809             if(0 != c->app_counter) GNUNET_free (c->apps);
810             if(0 != c->type_counter) GNUNET_free (c->types);
811             next = c->next;
812             GNUNET_free (c);
813             c = next;
814         } else {
815             c = c->next;
816         }
817     }
818     return;
819 }
820
821
822 /**
823  * Handler for new clients
824  * 
825  * @param cls closure
826  * @param client identification of the client
827  * @param message the actual message, which includes messages the client wants
828  */
829 static void
830 handle_local_new_client (void *cls,
831                          struct GNUNET_SERVER_Client *client,
832                          const struct GNUNET_MessageHeader *message)
833 {
834     struct GNUNET_MESH_ClientConnect    *cc_msg;
835     struct MeshClient                   *c;
836     unsigned int                        size;
837     uint16_t                            types;
838     uint16_t                            apps;
839
840     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "MESH: new client connected\n");
841     /* Check data sanity */
842     size = ntohs(message->size) - sizeof(struct GNUNET_MESH_ClientConnect);
843     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
844     types = ntohs(cc_msg->types);
845     apps = ntohs(cc_msg->applications);
846     if (size !=
847         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
848     {
849         GNUNET_break(0);
850         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
851         return;
852     }
853
854     /* Create new client structure */
855     c = GNUNET_malloc(sizeof(struct MeshClient));
856     c->handle = client;
857     if (types != 0) {
858         c->type_counter = types;
859         c->types = GNUNET_malloc(types * sizeof(uint16_t));
860         memcpy(c->types, &message[1], types * sizeof(uint16_t));
861     }
862     if (apps != 0) {
863         c->app_counter = apps;
864         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
865         memcpy(c->apps,
866                &message[1] + types * sizeof(uint16_t),
867                apps * sizeof(GNUNET_MESH_ApplicationType));
868     }
869     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
870                "MESH:  client has %u+%u subscriptions\n",
871                c->type_counter,
872                c->app_counter);
873
874     c->next = clients;
875     clients = c;
876     c->tunnels = GNUNET_CONTAINER_multihashmap_create(32);
877
878     GNUNET_SERVER_receive_done(client, GNUNET_OK);
879
880 }
881
882
883 /**
884  * Handler for requests of new tunnels
885  * 
886  * @param cls closure
887  * @param client identification of the client
888  * @param message the actual message
889  */
890 static void
891 handle_local_tunnel_create (void *cls,
892                             struct GNUNET_SERVER_Client *client,
893                             const struct GNUNET_MessageHeader *message)
894 {
895     struct GNUNET_MESH_TunnelMessage    *t_msg;
896     struct MeshTunnel                   *t;
897     struct MeshClient                   *c;
898     GNUNET_HashCode                     hash;
899
900     /* Sanity check for client registration */
901     if (NULL == (c = retrieve_client(client))) {
902         GNUNET_break(0);
903         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
904         return;
905     }
906
907     /* Message sanity check */
908     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
909         GNUNET_break(0);
910         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
911         return;
912     }
913
914     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
915     /* Sanity check for tunnel numbering */
916     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
917         GNUNET_break(0);
918         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
919         return;
920     }
921     /* Sanity check for duplicate tunnel IDs */
922     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
923         GNUNET_break(0);
924         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
925         return;
926     }
927
928     t = GNUNET_malloc(sizeof(struct MeshTunnel));
929     // FIXME: what if all 2^32 ID are taken?
930     while (NULL != retrieve_tunnel_by_pi(myid, next_tid)) next_tid++;
931     t->id.tid = next_tid++;
932     t->id.oid = myid;
933     t->local_tid = ntohl(t_msg->tunnel_id);
934     t->client = c;
935     t->peers = GNUNET_CONTAINER_multihashmap_create(32);
936
937     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
938     if (GNUNET_OK !=
939         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
940                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
941     {
942         GNUNET_break(0);
943         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
944         return;
945     }
946
947     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
948     if (GNUNET_OK !=
949         GNUNET_CONTAINER_multihashmap_put(tunnels, &hash, t,
950                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
951     {
952         GNUNET_break(0);
953         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
954         return;
955     }
956
957     GNUNET_SERVER_receive_done(client, GNUNET_OK);
958     return;
959 }
960
961
962 /**
963  * Handler for requests of deleting tunnels
964  * 
965  * @param cls closure
966  * @param client identification of the client
967  * @param message the actual message
968  */
969 static void
970 handle_local_tunnel_destroy (void *cls,
971                              struct GNUNET_SERVER_Client *client,
972                              const struct GNUNET_MessageHeader *message)
973 {
974     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
975     struct MeshClient                   *c;
976     struct MeshTunnel                   *t;
977     MESH_TunnelNumber                   tid;
978     GNUNET_HashCode                     hash;
979
980
981     /* Sanity check for client registration */
982     if (NULL == (c = retrieve_client(client))) {
983         GNUNET_break(0);
984         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
985         return;
986     }
987     /* Message sanity check */
988     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
989         GNUNET_break(0);
990         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
991         return;
992     }
993
994     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
995
996     /* Retrieve tunnel */
997     tid = ntohl(tunnel_msg->tunnel_id);
998
999     /* Remove from local id hashmap */
1000     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
1001     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
1002     GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t);
1003
1004     /* Remove from global id hashmap */
1005     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
1006     GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t);
1007
1008 //     notify_tunnel_destroy(t);
1009     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1010     return;
1011 }
1012
1013
1014 /**
1015  * Handler for connection requests to new peers
1016  * 
1017  * @param cls closure
1018  * @param client identification of the client
1019  * @param message the actual message (PeerControl)
1020  */
1021 static void
1022 handle_local_connect_add (void *cls,
1023                           struct GNUNET_SERVER_Client *client,
1024                           const struct GNUNET_MessageHeader *message)
1025 {
1026     struct GNUNET_MESH_PeerControl      *peer_msg;
1027     struct MeshClient                   *c;
1028     struct MeshTunnel                   *t;
1029     MESH_TunnelNumber                   tid;
1030     struct MeshPeerInfo                 *peer_info;
1031
1032
1033     /* Sanity check for client registration */
1034     if (NULL == (c = retrieve_client(client))) {
1035         GNUNET_break(0);
1036         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1037         return;
1038     }
1039
1040     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1041     /* Sanity check for message size */
1042     if (sizeof(struct GNUNET_MESH_PeerControl)
1043         != ntohs(peer_msg->header.size))
1044     {
1045         GNUNET_break(0);
1046         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1047         return;
1048     }
1049
1050     /* Tunnel exists? */
1051     tid = ntohl(peer_msg->tunnel_id);
1052     t = retrieve_tunnel_by_local_id(c, tid);
1053     if (NULL == t) {
1054         GNUNET_break(0);
1055         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1056         return;
1057     }
1058
1059     /* Does client own tunnel? */
1060     if (t->client->handle != client) {
1061         GNUNET_break(0);
1062         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1063         return;
1064     }
1065
1066     /* Ok, add peer to tunnel */
1067     peer_info = GNUNET_CONTAINER_multihashmap_get(peers,
1068                                                   &peer_msg->peer.hashPubKey);
1069     if (NULL == peer_info) {
1070         peer_info = (struct MeshPeerInfo *)
1071                     GNUNET_malloc(sizeof(struct MeshPeerInfo));
1072         GNUNET_CONTAINER_multihashmap_put(peers,
1073                             &peer_msg->peer.hashPubKey,
1074                             peer_info,
1075                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
1076         peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
1077         peer_info->state = MESH_PEER_SEARCHING;
1078     }
1079
1080     t->peers_total++;
1081     /* FIXME insert */
1082     /* Start DHT search if needed */
1083     if(MESH_PEER_READY != peer_info->state && NULL == peer_info->dhtget) {
1084         peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1085                                             GNUNET_TIME_UNIT_FOREVER_REL,
1086                                             GNUNET_BLOCK_TYPE_ANY,
1087                                             &peer_msg->peer.hashPubKey,
1088                                             4,    /* replication level */
1089                                             GNUNET_DHT_RO_RECORD_ROUTE,
1090                                             NULL, /* bloom filter */
1091                                             0,    /* mutator */
1092                                             NULL, /* xquery */
1093                                             0,    /* xquery bits */
1094                                             dht_get_response_handler,
1095                                             (void *)peer_info);
1096     }
1097
1098     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1099     return;
1100 }
1101
1102
1103 /**
1104  * Handler for disconnection requests of peers in a tunnel
1105  * 
1106  * @param cls closure
1107  * @param client identification of the client
1108  * @param message the actual message (PeerControl)
1109  */
1110 static void
1111 handle_local_connect_del (void *cls,
1112                           struct GNUNET_SERVER_Client *client,
1113                           const struct GNUNET_MessageHeader *message)
1114 {
1115     struct GNUNET_MESH_PeerControl      *peer_msg;
1116     struct MeshClient                   *c;
1117     struct MeshTunnel                   *t;
1118     MESH_TunnelNumber                   tid;
1119     GNUNET_PEER_Id                      peer_id;
1120
1121     /* Sanity check for client registration */
1122     if (NULL == (c = retrieve_client(client))) {
1123         GNUNET_break(0);
1124         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1125         return;
1126     }
1127     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1128     /* Sanity check for message size */
1129     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
1130         GNUNET_break(0);
1131         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1132         return;
1133     }
1134
1135     /* Tunnel exists? */
1136     tid = ntohl(peer_msg->tunnel_id);
1137     t = retrieve_tunnel_by_local_id(c, tid);
1138     if (NULL == t) {
1139             GNUNET_break(0);
1140             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1141             return;
1142         }
1143
1144     /* Does client own tunnel? */
1145     if (t->client->handle != client) {
1146         GNUNET_break(0);
1147         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1148         return;
1149     }
1150
1151     /* Ok, delete peer from tunnel */
1152     peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1153
1154     /* FIXME Delete paths */
1155     /* FIXME Delete peer info */
1156
1157     GNUNET_PEER_change_rc(peer_id, -1);
1158
1159     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1160     return;
1161 }
1162
1163
1164 /**
1165  * Handler for connection requests to new peers by type
1166  * 
1167  * @param cls closure
1168  * @param client identification of the client
1169  * @param message the actual message (ConnectPeerByType)
1170  */
1171 static void
1172 handle_local_connect_by_type (void *cls,
1173                               struct GNUNET_SERVER_Client *client,
1174                               const struct GNUNET_MessageHeader *message)
1175 {
1176     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1177     MESH_TunnelNumber                           tid;
1178     GNUNET_MESH_ApplicationType                 application;
1179     struct MeshClient                           *c;
1180     struct MeshTunnel                           *t;
1181
1182     /* Sanity check for client registration */
1183     if (NULL == (c = retrieve_client(client))) {
1184         GNUNET_break(0);
1185         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1186         return;
1187     }
1188
1189     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1190     /* Sanity check for message size */
1191     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1192             ntohs(connect_msg->header.size))
1193     {
1194         GNUNET_break(0);
1195         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1196         return;
1197     }
1198
1199     /* Tunnel exists? */
1200     tid = ntohl(connect_msg->tunnel_id);
1201     t = retrieve_tunnel_by_local_id(c, tid);
1202     if (NULL == t) {
1203         GNUNET_break(0);
1204         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1205         return;
1206     }
1207
1208     /* Does client own tunnel? */
1209     if (t->client->handle != client) {
1210         GNUNET_break(0);
1211         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1212         return;
1213     }
1214
1215     /* Ok, lets find a peer offering the service */
1216     application = ntohl(connect_msg->type);
1217     application++; // FIXME silence warnings
1218
1219     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1220     return;
1221 }
1222
1223
1224 /**
1225  * Handler for client traffic directed to one peer
1226  * 
1227  * @param cls closure
1228  * @param client identification of the client
1229  * @param message the actual message
1230  */
1231 static void
1232 handle_local_network_traffic (void *cls,
1233                          struct GNUNET_SERVER_Client *client,
1234                          const struct GNUNET_MessageHeader *message)
1235 {
1236     struct MeshClient                           *c;
1237     struct MeshTunnel                           *t;
1238     struct GNUNET_MESH_Data                     *data_msg;
1239     MESH_TunnelNumber                           tid;
1240
1241     /* Sanity check for client registration */
1242     if (NULL == (c = retrieve_client(client))) {
1243         GNUNET_break(0);
1244         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1245         return;
1246     }
1247     data_msg = (struct GNUNET_MESH_Data *)message;
1248     /* Sanity check for message size */
1249     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1250             ntohs(data_msg->header.size))
1251     {
1252         GNUNET_break(0);
1253         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1254         return;
1255     }
1256
1257     /* Tunnel exists? */
1258     tid = ntohl(data_msg->tunnel_id);
1259     t = retrieve_tunnel_by_local_id(c, tid);
1260     if (NULL == t) {
1261         GNUNET_break(0);
1262         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1263         return;
1264     }
1265
1266     /* Does client own tunnel? */
1267     if (t->client->handle != client) {
1268         GNUNET_break(0);
1269         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1270         return;
1271     }
1272
1273     /* TODO */
1274
1275     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1276     return;
1277 }
1278
1279 /**
1280  * Handler for client traffic directed to all peers in a tunnel
1281  * 
1282  * @param cls closure
1283  * @param client identification of the client
1284  * @param message the actual message
1285  */
1286 static void
1287 handle_local_network_traffic_bcast (void *cls,
1288                                     struct GNUNET_SERVER_Client *client,
1289                                     const struct GNUNET_MessageHeader *message)
1290 {
1291     struct MeshClient                           *c;
1292     struct MeshTunnel                           *t;
1293     struct GNUNET_MESH_DataBroadcast            *data_msg;
1294     MESH_TunnelNumber                           tid;
1295
1296     /* Sanity check for client registration */
1297     if (NULL == (c = retrieve_client(client))) {
1298         GNUNET_break(0);
1299         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1300         return;
1301     }
1302     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1303     /* Sanity check for message size */
1304     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1305         GNUNET_break(0);
1306         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1307         return;
1308     }
1309
1310     /* Tunnel exists? */
1311     tid = ntohl(data_msg->tunnel_id);
1312     t = retrieve_tunnel_by_local_id(c, tid);
1313     if (NULL == t) {
1314         GNUNET_break(0);
1315         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1316         return;
1317     }
1318
1319     /* Does client own tunnel? */
1320     if (t->client->handle != client) {
1321         GNUNET_break(0);
1322         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1323         return;
1324     }
1325
1326     /*  TODO */
1327
1328     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1329     return;
1330 }
1331
1332 /**
1333  * Functions to handle messages from clients
1334  */
1335 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1336   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1337   {&handle_local_tunnel_create, NULL,
1338    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1339    sizeof(struct GNUNET_MESH_TunnelMessage)},
1340   {&handle_local_tunnel_destroy, NULL,
1341    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1342    sizeof(struct GNUNET_MESH_TunnelMessage)},
1343   {&handle_local_connect_add, NULL,
1344    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1345    sizeof(struct GNUNET_MESH_PeerControl)},
1346   {&handle_local_connect_del, NULL,
1347    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1348    sizeof(struct GNUNET_MESH_PeerControl)},
1349   {&handle_local_connect_by_type, NULL,
1350    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1351    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1352   {&handle_local_network_traffic, NULL,
1353    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1354   {&handle_local_network_traffic_bcast, NULL,
1355    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1356   {NULL, NULL, 0, 0}
1357 };
1358
1359
1360 /**
1361  * To be called on core init/fail.
1362  *
1363  * @param cls service closure
1364  * @param server handle to the server for this service
1365  * @param identity the public identity of this peer
1366  * @param publicKey the public key of this peer
1367  */
1368 static void
1369 core_init (void *cls,
1370            struct GNUNET_CORE_Handle *server,
1371            const struct GNUNET_PeerIdentity *identity,
1372            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1373 {
1374     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1375                 "Core init\n");
1376     core_handle = server;
1377     myid = GNUNET_PEER_intern(identity);
1378     return;
1379 }
1380
1381 /**
1382  * Method called whenever a given peer connects.
1383  *
1384  * @param cls closure
1385  * @param peer peer identity this notification is about
1386  * @param atsi performance data for the connection
1387  */
1388 static void
1389 core_connect (void *cls,
1390               const struct GNUNET_PeerIdentity *peer,
1391               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1392 {
1393     GNUNET_PEER_Id      pid;
1394     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1395                 "Peer connected\n");
1396     pid = GNUNET_PEER_intern(peer);
1397     if (myid == pid) {
1398         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1399                 "     (self)\n");
1400     }
1401     return;
1402 }
1403
1404 /**
1405  * Method called whenever a peer disconnects.
1406  *
1407  * @param cls closure
1408  * @param peer peer identity this notification is about
1409  */
1410 static void
1411 core_disconnect (void *cls,
1412                 const struct
1413                 GNUNET_PeerIdentity *peer)
1414 {
1415     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1416                 "Peer disconnected\n");
1417     return;
1418 }
1419
1420 /******************************************************************************/
1421 /************************      MAIN FUNCTIONS      ****************************/
1422 /******************************************************************************/
1423
1424 /**
1425  * Task run during shutdown.
1426  *
1427  * @param cls unused
1428  * @param tc unused
1429  */
1430 static void
1431 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1432 {
1433     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1434                 "MESH shutting down\n");
1435     if (core_handle != NULL) {
1436         GNUNET_CORE_disconnect (core_handle);
1437         core_handle = NULL;
1438     }
1439     if (dht_handle != NULL) {
1440         GNUNET_DHT_disconnect (dht_handle);
1441         dht_handle = NULL;
1442     } 
1443 }
1444
1445 /**
1446  * Process mesh requests.
1447  *
1448  * @param cls closure
1449  * @param server the initialized server
1450  * @param c configuration to use
1451  */
1452 static void
1453 run (void *cls,
1454      struct GNUNET_SERVER_Handle *server,
1455      const struct GNUNET_CONFIGURATION_Handle *c)
1456 {
1457     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1458                 "MESH starting to run\n");
1459     GNUNET_SERVER_add_handlers (server, plugin_handlers);
1460     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1461     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
1462                             32,                                 /* queue size */
1463                             NULL,         /* Closure passed to MESH functions */
1464                             &core_init,      /* Call core_init once connected */
1465                             &core_connect,                 /* Handle connects */
1466                             &core_disconnect,  /* remove peers on disconnects */
1467                             NULL,       /* Do we care about "status" updates? */
1468                             NULL, /* Don't notify about all incoming messages */
1469                             GNUNET_NO,     /* For header only in notification */
1470                             NULL, /* Don't notify about all outbound messages */
1471                             GNUNET_NO,    /* For header-only out notification */
1472                             core_handlers);        /* Register these handlers */
1473     if (core_handle == NULL) {
1474         GNUNET_break(0);
1475     }
1476     dht_handle = GNUNET_DHT_connect(c, 64);
1477     if (dht_handle == NULL) {
1478         GNUNET_break(0);
1479     }
1480     next_tid = 0;
1481
1482     tunnels = GNUNET_CONTAINER_multihashmap_create(32);
1483     peers = GNUNET_CONTAINER_multihashmap_create(32);
1484
1485     /* Scheduled the task to clean up when shutdown is called */
1486     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1487                                   &shutdown_task, NULL);
1488
1489 }
1490
1491 /**
1492  * The main function for the mesh service.
1493  *
1494  * @param argc number of arguments from the command line
1495  * @param argv command line arguments
1496  * @return 0 ok, 1 on error
1497  */
1498 int
1499 main (int argc, char *const *argv)
1500 {
1501     int ret;
1502
1503     ret = (GNUNET_OK ==
1504            GNUNET_SERVICE_run (argc,
1505                                argv,
1506                                "mesh",
1507                                GNUNET_SERVICE_OPTION_NONE,
1508                                &run, NULL)) ? 0 : 1;
1509     return ret;
1510 }