WiP (create tunnel)
[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 #include "mesh.h"
49
50
51 /******************************************************************************/
52 /********************      MESH NETWORK MESSAGES     **************************/
53 /******************************************************************************/
54
55 /**
56  * Message for mesh path management
57  */
58 struct GNUNET_MESH_ManipulatePath
59 {
60     /**
61      * Type: GNUNET_MESSAGE_TYPE_MESH_PATH_[CREATE|CHANGE|ADD|DEL]
62      *
63      * Size: sizeof(struct GNUNET_MESH_ManipulatePath) +
64      *       path_length * sizeof (struct GNUNET_PeerIdentity)
65      */
66     struct GNUNET_MessageHeader header;
67
68     /**
69      * Global id of the tunnel this path belongs to,
70      * unique in conjunction with the origin.
71      */
72     uint32_t tid GNUNET_PACKED;
73
74     /**
75      * Information about speed requirements.  If the tunnel cannot sustain the 
76      * minimum bandwidth, packets are to be dropped.
77      */
78     uint32_t speed_min GNUNET_PACKED;
79
80     /**
81      * 64-bit alignment.
82      */
83     uint32_t reserved GNUNET_PACKED;
84
85     /**
86      * path_length structs defining the *whole* path from the origin [0] to the
87      * final destination [path_length-1].
88      */
89     /* struct GNUNET_PeerIdentity peers[path_length]; */
90 };
91
92 /**
93  * Message for mesh data traffic to all tunnel targets.
94  */
95 struct GNUNET_MESH_OriginMulticast
96 {
97     /**
98      * Type: GNUNET_MESSAGE_TYPE_DATA_MULTICAST
99      */
100     struct GNUNET_MessageHeader header;
101
102     /**
103      * TID of the tunnel
104      */
105     uint32_t tid GNUNET_PACKED;
106
107     /**
108      * OID of the tunnel
109      */
110     struct GNUNET_PeerIdentity oid;
111
112     /**
113      * Payload follows
114      */
115 };
116
117
118 /**
119  * Message for mesh data traffic to a particular destination from origin.
120  */
121 struct GNUNET_MESH_DataMessageFromOrigin
122 {
123     /**
124      * Type: GNUNET_MESSAGE_TYPE_DATA_MESSAGE_FROM_ORIGIN
125      */
126     struct GNUNET_MessageHeader header;
127
128     /**
129      * TID of the tunnel
130      */
131     uint32_t tid GNUNET_PACKED;
132
133     /**
134      * OID of the tunnel
135      */
136     struct GNUNET_PeerIdentity oid;
137
138     /**
139      * Destination.
140      */
141     struct GNUNET_PeerIdentity destination;
142
143     /**
144      * Payload follows
145      */
146 };
147
148
149 /**
150  * Message for mesh data traffic from a tunnel participant to origin.
151  */
152 struct GNUNET_MESH_DataMessageToOrigin
153 {
154     /**
155      * Type: GNUNET_MESSAGE_TYPE_DATA_MESSAGE_TO_ORIGIN
156      */
157     struct GNUNET_MessageHeader header;
158
159     /**
160      * TID of the tunnel
161      */
162     uint32_t tid GNUNET_PACKED;
163
164     /**
165      * OID of the tunnel
166      */
167     struct GNUNET_PeerIdentity oid;
168
169     /**
170      * Sender of the message.
171      */
172     struct GNUNET_PeerIdentity sender;
173
174     /**
175      * Payload follows
176      */
177 };
178
179 /**
180  * Message for mesh flow control
181  */
182 struct GNUNET_MESH_SpeedNotify
183 {
184     /**
185      * Type: GNUNET_MESSAGE_TYPE_DATA_SPEED_NOTIFY
186      */
187     struct GNUNET_MessageHeader header;
188
189     /**
190      * TID of the tunnel
191      */
192     uint32_t tid GNUNET_PACKED;
193
194     /**
195      * OID of the tunnel
196      */
197     struct GNUNET_PeerIdentity oid;
198
199     /**
200      * Slowest link down the path (above minimum speed requirement).
201      */
202     uint32_t speed_min;
203
204 };
205
206 /******************************************************************************/
207 /************************      DATA STRUCTURES     ****************************/
208 /******************************************************************************/
209
210 /**
211  * All the states a peer participating in a tunnel can be in.
212  */
213 enum PeerState
214 {
215     /**
216      * Request sent, not yet answered.
217      */
218     MESH_PEER_WAITING,
219
220     /**
221      * Peer connected and ready to accept data
222      */
223     MESH_PEER_READY,
224
225     /**
226      * Peer connected previosly but not responding
227      */
228     MESH_PEER_RECONNECTING,
229
230 };
231
232 /**
233  * Struct containing all information regarding a given peer
234  */
235 struct PeerInfo
236 {
237     /**
238      * ID of the peer
239      */
240     GNUNET_PEER_Id              id;
241
242     /**
243      * Is the peer reachable? Is the peer even connected?
244      */
245     enum PeerState              state;
246
247     /**
248      * Who to send the data to --- FIXME what about multiple (alternate) paths?
249      */
250     GNUNET_PEER_Id              first_hop;
251
252     /**
253      * Max data rate to this peer
254      */
255     uint32_t                    max_speed;
256 };
257
258
259 typedef uint32_t MESH_PathID;
260 /**
261  * Information regarding a path
262  */
263 struct Path
264 {
265     /**
266      * Double linked list
267      */
268     struct Path                 *next;
269     struct Path                 *prev;
270     /**
271      * Id of the path, in case it's needed
272      */
273     MESH_PathID                 id;
274
275     /**
276      * Whether the path is serving traffic in a tunnel or is a backup
277      */
278     int                         in_use;
279
280     /**
281      * List of all the peers that form the path from origin to target
282      */
283     GNUNET_PEER_Id              *peers;
284 };
285
286
287 struct Client; /* FWD declaration */
288 /**
289  * Struct containing all information regarding a tunnel
290  * For an intermediate node the improtant info used will be:
291  * - OID        \ To identify
292  * - TID        / the tunnel
293  * - paths[0]   | To know where to send it next
294  * - metainfo: ready, speeds, accounting
295  * For an end node more fields will be needed (client-handling)
296  */
297 struct MESH_tunnel
298 {
299
300     /**
301      * Double linked list
302      */
303     struct MESH_tunnel          *next;
304     struct MESH_tunnel          *prev;
305
306     /**
307      * Origin ID: Node that created the tunnel
308      */
309     GNUNET_PEER_Id              oid;
310
311     /**
312      * Tunnel number (unique for a given oid)
313      */
314     MESH_TunnelID               tid;
315
316     /**
317      * Minimal speed for this tunnel in kb/s
318      */
319     uint32_t                    speed_min;
320
321     /**
322      * Maximal speed for this tunnel in kb/s
323      */
324     uint32_t                    speed_max;
325
326     /**
327      * Last time the tunnel was used
328      */
329     struct GNUNET_TIME_Absolute timestamp;
330
331     /**
332      * Peers in the tunnel, for future optimizations
333      */
334     struct PeerInfo             *peers_head;
335     struct PeerInfo             *peers_tail;
336
337     /**
338      * Number of peers that are connected and potentially ready to receive data
339      */
340     unsigned int                peers_ready;
341
342     /**
343      * Number of peers that have been added to the tunnel
344      */
345     unsigned int                peers_total;
346
347     /**
348      * Paths (used and backup)
349      */
350     struct Path                 *paths_head;
351     struct Path                 *paths_tail;
352
353     /**
354      * If this tunnel was created by a local client, what's its handle?
355      */
356     struct Client               *client;
357
358     /**
359      * Messages ready to transmit??? -- FIXME real queues needed
360      */
361     struct GNUNET_MessageHeader *msg_out;
362
363     /**
364      * Messages received and not processed??? -- FIXME real queues needed
365      */
366     struct GNUNET_MessageHeader *msg_in;
367
368 };
369
370 /**
371  * Struct containing information about a client of the service
372  */
373 struct Client
374 {
375     /**
376      * Double linked list
377      */
378     struct Client               *next;
379     struct Client               *prev;
380
381     /**
382      * Tunnels that belong to this client, for convenience on disconnect
383      */
384     struct MESH_tunnel          *tunnels_head;
385     struct MESH_tunnel          *tunnels_tail;
386
387     /**
388      * Handle to communicate with the client
389      */
390     struct GNUNET_SERVER_Client *handle;
391
392     /**
393      * Messages that this client has declared interest in
394      */
395     GNUNET_MESH_ApplicationType *messages_subscribed;
396     unsigned int                subscription_counter;
397
398 };
399
400 /******************************************************************************/
401 /***********************      GLOBAL VARIABLES     ****************************/
402 /******************************************************************************/
403
404 /**
405  * All the clients
406  */
407 static struct Client            *clients_head;
408 static struct Client            *clients_tail;
409
410 /**
411  * All the tunnels
412  */
413 static struct MESH_tunnel       *tunnels_head;
414 static struct MESH_tunnel       *tunnels_tail;
415
416 /**
417  * All the paths (for future path optimization)
418  */
419 // static struct Path             *paths_head;
420 // static struct Path             *paths_tail;
421
422 /******************************************************************************/
423 /********************      MESH NETWORK HANDLERS     **************************/
424 /******************************************************************************/
425
426 /**
427  * Core handler for path creation
428  * struct GNUNET_CORE_MessageHandler
429  *
430  * @param cls closure
431  * @param message message
432  * @param peer peer identity this notification is about
433  * @param atsi performance data
434  * @return GNUNET_OK to keep the connection open,
435  *         GNUNET_SYSERR to close it (signal serious error)
436  *
437  */
438 static int
439 handle_mesh_path_create (void *cls,
440                               const struct GNUNET_PeerIdentity *peer,
441                               const struct GNUNET_MessageHeader *message,
442                               const struct GNUNET_TRANSPORT_ATS_Information
443                               *atsi)
444 {
445   /*
446    * EXAMPLE OF USING THE API
447    * NOT ACTUAL CODE!!!!!
448    */
449   /*client *c;
450   tunnel *t;
451
452   t = new;
453   GNUNET_CONTAINER_DLL_insert (c->my_tunnels_head,
454                                c->my_tunnels_tail,
455                                t);
456
457   while (NULL != (t = c->my_tunnels_head))
458     {
459       GNUNET_CONTAINER_DLL_remove (c->my_tunnels_head,
460                                    c->my_tunnels_tail,
461                                    t);
462       GNUNET_free (t);
463     }
464   */
465
466
467     /* Extract path */
468     /* Find origin & self */
469     /* Search for origin in local tunnels */
470     /* Create tunnel / add path */
471     /* Retransmit to next link in chain, if any (core_notify + callback) */
472     return GNUNET_OK;
473 }
474
475 /**
476  * Core handler for mesh network traffic
477  *
478  * @param cls closure
479  * @param message message
480  * @param peer peer identity this notification is about
481  * @param atsi performance data
482  * @return GNUNET_OK to keep the connection open,
483  *         GNUNET_SYSERR to close it (signal serious error)
484  */
485 static int
486 handle_mesh_network_traffic (void *cls,
487                              const struct GNUNET_PeerIdentity *peer,
488                              const struct GNUNET_MessageHeader *message,
489                              const struct GNUNET_TRANSPORT_ATS_Information
490                              *atsi)
491 {
492     if(GNUNET_MESSAGE_TYPE_MESH_DATA_GO == ntohs(message->type)) {
493         /* Retransmit to next in path of tunnel identified by message */
494         return GNUNET_OK;
495     } else { /* GNUNET_MESSAGE_TYPE_MESH_DATA_BACK */
496         /* Retransmit to previous in path of tunnel identified by message */
497         return GNUNET_OK;
498     }
499 }
500
501 /**
502  * Functions to handle messages from core
503  */
504 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
505   {&handle_mesh_path_create, GNUNET_MESSAGE_TYPE_MESH_PATH_CREATE, 0},
506   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_GO, 0},
507   {&handle_mesh_network_traffic, GNUNET_MESSAGE_TYPE_MESH_DATA_BACK, 0},
508   {NULL, 0, 0}
509 };
510
511
512
513 /******************************************************************************/
514 /*********************       MESH LOCAL HANDLES      **************************/
515 /******************************************************************************/
516
517 /**
518  * Handler for client disconnection
519  *
520  * @param cls closure
521  * @param client identification of the client; NULL
522  *        for the last call when the server is destroyed
523  */
524 static void
525 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
526 {
527     struct Client       *c, *next;
528     struct MESH_tunnel  *t;
529
530     /* If there are no clients registered, something is wrong... or is it?
531      * FIXME: what happens if a client connects, doesn't send a MESH_Connect
532      * and disconnects? Does the service get a disconnect notification anyway?
533      */
534     GNUNET_assert(NULL != clients_head);
535     for (c = clients_head; c != clients_head; c = next) {
536         if (c->handle == client) {
537             GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
538             while (NULL != (t = c->tunnels_head)) {
539                 GNUNET_CONTAINER_DLL_remove (c->tunnels_head, c->tunnels_tail, t);
540                 GNUNET_CONTAINER_DLL_remove (tunnels_head, tunnels_tail, t);
541                 /* TODO free paths and other tunnel dynamic structures */
542                 GNUNET_free (t);
543             }
544             GNUNET_free (c->messages_subscribed);
545             next = c->next;
546             GNUNET_free (c);
547         } else {
548             next = c->next;
549         }
550     }
551
552     return;
553 }
554
555 /**
556  * Handler for new clients
557  * 
558  * @param cls closure
559  * @param client identification of the client
560  * @param message the actual message, which includes messages the client wants
561  */
562 static void
563 handle_local_new_client (void *cls,
564                          struct GNUNET_SERVER_Client *client,
565                          const struct GNUNET_MessageHeader *message)
566 {
567     struct Client               *c;
568     unsigned int                payload_size;
569 //     FIXME: is this needed? should we delete the GNUNET_MESH_Connect struct?
570 //     struct GNUNET_MESH_Connect  *connect_msg;
571 // 
572 //     connect_msg = (struct GNUNET_MESH_Connect *) message;
573
574     /* FIXME: is this a good idea? */
575     GNUNET_assert(GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT == message->type);
576
577     /* Check data sanity */
578     payload_size = message->size - sizeof(struct GNUNET_MessageHeader);
579     if (0 != payload_size % sizeof(GNUNET_MESH_ApplicationType)) {
580         GNUNET_break(0);
581         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
582         return;
583     }
584
585     /* Create new client structure */
586     c = GNUNET_malloc(sizeof(struct Client));
587     c->handle = client;
588     c->tunnels_head = NULL;
589     c->tunnels_tail = NULL;
590     if(payload_size != 0) {
591         c->messages_subscribed = GNUNET_malloc(payload_size);
592         memcpy(c->messages_subscribed, &message[1], payload_size);
593     } else {
594         c->messages_subscribed = NULL;
595     }
596     c->subscription_counter = payload_size/sizeof(GNUNET_MESH_ApplicationType);
597
598     /* Insert new client in DLL */
599     GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
600
601     GNUNET_SERVER_receive_done(client, GNUNET_OK);
602 }
603
604 /**
605  * Handler for requests of new tunnels
606  * 
607  * @param cls closure
608  * @param client identification of the client
609  * @param message the actual message
610  */
611 static void
612 handle_local_tunnel_create (void *cls,
613                             struct GNUNET_SERVER_Client *client,
614                             const struct GNUNET_MessageHeader *message)
615 {
616     struct Client                       *c;
617     struct GNUNET_MESH_TunnelMessage    *tunnel_msg;
618     struct MESH_tunnel                  *t;
619
620     /* Sanity check for client registration */
621     /* TODO: refactor into new function */
622     for (c = clients_head; c != clients_head; c = c->next) {
623         if(c->handle == client) break;
624     }
625     if(c->handle != client) { /* Client hasn't registered, not a good thing */
626         GNUNET_break(0);
627         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
628         return;
629     }
630
631     /* Message sanity check */
632     /* FIXME: two different checks, to know why it fails? */
633     if(sizeof(struct GNUNET_MESH_TunnelMessage) != message->size ||
634       GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE != message->type) {
635         GNUNET_break(0);
636         GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
637         return;
638     }
639
640     tunnel_msg = (struct GNUNET_MESH_TunnelMessage *) message;
641     /* Sanity check for tunnel numbering */
642     if(0 == (tunnel_msg->tunnel_id & 0x80000000)) {
643             GNUNET_break(0);
644             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
645             return;
646         }
647     /* Sanity check for duplicate tunnel IDs */
648     for (t = tunnels_head; t != tunnels_head; t = t->next) {
649         /* TODO - maybe this is not enough, need to consider the whole
650          * local/global numbering system, but probably it's ok (WiP)
651          */
652         if(t->tid == tunnel_msg->tunnel_id) {
653             GNUNET_break(0);
654             GNUNET_SERVER_receive_done(client, GNUNET_SYSERR);
655             return;
656         }
657     }
658     //tunnel_msg->tunnel_id;
659     
660     
661     return;
662 }
663
664 /**
665  * Handler for requests of deleting tunnels
666  * 
667  * @param cls closure
668  * @param client identification of the client
669  * @param message the actual message
670  */
671 static void
672 handle_local_tunnel_destroy (void *cls,
673                              struct GNUNET_SERVER_Client *client,
674                              const struct GNUNET_MessageHeader *message)
675 {
676     return;
677 }
678
679 /**
680  * Handler for connection requests to new peers
681  * 
682  * @param cls closure
683  * @param client identification of the client
684  * @param message the actual message
685  */
686 static void
687 handle_local_connect (void *cls,
688                          struct GNUNET_SERVER_Client *client,
689                          const struct GNUNET_MessageHeader *message)
690 {
691     return;
692 }
693
694 /**
695  * Handler for client traffic
696  * 
697  * @param cls closure
698  * @param client identification of the client
699  * @param message the actual message
700  */
701 static void
702 handle_local_network_traffic (void *cls,
703                          struct GNUNET_SERVER_Client *client,
704                          const struct GNUNET_MessageHeader *message)
705 {
706     return;
707 }
708
709 /**
710  * Functions to handle messages from clients
711  */
712 static struct GNUNET_SERVER_MessageHandler plugin_handlers[] = {
713   {&handle_local_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
714   {&handle_local_tunnel_create, NULL,
715    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE, 0},
716   {&handle_local_tunnel_destroy, NULL,
717    GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY, 0},
718   {&handle_local_connect, NULL,
719    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_ADD, 0},
720   {&handle_local_connect, NULL,
721    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_DEL, 0},
722   {&handle_local_connect, NULL,
723    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_BY_TYPE,
724    sizeof(struct GNUNET_MESH_ConnectPeerByType)},
725   {&handle_local_connect, NULL,
726    GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT_PEER_CANCEL, 0},
727   {&handle_local_network_traffic, NULL,
728    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0}, /* FIXME needed? */
729   {&handle_local_network_traffic, NULL,
730    GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA_BROADCAST, 0}, /* FIXME needed? */
731   {NULL, NULL, 0, 0}
732 };
733
734
735 /**
736  * To be called on core init/fail.
737  *
738  * @param cls service closure
739  * @param server handle to the server for this service
740  * @param identity the public identity of this peer
741  * @param publicKey the public key of this peer
742  */
743 static void
744 core_init (void *cls,
745            struct GNUNET_CORE_Handle *server,
746            const struct GNUNET_PeerIdentity *identity,
747            const struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded *publicKey)
748 {
749     return;
750 }
751
752 /**
753  * Method called whenever a given peer connects.
754  *
755  * @param cls closure
756  * @param peer peer identity this notification is about
757  * @param atsi performance data for the connection
758  */
759 static void
760 core_connect (void *cls,
761               const struct GNUNET_PeerIdentity *peer,
762               const struct GNUNET_TRANSPORT_ATS_Information *atsi)
763 {
764     return;
765 }
766
767 /**
768  * Method called whenever a peer disconnects.
769  *
770  * @param cls closure
771  * @param peer peer identity this notification is about
772  */
773 static void
774 core_disconnect (void *cls,
775                 const struct
776                 GNUNET_PeerIdentity *peer)
777 {
778     return;
779 }
780
781 /******************************************************************************/
782 /************************      MAIN FUNCTIONS      ****************************/
783 /******************************************************************************/
784
785 /**
786  * Process mesh requests. FIXME NON FUNCTIONAL, SKELETON
787  *
788  * @param cls closure
789  * @param server the initialized server
790  * @param c configuration to use
791  */
792 static void
793 run (void *cls,
794      struct GNUNET_SERVER_Handle *server,
795      const struct GNUNET_CONFIGURATION_Handle *c)
796 {
797   struct GNUNET_CORE_Handle *core;
798
799   GNUNET_SERVER_add_handlers (server, plugin_handlers);
800   GNUNET_SERVER_disconnect_notify (server, &handle_client_disconnect, NULL);
801   core = GNUNET_CORE_connect (c,                        /* Main configuration */
802                             32,                                 /* queue size */
803                             NULL,         /* Closure passed to MESH functions */
804                             &core_init,      /* Call core_init once connected */
805                             &core_connect,                 /* Handle connects */
806                             &core_disconnect,  /* remove peers on disconnects */
807                             NULL,       /* Do we care about "status" updates? */
808                             NULL, /* Don't notify about all incoming messages */
809                             GNUNET_NO,     /* For header only in notification */
810                             NULL, /* Don't notify about all outbound messages */
811                             GNUNET_NO,    /* For header-only out notification */
812                             core_handlers);        /* Register these handlers */
813
814   if (core == NULL)
815     return;
816 }
817
818 /**
819  * The main function for the mesh service.
820  *
821  * @param argc number of arguments from the command line
822  * @param argv command line arguments
823  * @return 0 ok, 1 on error
824  */
825 int
826 main (int argc, char *const *argv)
827 {
828     int ret;
829
830     ret = (GNUNET_OK ==
831            GNUNET_SERVICE_run (argc,
832                                argv,
833                                "mesh",
834                                GNUNET_SERVICE_OPTION_NONE,
835                                &run, NULL)) ? 0 : 1;
836     return ret;
837     }