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