X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Farm%2Fgnunet-service-arm.c;h=19088c5cb7ec57bd526ead12252651986169bba1;hb=03512957fb04969d08fb7eac0952a747aa9596ae;hp=21fbdca43c2e72432e81302698044d3b5bfc6b24;hpb=d8c53b12a818ff7cf82d06a1a69c395bdef85ee6;p=oweals%2Fgnunet.git diff --git a/src/arm/gnunet-service-arm.c b/src/arm/gnunet-service-arm.c index 21fbdca43..19088c5cb 100644 --- a/src/arm/gnunet-service-arm.c +++ b/src/arm/gnunet-service-arm.c @@ -1,6 +1,6 @@ /* This file is part of GNUnet. - Copyright (C) 2009, 2010, 2011, 2015 GNUnet e.V. + Copyright (C) 2009-2011, 2015, 2016 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 @@ -29,6 +29,11 @@ #include "gnunet_protocols.h" #include "arm.h" +#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__) + +#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall) + + #if HAVE_WAIT4 /** * Name of the file for writing resource utilization summaries to. @@ -82,7 +87,7 @@ struct ServiceListeningInfo struct ServiceList *sl; /** - * Number of bytes in 'service_addr' + * Number of bytes in @e service_addr */ socklen_t service_addr_len; @@ -143,7 +148,7 @@ struct ServiceList * Client to notify upon kill completion (waitpid), NULL * if we should simply restart the process. */ - struct GNUNET_SERVER_Client *killing_client; + struct GNUNET_SERVICE_Client *killing_client; /** * ID of the request that killed the service (for reporting back). @@ -242,91 +247,402 @@ static int start_user = GNUNET_YES; static int start_system = GNUNET_YES; /** - * Handle to our server instance. Our server is a bit special in that + * Handle to our service instance. Our service is a bit special in that * its service is not immediately stopped once we get a shutdown * request (since we need to continue service until all of our child - * processes are dead). This handle is used to shut down the server + * processes are dead). This handle is used to shut down the service * (and thus trigger process termination) once all child processes are * also dead. A special option in the ARM configuration modifies the * behaviour of the service implementation to not do the shutdown * immediately. */ -static struct GNUNET_SERVER_Handle *server; +static struct GNUNET_SERVICE_Handle *service; /** * Context for notifications we need to send to our clients. */ -static struct GNUNET_SERVER_NotificationContext *notifier; +static struct GNUNET_NotificationContext *notifier; /** - * Transmit a status result message. + * Add the given UNIX domain path as an address to the + * list (as the first entry). * - * @param cls a `unit16_t *` with message type - * @param size number of bytes available in @a buf - * @param buf where to copy the message, NULL on error - * @return number of bytes copied to @a buf + * @param saddrs array to update + * @param saddrlens where to store the address length + * @param unixpath path to add + * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This + * parameter is ignore on systems other than LINUX */ -static size_t -write_result (void *cls, size_t size, void *buf) +static void +add_unixpath (struct sockaddr **saddrs, + socklen_t *saddrlens, + const char *unixpath, + int abstract) { - struct GNUNET_ARM_ResultMessage *msg = cls; - size_t msize; +#ifdef AF_UNIX + struct sockaddr_un *un; - if (NULL == buf) - { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Could not send status result to client\n")); - GNUNET_free (msg); - return 0; /* error, not much we can do */ - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending status response %u to client\n", - (unsigned int) msg->result); - msize = msg->arm_msg.header.size; - GNUNET_assert (size >= msize); - msg->arm_msg.header.size = htons (msg->arm_msg.header.size); - msg->arm_msg.header.type = htons (msg->arm_msg.header.type); - msg->result = htonl (msg->result); - msg->arm_msg.request_id = GNUNET_htonll (msg->arm_msg.request_id); - GNUNET_memcpy (buf, msg, msize); - GNUNET_free (msg); - return msize; + un = GNUNET_new (struct sockaddr_un); + un->sun_family = AF_UNIX; + strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1); +#ifdef LINUX + if (GNUNET_YES == abstract) + un->sun_path[0] = '\0'; +#endif +#if HAVE_SOCKADDR_UN_SUN_LEN + un->sun_len = (u_char) sizeof (struct sockaddr_un); +#endif + *saddrs = (struct sockaddr *) un; + *saddrlens = sizeof (struct sockaddr_un); +#else + /* this function should never be called + * unless AF_UNIX is defined! */ + GNUNET_assert (0); +#endif } /** - * Transmit the list of running services. + * Get the list of addresses that a server for the given service + * should bind to. * - * @param cls pointer to `struct GNUNET_ARM_ListResultMessage` with the message - * @param size number of bytes available in @a buf - * @param buf where to copy the message, NULL on error - * @return number of bytes copied to @a buf + * @param service_name name of the service + * @param cfg configuration (which specifies the addresses) + * @param addrs set (call by reference) to an array of pointers to the + * addresses the server should bind to and listen on; the + * array will be NULL-terminated (on success) + * @param addr_lens set (call by reference) to an array of the lengths + * of the respective `struct sockaddr` struct in the @a addrs + * array (on success) + * @return number of addresses found on success, + * #GNUNET_SYSERR if the configuration + * did not specify reasonable finding information or + * if it specified a hostname that could not be resolved; + * #GNUNET_NO if the number of addresses configured is + * zero (in this case, `*addrs` and `*addr_lens` will be + * set to NULL). */ -static size_t -write_list_result (void *cls, size_t size, void *buf) +static int +get_server_addresses (const char *service_name, + const struct GNUNET_CONFIGURATION_Handle *cfg, + struct sockaddr ***addrs, + socklen_t ** addr_lens) { - struct GNUNET_ARM_ListResultMessage *msg = cls; - size_t rslt_size; + int disablev6; + struct GNUNET_NETWORK_Handle *desc; + unsigned long long port; + char *unixpath; + struct addrinfo hints; + struct addrinfo *res; + struct addrinfo *pos; + struct addrinfo *next; + unsigned int i; + int resi; + int ret; + int abstract; + struct sockaddr **saddrs; + socklen_t *saddrlens; + char *hostname; + + *addrs = NULL; + *addr_lens = NULL; + desc = NULL; + if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6")) + { + if (GNUNET_SYSERR == + (disablev6 = + GNUNET_CONFIGURATION_get_value_yesno (cfg, service_name, "DISABLEV6"))) + return GNUNET_SYSERR; + } + else + disablev6 = GNUNET_NO; - if (NULL == buf) + if (! disablev6) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - _("Could not send list result to client\n")); - GNUNET_free (msg); - return 0; /* error, not much we can do */ + /* probe IPv6 support */ + desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); + if (NULL == desc) + { + if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) || + (EACCES == errno)) + { + LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket"); + return GNUNET_SYSERR; + } + LOG (GNUNET_ERROR_TYPE_INFO, + _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"), + service_name, STRERROR (errno)); + disablev6 = GNUNET_YES; + } + else + { + GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); + desc = NULL; + } + } + + port = 0; + if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "PORT")) + { + if (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_number (cfg, service_name, + "PORT", &port)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Require valid port number for service `%s' in configuration!\n"), + service_name); + } + if (port > 65535) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Require valid port number for service `%s' in configuration!\n"), + service_name); + return GNUNET_SYSERR; + } + } + + if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO")) + { + GNUNET_break (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_string (cfg, service_name, + "BINDTO", &hostname)); } + else + hostname = NULL; - rslt_size = msg->arm_msg.header.size; - GNUNET_assert (size >= rslt_size); - msg->arm_msg.header.size = htons (msg->arm_msg.header.size); - msg->arm_msg.header.type = htons (msg->arm_msg.header.type); - msg->arm_msg.request_id = GNUNET_htonll (msg->arm_msg.request_id); - msg->count = htons (msg->count); + unixpath = NULL; + abstract = GNUNET_NO; +#ifdef AF_UNIX + if ((GNUNET_YES == + GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) && + (GNUNET_OK == + GNUNET_CONFIGURATION_get_value_filename (cfg, service_name, "UNIXPATH", + &unixpath)) && + (0 < strlen (unixpath))) + { + /* probe UNIX support */ + struct sockaddr_un s_un; + + if (strlen (unixpath) >= sizeof (s_un.sun_path)) + { + LOG (GNUNET_ERROR_TYPE_WARNING, + _("UNIXPATH `%s' too long, maximum length is %llu\n"), unixpath, + (unsigned long long) sizeof (s_un.sun_path)); + unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath); + LOG (GNUNET_ERROR_TYPE_INFO, + _("Using `%s' instead\n"), + unixpath); + } +#ifdef LINUX + abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, + "TESTING", + "USE_ABSTRACT_SOCKETS"); + if (GNUNET_SYSERR == abstract) + abstract = GNUNET_NO; +#endif + if ((GNUNET_YES != abstract) + && (GNUNET_OK != + GNUNET_DISK_directory_create_for_file (unixpath))) + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, + "mkdir", + unixpath); + } + if (NULL != unixpath) + { + desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0); + if (NULL == desc) + { + if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) || + (EACCES == errno)) + { + LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR, "socket"); + GNUNET_free_non_null (hostname); + GNUNET_free (unixpath); + return GNUNET_SYSERR; + } + LOG (GNUNET_ERROR_TYPE_INFO, + _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"), + service_name, + STRERROR (errno)); + GNUNET_free (unixpath); + unixpath = NULL; + } + else + { + GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (desc)); + desc = NULL; + } + } +#endif - GNUNET_memcpy (buf, msg, rslt_size); - GNUNET_free (msg); - return rslt_size; + if ((0 == port) && (NULL == unixpath)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"), + service_name); + GNUNET_free_non_null (hostname); + return GNUNET_SYSERR; + } + if (0 == port) + { + saddrs = GNUNET_malloc (2 * sizeof (struct sockaddr *)); + saddrlens = GNUNET_malloc (2 * sizeof (socklen_t)); + add_unixpath (saddrs, saddrlens, unixpath, abstract); + GNUNET_free_non_null (unixpath); + GNUNET_free_non_null (hostname); + *addrs = saddrs; + *addr_lens = saddrlens; + return 1; + } + + if (NULL != hostname) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Resolving `%s' since that is where `%s' will bind to.\n", + hostname, + service_name); + memset (&hints, 0, sizeof (struct addrinfo)); + if (disablev6) + hints.ai_family = AF_INET; + hints.ai_protocol = IPPROTO_TCP; + if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) || + (NULL == res)) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Failed to resolve `%s': %s\n"), + hostname, + gai_strerror (ret)); + GNUNET_free (hostname); + GNUNET_free_non_null (unixpath); + return GNUNET_SYSERR; + } + next = res; + i = 0; + while (NULL != (pos = next)) + { + next = pos->ai_next; + if ((disablev6) && (pos->ai_family == AF_INET6)) + continue; + i++; + } + if (0 == i) + { + LOG (GNUNET_ERROR_TYPE_ERROR, + _("Failed to find %saddress for `%s'.\n"), + disablev6 ? "IPv4 " : "", + hostname); + freeaddrinfo (res); + GNUNET_free (hostname); + GNUNET_free_non_null (unixpath); + return GNUNET_SYSERR; + } + resi = i; + if (NULL != unixpath) + resi++; + saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); + saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); + i = 0; + if (NULL != unixpath) + { + add_unixpath (saddrs, saddrlens, unixpath, abstract); + i++; + } + next = res; + while (NULL != (pos = next)) + { + next = pos->ai_next; + if ((disablev6) && (AF_INET6 == pos->ai_family)) + continue; + if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol)) + continue; /* not TCP */ + if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype)) + continue; /* huh? */ + LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n", + service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen)); + if (AF_INET == pos->ai_family) + { + GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen); + saddrlens[i] = pos->ai_addrlen; + saddrs[i] = GNUNET_malloc (saddrlens[i]); + GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); + ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); + } + else + { + GNUNET_assert (AF_INET6 == pos->ai_family); + GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen); + saddrlens[i] = pos->ai_addrlen; + saddrs[i] = GNUNET_malloc (saddrlens[i]); + GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]); + ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); + } + i++; + } + GNUNET_free (hostname); + freeaddrinfo (res); + resi = i; + } + else + { + /* will bind against everything, just set port */ + if (disablev6) + { + /* V4-only */ + resi = 1; + if (NULL != unixpath) + resi++; + i = 0; + saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); + saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); + if (NULL != unixpath) + { + add_unixpath (saddrs, saddrlens, unixpath, abstract); + i++; + } + saddrlens[i] = sizeof (struct sockaddr_in); + saddrs[i] = GNUNET_malloc (saddrlens[i]); +#if HAVE_SOCKADDR_IN_SIN_LEN + ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i]; +#endif + ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; + ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); + } + else + { + /* dual stack */ + resi = 2; + if (NULL != unixpath) + resi++; + saddrs = GNUNET_malloc ((resi + 1) * sizeof (struct sockaddr *)); + saddrlens = GNUNET_malloc ((resi + 1) * sizeof (socklen_t)); + i = 0; + if (NULL != unixpath) + { + add_unixpath (saddrs, saddrlens, unixpath, abstract); + i++; + } + saddrlens[i] = sizeof (struct sockaddr_in6); + saddrs[i] = GNUNET_malloc (saddrlens[i]); +#if HAVE_SOCKADDR_IN_SIN_LEN + ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0]; +#endif + ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6; + ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port); + i++; + saddrlens[i] = sizeof (struct sockaddr_in); + saddrs[i] = GNUNET_malloc (saddrlens[i]); +#if HAVE_SOCKADDR_IN_SIN_LEN + ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1]; +#endif + ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET; + ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port); + } + } + GNUNET_free_non_null (unixpath); + *addrs = saddrs; + *addr_lens = saddrlens; + return resi; } @@ -341,24 +657,20 @@ write_list_result (void *cls, size_t size, void *buf) * @return NULL if it was not found */ static void -signal_result (struct GNUNET_SERVER_Client *client, +signal_result (struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_ARM_ResultMessage *msg; - size_t msize; - - msize = sizeof (struct GNUNET_ARM_ResultMessage); - msg = GNUNET_malloc (msize); - msg->arm_msg.header.size = msize; - msg->arm_msg.header.type = GNUNET_MESSAGE_TYPE_ARM_RESULT; - msg->result = result; - msg->arm_msg.request_id = request_id; - - GNUNET_SERVER_notify_transmit_ready (client, msize, - GNUNET_TIME_UNIT_FOREVER_REL, - write_result, msg); + + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_ARM_RESULT); + msg->result = htonl (result); + msg->arm_msg.request_id = GNUNET_htonll (request_id); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); } @@ -373,30 +685,37 @@ signal_result (struct GNUNET_SERVER_Client *client, static void broadcast_status (const char *name, enum GNUNET_ARM_ServiceStatus status, - struct GNUNET_SERVER_Client *unicast) + struct GNUNET_SERVICE_Client *unicast) { + struct GNUNET_MQ_Envelope *env; struct GNUNET_ARM_StatusMessage *msg; size_t namelen; - if (NULL == notifier) - return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Sending status %u of service `%s' to client\n", - (unsigned int) status, name); - namelen = strlen (name); - msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_StatusMessage) + namelen + 1); - msg->header.size = htons (sizeof (struct GNUNET_ARM_StatusMessage) + namelen + 1); - msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_STATUS); + "Sending status %u of service `%s' to client\n", + (unsigned int) status, + name); + namelen = strlen (name) + 1; + env = GNUNET_MQ_msg_extra (msg, + namelen, + GNUNET_MESSAGE_TYPE_ARM_STATUS); msg->status = htonl ((uint32_t) (status)); - GNUNET_memcpy ((char *) &msg[1], name, namelen + 1); - + GNUNET_memcpy ((char *) &msg[1], + name, + namelen); if (NULL == unicast) - GNUNET_SERVER_notification_context_broadcast (notifier, - (struct GNUNET_MessageHeader *) msg, GNUNET_YES); + { + if (NULL != notifier) + GNUNET_notification_context_broadcast (notifier, + &msg->header, + GNUNET_YES); + GNUNET_MQ_discard (env); + } else - GNUNET_SERVER_notification_context_unicast (notifier, unicast, - (const struct GNUNET_MessageHeader *) msg, GNUNET_NO); - GNUNET_free (msg); + { + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (unicast), + env); + } } @@ -410,7 +729,7 @@ broadcast_status (const char *name, */ static void start_process (struct ServiceList *sl, - struct GNUNET_SERVER_Client *client, + struct GNUNET_SERVICE_Client *client, uint64_t request_id) { char *loprefix; @@ -430,16 +749,20 @@ start_process (struct ServiceList *sl, { GNUNET_array_append (lsocks, ls, GNUNET_NETWORK_get_fd (sli->listen_socket)); - if (sli->accept_task != NULL) + if (NULL != sli->accept_task) { GNUNET_SCHEDULER_cancel (sli->accept_task); sli->accept_task = NULL; } } #if WINDOWS - GNUNET_array_append (lsocks, ls, INVALID_SOCKET); + GNUNET_array_append (lsocks, + ls, + INVALID_SOCKET); #else - GNUNET_array_append (lsocks, ls, -1); + GNUNET_array_append (lsocks, + ls, + -1); #endif /* obtain configuration */ @@ -449,13 +772,18 @@ start_process (struct ServiceList *sl, "PREFIX", &loprefix)) loprefix = GNUNET_strdup (prefix_command); + else + loprefix = GNUNET_CONFIGURATION_expand_dollar (cfg, + loprefix); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, sl->name, "OPTIONS", &options)) options = NULL; - + else + options = GNUNET_CONFIGURATION_expand_dollar (cfg, + options); { char *new_options; char *optpos; @@ -463,7 +791,8 @@ start_process (struct ServiceList *sl, fin_options = GNUNET_strdup (final_option); /* replace '{}' with service name */ - while (NULL != (optpos = strstr (fin_options, "{}"))) + while (NULL != (optpos = strstr (fin_options, + "{}"))) { /* terminate string at opening parenthesis */ *optpos = 0; @@ -483,6 +812,7 @@ start_process (struct ServiceList *sl, "%s %s", fin_options, optpos); + GNUNET_free (fin_options); GNUNET_free (optpos); } else @@ -597,7 +927,7 @@ start_process (struct ServiceList *sl, } GNUNET_free (binary); GNUNET_free (quotedbinary); - if (sl->proc == NULL) + if (NULL == sl->proc) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Failed to start service `%s'\n"), @@ -613,14 +943,21 @@ start_process (struct ServiceList *sl, GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Starting service `%s'\n"), sl->name); - broadcast_status (sl->name, GNUNET_ARM_SERVICE_STARTING, NULL); + broadcast_status (sl->name, + GNUNET_ARM_SERVICE_STARTING, + NULL); if (client) - signal_result (client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING); + signal_result (client, + sl->name, + request_id, + GNUNET_ARM_RESULT_STARTING); } /* clean up */ GNUNET_free (loprefix); GNUNET_free (options); - GNUNET_array_grow (lsocks, ls, 0); + GNUNET_array_grow (lsocks, + ls, + 0); } @@ -689,15 +1026,23 @@ create_listen_socket (struct sockaddr *sa, switch (sa->sa_family) { case AF_INET: - sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0); + sock = GNUNET_NETWORK_socket_create (PF_INET, + SOCK_STREAM, + 0); break; case AF_INET6: - sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0); + sock = GNUNET_NETWORK_socket_create (PF_INET6, + SOCK_STREAM, + 0); break; case AF_UNIX: - if (strcmp (GNUNET_a2s (sa, addr_len), "@") == 0) /* Do not bind to blank UNIX path! */ + if (0 == strcmp (GNUNET_a2s (sa, + addr_len), + "@")) /* Do not bind to blank UNIX path! */ return; - sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0); + sock = GNUNET_NETWORK_socket_create (PF_UNIX, + SOCK_STREAM, + 0); break; default: GNUNET_break (0); @@ -709,18 +1054,27 @@ create_listen_socket (struct sockaddr *sa, { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Unable to create socket for service `%s': %s\n"), - sl->name, STRERROR (errno)); + sl->name, + STRERROR (errno)); GNUNET_free (sa); return; } - if (GNUNET_NETWORK_socket_setsockopt - (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK) + if (GNUNET_OK != + GNUNET_NETWORK_socket_setsockopt (sock, + SOL_SOCKET, + SO_REUSEADDR, + &on, + sizeof (on))) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); #ifdef IPV6_V6ONLY - if ((sa->sa_family == AF_INET6) && - (GNUNET_NETWORK_socket_setsockopt - (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK)) + if ( (sa->sa_family == AF_INET6) && + (GNUNET_OK != + GNUNET_NETWORK_socket_setsockopt (sock, + IPPROTO_IPV6, + IPV6_V6ONLY, + &on, + sizeof (on))) ) GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK, "setsockopt"); #endif @@ -729,14 +1083,18 @@ create_listen_socket (struct sockaddr *sa, GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa); #endif if (GNUNET_OK != - GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len)) + GNUNET_NETWORK_socket_bind (sock, + (const struct sockaddr *) sa, + addr_len)) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, _("Unable to bind listening socket for service `%s' to address `%s': %s\n"), sl->name, - GNUNET_a2s (sa, addr_len), + GNUNET_a2s (sa, + addr_len), STRERROR (errno)); - GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (sock)); GNUNET_free (sa); return; } @@ -749,10 +1107,12 @@ create_listen_socket (struct sockaddr *sa, ) { match_uid = - GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, + GNUNET_CONFIGURATION_get_value_yesno (cfg, + sl->name, "UNIX_MATCH_UID"); match_gid = - GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, + GNUNET_CONFIGURATION_get_value_yesno (cfg, + sl->name, "UNIX_MATCH_GID"); GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path, match_uid, @@ -760,24 +1120,30 @@ create_listen_socket (struct sockaddr *sa, } #endif - if (GNUNET_NETWORK_socket_listen (sock, 5) != GNUNET_OK) + if (GNUNET_OK != + GNUNET_NETWORK_socket_listen (sock, 5)) { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "listen"); - GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock)); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, + "listen"); + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (sock)); GNUNET_free (sa); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("ARM now monitors connections to service `%s' at `%s'\n"), - sl->name, GNUNET_a2s (sa, addr_len)); + sl->name, + GNUNET_a2s (sa, + addr_len)); sli = GNUNET_new (struct ServiceListeningInfo); sli->service_addr = sa; sli->service_addr_len = addr_len; sli->listen_socket = sock; sli->sl = sl; - sli->accept_task = - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, sock, - &accept_connection, sli); + sli->accept_task + = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + sock, + &accept_connection, sli); GNUNET_CONTAINER_DLL_insert (sl->listen_head, sl->listen_tail, sli); @@ -794,7 +1160,9 @@ static void free_service (struct ServiceList *sl) { GNUNET_assert (GNUNET_YES == in_shutdown); - GNUNET_CONTAINER_DLL_remove (running_head, running_tail, sl); + GNUNET_CONTAINER_DLL_remove (running_head, + running_tail, + sl); GNUNET_assert (NULL == sl->listen_head); GNUNET_free_non_null (sl->config); GNUNET_free_non_null (sl->binary); @@ -804,61 +1172,79 @@ free_service (struct ServiceList *sl) /** - * Handle START-message. + * Check START-message. * - * @param cls closure (always NULL) - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param amsg the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ +static int +check_start (void *cls, + const struct GNUNET_ARM_Message *amsg) +{ + uint16_t size; + const char *servicename; + + size = ntohs (amsg->header.size) - sizeof (struct GNUNET_ARM_Message); + servicename = (const char *) &amsg[1]; + if ( (0 == size) || + (servicename[size - 1] != '\0') ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Handle START-message. + * + * @param cls identification of the client + * @param amsg the actual message + */ static void handle_start (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) + const struct GNUNET_ARM_Message *amsg) { + struct GNUNET_SERVICE_Client *client = cls; const char *servicename; struct ServiceList *sl; - uint16_t size; uint64_t request_id; - struct GNUNET_ARM_Message *amsg; - amsg = (struct GNUNET_ARM_Message *) message; request_id = GNUNET_ntohll (amsg->request_id); - size = ntohs (amsg->header.size); - size -= sizeof (struct GNUNET_ARM_Message); servicename = (const char *) &amsg[1]; - if ((size == 0) || (servicename[size - 1] != '\0')) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } + GNUNET_SERVICE_client_continue (client); if (GNUNET_YES == in_shutdown) { - signal_result (client, servicename, request_id, + signal_result (client, + servicename, + request_id, GNUNET_ARM_RESULT_IN_SHUTDOWN); - GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } sl = find_service (servicename); if (NULL == sl) { - signal_result (client, servicename, request_id, + signal_result (client, + servicename, + request_id, GNUNET_ARM_RESULT_IS_NOT_KNOWN); - GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } sl->force_start = GNUNET_YES; if (NULL != sl->proc) { - signal_result (client, servicename, request_id, + signal_result (client, + servicename, + request_id, GNUNET_ARM_RESULT_IS_STARTED_ALREADY); - GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } - start_process (sl, client, request_id); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + start_process (sl, + client, + request_id); } @@ -877,73 +1263,87 @@ trigger_shutdown (void *cls) /** - * Handle STOP-message. + * Check STOP-message. * - * @param cls closure (always NULL) - * @param client identification of the client - * @param message the actual message + * @param cls identification of the client + * @param amsg the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ +static int +check_stop (void *cls, + const struct GNUNET_ARM_Message *amsg) +{ + uint16_t size; + const char *servicename; + + size = ntohs (amsg->header.size) - sizeof (struct GNUNET_ARM_Message); + servicename = (const char *) &amsg[1]; + if ( (0 == size) || + (servicename[size - 1] != '\0') ) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + return GNUNET_OK; +} + + +/** + * Handle STOP-message. + * + * @param cls identification of the client + * @param amsg the actual message + */ static void handle_stop (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) + const struct GNUNET_ARM_Message *amsg) { + struct GNUNET_SERVICE_Client *client = cls; struct ServiceList *sl; const char *servicename; - uint16_t size; uint64_t request_id; - struct GNUNET_ARM_Message *amsg; - amsg = (struct GNUNET_ARM_Message *) message; request_id = GNUNET_ntohll (amsg->request_id); - size = ntohs (amsg->header.size); - size -= sizeof (struct GNUNET_ARM_Message); servicename = (const char *) &amsg[1]; - if ((size == 0) || (servicename[size - 1] != '\0')) - { - GNUNET_break (0); - GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); - return; - } GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Preparing to stop `%s'\n"), servicename); - if (0 == strcasecmp (servicename, "arm")) + GNUNET_SERVICE_client_continue (client); + if (0 == strcasecmp (servicename, + "arm")) { broadcast_status (servicename, - GNUNET_ARM_SERVICE_STOPPING, NULL); + GNUNET_ARM_SERVICE_STOPPING, + NULL); signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING); - GNUNET_SERVER_client_persist_ (client); - GNUNET_SCHEDULER_add_now (&trigger_shutdown, NULL); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_SERVICE_client_persist (client); + GNUNET_SCHEDULER_add_now (&trigger_shutdown, + NULL); return; } sl = find_service (servicename); - if (sl == NULL) - { - signal_result (client, - servicename, - request_id, - GNUNET_ARM_RESULT_IS_NOT_KNOWN); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } + if (NULL == sl) + { + signal_result (client, + servicename, + request_id, + GNUNET_ARM_RESULT_IS_NOT_KNOWN); + return; + } sl->force_start = GNUNET_NO; if (GNUNET_YES == in_shutdown) - { - /* shutdown in progress */ - signal_result (client, - servicename, - request_id, - GNUNET_ARM_RESULT_IN_SHUTDOWN); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - return; - } + { + /* shutdown in progress */ + signal_result (client, + servicename, + request_id, + GNUNET_ARM_RESULT_IN_SHUTDOWN); + return; + } if (NULL != sl->killing_client) { /* killing already in progress */ @@ -951,7 +1351,6 @@ handle_stop (void *cls, servicename, request_id, GNUNET_ARM_RESULT_IS_STOPPING_ALREADY); - GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } if (NULL == sl->proc) @@ -961,7 +1360,6 @@ handle_stop (void *cls, servicename, request_id, GNUNET_ARM_RESULT_IS_STOPPED_ALREADY); - GNUNET_SERVER_receive_done (client, GNUNET_OK); return; } GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -972,41 +1370,37 @@ handle_stop (void *cls, NULL); /* no signal_start - only when it's STOPPED */ sl->killed_at = GNUNET_TIME_absolute_get (); - if (0 != GNUNET_OS_process_kill (sl->proc, GNUNET_TERM_SIG)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + if (0 != GNUNET_OS_process_kill (sl->proc, + GNUNET_TERM_SIG)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "kill"); sl->killing_client = client; sl->killing_client_request_id = request_id; - GNUNET_SERVER_client_keep (client); - GNUNET_SERVER_receive_done (client, GNUNET_OK); } /** * Handle LIST-message. * - * @param cls closure (always NULL) - * @param client identification of the client + * @param cls identification of the client * @param message the actual message */ static void handle_list (void *cls, - struct GNUNET_SERVER_Client *client, - const struct GNUNET_MessageHeader *message) + const struct GNUNET_ARM_Message *request) { + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; struct GNUNET_ARM_ListResultMessage *msg; - struct GNUNET_ARM_Message *request; size_t string_list_size; - size_t total_size; struct ServiceList *sl; uint16_t count; + char *pos; - if (NULL == client) - return; - - request = (struct GNUNET_ARM_Message *) message; GNUNET_break (0 == ntohl (request->reserved)); count = 0; string_list_size = 0; + /* first count the running processes get their name's size */ for (sl = running_head; NULL != sl; sl = sl->next) { @@ -1019,30 +1413,51 @@ handle_list (void *cls, } } - total_size = sizeof (struct GNUNET_ARM_ListResultMessage) - + string_list_size; - msg = GNUNET_malloc (total_size); - msg->arm_msg.header.size = total_size; - msg->arm_msg.header.type = GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT; - msg->arm_msg.reserved = htonl (0); - msg->arm_msg.request_id = GNUNET_ntohll (request->request_id); - msg->count = count; + env = GNUNET_MQ_msg_extra (msg, + string_list_size, + GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT); + msg->arm_msg.request_id = request->request_id; + msg->count = htons (count); - char *pos = (char *)&msg[1]; + pos = (char *) &msg[1]; for (sl = running_head; NULL != sl; sl = sl->next) { if (NULL != sl->proc) { size_t s = strlen (sl->name) + strlen (sl->binary) + 4; - GNUNET_snprintf (pos, s, "%s (%s)", sl->name, sl->binary); + GNUNET_snprintf (pos, + s, + "%s (%s)", + sl->name, + sl->binary); pos += s; } } - GNUNET_SERVER_notify_transmit_ready (client, - total_size, - GNUNET_TIME_UNIT_FOREVER_REL, - &write_list_result, msg); - GNUNET_SERVER_receive_done (client, GNUNET_OK); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); +} + + +/** + * Handle TEST-message by sending back TEST. + * + * @param cls identification of the client + * @param message the actual message + */ +static void +handle_test (void *cls, + const struct GNUNET_MessageHeader *message) +{ + struct GNUNET_SERVICE_Client *client = cls; + struct GNUNET_MQ_Envelope *env; + struct GNUNET_MessageHeader *msg; + + env = GNUNET_MQ_msg (msg, + GNUNET_MESSAGE_TYPE_ARM_TEST); + GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client), + env); + GNUNET_SERVICE_client_continue (client); } @@ -1053,22 +1468,23 @@ handle_list (void *cls, static void do_shutdown () { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n"); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Last shutdown phase\n"); if (NULL != notifier) { - GNUNET_SERVER_notification_context_destroy (notifier); + GNUNET_notification_context_destroy (notifier); notifier = NULL; } - if (NULL != server) - { - GNUNET_SERVER_destroy (server); - server = NULL; - } + if (NULL != service) + { + GNUNET_SERVICE_shutdown (service); + service = NULL; + } if (NULL != child_death_task) - { - GNUNET_SCHEDULER_cancel (child_death_task); - child_death_task = NULL; - } + { + GNUNET_SCHEDULER_cancel (child_death_task); + child_death_task = NULL; + } } @@ -1082,7 +1498,7 @@ static unsigned int list_count (struct ServiceList *running_head) { struct ServiceList *i; - unsigned int res = 0; + unsigned int res; for (res = 0, i = running_head; i; i = i->next, res++) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, @@ -1116,20 +1532,20 @@ shutdown_task (void *cls) for (pos = running_head; NULL != pos; pos = pos->next) { while (NULL != (sli = pos->listen_head)) + { + GNUNET_CONTAINER_DLL_remove (pos->listen_head, + pos->listen_tail, + sli); + if (NULL != sli->accept_task) { - GNUNET_CONTAINER_DLL_remove (pos->listen_head, - pos->listen_tail, - sli); - if (NULL != sli->accept_task) - { - GNUNET_SCHEDULER_cancel (sli->accept_task); - sli->accept_task = NULL; - } - GNUNET_break (GNUNET_OK == - GNUNET_NETWORK_socket_close (sli->listen_socket)); - GNUNET_free (sli->service_addr); - GNUNET_free (sli); + GNUNET_SCHEDULER_cancel (sli->accept_task); + sli->accept_task = NULL; } + GNUNET_break (GNUNET_OK == + GNUNET_NETWORK_socket_close (sli->listen_socket)); + GNUNET_free (sli->service_addr); + GNUNET_free (sli); + } } /* then, shutdown all existing service processes */ nxt = running_head; @@ -1142,8 +1558,10 @@ shutdown_task (void *cls) "Stopping service `%s'\n", pos->name); pos->killed_at = GNUNET_TIME_absolute_get (); - if (0 != GNUNET_OS_process_kill (pos->proc, GNUNET_TERM_SIG)) - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill"); + if (0 != GNUNET_OS_process_kill (pos->proc, + GNUNET_TERM_SIG)) + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "kill"); } else { @@ -1193,7 +1611,9 @@ delayed_restart_task (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Restarting service `%s'.\n"), sl->name); - start_process (sl, NULL, 0); + start_process (sl, + NULL, + 0); } else { @@ -1202,11 +1622,11 @@ delayed_restart_task (void *cls) if (NULL == sli->accept_task) { /* accept was actually paused, so start it again */ - sli->accept_task = - GNUNET_SCHEDULER_add_read_net - (GNUNET_TIME_UNIT_FOREVER_REL, - sli->listen_socket, - &accept_connection, sli); + sli->accept_task + = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, + sli->listen_socket, + &accept_connection, + sli); } } } @@ -1223,11 +1643,13 @@ delayed_restart_task (void *cls) { GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Will restart process in %s\n", - GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay, GNUNET_YES)); + GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay, + GNUNET_YES)); child_restart_task = GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay, GNUNET_SCHEDULER_PRIORITY_IDLE, - &delayed_restart_task, NULL); + &delayed_restart_task, + NULL); } } @@ -1256,7 +1678,9 @@ maint_child_death (void *cls) GNUNET_DISK_PIPE_END_READ); child_death_task = NULL; /* consume the signal */ - GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof (c))); + GNUNET_break (0 < GNUNET_DISK_file_read (pr, + &c, + sizeof (c))); /* check for services that died (WAITPID) */ next = running_head; @@ -1376,7 +1800,6 @@ maint_child_death (void *cls) signal_result (pos->killing_client, pos->name, pos->killing_client_request_id, GNUNET_ARM_RESULT_STOPPED); - GNUNET_SERVER_client_drop (pos->killing_client); pos->killing_client = NULL; pos->killing_client_request_id = 0; } @@ -1451,9 +1874,10 @@ sighandler_child_death () int old_errno = errno; /* back-up errno */ GNUNET_break (1 == - GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle - (sigpipe, GNUNET_DISK_PIPE_END_WRITE), - &c, sizeof (c))); + GNUNET_DISK_file_write (GNUNET_DISK_pipe_handle (sigpipe, + GNUNET_DISK_PIPE_END_WRITE), + &c, + sizeof (c))); errno = old_errno; /* restore errno */ } @@ -1479,18 +1903,26 @@ setup_service (void *cls, int ret; unsigned int i; - if (strcasecmp (section, "arm") == 0) + if (0 == strcasecmp (section, + "arm")) return; if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary)) + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + "BINARY", + &binary)) { /* not a service section */ return; } if ((GNUNET_YES == - GNUNET_CONFIGURATION_have_value (cfg, section, "USER_SERVICE")) && + GNUNET_CONFIGURATION_have_value (cfg, + section, + "USER_SERVICE")) && (GNUNET_YES == - GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "USER_SERVICE"))) + GNUNET_CONFIGURATION_get_value_yesno (cfg, + section, + "USER_SERVICE"))) { if (GNUNET_NO == start_user) { @@ -1516,7 +1948,8 @@ setup_service (void *cls, } config = NULL; if (( (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_filename (cfg, section, + GNUNET_CONFIGURATION_get_value_filename (cfg, + section, "CONFIG", &config)) && (GNUNET_OK != @@ -1574,10 +2007,10 @@ setup_service (void *cls, "AUTOSTART")) return; } - if (0 >= (ret = GNUNET_SERVICE_get_server_addresses (section, - cfg, - &addrs, - &addr_lens))) + if (0 >= (ret = get_server_addresses (section, + cfg, + &addrs, + &addr_lens))) return; /* this will free (or capture) addrs[i] */ for (i = 0; i < ret; i++) @@ -1590,46 +2023,71 @@ setup_service (void *cls, /** - * A client connected, add it to the notification context. + * A client connected, mark as a monitoring client. * * @param cls closure * @param client identification of the client + * @param mq queue to talk to @a client + * @return @a client */ -static void -handle_client_connecting (void *cls, - struct GNUNET_SERVER_Client *client) +static void * +client_connect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + struct GNUNET_MQ_Handle *mq) { /* All clients are considered to be of the "monitor" kind * (that is, they don't affect ARM shutdown). */ - if (NULL != client) - GNUNET_SERVER_client_mark_monitor (client); + GNUNET_SERVICE_client_mark_monitor (client); + return client; } /** - * Handle MONITOR-message. + * A client disconnected, clean up associated state. * - * @param cls closure (always NULL) + * @param cls closure * @param client identification of the client + * @param app_ctx must match @a client + */ +static void +client_disconnect_cb (void *cls, + struct GNUNET_SERVICE_Client *client, + void *app_ctx) +{ + struct ServiceList *sl; + + GNUNET_assert (client == app_ctx); + + for (sl = running_head; NULL != sl; sl = sl->next) + if (sl->killing_client == client) + sl->killing_client = NULL; +} + + +/** + * Handle MONITOR-message. + * + * @param cls identification of the client * @param message the actual message * @return #GNUNET_OK to keep the connection open, * #GNUNET_SYSERR to close it (signal serious error) */ static void handle_monitor (void *cls, - struct GNUNET_SERVER_Client *client, const struct GNUNET_MessageHeader *message) { + struct GNUNET_SERVICE_Client *client = cls; + /* FIXME: might want to start by letting monitor know about services that are already running */ /* Removal is handled by the server implementation, internally. */ - if ((NULL != client) && (NULL != notifier)) - { - GNUNET_SERVER_notification_context_add (notifier, client); - broadcast_status ("arm", GNUNET_ARM_SERVICE_MONITORING_STARTED, client); - GNUNET_SERVER_receive_done (client, GNUNET_OK); - } + GNUNET_notification_context_add (notifier, + GNUNET_SERVICE_client_get_mq (client)); + broadcast_status ("arm", + GNUNET_ARM_SERVICE_MONITORING_STARTED, + client); + GNUNET_SERVICE_client_continue (client); } @@ -1637,34 +2095,26 @@ handle_monitor (void *cls, * Process arm requests. * * @param cls closure - * @param serv the initialized server + * @param serv the initialized service * @param c configuration to use */ static void -run (void *cls, struct GNUNET_SERVER_Handle *serv, - const struct GNUNET_CONFIGURATION_Handle *c) +run (void *cls, + const struct GNUNET_CONFIGURATION_Handle *c, + struct GNUNET_SERVICE_Handle *serv) { - static const struct GNUNET_SERVER_MessageHandler handlers[] = { - {&handle_start, NULL, GNUNET_MESSAGE_TYPE_ARM_START, 0}, - {&handle_stop, NULL, GNUNET_MESSAGE_TYPE_ARM_STOP, 0}, - {&handle_monitor, NULL, GNUNET_MESSAGE_TYPE_ARM_MONITOR, - sizeof (struct GNUNET_MessageHeader)}, - {&handle_list, NULL, GNUNET_MESSAGE_TYPE_ARM_LIST, - sizeof (struct GNUNET_ARM_Message)}, - {NULL, NULL, 0, 0} - }; struct ServiceList *sl; cfg = c; - server = serv; - GNUNET_assert (NULL != serv); + service = serv; GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); child_death_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_DISK_pipe_handle (sigpipe, GNUNET_DISK_PIPE_END_READ), - &maint_child_death, NULL); + &maint_child_death, + NULL); #if HAVE_WAIT4 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename (cfg, @@ -1688,12 +2138,18 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv, "GLOBAL_PREFIX", &prefix_command)) prefix_command = GNUNET_strdup (""); + else + prefix_command = GNUNET_CONFIGURATION_expand_dollar (cfg, + prefix_command); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "ARM", "GLOBAL_POSTFIX", &final_option)) final_option = GNUNET_strdup (""); + else + final_option = GNUNET_CONFIGURATION_expand_dollar (cfg, + final_option); if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", @@ -1710,20 +2166,17 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv, GNUNET_break (GNUNET_YES == start_system); start_user = GNUNET_NO; } - GNUNET_CONFIGURATION_iterate_sections (cfg, &setup_service, NULL); + GNUNET_CONFIGURATION_iterate_sections (cfg, + &setup_service, + NULL); /* start default services... */ for (sl = running_head; NULL != sl; sl = sl->next) if (GNUNET_YES == sl->force_start) - start_process (sl, NULL, 0); - notifier - = GNUNET_SERVER_notification_context_create (server, - MAX_NOTIFY_QUEUE); - GNUNET_SERVER_connect_notify (server, - &handle_client_connecting, NULL); - /* process client requests */ - GNUNET_SERVER_add_handlers (server, - handlers); + start_process (sl, + NULL, + 0); + notifier = GNUNET_notification_context_create (MAX_NOTIFY_QUEUE); } @@ -1735,19 +2188,52 @@ run (void *cls, struct GNUNET_SERVER_Handle *serv, * @return 0 ok, 1 on error */ int -main (int argc, char *const *argv) +main (int argc, + char *const *argv) { int ret; struct GNUNET_SIGNAL_Context *shc_chld; + struct GNUNET_MQ_MessageHandler handlers[] = { + GNUNET_MQ_hd_var_size (start, + GNUNET_MESSAGE_TYPE_ARM_START, + struct GNUNET_ARM_Message, + NULL), + GNUNET_MQ_hd_var_size (stop, + GNUNET_MESSAGE_TYPE_ARM_STOP, + struct GNUNET_ARM_Message, + NULL), + GNUNET_MQ_hd_fixed_size (monitor, + GNUNET_MESSAGE_TYPE_ARM_MONITOR, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_hd_fixed_size (list, + GNUNET_MESSAGE_TYPE_ARM_LIST, + struct GNUNET_ARM_Message, + NULL), + GNUNET_MQ_hd_fixed_size (test, + GNUNET_MESSAGE_TYPE_ARM_TEST, + struct GNUNET_MessageHeader, + NULL), + GNUNET_MQ_handler_end () + }; - sigpipe = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO); - GNUNET_assert (sigpipe != NULL); + sigpipe = GNUNET_DISK_pipe (GNUNET_NO, + GNUNET_NO, + GNUNET_NO, + GNUNET_NO); + GNUNET_assert (NULL != sigpipe); shc_chld = - GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, &sighandler_child_death); - ret = - (GNUNET_OK == - GNUNET_SERVICE_run (argc, argv, "arm", - GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, &run, NULL)) ? 0 : 1; + GNUNET_SIGNAL_handler_install (GNUNET_SIGCHLD, + &sighandler_child_death); + ret = GNUNET_SERVICE_run_ (argc, + argv, + "arm", + GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, + &run, + &client_connect_cb, + &client_disconnect_cb, + NULL, + handlers); #if HAVE_WAIT4 if (NULL != wait_file) {