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