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