Previous: , Up: Writing a Service   [Contents]


4.4.2 Starting a Service

The key API definition for creating a service is the GNUNET\_SERVICE\_MAIN macro:

GNUNET_SERVICE_MAIN
("service-name",
 GNUNET_SERVICE_OPTION_NONE,
 &run,
 &client_connect_cb,
 &client_disconnect_cb,
 NULL,
 GNUNET_MQ_hd_fixed_size (...),
 GNUNET_MQ_hd_var_size (...),
 GNUNET_MQ_handler_end ());

In addition to the service name and flags, the macro takes three functions, typically called run, client\_connect\_cb and client\_disconnect\_cb as well as an array of message handlers that will be called for incoming messages from clients.

A minimal version of the three central service funtions would look like this:

static void
run (void *cls,
     const struct GNUNET_CONFIGURATION_Handle *c,
     struct GNUNET_SERVICE_Handle *service)
{
}

static void *
client_connect_cb (void *cls,
                   struct GNUNET_SERVICE_Client *c,
                   struct GNUNET_MQ_Handle *mq)
{
  return c;
}

static void
client_disconnect_cb (void *cls,
                      struct GNUNET_SERVICE_Client *c,
                      void *internal_cls)
{
  GNUNET_assert (c == internal_cls);
}

Exercise: Write a stub service that processes no messages at all in your code. Create a default configuration for it, integrate it with the build system and start the service from gnunet-service-arm using gnunet-arm -i NAME.

Exercise: Figure out how to set the closure (cls) for handlers of a service.

Exercise: Figure out how to send messages from the service back to the client.

Each handler function in the service must eventually (possibly in some asynchronous continuation) call GNUNET\_SERVICE\_client\_continue(). Only after this call additional messages from the same client may be processed. This way, the service can throttle processing messages from the same client.

Exercise: Change the service to “handle” the message from your client (for now, by printing a message). What happens if you forget to call GNUNET\_SERVICE\_client\_continue()?