WiP (service rewrite)
[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 /**
375  * Search for a tunnel by global ID
376  */
377 static struct MeshTunnel *
378 retrieve_tunnel (struct GNUNET_PeerIdentity *oid, MESH_TunnelNumber tid)
379 {
380     struct MESH_TunnelID        id;
381     GNUNET_HashCode             hash;
382
383     id.oid = GNUNET_PEER_intern(oid);
384     GNUNET_PEER_change_rc(id.oid, -1);
385     id.tid = tid;
386
387     GNUNET_CRYPTO_hash(&id, sizeof(struct MESH_TunnelID), &hash);
388     return GNUNET_CONTAINER_multihashmap_get(tunnels, &hash);
389 }
390
391 /**
392  * Destroy the path and free any allocated resources linked to it
393  * @param t tunnel the path belongs to
394  * @param p the path to destroy
395  * @return GNUNET_OK on success
396  */
397 static int
398 destroy_path(struct MeshTunnel  *t, struct MeshPath *p)
399 {
400     GNUNET_PEER_decrement_rcs(p->peers, p->length);
401     GNUNET_free(p->peers);
402     GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
403     GNUNET_free(p);
404     return GNUNET_OK;
405 }
406
407 /**
408  * Destroy the peer_info and free any allocated resources linked to it
409  * @param t tunnel the path belongs to
410  * @param pi the peer_info to destroy
411  * @return GNUNET_OK on success
412  */
413 static int
414 destroy_peer_info(struct MeshTunnel  *t, struct MeshPeerInfo *pi)
415 {
416     GNUNET_PEER_change_rc(pi->id, -1);
417     /* FIXME delete from list */
418     GNUNET_free(pi);
419     return GNUNET_OK;
420 }
421
422 /**
423  * Destroy the tunnel and free any allocated resources linked to it
424  * @param c client the tunnel belongs to
425  * @param t the tunnel to destroy
426  * @return GNUNET_OK on success
427  */
428 static int
429 destroy_tunnel(struct MeshClient *c, struct MeshTunnel  *t)
430 {
431     struct MeshPath         *path;
432     GNUNET_HashCode         hash;
433     int                     r;
434
435     if (NULL == t) return GNUNET_OK;
436
437     for (path = t->paths_head; path != NULL; path = t->paths_head) {
438         if(GNUNET_OK != destroy_path(t, path)) r = GNUNET_SYSERR;
439     }
440
441     GNUNET_CRYPTO_hash(&t->id, sizeof(struct MESH_TunnelID), &hash);
442     if(GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove(tunnels, &hash, t)) {
443         r = GNUNET_SYSERR;
444     }
445
446     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
447     if(GNUNET_YES !=
448         GNUNET_CONTAINER_multihashmap_remove(c->tunnels, &hash, t))
449     {
450         r = GNUNET_SYSERR;
451     }
452     GNUNET_free(t);
453     return r;
454 }
455
456 /******************************************************************************/
457 /********************      MESH NETWORK HANDLERS     **************************/
458 /******************************************************************************/
459
460 /**
461  * FIXME: rewrite
462  * Function called to notify a client about the socket
463  * being ready to queue more data.  "buf" will be
464  * NULL and "size" zero if the socket was closed for
465  * writing in the meantime.
466  *
467  * @param cls closure
468  * @param size number of bytes available in buf
469  * @param buf where the callee should write the message
470  * @return number of bytes written to buf
471  */
472 static size_t
473 send_core_create_path_for_peer (void *cls, size_t size, void *buf)
474 {
475     size_t                              size_needed;
476     struct MeshPeerInfo                 *peer_info;
477     struct GNUNET_MESH_ManipulatePath   *msg;
478     struct MeshPath                     *p;
479     struct GNUNET_PeerIdentity          peer_id;
480     struct GNUNET_PeerIdentity          *peer_ptr;
481     int                                 i;
482
483     if (0 == size && NULL == buf) {
484         // TODO retry? cancel?
485         return 0;
486     }
487     peer_info = (struct MeshPeerInfo *)cls;
488     peer_info->dhtget = NULL;
489 //     p = peer_info->t->paths_head;
490     while (NULL != p) {
491         if (p->peers[p->length-1] == peer_info->id) {
492             break;
493         }
494         p = p->next;
495     }
496     if (p == NULL) return 0; // TODO Notify ERROR Path not found
497
498     size_needed = sizeof(struct GNUNET_MESH_ManipulatePath)
499                   + p->length * sizeof(struct GNUNET_PeerIdentity);
500     if (size < size_needed) {
501         // TODO retry? cancel?
502         return 0;
503     }
504
505     msg = (struct GNUNET_MESH_ManipulatePath *) buf;
506     msg->header.size = htons(sizeof(struct GNUNET_MESH_ManipulatePath));
507     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE);
508     msg->speed_min = 0;
509
510     peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
511     for (i = 0; i < p->length; i++) {
512         GNUNET_PEER_resolve(p->peers[i], &peer_id);
513         memcpy(&peer_ptr[i], &peer_id, sizeof(struct GNUNET_PeerIdentity));
514     }
515
516     peer_info->state = MESH_PEER_WAITING;
517
518     return size_needed;
519 }
520
521
522 /**
523  * Send another peer a notification to destroy a tunnel
524  * @param cls The tunnel to destroy
525  * @param size Size in the buffer
526  * @param buf Memory where to put the data to transmit
527  * @return Size of data put in buffer
528  */
529 static size_t
530 send_p2p_tunnel_destroy(void *cls, size_t size, void *buf)
531 {
532     struct MeshTunnel                   *t = cls;
533     struct MeshClient                   *c;
534     struct GNUNET_MESH_TunnelMessage    *msg;
535
536     c = t->client;
537     msg = buf;
538     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY); /*FIXME*/
539     msg->header.size = htons(sizeof(struct GNUNET_MESH_TunnelMessage));
540     msg->tunnel_id = htonl(t->id.tid);
541
542     destroy_tunnel(c, t);
543     return sizeof(struct GNUNET_MESH_TunnelMessage);
544 }
545
546
547 /**
548  * Core handler for path creation
549  * struct GNUNET_CORE_MessageHandler
550  *
551  * @param cls closure
552  * @param message message
553  * @param peer peer identity this notification is about
554  * @param atsi performance data
555  * @return GNUNET_OK to keep the connection open,
556  *         GNUNET_SYSERR to close it (signal serious error)
557  *
558  */
559 static int
560 handle_mesh_path_create (void *cls,
561                               const struct GNUNET_PeerIdentity *peer,
562                               const struct GNUNET_MessageHeader *message,
563                               const struct GNUNET_TRANSPORT_ATS_Information
564                               *atsi)
565 {
566     /* Extract path */
567     /* Find origin & self */
568     /* Search for origin in local tunnels */
569     /* Create tunnel / add path */
570     /* Retransmit to next link in chain, if any (core_notify + callback) */
571     return GNUNET_OK;
572 }
573
574
575 /**
576  * Core handler for mesh network traffic
577  *
578  * @param cls closure
579  * @param message message
580  * @param peer peer identity this notification is about
581  * @param atsi performance data
582  * @return GNUNET_OK to keep the connection open,
583  *         GNUNET_SYSERR to close it (signal serious error)
584  */
585 static int
586 handle_mesh_network_traffic (void *cls,
587                              const struct GNUNET_PeerIdentity *peer,
588                              const struct GNUNET_MessageHeader *message,
589                              const struct GNUNET_TRANSPORT_ATS_Information
590                              *atsi)
591 {
592     if (GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
593         /* Retransmit to next in path of tunnel identified by message */
594         return GNUNET_OK;
595     } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
596         /* Retransmit to previous in path of tunnel identified by message */
597         return GNUNET_OK;
598     }
599 }
600
601
602 /**
603  * Functions to handle messages from core
604  */
605 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
606   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
607   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
608   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
609   {NULL, 0, 0}
610 };
611
612
613
614 /******************************************************************************/
615 /*********************       MESH LOCAL HANDLES      **************************/
616 /******************************************************************************/
617
618 static int
619 delete_tunnel_entry (void *cls, const GNUNET_HashCode * key, void *value) {
620     int r;
621     r = destroy_tunnel((struct MeshClient *) cls, (struct MeshTunnel *) value);
622     return r;
623 }
624
625 /**
626  * notify_client_connection_failure: notify a client that the connection to the
627  * requested remote peer is not possible (for instance, no route found)
628  * Function called when the socket is ready to queue more data."buf" will be
629  * NULL and "size" zero if the socket was closed for writing in the meantime.
630  *
631  * @param cls closure
632  * @param size number of bytes available in buf
633  * @param buf where the callee should write the message
634  * @return number of bytes written to buf
635  */
636 static size_t
637 notify_client_connection_failure (void *cls, size_t size, void *buf)
638 {
639     int                                 size_needed;
640     struct MeshPeerInfo                 *peer_info;
641     struct GNUNET_MESH_PeerControl      *msg;
642     struct GNUNET_PeerIdentity          id;
643
644     if (0 == size && NULL == buf) {
645         // TODO retry? cancel?
646         return 0;
647     }
648
649     size_needed = sizeof(struct GNUNET_MESH_PeerControl);
650     peer_info = (struct MeshPeerInfo *) cls;
651     msg = (struct GNUNET_MESH_PeerControl *) buf;
652     msg->header.size = htons(sizeof(struct GNUNET_MESH_PeerControl));
653     msg->header.type = htons(GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DISCONNECTED);
654 //     msg->tunnel_id = htonl(peer_info->t->tid);
655     GNUNET_PEER_resolve(peer_info->id, &id);
656     memcpy(&msg->peer, &id, sizeof(struct GNUNET_PeerIdentity));
657
658     return size_needed;
659 }
660
661
662 /**
663  * FIXME: rewrite
664  * Function to process paths received for a new peer addition. The recorded
665  * paths form the initial tunnel, which can be optimized later.
666  * Called on each result obtained for the DHT search.
667  *
668  * @param cls closure
669  * @param exp when will this value expire
670  * @param key key of the result
671  * @param get_path NULL-terminated array of pointers
672  *                 to the peers on reverse GET path (or NULL if not recorded)
673  * @param put_path NULL-terminated array of pointers
674  *                 to the peers on the PUT path (or NULL if not recorded)
675  * @param type type of the result
676  * @param size number of bytes in data
677  * @param data pointer to the result data
678  */
679 static void
680 dht_get_response_handler(void *cls,
681                         struct GNUNET_TIME_Absolute exp,
682                         const GNUNET_HashCode * key,
683                         const struct GNUNET_PeerIdentity * const *get_path,
684                         const struct GNUNET_PeerIdentity * const *put_path,
685                         enum GNUNET_BLOCK_Type type,
686                         size_t size,
687                         const void *data)
688 {
689     struct MeshPeerInfo         *peer_info;
690     struct MeshTunnel           *t;
691     struct MeshPath             *p;
692     int                         i;
693
694     peer_info = (struct MeshPeerInfo *)cls;
695 //     t = peer_info->t;
696
697     if (NULL == get_path || NULL == put_path) {
698         // TODO: find ourselves some alternate initial path to the destination
699         GNUNET_SERVER_notify_transmit_ready(
700             t->client->handle,
701             sizeof(struct GNUNET_MESH_PeerControl),
702             GNUNET_TIME_UNIT_FOREVER_REL,
703             &notify_client_connection_failure,
704             peer_info
705         );
706     }
707
708     p = GNUNET_malloc(sizeof(struct MeshPath));
709     GNUNET_CONTAINER_DLL_insert(t->paths_head, t->paths_tail, p);
710     for (i = 0; get_path[i] != NULL; i++);
711     for (i--; i >= 0; i--) {
712         p->peers = GNUNET_realloc(p->peers,
713                                    sizeof(GNUNET_PEER_Id) * (p->length + 1));
714         p->peers[p->length] = GNUNET_PEER_intern(get_path[i]);
715         p->length++;
716     }
717     for (i = 0; put_path[i] != NULL; i++);
718     for (i--; i >= 0; i--) {
719         p->peers = GNUNET_realloc(p->peers,
720                                   sizeof(GNUNET_PEER_Id) * (p->length + 1));
721         p->peers[p->length] = GNUNET_PEER_intern(put_path[i]);
722         p->length++;
723     }
724     // p->id = 0; // FIXME generate ID or remove field
725     p->in_use = 0;
726     // peer_info->first_hop = p->peers[1]; // FIXME do this on path completion
727     GNUNET_CORE_notify_transmit_ready(core_handle,
728                                       0,
729                                       0,
730                                       GNUNET_TIME_UNIT_FOREVER_REL,
731                                       get_path[1],
732                                       sizeof(struct GNUNET_MESH_ManipulatePath)
733                                         + (p->length
734                                         * sizeof (struct GNUNET_PeerIdentity)),
735                                       &send_core_create_path_for_peer,
736                                       peer_info);
737     return;
738 }
739
740
741 /**
742  * Handler for client disconnection
743  *
744  * @param cls closure
745  * @param client identification of the client; NULL
746  *        for the last call when the server is destroyed
747  */
748 static void
749 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
750 {
751     struct MeshClient   *c;
752     struct MeshClient   *next;
753
754     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
755                "MESH: client disconnected\n");
756     c = clients;
757     while (NULL != c) {
758         if (c->handle == client) {
759             GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
760                "MESH: matching client found, cleaning\n");
761             GNUNET_CONTAINER_multihashmap_iterate(c->tunnels,
762                                                   &delete_tunnel_entry,
763                                                   c);
764             GNUNET_CONTAINER_multihashmap_destroy(c->tunnels);
765             if(0 != c->app_counter) GNUNET_free (c->apps);
766             if(0 != c->type_counter) GNUNET_free (c->types);
767             next = c->next;
768             GNUNET_free (c);
769             c = next;
770         } else {
771             c = c->next;
772         }
773     }
774     return;
775 }
776
777
778 /**
779  * Handler for new clients
780  * 
781  * @param cls closure
782  * @param client identification of the client
783  * @param message the actual message, which includes messages the client wants
784  */
785 static void
786 handle_local_new_client (void *cls,
787                          struct GNUNET_SERVER_Client *client,
788                          const struct GNUNET_MessageHeader *message)
789 {
790     struct GNUNET_MESH_ClientConnect    *cc_msg;
791     struct MeshClient                   *c;
792     unsigned int                        payload_size;
793     uint16_t                            types;
794     uint16_t                            apps;
795
796     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
797                "MESH: new client connected\n");
798     /* Check data sanity */
799     payload_size = ntohs(message->size)
800                    - sizeof(struct GNUNET_MESH_ClientConnect);
801     cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
802     types = ntohs(cc_msg->types);
803     apps = ntohs(cc_msg->applications);
804     if (payload_size != 
805         types * sizeof(uint16_t) + apps * sizeof(GNUNET_MESH_ApplicationType))
806     {
807         GNUNET_break(0);
808         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
809         return;
810     }
811
812     /* Create new client structure */
813     c = GNUNET_malloc(sizeof(struct MeshClient));
814     c->handle = client;
815     if (types != 0) {
816         c->type_counter = types;
817         c->types = GNUNET_malloc(types * sizeof(uint16_t));
818         memcpy(c->types, &message[1], types * sizeof(uint16_t));
819     }
820     if (apps != 0) {
821         c->app_counter = apps;
822         c->apps = GNUNET_malloc(apps * sizeof(GNUNET_MESH_ApplicationType));
823         memcpy(c->apps,
824                &message[1] + types * sizeof(uint16_t),
825                apps * sizeof(GNUNET_MESH_ApplicationType));
826     }
827     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
828                "MESH:  client has %u+%u subscriptions\n",
829                c->type_counter,
830                c->app_counter);
831
832     /* Insert new client in DLL */
833     /* FIXME insert client */
834     c->tunnels = GNUNET_CONTAINER_multihashmap_create(100);
835
836     GNUNET_SERVER_receive_done(client, GNUNET_OK);
837
838 }
839
840
841 /**
842  * Handler for requests of new tunnels
843  * 
844  * @param cls closure
845  * @param client identification of the client
846  * @param message the actual message
847  */
848 static void
849 handle_local_tunnel_create (void *cls,
850                             struct GNUNET_SERVER_Client *client,
851                             const struct GNUNET_MessageHeader *message)
852 {
853     struct GNUNET_MESH_TunnelMessage    *t_msg;
854     struct MeshTunnel                   *t;
855     struct MeshClient                   *c;
856     GNUNET_HashCode                     hash;
857
858     /* Sanity check for client registration */
859     if (NULL == (c = retrieve_client(client))) {
860         GNUNET_break(0);
861         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
862         return;
863     }
864
865     /* Message sanity check */
866     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
867         GNUNET_break(0);
868         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
869         return;
870     }
871
872     t_msg = (struct GNUNET_MESH_TunnelMessage *) message;
873     /* Sanity check for tunnel numbering */
874     if (0 == (ntohl(t_msg->tunnel_id) & GNUNET_MESH_LOCAL_TUNNEL_ID_MARK)) {
875         GNUNET_break(0);
876         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
877         return;
878     }
879     /* Sanity check for duplicate tunnel IDs */
880     if(NULL != retrieve_tunnel_by_local_id(c, ntohl(t_msg->tunnel_id))) {
881         GNUNET_break(0);
882         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
883         return;
884     }
885     t = GNUNET_malloc(sizeof(struct MeshTunnel ));
886     // FIXME:what if all 2^32 ID are taken?
887     while (NULL != retrieve_tunnel_by_local_id(c, next_tid)) next_tid++;
888     t->id.tid = next_tid++;
889     t->id.oid = myid;
890     t->local_tid = ntohl(t_msg->tunnel_id);
891     t->client = c;
892
893     GNUNET_CRYPTO_hash(&t->local_tid, sizeof(MESH_TunnelNumber), &hash);
894     if (GNUNET_OK !=
895         GNUNET_CONTAINER_multihashmap_put(c->tunnels, &hash, t,
896                             GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
897     {
898         GNUNET_break(0);
899         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
900         return;
901     }
902
903     /* FIXME insert */
904
905     GNUNET_SERVER_receive_done(client, GNUNET_OK);
906     return;
907 }
908
909
910 /**
911  * Handler for requests of deleting tunnels
912  * 
913  * @param cls closure
914  * @param client identification of the client
915  * @param message the actual message
916  */
917 static void
918 handle_local_tunnel_destroy (void *cls,
919                              struct GNUNET_SERVER_Client *client,
920                              const struct GNUNET_MessageHeader *message)
921 {
922     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
923     struct MeshClient                   *c;
924     struct MeshTunnel                   *t;
925     MESH_TunnelNumber                   tid;
926     GNUNET_HashCode                     hash;
927
928
929     /* Sanity check for client registration */
930     if (NULL == (c = retrieve_client(client))) {
931         GNUNET_break(0);
932         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
933         return;
934     }
935     /* Message sanity check */
936     if (sizeof(struct GNUNET_MESH_TunnelMessage) != ntohs(message->size)) {
937         GNUNET_break(0);
938         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
939         return;
940     }
941
942     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
943
944     /* Retrieve tunnel */
945     tid = ntohl(tunnel_msg->tunnel_id);
946     GNUNET_CRYPTO_hash(&tid, sizeof(MESH_TunnelNumber), &hash);
947     t = GNUNET_CONTAINER_multihashmap_get(c->tunnels, &hash);
948     GNUNET_CONTAINER_multihashmap_remove_all(c->tunnels, &hash);
949     GNUNET_CORE_notify_transmit_ready(core_handle,
950                                       1,
951                                       1,
952                                       GNUNET_TIME_UNIT_FOREVER_REL,
953                                       NULL,
954                                       sizeof(struct GNUNET_MESH_TunnelMessage),
955                                       &send_p2p_tunnel_destroy,
956                                       t);
957
958     GNUNET_SERVER_receive_done(client, GNUNET_OK);
959     return;
960 }
961
962
963 /**
964  * Handler for connection requests to new peers
965  * 
966  * @param cls closure
967  * @param client identification of the client
968  * @param message the actual message (PeerControl)
969  */
970 static void
971 handle_local_connect_add (void *cls,
972                           struct GNUNET_SERVER_Client *client,
973                           const struct GNUNET_MessageHeader *message)
974 {
975     struct GNUNET_MESH_PeerControl      *peer_msg;
976     struct MeshClient                   *c;
977     struct MeshTunnel                   *t;
978     MESH_TunnelNumber                   tid;
979     struct MeshPeerInfo                 *peer_info;
980     GNUNET_HashCode                     key;
981
982
983     /* Sanity check for client registration */
984     if (NULL == (c = retrieve_client(client))) {
985         GNUNET_break(0);
986         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
987         return;
988     }
989
990     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
991     /* Sanity check for message size */
992     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
993         GNUNET_break(0);
994         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
995         return;
996     }
997
998     /* Tunnel exists? */
999     tid = ntohl(peer_msg->tunnel_id);
1000     t = retrieve_tunnel_by_local_id(c, tid);
1001     if (NULL == t) {
1002         GNUNET_break(0);
1003         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1004         return;
1005     }
1006
1007     /* Does client own tunnel? */
1008     if (t->client->handle != client) {
1009         GNUNET_break(0);
1010         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1011         return;
1012     }
1013
1014     /* Ok, add peer to tunnel */
1015     peer_info = (struct MeshPeerInfo *) GNUNET_malloc(sizeof(struct MeshPeerInfo));
1016     peer_info->id = GNUNET_PEER_intern(&peer_msg->peer);
1017     peer_info->state = MESH_PEER_SEARCHING;
1018     t->peers_total++;
1019     /* FIXME insert */
1020     /* Start DHT search */
1021     GNUNET_CRYPTO_hash (&peer_msg->peer,
1022                         sizeof(struct GNUNET_PeerIdentity),
1023                         &key);
1024     peer_info->dhtget = GNUNET_DHT_get_start(dht_handle,
1025                                             GNUNET_TIME_UNIT_FOREVER_REL,
1026                                             GNUNET_BLOCK_TYPE_ANY,
1027                                             &key,
1028                                             4,    /* replication level */
1029                                             GNUNET_DHT_RO_RECORD_ROUTE,
1030                                             NULL, /* bloom filter */
1031                                             0,    /* mutator */
1032                                             NULL, /* xquery */
1033                                             0,    /* xquery bits */
1034                                             dht_get_response_handler,
1035                                             (void *)peer_info);
1036
1037     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1038     return;
1039 }
1040
1041
1042 /**
1043  * Handler for disconnection requests of peers in a tunnel
1044  * 
1045  * @param cls closure
1046  * @param client identification of the client
1047  * @param message the actual message (PeerControl)
1048  */
1049 static void
1050 handle_local_connect_del (void *cls,
1051                           struct GNUNET_SERVER_Client *client,
1052                           const struct GNUNET_MessageHeader *message)
1053 {
1054     struct GNUNET_MESH_PeerControl      *peer_msg;
1055     struct MeshClient                   *c;
1056     struct MeshTunnel                   *t;
1057     struct MeshPath                     *p;
1058     struct MeshPath                     *aux_path;
1059     MESH_TunnelNumber                   tid;
1060     GNUNET_PEER_Id                      peer_id;
1061
1062     /* Sanity check for client registration */
1063     if (NULL == (c = retrieve_client(client))) {
1064         GNUNET_break(0);
1065         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1066         return;
1067     }
1068     peer_msg = (struct GNUNET_MESH_PeerControl *)message;
1069     /* Sanity check for message size */
1070     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(peer_msg->header.size)) {
1071         GNUNET_break(0);
1072         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1073         return;
1074     }
1075
1076     /* Tunnel exists? */
1077     tid = ntohl(peer_msg->tunnel_id);
1078     t = retrieve_tunnel_by_local_id(c, tid);
1079     if (NULL == t) {
1080             GNUNET_break(0);
1081             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1082             return;
1083         }
1084
1085     /* Does client own tunnel? */
1086     if (t->client->handle != client) {
1087         GNUNET_break(0);
1088         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1089         return;
1090     }
1091
1092     /* Ok, delete peer from tunnel */
1093     peer_id = GNUNET_PEER_intern(&peer_msg->peer);
1094
1095     /* Delete paths */
1096     p = t->paths_head;
1097     while (p != NULL) {
1098         if (p->peers[p->length-1] == peer_id) { /* one path per destination */
1099             GNUNET_CONTAINER_DLL_remove(t->paths_head, t->paths_tail, p);
1100             GNUNET_PEER_decrement_rcs(p->peers, p->length);
1101             aux_path = p;
1102             p = p->next;
1103             GNUNET_free(aux_path);
1104         } else {
1105             p = p->next;
1106         }
1107     }
1108
1109     /* FIXME Delete peer info */
1110
1111     GNUNET_PEER_change_rc(peer_id, -1);
1112
1113     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1114     return;
1115 }
1116
1117
1118 /**
1119  * Handler for connection requests to new peers by type
1120  * 
1121  * @param cls closure
1122  * @param client identification of the client
1123  * @param message the actual message (ConnectPeerByType)
1124  */
1125 static void
1126 handle_local_connect_by_type (void *cls,
1127                               struct GNUNET_SERVER_Client *client,
1128                               const struct GNUNET_MessageHeader *message)
1129 {
1130     struct GNUNET_MESH_ConnectPeerByType        *connect_msg;
1131     MESH_TunnelNumber                           tid;
1132     GNUNET_MESH_ApplicationType                 application;
1133     struct MeshClient                           *c;
1134     struct MeshTunnel                           *t;
1135
1136     /* Sanity check for client registration */
1137     if (NULL == (c = retrieve_client(client))) {
1138         GNUNET_break(0);
1139         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1140         return;
1141     }
1142
1143     connect_msg = (struct GNUNET_MESH_ConnectPeerByType *)message;
1144     /* Sanity check for message size */
1145     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1146             ntohs(connect_msg->header.size))
1147     {
1148         GNUNET_break(0);
1149         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1150         return;
1151     }
1152
1153     /* Tunnel exists? */
1154     tid = ntohl(connect_msg->tunnel_id);
1155     t = retrieve_tunnel_by_local_id(c, tid);
1156     if (NULL == t) {
1157         GNUNET_break(0);
1158         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1159         return;
1160     }
1161
1162     /* Does client own tunnel? */
1163     if (t->client->handle != client) {
1164         GNUNET_break(0);
1165         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1166         return;
1167     }
1168
1169     /* Ok, lets find a peer offering the service */
1170     application = ntohl(connect_msg->type);
1171     application++; // FIXME silence warnings
1172
1173     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1174     return;
1175 }
1176
1177
1178 /**
1179  * Handler for client traffic directed to one peer
1180  * 
1181  * @param cls closure
1182  * @param client identification of the client
1183  * @param message the actual message
1184  */
1185 static void
1186 handle_local_network_traffic (void *cls,
1187                          struct GNUNET_SERVER_Client *client,
1188                          const struct GNUNET_MessageHeader *message)
1189 {
1190     struct MeshClient                           *c;
1191     struct MeshTunnel                           *t;
1192     struct GNUNET_MESH_Data                     *data_msg;
1193     MESH_TunnelNumber                           tid;
1194
1195     /* Sanity check for client registration */
1196     if (NULL == (c = retrieve_client(client))) {
1197         GNUNET_break(0);
1198         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1199         return;
1200     }
1201     data_msg = (struct GNUNET_MESH_Data *)message;
1202     /* Sanity check for message size */
1203     if (sizeof(struct GNUNET_MESH_PeerControl) !=
1204             ntohs(data_msg->header.size))
1205     {
1206         GNUNET_break(0);
1207         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1208         return;
1209     }
1210
1211     /* Tunnel exists? */
1212     tid = ntohl(data_msg->tunnel_id);
1213     t = retrieve_tunnel_by_local_id(c, tid);
1214     if (NULL == t) {
1215         GNUNET_break(0);
1216         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1217         return;
1218     }
1219
1220     /* Does client own tunnel? */
1221     if (t->client->handle != client) {
1222         GNUNET_break(0);
1223         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1224         return;
1225     }
1226
1227     /* TODO */
1228
1229     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1230     return;
1231 }
1232
1233 /**
1234  * Handler for client traffic directed to all peers in a tunnel
1235  * 
1236  * @param cls closure
1237  * @param client identification of the client
1238  * @param message the actual message
1239  */
1240 static void
1241 handle_local_network_traffic_bcast (void *cls,
1242                                     struct GNUNET_SERVER_Client *client,
1243                                     const struct GNUNET_MessageHeader *message)
1244 {
1245     struct MeshClient                           *c;
1246     struct MeshTunnel                           *t;
1247     struct GNUNET_MESH_DataBroadcast            *data_msg;
1248     MESH_TunnelNumber                           tid;
1249
1250     /* Sanity check for client registration */
1251     if (NULL == (c = retrieve_client(client))) {
1252         GNUNET_break(0);
1253         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1254         return;
1255     }
1256     data_msg = (struct GNUNET_MESH_DataBroadcast *)message;
1257     /* Sanity check for message size */
1258     if (sizeof(struct GNUNET_MESH_PeerControl) != ntohs(data_msg->header.size)) {
1259         GNUNET_break(0);
1260         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1261         return;
1262     }
1263
1264     /* Tunnel exists? */
1265     tid = ntohl(data_msg->tunnel_id);
1266     t = retrieve_tunnel_by_local_id(c, tid);
1267     if (NULL == t) {
1268         GNUNET_break(0);
1269         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1270         return;
1271     }
1272
1273     /* Does client own tunnel? */
1274     if (t->client->handle != client) {
1275         GNUNET_break(0);
1276         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
1277         return;
1278     }
1279
1280     /*  TODO */
1281
1282     GNUNET_SERVER_receive_done(client, GNUNET_OK);
1283     return;
1284 }
1285
1286 /**
1287  * Functions to handle messages from clients
1288  */
1289 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
1290   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
1291   {&handle_local_tunnel_create, NULL,
1292    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE,
1293    sizeof(struct GNUNET_MESH_TunnelMessage)},
1294   {&handle_local_tunnel_destroy, NULL,
1295    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY,
1296    sizeof(struct GNUNET_MESH_TunnelMessage)},
1297   {&handle_local_connect_add, NULL,
1298    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD,
1299    sizeof(struct GNUNET_MESH_PeerControl)},
1300   {&handle_local_connect_del, NULL,
1301    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL,
1302    sizeof(struct GNUNET_MESH_PeerControl)},
1303   {&handle_local_connect_by_type, NULL,
1304    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
1305    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
1306   {&handle_local_network_traffic, NULL,
1307    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
1308   {&handle_local_network_traffic_bcast, NULL,
1309    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0},
1310   {NULL, NULL, 0, 0}
1311 };
1312
1313
1314 /**
1315  * To be called on core init/fail.
1316  *
1317  * @param cls service closure
1318  * @param server handle to the server for this service
1319  * @param identity the public identity of this peer
1320  * @param publicKey the public key of this peer
1321  */
1322 static void
1323 core_init (void *cls,
1324            struct GNUNET_CORE_Handle *server,
1325            const struct GNUNET_PeerIdentity *identity,
1326            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
1327 {
1328     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1329                 "Core init\n");
1330     core_handle = server;
1331     myid = GNUNET_PEER_intern(identity);
1332     return;
1333 }
1334
1335 /**
1336  * Method called whenever a given peer connects.
1337  *
1338  * @param cls closure
1339  * @param peer peer identity this notification is about
1340  * @param atsi performance data for the connection
1341  */
1342 static void
1343 core_connect (void *cls,
1344               const struct GNUNET_PeerIdentity *peer,
1345               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
1346 {
1347     GNUNET_PEER_Id      pid;
1348     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1349                 "Peer connected\n");
1350     pid = GNUNET_PEER_intern(peer);
1351     if (myid == pid) {
1352         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1353                 "     (self)\n");
1354     }
1355     return;
1356 }
1357
1358 /**
1359  * Method called whenever a peer disconnects.
1360  *
1361  * @param cls closure
1362  * @param peer peer identity this notification is about
1363  */
1364 static void
1365 core_disconnect (void *cls,
1366                 const struct
1367                 GNUNET_PeerIdentity *peer)
1368 {
1369     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1370                 "Peer disconnected\n");
1371     return;
1372 }
1373
1374 /******************************************************************************/
1375 /************************      MAIN FUNCTIONS      ****************************/
1376 /******************************************************************************/
1377
1378 /**
1379  * Task run during shutdown.
1380  *
1381  * @param cls unused
1382  * @param tc unused
1383  */
1384 static void
1385 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1386 {
1387     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1388                 "MESH shutting down\n");
1389     if (core_handle != NULL) {
1390         GNUNET_CORE_disconnect (core_handle);
1391         core_handle = NULL;
1392     }
1393     if (dht_handle != NULL) {
1394         GNUNET_DHT_disconnect (dht_handle);
1395         dht_handle = NULL;
1396     } 
1397 }
1398
1399 /**
1400  * Process mesh requests.
1401  *
1402  * @param cls closure
1403  * @param server the initialized server
1404  * @param c configuration to use
1405  */
1406 static void
1407 run (void *cls,
1408      struct GNUNET_SERVER_Handle *server,
1409      const struct GNUNET_CONFIGURATION_Handle *c)
1410 {
1411     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1412                 "MESH starting to run\n");
1413     GNUNET_SERVER_add_handlers (server, plugin_handlers);
1414     GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
1415     core_handle = GNUNET_CORE_connect (c,               /* Main configuration */
1416                             32,                                 /* queue size */
1417                             NULL,         /* Closure passed to MESH functions */
1418                             &core_init,      /* Call core_init once connected */
1419                             &core_connect,                 /* Handle connects */
1420                             &core_disconnect,  /* remove peers on disconnects */
1421                             NULL,       /* Do we care about "status" updates? */
1422                             NULL, /* Don't notify about all incoming messages */
1423                             GNUNET_NO,     /* For header only in notification */
1424                             NULL, /* Don't notify about all outbound messages */
1425                             GNUNET_NO,    /* For header-only out notification */
1426                             core_handlers);        /* Register these handlers */
1427     if (core_handle == NULL) {
1428         GNUNET_break(0);
1429     }
1430     dht_handle = GNUNET_DHT_connect(c, 100); /* FIXME ht len correct size? */
1431     if (dht_handle == NULL) {
1432         GNUNET_break(0);
1433     }
1434     next_tid = 0;
1435
1436     /* Scheduled the task to clean up when shutdown is called */
1437     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1438                                   &shutdown_task, NULL);
1439
1440 }
1441
1442 /**
1443  * The main function for the mesh service.
1444  *
1445  * @param argc number of arguments from the command line
1446  * @param argv command line arguments
1447  * @return 0 ok, 1 on error
1448  */
1449 int
1450 main (int argc, char *const *argv)
1451 {
1452     int ret;
1453
1454     ret = (GNUNET_OK ==
1455            GNUNET_SERVICE_run (argc,
1456                                argv,
1457                                "mesh",
1458                                GNUNET_SERVICE_OPTION_NONE,
1459                                &run, NULL)) ? 0 : 1;
1460     return ret;
1461 }