X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Finclude%2Fgnunet_service_lib.h;h=be52cce441c60ef692bf1a5e3140cb3c9a3a0209;hb=5fb272d662eca0707b1a5c7747ae476f8157d332;hp=82089954edb497c78a6055d0edfcc93f6d1dfeee;hpb=cf45b8dff29c366d51aa2e6ea6a64b99b514b9c9;p=oweals%2Fgnunet.git diff --git a/src/include/gnunet_service_lib.h b/src/include/gnunet_service_lib.h index 82089954e..be52cce44 100644 --- a/src/include/gnunet_service_lib.h +++ b/src/include/gnunet_service_lib.h @@ -1,27 +1,33 @@ /* This file is part of GNUnet. - (C) 2009 Christian Grothoff (and other contributing authors) + Copyright (C) 2009-2013, 2016, 2017 GNUnet e.V. - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. + GNUnet is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, + or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. + Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . */ /** - * @file include/gnunet_service_lib.h - * @brief functions related to starting services * @author Christian Grothoff + * + * @file + * Functions related to starting services + * + * @defgroup service Service library + * Start service processes. + * + * @see [Documentation](https://gnunet.org/developer-handbook-util-services) + * + * @{ */ #ifndef GNUNET_SERVICE_LIB_H @@ -36,81 +42,378 @@ extern "C" #endif #include "gnunet_configuration_lib.h" -#include "gnunet_server_lib.h" +#include "gnunet_mq_lib.h" + + +/** + * Options for the service (bitmask). + */ +enum GNUNET_SERVICE_Options +{ + /** + * Use defaults. Terminates all client connections and the listen + * sockets immediately upon receiving the shutdown signal. + */ + GNUNET_SERVICE_OPTION_NONE = 0, + + /** + * Do not trigger server shutdown on signal at all; instead, allow + * for the user to terminate the server explicitly when needed + * by calling #GNUNET_SERVICE_shutdown(). + */ + GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN = 1, + + /** + * Trigger a SOFT server shutdown on signals, allowing active + * non-monitor clients to complete their transactions. + */ + GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN = 2 +}; + + + +/* **************** NEW SERVICE API ********************** */ + +/** + * Handle to a service. + */ +struct GNUNET_SERVICE_Handle; + + +/** + * Handle to a client that is connected to a service. + */ +struct GNUNET_SERVICE_Client; + /** - * Function called by the service's run - * method to run service-specific setup code. + * Callback to initialize a service, called exactly once when the service is run. * - * @param cls closure - * @param sched scheduler to use - * @param server the initialized server - * @param cfg configuration to use + * @param cls closure passed to #GNUNET_SERVICE_MAIN + * @param cfg configuration to use for this service + * @param sh handle to the newly create service */ -typedef void (*GNUNET_SERVICE_Main) (void *cls, - struct GNUNET_SCHEDULER_Handle * sched, - struct GNUNET_SERVER_Handle * server, - const struct GNUNET_CONFIGURATION_Handle * - cfg); +typedef void +(*GNUNET_SERVICE_InitCallback)(void *cls, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct GNUNET_SERVICE_Handle *sh); /** - * Run a standard GNUnet service startup sequence (initialize loggers - * and configuration, parse options). + * Callback to be called when a client connects to the service. * - * @param argc number of command line arguments - * @param argv command line arguments - * @param serviceName our service name - * @param task main task of the service - * @param task_cls closure for task - * @return GNUNET_SYSERR on error, GNUNET_OK - * if we shutdown nicely + * @param cls closure for the service + * @param c the new client that connected to the service + * @param mq the message queue used to send messages to the client + * @return the client-specific (`internal') closure */ -int GNUNET_SERVICE_run (int argc, - char *const *argv, - const char *serviceName, - GNUNET_SERVICE_Main task, - void *task_cls); +typedef void * +(*GNUNET_SERVICE_ConnectHandler)(void *cls, + struct GNUNET_SERVICE_Client *c, + struct GNUNET_MQ_Handle *mq); + +/** + * Callback to be called when a client disconnected from the service + * + * @param cls closure for the service + * @param c the client that disconnected + * @param internal_cls the client-specific (`internal') closure + */ +typedef void +(*GNUNET_SERVICE_DisconnectHandler)(void *cls, + struct GNUNET_SERVICE_Client *c, + void *internal_cls); -struct GNUNET_SERVICE_Context; /** - * Run a service startup sequence within an existing - * initialized system. + * Low-level function to start a service if the scheduler + * is already running. Should only be used directly in + * special cases. + * + * The function will launch the service with the name @a service_name + * using the @a service_options to configure its shutdown + * behavior. When clients connect or disconnect, the respective + * @a connect_cb or @a disconnect_cb functions will be called. For + * messages received from the clients, the respective @a handlers will + * be invoked; for the closure of the handlers we use the return value + * from the @a connect_cb invocation of the respective client. * - * @param serviceName our service name - * @param sched scheduler to use + * Each handler MUST call #GNUNET_SERVICE_client_continue() after each + * message to receive further messages from this client. If + * #GNUNET_SERVICE_client_continue() is not called within a short + * time, a warning will be logged. If delays are expected, services + * should call #GNUNET_SERVICE_client_disable_continue_warning() to + * disable the warning. + * + * Clients sending invalid messages (based on @a handlers) will be + * dropped. Additionally, clients can be dropped at any time using + * #GNUNET_SERVICE_client_drop(). + * + * The service must be stopped using #GNUNET_SERVICE_stop(). + * + * @param service_name name of the service to run * @param cfg configuration to use - * @return NULL on error, service handle + * @param connect_cb function to call whenever a client connects + * @param disconnect_cb function to call whenever a client disconnects + * @param cls closure argument for @a connect_cb and @a disconnect_cb + * @param handlers NULL-terminated array of message handlers for the service, + * the closure will be set to the value returned by + * the @a connect_cb for the respective connection + * @return NULL on error + */ +struct GNUNET_SERVICE_Handle * +GNUNET_SERVICE_start (const char *service_name, + const struct GNUNET_CONFIGURATION_Handle *cfg, + GNUNET_SERVICE_ConnectHandler connect_cb, + GNUNET_SERVICE_DisconnectHandler disconnect_cb, + void *cls, + const struct GNUNET_MQ_MessageHandler *handlers); + + +/** + * Stops a service that was started with #GNUNET_SERVICE_start(). + * + * @param srv service to stop + */ +void +GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Handle *srv); + + +/** + * Creates the "main" function for a GNUnet service. You + * should almost always use the #GNUNET_SERVICE_MAIN macro + * instead of calling this function directly (except + * for ARM, which should call this function directly). + * + * The function will launch the service with the name @a service_name + * using the @a service_options to configure its shutdown + * behavior. Once the service is ready, the @a init_cb will be called + * for service-specific initialization. @a init_cb will be given the + * service handler which can be used to control the service's + * availability. When clients connect or disconnect, the respective + * @a connect_cb or @a disconnect_cb functions will be called. For + * messages received from the clients, the respective @a handlers will + * be invoked; for the closure of the handlers we use the return value + * from the @a connect_cb invocation of the respective client. + * + * Each handler MUST call #GNUNET_SERVICE_client_continue() after each + * message to receive further messages from this client. If + * #GNUNET_SERVICE_client_continue() is not called within a short + * time, a warning will be logged. If delays are expected, services + * should call #GNUNET_SERVICE_client_disable_continue_warning() to + * disable the warning. + * + * Clients sending invalid messages (based on @a handlers) will be + * dropped. Additionally, clients can be dropped at any time using + * #GNUNET_SERVICE_client_drop(). + * + * @param argc number of command-line arguments in @a argv + * @param argv array of command-line arguments + * @param service_name name of the service to run + * @param options options controlling shutdown of the service + * @param service_init_cb function to call once the service is ready + * @param connect_cb function to call whenever a client connects + * @param disconnect_cb function to call whenever a client disconnects + * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb + * @param handlers NULL-terminated array of message handlers for the service, + * the closure will be set to the value returned by + * the @a connect_cb for the respective connection + * @return 0 on success, non-zero on error + */ +int +GNUNET_SERVICE_run_ (int argc, + char *const *argv, + const char *service_name, + enum GNUNET_SERVICE_Options options, + GNUNET_SERVICE_InitCallback service_init_cb, + GNUNET_SERVICE_ConnectHandler connect_cb, + GNUNET_SERVICE_DisconnectHandler disconnect_cb, + void *cls, + const struct GNUNET_MQ_MessageHandler *handlers); + + +/** + * Creates the "main" function for a GNUnet service. You + * MUST use this macro to define GNUnet services (except + * for ARM, which MUST NOT use the macro). The reason is + * the GNUnet-as-a-library project, where we will not define + * a main function anywhere but in ARM. + * + * The macro will launch the service with the name @a service_name + * using the @a service_options to configure its shutdown + * behavior. Once the service is ready, the @a init_cb will be called + * for service-specific initialization. @a init_cb will be given the + * service handler which can be used to control the service's + * availability. When clients connect or disconnect, the respective + * @a connect_cb or @a disconnect_cb functions will be called. For + * messages received from the clients, the respective @a handlers will + * be invoked; for the closure of the handlers we use the return value + * from the @a connect_cb invocation of the respective client. + * + * Each handler MUST call #GNUNET_SERVICE_client_continue() after each + * message to receive further messages from this client. If + * #GNUNET_SERVICE_client_continue() is not called within a short + * time, a warning will be logged. If delays are expected, services + * should call #GNUNET_SERVICE_client_disable_continue_warning() to + * disable the warning. + * + * Clients sending invalid messages (based on @a handlers) will be + * dropped. Additionally, clients can be dropped at any time using + * #GNUNET_SERVICE_client_drop(). + * + * @param service_name name of the service to run + * @param options options controlling shutdown of the service + * @param service_init_cb function to call once the service is ready + * @param connect_cb function to call whenever a client connects + * @param disconnect_cb function to call whenever a client disconnects + * @param cls closure argument for @a service_init_cb, @a connect_cb and @a disconnect_cb + * @param ... array of message handlers for the service, terminated + * by #GNUNET_MQ_handler_end(); + * the closure will be set to the value returned by + * the @a connect_cb for the respective connection + * @return 0 on success, non-zero on error + * + * Sample invocation: + * + * GNUNET_SERVICE_MAIN + * ("resolver", + * GNUNET_SERVICE_OPTION_NONE, + * &init_cb, + * &connect_cb, + * &disconnect_cb, + * closure_for_cb, + * GNUNET_MQ_hd_var_size (get, + * GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST, + * struct GNUNET_RESOLVER_GetMessage, + * NULL), + * GNUNET_MQ_handler_end ()); + * + */ +#define GNUNET_SERVICE_MAIN(service_name,service_options,init_cb,connect_cb,disconnect_cb,cls,...) \ + int \ + main (int argc,\ + char *const *argv)\ + { \ + struct GNUNET_MQ_MessageHandler mh[] = { \ + __VA_ARGS__ \ + }; \ + return GNUNET_SERVICE_run_ (argc, \ + argv, \ + service_name, \ + service_options, \ + init_cb, \ + connect_cb, \ + disconnect_cb, \ + cls, \ + mh); \ + } + + +/** + * Suspend accepting connections from the listen socket temporarily. + * Resume activity using #GNUNET_SERVICE_resume. + * + * @param sh service to stop accepting connections. + */ +void +GNUNET_SERVICE_suspend (struct GNUNET_SERVICE_Handle *sh); + + +/** + * Resume accepting connections from the listen socket. + * + * @param sh service to resume accepting connections. + */ +void +GNUNET_SERVICE_resume (struct GNUNET_SERVICE_Handle *sh); + + +/** + * Continue receiving further messages from the given client. + * Must be called after each message received. + * + * @param c the client to continue receiving from */ -struct GNUNET_SERVICE_Context *GNUNET_SERVICE_start (const char *serviceName, - struct - GNUNET_SCHEDULER_Handle - *sched, - const struct - GNUNET_CONFIGURATION_Handle - *cfg); +void +GNUNET_SERVICE_client_continue (struct GNUNET_SERVICE_Client *c); /** - * Obtain the server used by a service. Note that the server must NOT - * be destroyed by the caller. + * Obtain the message queue of @a c. Convenience function. * - * @param ctx the service context returned from the start function - * @return handle to the server for this service, NULL if there is none + * @param c the client to continue receiving from + * @return the message queue of @a c */ -struct GNUNET_SERVER_Handle *GNUNET_SERVICE_get_server (struct - GNUNET_SERVICE_Context - *ctx); +struct GNUNET_MQ_Handle * +GNUNET_SERVICE_client_get_mq (struct GNUNET_SERVICE_Client *c); /** - * Stop a service that was started with "GNUNET_SERVICE_start". + * Disable the warning the server issues if a message is not + * acknowledged in a timely fashion. Use this call if a client is + * intentionally delayed for a while. Only applies to the current + * message. * - * @param sctx the service context returned from the start function + * @param c client for which to disable the warning */ -void GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx); +void +GNUNET_SERVICE_client_disable_continue_warning (struct GNUNET_SERVICE_Client *c); + + +/** + * Ask the server to disconnect from the given client. This is the + * same as returning #GNUNET_SYSERR within the check procedure when + * handling a message, except that it allows dropping of a client even + * when not handling a message from that client. The `disconnect_cb` + * will be called on @a c even if the application closes the connection + * using this function. + * + * This function should be called (outside of util's internal logic) + * if (and usually only if) the client has violated the + * protocol. Otherwise, we should leave it to the client to disconnect + * from the service. + * + * @param c client to disconnect now + */ +void +GNUNET_SERVICE_client_drop (struct GNUNET_SERVICE_Client *c); + + +/** + * Explicitly stops the service. + * + * @param sh server to shutdown + */ +void +GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh); + + +/** + * Set the 'monitor' flag on this client. Clients which have been + * marked as 'monitors' won't prevent the server from shutting down + * once #GNUNET_SERVICE_stop_listening() has been invoked. The idea is + * that for "normal" clients we likely want to allow them to process + * their requests; however, monitor-clients are likely to 'never' + * disconnect during shutdown and thus will not be considered when + * determining if the server should continue to exist after + * shutdown has been triggered. + * + * @param c client to mark as a monitor + */ +void +GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c); + + +/** + * Set the persist option on this client. Indicates that the + * underlying socket or fd should never really be closed. Used for + * indicating process death. + * + * @param c client to persist the socket (never to be closed) + */ +void +GNUNET_SERVICE_client_persist (struct GNUNET_SERVICE_Client *c); #if 0 /* keep Emacsens' auto-indent happy */ @@ -122,4 +425,7 @@ void GNUNET_SERVICE_stop (struct GNUNET_SERVICE_Context *sctx); /* ifndef GNUNET_SERVICE_LIB_H */ #endif + +/** @} */ /* end of group service */ + /* end of gnunet_service_lib.h */