2 This file is part of GNUnet.
3 Copyright (C) 2009-2011, 2015, 2016 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
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 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file arm/gnunet-service-arm.c
23 * @brief the automated restart manager service
24 * @author Christian Grothoff
27 #include "gnunet_util_lib.h"
28 #include "gnunet_arm_service.h"
29 #include "gnunet_protocols.h"
32 #define LOG(kind, ...) GNUNET_log_from(kind, "util", __VA_ARGS__)
34 #define LOG_STRERROR(kind, syscall) \
35 GNUNET_log_from_strerror(kind, "util", syscall)
40 * Name of the file for writing resource utilization summaries to.
42 static char *wait_filename;
45 * Handle for the file for writing resource summaries.
47 static FILE *wait_file;
52 * How many messages do we queue up at most for optional
53 * notifications to a client? (this can cause notifications
54 * about outgoing messages to be dropped).
56 #define MAX_NOTIFY_QUEUE 1024
60 * List of our services.
66 * Record with information about a listen socket we have open.
68 struct ServiceListeningInfo {
70 * This is a linked list.
72 struct ServiceListeningInfo *next;
75 * This is a linked list.
77 struct ServiceListeningInfo *prev;
80 * Address this socket is listening on.
82 struct sockaddr *service_addr;
85 * Service this listen socket is for.
87 struct ServiceList *sl;
90 * Number of bytes in @e service_addr
92 socklen_t service_addr_len;
95 * Our listening socket.
97 struct GNUNET_NETWORK_Handle *listen_socket;
100 * Task doing the accepting.
102 struct GNUNET_SCHEDULER_Task *accept_task;
107 * List of our services.
111 * This is a doubly-linked list.
113 struct ServiceList *next;
116 * This is a doubly-linked list.
118 struct ServiceList *prev;
121 * Linked list of listen sockets associated with this service.
123 struct ServiceListeningInfo *listen_head;
126 * Linked list of listen sockets associated with this service.
128 struct ServiceListeningInfo *listen_tail;
131 * Name of the service.
136 * Name of the binary used.
141 * Name of the configuration file used.
146 * Client to notify upon kill completion (waitpid), NULL
147 * if we should simply restart the process.
149 struct GNUNET_SERVICE_Client *killing_client;
152 * ID of the request that killed the service (for reporting back).
154 uint64_t killing_client_request_id;
157 * Process structure pointer of the child.
159 struct GNUNET_OS_Process *proc;
162 * Process exponential backoff time
164 struct GNUNET_TIME_Relative backoff;
167 * Absolute time at which the process is scheduled to restart in case of death
169 struct GNUNET_TIME_Absolute restart_at;
172 * Time we asked the service to shut down (used to calculate time it took
173 * the service to terminate).
175 struct GNUNET_TIME_Absolute killed_at;
178 * Is this service to be started by default (or did a client tell us explicitly
179 * to start it)? #GNUNET_NO if the service is started only upon 'accept' on a
180 * listen socket or possibly explicitly by a client changing the value.
185 * Should we use pipes to signal this process? (YES for Java binaries and if we
192 * List of running services.
194 static struct ServiceList *running_head;
197 * List of running services.
199 static struct ServiceList *running_tail;
204 static const struct GNUNET_CONFIGURATION_Handle *cfg;
207 * Command to prepend to each actual command.
209 static char *prefix_command;
212 * Option to append to each actual command.
214 static char *final_option;
217 * ID of task called whenever we get a SIGCHILD.
219 static struct GNUNET_SCHEDULER_Task *child_death_task;
222 * ID of task called whenever the timeout for restarting a child
225 static struct GNUNET_SCHEDULER_Task *child_restart_task;
228 * Pipe used to communicate shutdown via signal.
230 static struct GNUNET_DISK_PipeHandle *sigpipe;
233 * Are we in shutdown mode?
235 static int in_shutdown;
238 * Return value from main
240 static int global_ret;
243 * Are we starting user services?
245 static int start_user = GNUNET_YES;
248 * Are we starting system services?
250 static int start_system = GNUNET_YES;
253 * Handle to our service instance. Our service is a bit special in that
254 * its service is not immediately stopped once we get a shutdown
255 * request (since we need to continue service until all of our child
256 * processes are dead). This handle is used to shut down the service
257 * (and thus trigger process termination) once all child processes are
258 * also dead. A special option in the ARM configuration modifies the
259 * behaviour of the service implementation to not do the shutdown
262 static struct GNUNET_SERVICE_Handle *service;
265 * Context for notifications we need to send to our clients.
267 static struct GNUNET_NotificationContext *notifier;
271 * Add the given UNIX domain path as an address to the
272 * list (as the first entry).
274 * @param saddrs array to update
275 * @param saddrlens where to store the address length
276 * @param unixpath path to add
277 * @param abstract #GNUNET_YES to add an abstract UNIX domain socket. This
278 * parameter is ignore on systems other than LINUX
281 add_unixpath(struct sockaddr **saddrs,
282 socklen_t *saddrlens,
283 const char *unixpath,
287 struct sockaddr_un *un;
289 un = GNUNET_new(struct sockaddr_un);
290 un->sun_family = AF_UNIX;
291 GNUNET_strlcpy(un->sun_path, unixpath, sizeof(un->sun_path));
293 if (GNUNET_YES == abstract)
294 un->sun_path[0] = '\0';
296 #if HAVE_SOCKADDR_UN_SUN_LEN
297 un->sun_len = (u_char)sizeof(struct sockaddr_un);
299 *saddrs = (struct sockaddr *)un;
300 *saddrlens = sizeof(struct sockaddr_un);
302 /* this function should never be called
303 * unless AF_UNIX is defined! */
310 * Get the list of addresses that a server for the given service
313 * @param service_name name of the service
314 * @param cfg configuration (which specifies the addresses)
315 * @param addrs set (call by reference) to an array of pointers to the
316 * addresses the server should bind to and listen on; the
317 * array will be NULL-terminated (on success)
318 * @param addr_lens set (call by reference) to an array of the lengths
319 * of the respective `struct sockaddr` struct in the @a addrs
321 * @return number of addresses found on success,
322 * #GNUNET_SYSERR if the configuration
323 * did not specify reasonable finding information or
324 * if it specified a hostname that could not be resolved;
325 * #GNUNET_NO if the number of addresses configured is
326 * zero (in this case, `*addrs` and `*addr_lens` will be
330 get_server_addresses(const char *service_name,
331 const struct GNUNET_CONFIGURATION_Handle *cfg,
332 struct sockaddr ***addrs,
333 socklen_t **addr_lens)
336 struct GNUNET_NETWORK_Handle *desc;
337 unsigned long long port;
339 struct addrinfo hints;
340 struct addrinfo *res;
341 struct addrinfo *pos;
342 struct addrinfo *next;
347 struct sockaddr **saddrs;
348 socklen_t *saddrlens;
354 if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "DISABLEV6"))
357 (disablev6 = GNUNET_CONFIGURATION_get_value_yesno(cfg,
360 return GNUNET_SYSERR;
363 disablev6 = GNUNET_NO;
367 /* probe IPv6 support */
368 desc = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
371 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
374 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "socket");
375 return GNUNET_SYSERR;
377 LOG(GNUNET_ERROR_TYPE_INFO,
379 "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
382 disablev6 = GNUNET_YES;
386 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(desc));
392 if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "PORT"))
394 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number(cfg,
399 LOG(GNUNET_ERROR_TYPE_ERROR,
400 _("Require valid port number for service `%s' in configuration!\n"),
405 LOG(GNUNET_ERROR_TYPE_ERROR,
406 _("Require valid port number for service `%s' in configuration!\n"),
408 return GNUNET_SYSERR;
412 if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "BINDTO"))
414 GNUNET_break(GNUNET_OK ==
415 GNUNET_CONFIGURATION_get_value_string(cfg,
424 abstract = GNUNET_NO;
427 GNUNET_CONFIGURATION_have_value(cfg, service_name, "UNIXPATH")) &&
428 (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename(cfg,
432 (0 < strlen(unixpath)))
434 /* probe UNIX support */
435 struct sockaddr_un s_un;
437 if (strlen(unixpath) >= sizeof(s_un.sun_path))
439 LOG(GNUNET_ERROR_TYPE_WARNING,
440 _("UNIXPATH `%s' too long, maximum length is %llu\n"),
442 (unsigned long long)sizeof(s_un.sun_path));
443 unixpath = GNUNET_NETWORK_shorten_unixpath(unixpath);
444 LOG(GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath);
447 abstract = GNUNET_CONFIGURATION_get_value_yesno(cfg,
449 "USE_ABSTRACT_SOCKETS");
450 if (GNUNET_SYSERR == abstract)
451 abstract = GNUNET_NO;
453 if ((GNUNET_YES != abstract) &&
454 (GNUNET_OK != GNUNET_DISK_directory_create_for_file(unixpath)))
455 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR, "mkdir", unixpath);
457 if (NULL != unixpath)
459 desc = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_STREAM, 0);
462 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
465 LOG_STRERROR(GNUNET_ERROR_TYPE_ERROR, "socket");
466 GNUNET_free_non_null(hostname);
467 GNUNET_free(unixpath);
468 return GNUNET_SYSERR;
470 LOG(GNUNET_ERROR_TYPE_INFO,
472 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
475 GNUNET_free(unixpath);
480 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(desc));
486 if ((0 == port) && (NULL == unixpath))
488 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno(cfg,
491 LOG(GNUNET_ERROR_TYPE_ERROR,
493 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
495 GNUNET_free_non_null(hostname);
496 return GNUNET_SYSERR;
500 saddrs = GNUNET_new_array(2, struct sockaddr *);
501 saddrlens = GNUNET_new_array(2, socklen_t);
502 add_unixpath(saddrs, saddrlens, unixpath, abstract);
503 GNUNET_free_non_null(unixpath);
504 GNUNET_free_non_null(hostname);
506 *addr_lens = saddrlens;
510 if (NULL != hostname)
512 LOG(GNUNET_ERROR_TYPE_DEBUG,
513 "Resolving `%s' since that is where `%s' will bind to.\n",
516 memset(&hints, 0, sizeof(struct addrinfo));
518 hints.ai_family = AF_INET;
519 hints.ai_protocol = IPPROTO_TCP;
520 if ((0 != (ret = getaddrinfo(hostname, NULL, &hints, &res))) ||
523 LOG(GNUNET_ERROR_TYPE_ERROR,
524 _("Failed to resolve `%s': %s\n"),
527 GNUNET_free(hostname);
528 GNUNET_free_non_null(unixpath);
529 return GNUNET_SYSERR;
533 while (NULL != (pos = next))
536 if ((disablev6) && (pos->ai_family == AF_INET6))
542 LOG(GNUNET_ERROR_TYPE_ERROR,
543 _("Failed to find %saddress for `%s'.\n"),
544 disablev6 ? "IPv4 " : "",
547 GNUNET_free(hostname);
548 GNUNET_free_non_null(unixpath);
549 return GNUNET_SYSERR;
552 if (NULL != unixpath)
554 saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
555 saddrlens = GNUNET_new_array(resi + 1, socklen_t);
557 if (NULL != unixpath)
559 add_unixpath(saddrs, saddrlens, unixpath, abstract);
563 while (NULL != (pos = next))
566 if ((disablev6) && (AF_INET6 == pos->ai_family))
568 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
569 continue; /* not TCP */
570 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
572 LOG(GNUNET_ERROR_TYPE_DEBUG,
573 "Service `%s' will bind to `%s'\n",
575 GNUNET_a2s(pos->ai_addr, pos->ai_addrlen));
576 if (AF_INET == pos->ai_family)
578 GNUNET_assert(sizeof(struct sockaddr_in) == pos->ai_addrlen);
579 saddrlens[i] = pos->ai_addrlen;
580 saddrs[i] = GNUNET_malloc(saddrlens[i]);
581 GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
582 ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
586 GNUNET_assert(AF_INET6 == pos->ai_family);
587 GNUNET_assert(sizeof(struct sockaddr_in6) == pos->ai_addrlen);
588 saddrlens[i] = pos->ai_addrlen;
589 saddrs[i] = GNUNET_malloc(saddrlens[i]);
590 GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
591 ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
595 GNUNET_free(hostname);
601 /* will bind against everything, just set port */
606 if (NULL != unixpath)
609 saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
610 saddrlens = GNUNET_new_array(resi + 1, socklen_t);
611 if (NULL != unixpath)
613 add_unixpath(saddrs, saddrlens, unixpath, abstract);
616 saddrlens[i] = sizeof(struct sockaddr_in);
617 saddrs[i] = GNUNET_malloc(saddrlens[i]);
618 #if HAVE_SOCKADDR_IN_SIN_LEN
619 ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[i];
621 ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
622 ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
628 if (NULL != unixpath)
630 saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
631 saddrlens = GNUNET_new_array(resi + 1, socklen_t);
633 if (NULL != unixpath)
635 add_unixpath(saddrs, saddrlens, unixpath, abstract);
638 saddrlens[i] = sizeof(struct sockaddr_in6);
639 saddrs[i] = GNUNET_malloc(saddrlens[i]);
640 #if HAVE_SOCKADDR_IN_SIN_LEN
641 ((struct sockaddr_in6 *)saddrs[i])->sin6_len = saddrlens[0];
643 ((struct sockaddr_in6 *)saddrs[i])->sin6_family = AF_INET6;
644 ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
646 saddrlens[i] = sizeof(struct sockaddr_in);
647 saddrs[i] = GNUNET_malloc(saddrlens[i]);
648 #if HAVE_SOCKADDR_IN_SIN_LEN
649 ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[1];
651 ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
652 ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
655 GNUNET_free_non_null(unixpath);
657 *addr_lens = saddrlens;
663 * Signal our client that we will start or stop the
666 * @param client who is being signalled
667 * @param name name of the service
668 * @param request_id id of the request that is being responded to.
669 * @param result message type to send
670 * @return NULL if it was not found
673 signal_result(struct GNUNET_SERVICE_Client *client,
676 enum GNUNET_ARM_Result result)
678 struct GNUNET_MQ_Envelope *env;
679 struct GNUNET_ARM_ResultMessage *msg;
682 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_ARM_RESULT);
683 msg->result = htonl(result);
684 msg->arm_msg.request_id = GNUNET_htonll(request_id);
685 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(client), env);
690 * Tell all clients about status change of a service.
692 * @param name name of the service
693 * @param status message type to send
694 * @param unicast if not NULL, send to this client only.
695 * otherwise, send to all clients in the notifier
698 broadcast_status(const char *name,
699 enum GNUNET_ARM_ServiceStatus status,
700 struct GNUNET_SERVICE_Client *unicast)
702 struct GNUNET_MQ_Envelope *env;
703 struct GNUNET_ARM_StatusMessage *msg;
706 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
707 "Sending status %u of service `%s' to client\n",
708 (unsigned int)status,
710 namelen = strlen(name) + 1;
711 env = GNUNET_MQ_msg_extra(msg, namelen, GNUNET_MESSAGE_TYPE_ARM_STATUS);
712 msg->status = htonl((uint32_t)(status));
713 GNUNET_memcpy((char *)&msg[1], name, namelen);
716 if (NULL != notifier)
717 GNUNET_notification_context_broadcast(notifier,
720 GNUNET_MQ_discard(env);
724 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(unicast), env);
730 * Actually start the process for the given service.
732 * @param sl identifies service to start
733 * @param client that asked to start the service (may be NULL)
734 * @param request_id id of the request in response to which the process is
735 * being started. 0 if starting was not requested.
738 start_process(struct ServiceList *sl,
739 struct GNUNET_SERVICE_Client *client,
745 int is_simple_service;
746 struct ServiceListeningInfo *sli;
752 /* calculate listen socket list */
755 for (sli = sl->listen_head; NULL != sli; sli = sli->next)
757 GNUNET_array_append(lsocks,
759 GNUNET_NETWORK_get_fd(sli->listen_socket));
760 if (NULL != sli->accept_task)
762 GNUNET_SCHEDULER_cancel(sli->accept_task);
763 sli->accept_task = NULL;
767 GNUNET_array_append(lsocks, ls, INVALID_SOCKET);
769 GNUNET_array_append(lsocks, ls, -1);
772 /* obtain configuration */
773 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg,
777 loprefix = GNUNET_strdup(prefix_command);
779 loprefix = GNUNET_CONFIGURATION_expand_dollar(cfg, loprefix);
780 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg,
786 options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
792 fin_options = GNUNET_strdup(final_option);
793 /* replace '{}' with service name */
794 while (NULL != (optpos = strstr(fin_options, "{}")))
796 /* terminate string at opening parenthesis */
798 GNUNET_asprintf(&new_options,
803 GNUNET_free(fin_options);
804 fin_options = new_options;
808 /* combine "fin_options" with "options" */
810 GNUNET_asprintf(&options, "%s %s", fin_options, optpos);
811 GNUNET_free(fin_options);
816 /* only have "fin_options", use that */
817 options = fin_options;
820 options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
821 use_debug = GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "DEBUG");
823 const char *service_type = NULL;
824 const char *choices[] = { "GNUNET", "SIMPLE", NULL };
826 is_simple_service = GNUNET_NO;
827 if ((GNUNET_OK == GNUNET_CONFIGURATION_get_value_choice(cfg,
832 (0 == strcasecmp(service_type, "SIMPLE")))
833 is_simple_service = GNUNET_YES;
836 GNUNET_assert(NULL == sl->proc);
837 if (GNUNET_YES == is_simple_service)
839 /* A simple service will receive no GNUnet specific
840 command line options. */
841 binary = GNUNET_strdup(sl->binary);
842 binary = GNUNET_CONFIGURATION_expand_dollar(cfg, binary);
843 GNUNET_asprintf("edbinary, "\"%s\"", sl->binary);
844 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
845 "Starting simple service `%s' using binary `%s'\n",
848 /* FIXME: dollar expansion should only be done outside
849 * of ''-quoted strings, escaping should be considered. */
851 options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
852 sl->proc = GNUNET_OS_start_process_s(sl->pipe_control,
853 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
862 /* actually start process */
863 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
864 "Starting service `%s' using binary `%s' and configuration `%s'\n",
868 binary = GNUNET_OS_get_libexec_binary_path(sl->binary);
869 GNUNET_asprintf("edbinary, "\"%s\"", binary);
871 if (GNUNET_YES == use_debug)
873 if (NULL == sl->config)
874 sl->proc = GNUNET_OS_start_process_s(sl->pipe_control,
875 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
884 sl->proc = GNUNET_OS_start_process_s(sl->pipe_control,
885 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
898 if (NULL == sl->config)
899 sl->proc = GNUNET_OS_start_process_s(sl->pipe_control,
900 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
907 sl->proc = GNUNET_OS_start_process_s(sl->pipe_control,
908 GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
919 GNUNET_free(quotedbinary);
920 if (NULL == sl->proc)
922 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
923 _("Failed to start service `%s'\n"),
926 signal_result(client,
929 GNUNET_ARM_RESULT_START_FAILED);
933 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
934 _("Starting service `%s'\n"),
936 broadcast_status(sl->name, GNUNET_ARM_SERVICE_STARTING, NULL);
938 signal_result(client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING);
941 GNUNET_free(loprefix);
942 GNUNET_free(options);
943 GNUNET_array_grow(lsocks, ls, 0);
948 * Find the process with the given service
949 * name in the given list and return it.
951 * @param name which service entry to look up
952 * @return NULL if it was not found
954 static struct ServiceList *
955 find_service(const char *name)
957 struct ServiceList *sl;
962 if (0 == strcasecmp(sl->name, name))
971 * First connection has come to the listening socket associated with the service,
972 * create the service in order to relay the incoming connection to it
974 * @param cls callback data, `struct ServiceListeningInfo` describing a listen socket
977 accept_connection(void *cls)
979 struct ServiceListeningInfo *sli = cls;
980 struct ServiceList *sl = sli->sl;
982 sli->accept_task = NULL;
983 GNUNET_assert(GNUNET_NO == in_shutdown);
984 start_process(sl, NULL, 0);
989 * Creating a listening socket for each of the service's addresses and
990 * wait for the first incoming connection to it
992 * @param sa address associated with the service
993 * @param addr_len length of @a sa
994 * @param sl service entry for the service in question
997 create_listen_socket(struct sockaddr *sa,
999 struct ServiceList *sl)
1002 struct GNUNET_NETWORK_Handle *sock;
1003 struct ServiceListeningInfo *sli;
1010 switch (sa->sa_family)
1013 sock = GNUNET_NETWORK_socket_create(PF_INET, SOCK_STREAM, 0);
1017 sock = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
1021 if (0 == strcmp(GNUNET_a2s(sa, addr_len),
1022 "@")) /* Do not bind to blank UNIX path! */
1024 sock = GNUNET_NETWORK_socket_create(PF_UNIX, SOCK_STREAM, 0);
1030 errno = EAFNOSUPPORT;
1035 GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
1036 _("Unable to create socket for service `%s': %s\n"),
1042 if (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt(sock,
1047 GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1050 if ((sa->sa_family == AF_INET6) &&
1051 (GNUNET_OK != GNUNET_NETWORK_socket_setsockopt(sock,
1056 GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
1060 if (AF_UNIX == sa->sa_family)
1061 GNUNET_NETWORK_unix_precheck((struct sockaddr_un *)sa);
1064 GNUNET_NETWORK_socket_bind(sock, (const struct sockaddr *)sa, addr_len))
1067 GNUNET_ERROR_TYPE_WARNING,
1069 "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1071 GNUNET_a2s(sa, addr_len),
1073 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(sock));
1078 if ((AF_UNIX == sa->sa_family)
1080 /* Permission settings are not required when abstract sockets are used */
1081 && ('\0' != ((const struct sockaddr_un *)sa)->sun_path[0])
1086 GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "UNIX_MATCH_UID");
1088 GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "UNIX_MATCH_GID");
1089 GNUNET_DISK_fix_permissions(((const struct sockaddr_un *)sa)->sun_path,
1094 if (GNUNET_OK != GNUNET_NETWORK_socket_listen(sock, 5))
1096 GNUNET_log_strerror(GNUNET_ERROR_TYPE_ERROR, "listen");
1097 GNUNET_break(GNUNET_OK == GNUNET_NETWORK_socket_close(sock));
1101 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1102 _("ARM now monitors connections to service `%s' at `%s'\n"),
1104 GNUNET_a2s(sa, addr_len));
1105 sli = GNUNET_new(struct ServiceListeningInfo);
1106 sli->service_addr = sa;
1107 sli->service_addr_len = addr_len;
1108 sli->listen_socket = sock;
1111 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
1115 GNUNET_CONTAINER_DLL_insert(sl->listen_head, sl->listen_tail, sli);
1120 * Remove and free an entry in the service list. Listen sockets
1121 * must have already been cleaned up. Only to be called during shutdown.
1123 * @param sl entry to free
1126 free_service(struct ServiceList *sl)
1128 GNUNET_assert(GNUNET_YES == in_shutdown);
1129 GNUNET_CONTAINER_DLL_remove(running_head, running_tail, sl);
1130 GNUNET_assert(NULL == sl->listen_head);
1131 GNUNET_free_non_null(sl->config);
1132 GNUNET_free_non_null(sl->binary);
1133 GNUNET_free(sl->name);
1139 * Check START-message.
1141 * @param cls identification of the client
1142 * @param amsg the actual message
1143 * @return #GNUNET_OK to keep the connection open,
1144 * #GNUNET_SYSERR to close it (signal serious error)
1147 check_start(void *cls, const struct GNUNET_ARM_Message *amsg)
1150 GNUNET_MQ_check_zero_termination(amsg);
1156 * Handle START-message.
1158 * @param cls identification of the client
1159 * @param amsg the actual message
1162 handle_start(void *cls, const struct GNUNET_ARM_Message *amsg)
1164 struct GNUNET_SERVICE_Client *client = cls;
1165 const char *servicename;
1166 struct ServiceList *sl;
1167 uint64_t request_id;
1169 request_id = GNUNET_ntohll(amsg->request_id);
1170 servicename = (const char *)&amsg[1];
1171 GNUNET_SERVICE_client_continue(client);
1172 if (GNUNET_YES == in_shutdown)
1174 signal_result(client,
1177 GNUNET_ARM_RESULT_IN_SHUTDOWN);
1180 sl = find_service(servicename);
1183 signal_result(client,
1186 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
1189 sl->force_start = GNUNET_YES;
1190 if (NULL != sl->proc)
1192 signal_result(client,
1195 GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
1198 start_process(sl, client, request_id);
1203 * Start a shutdown sequence.
1205 * @param cls closure (refers to service)
1208 trigger_shutdown(void *cls)
1211 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1212 GNUNET_SCHEDULER_shutdown();
1217 * Check STOP-message.
1219 * @param cls identification of the client
1220 * @param amsg the actual message
1221 * @return #GNUNET_OK to keep the connection open,
1222 * #GNUNET_SYSERR to close it (signal serious error)
1225 check_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
1228 GNUNET_MQ_check_zero_termination(amsg);
1234 * Handle STOP-message.
1236 * @param cls identification of the client
1237 * @param amsg the actual message
1240 handle_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
1242 struct GNUNET_SERVICE_Client *client = cls;
1243 struct ServiceList *sl;
1244 const char *servicename;
1245 uint64_t request_id;
1247 request_id = GNUNET_ntohll(amsg->request_id);
1248 servicename = (const char *)&amsg[1];
1249 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1250 _("Preparing to stop `%s'\n"),
1252 GNUNET_SERVICE_client_continue(client);
1253 if (0 == strcasecmp(servicename, "arm"))
1255 broadcast_status(servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1256 signal_result(client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1257 GNUNET_SERVICE_client_persist(client);
1258 GNUNET_SCHEDULER_add_now(&trigger_shutdown, NULL);
1261 sl = find_service(servicename);
1264 signal_result(client,
1267 GNUNET_ARM_RESULT_IS_NOT_KNOWN);
1270 sl->force_start = GNUNET_NO;
1271 if (GNUNET_YES == in_shutdown)
1273 /* shutdown in progress */
1274 signal_result(client,
1277 GNUNET_ARM_RESULT_IN_SHUTDOWN);
1280 if (NULL != sl->killing_client)
1282 /* killing already in progress */
1283 signal_result(client,
1286 GNUNET_ARM_RESULT_IS_STOPPING_ALREADY);
1289 if (NULL == sl->proc)
1291 /* process is down */
1292 signal_result(client,
1295 GNUNET_ARM_RESULT_IS_STOPPED_ALREADY);
1298 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1299 "Sending kill signal to service `%s', waiting for process to die.\n",
1301 broadcast_status(servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1302 /* no signal_start - only when it's STOPPED */
1303 sl->killed_at = GNUNET_TIME_absolute_get();
1304 if (0 != GNUNET_OS_process_kill(sl->proc, GNUNET_TERM_SIG))
1305 GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "kill");
1306 sl->killing_client = client;
1307 sl->killing_client_request_id = request_id;
1312 * Handle LIST-message.
1314 * @param cls identification of the client
1315 * @param message the actual message
1318 handle_list(void *cls, const struct GNUNET_ARM_Message *request)
1320 struct GNUNET_SERVICE_Client *client = cls;
1321 struct GNUNET_MQ_Envelope *env;
1322 struct GNUNET_ARM_ListResultMessage *msg;
1323 size_t string_list_size;
1324 struct ServiceList *sl;
1328 GNUNET_break(0 == ntohl(request->reserved));
1330 string_list_size = 0;
1332 /* first count the running processes get their name's size */
1333 for (sl = running_head; NULL != sl; sl = sl->next)
1335 if (NULL != sl->proc)
1337 string_list_size += strlen(sl->name);
1338 string_list_size += strlen(sl->binary);
1339 string_list_size += 4;
1344 env = GNUNET_MQ_msg_extra(msg,
1346 GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT);
1347 msg->arm_msg.request_id = request->request_id;
1348 msg->count = htons(count);
1350 pos = (char *)&msg[1];
1351 for (sl = running_head; NULL != sl; sl = sl->next)
1353 if (NULL != sl->proc)
1355 size_t s = strlen(sl->name) + strlen(sl->binary) + 4;
1356 GNUNET_snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
1360 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(client), env);
1361 GNUNET_SERVICE_client_continue(client);
1366 * Handle TEST-message by sending back TEST.
1368 * @param cls identification of the client
1369 * @param message the actual message
1372 handle_test(void *cls, const struct GNUNET_MessageHeader *message)
1374 struct GNUNET_SERVICE_Client *client = cls;
1375 struct GNUNET_MQ_Envelope *env;
1376 struct GNUNET_MessageHeader *msg;
1379 env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_ARM_TEST);
1380 GNUNET_MQ_send(GNUNET_SERVICE_client_get_mq(client), env);
1381 GNUNET_SERVICE_client_continue(client);
1386 * We are done with everything. Stop remaining
1387 * tasks, signal handler and the server.
1392 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1393 if (NULL != notifier)
1395 GNUNET_notification_context_destroy(notifier);
1398 if (NULL != service)
1400 GNUNET_SERVICE_shutdown(service);
1403 if (NULL != child_death_task)
1405 GNUNET_SCHEDULER_cancel(child_death_task);
1406 child_death_task = NULL;
1412 * Count how many services are still active.
1414 * @param running_head list of services
1415 * @return number of active services found
1418 list_count(struct ServiceList *running_head)
1420 struct ServiceList *i;
1423 for (res = 0, i = running_head; NULL != i; i = i->next, res++)
1424 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "%s\n", i->name);
1430 * Task run for shutdown.
1432 * @param cls closure, NULL if we need to self-restart
1435 shutdown_task(void *cls)
1437 struct ServiceList *pos;
1438 struct ServiceList *nxt;
1439 struct ServiceListeningInfo *sli;
1442 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1443 if (NULL != child_restart_task)
1445 GNUNET_SCHEDULER_cancel(child_restart_task);
1446 child_restart_task = NULL;
1448 in_shutdown = GNUNET_YES;
1449 /* first, stop listening */
1450 for (pos = running_head; NULL != pos; pos = pos->next)
1452 while (NULL != (sli = pos->listen_head))
1454 GNUNET_CONTAINER_DLL_remove(pos->listen_head, pos->listen_tail, sli);
1455 if (NULL != sli->accept_task)
1457 GNUNET_SCHEDULER_cancel(sli->accept_task);
1458 sli->accept_task = NULL;
1460 GNUNET_break(GNUNET_OK ==
1461 GNUNET_NETWORK_socket_close(sli->listen_socket));
1462 GNUNET_free(sli->service_addr);
1466 /* then, shutdown all existing service processes */
1468 while (NULL != (pos = nxt))
1471 if (NULL != pos->proc)
1473 GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1474 pos->killed_at = GNUNET_TIME_absolute_get();
1475 if (0 != GNUNET_OS_process_kill(pos->proc, GNUNET_TERM_SIG))
1476 GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "kill");
1483 /* finally, should all service processes be already gone, terminate for real */
1484 if (NULL == running_head)
1487 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1488 "Delaying shutdown, have %u childs still running\n",
1489 list_count(running_head));
1494 * Task run whenever it is time to restart a child that died.
1496 * @param cls closure, always NULL
1499 delayed_restart_task(void *cls)
1502 struct ServiceList *sl;
1503 struct GNUNET_TIME_Relative lowestRestartDelay;
1504 struct ServiceListeningInfo *sli;
1507 child_restart_task = NULL;
1508 GNUNET_assert(GNUNET_NO == in_shutdown);
1509 lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1511 /* check for services that need to be restarted due to
1512 * configuration changes or because the last restart failed */
1513 for (sl = running_head; NULL != sl; sl = sl->next)
1515 if (NULL != sl->proc)
1517 /* service is currently not running */
1518 if (0 == GNUNET_TIME_absolute_get_remaining(sl->restart_at).rel_value_us)
1520 /* restart is now allowed */
1521 if (sl->force_start)
1523 /* process should run by default, start immediately */
1524 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1525 _("Restarting service `%s'.\n"),
1527 start_process(sl, NULL, 0);
1531 /* process is run on-demand, ensure it is re-started if there is demand */
1532 for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1533 if (NULL == sli->accept_task)
1535 /* accept was actually paused, so start it again */
1537 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
1546 /* update calculation for earliest time to reactivate a service */
1547 lowestRestartDelay =
1548 GNUNET_TIME_relative_min(lowestRestartDelay,
1549 GNUNET_TIME_absolute_get_remaining(
1553 if (lowestRestartDelay.rel_value_us !=
1554 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1556 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1557 "Will restart process in %s\n",
1558 GNUNET_STRINGS_relative_time_to_string(lowestRestartDelay,
1560 child_restart_task =
1561 GNUNET_SCHEDULER_add_delayed_with_priority(lowestRestartDelay,
1562 GNUNET_SCHEDULER_PRIORITY_IDLE,
1563 &delayed_restart_task,
1570 * Task triggered whenever we receive a SIGCHLD (child
1573 * @param cls closure, NULL
1576 maint_child_death(void *cls)
1578 struct ServiceList *pos;
1579 struct ServiceList *next;
1580 struct ServiceListeningInfo *sli;
1581 const char *statstr;
1585 enum GNUNET_OS_ProcessStatusType statusType;
1586 unsigned long statusCode;
1587 const struct GNUNET_DISK_FileHandle *pr;
1590 pr = GNUNET_DISK_pipe_handle(sigpipe, GNUNET_DISK_PIPE_END_READ);
1591 child_death_task = NULL;
1592 /* consume the signal */
1593 GNUNET_break(0 < GNUNET_DISK_file_read(pr, &c, sizeof(c)));
1595 /* check for services that died (WAITPID) */
1596 next = running_head;
1597 while (NULL != (pos = next))
1601 if (NULL == pos->proc)
1603 if (GNUNET_YES == in_shutdown)
1608 if (NULL != wait_file)
1610 /* need to use 'wait4()' to obtain and log performance data */
1615 pid = GNUNET_OS_process_get_pid(pos->proc);
1616 ret = wait4(pid, &status, WNOHANG, &ru);
1618 continue; /* no process done */
1619 if (WIFEXITED(status))
1621 statusType = GNUNET_OS_PROCESS_EXITED;
1622 statusCode = WEXITSTATUS(status);
1624 else if (WIFSIGNALED(status))
1626 statusType = GNUNET_OS_PROCESS_SIGNALED;
1627 statusCode = WTERMSIG(status);
1629 else if (WIFSTOPPED(status))
1631 statusType = GNUNET_OS_PROCESS_SIGNALED;
1632 statusCode = WSTOPSIG(status);
1635 else if (WIFCONTINUED(status))
1637 statusType = GNUNET_OS_PROCESS_RUNNING;
1643 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1646 if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1647 (GNUNET_OS_PROCESS_SIGNALED == statusType))
1649 double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1650 double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1652 "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1657 (unsigned long long)ru.ru_maxrss,
1658 (unsigned long long)ru.ru_inblock,
1659 (unsigned long long)ru.ru_oublock,
1660 (unsigned long long)ru.ru_nvcsw,
1661 (unsigned long long)ru.ru_nivcsw);
1664 else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1666 if ((GNUNET_SYSERR == (ret = GNUNET_OS_process_status(pos->proc,
1669 (ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1670 (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1671 (statusType == GNUNET_OS_PROCESS_RUNNING))
1674 if (statusType == GNUNET_OS_PROCESS_EXITED)
1676 statstr = _(/* process termination method */ "exit");
1677 statcode = statusCode;
1679 else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1681 statstr = _(/* process termination method */ "signal");
1682 statcode = statusCode;
1686 statstr = _(/* process termination method */ "unknown");
1689 if (0 != pos->killed_at.abs_value_us)
1691 GNUNET_log(GNUNET_ERROR_TYPE_INFO,
1692 _("Service `%s' took %s to terminate\n"),
1694 GNUNET_STRINGS_relative_time_to_string(
1695 GNUNET_TIME_absolute_get_duration(pos->killed_at),
1698 GNUNET_OS_process_destroy(pos->proc);
1700 broadcast_status(pos->name, GNUNET_ARM_SERVICE_STOPPED, NULL);
1701 if (NULL != pos->killing_client)
1703 signal_result(pos->killing_client,
1705 pos->killing_client_request_id,
1706 GNUNET_ARM_RESULT_STOPPED);
1707 pos->killing_client = NULL;
1708 pos->killing_client_request_id = 0;
1710 if (GNUNET_YES != in_shutdown)
1712 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1714 /* process terminated normally, allow restart at any time */
1715 pos->restart_at.abs_value_us = 0;
1717 GNUNET_ERROR_TYPE_INFO,
1718 _("Service `%s' terminated normally, will restart at any time\n"),
1720 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1721 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1723 GNUNET_break(NULL == sli->accept_task);
1725 GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL,
1734 GNUNET_ERROR_TYPE_INFO,
1735 _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1739 GNUNET_STRINGS_relative_time_to_string(pos->backoff, GNUNET_YES));
1741 /* Reduce backoff based on runtime of the process,
1742 so that there is a cool-down if a process actually
1743 runs for a while. */
1744 struct GNUNET_TIME_Relative runtime;
1745 unsigned int minutes;
1747 runtime = GNUNET_TIME_absolute_get_duration(pos->restart_at);
1749 runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1751 pos->backoff = GNUNET_TIME_UNIT_ZERO;
1753 pos->backoff.rel_value_us <<= minutes;
1755 /* schedule restart */
1756 pos->restart_at = GNUNET_TIME_relative_to_absolute(pos->backoff);
1757 pos->backoff = GNUNET_TIME_STD_BACKOFF(pos->backoff);
1758 if (NULL != child_restart_task)
1759 GNUNET_SCHEDULER_cancel(child_restart_task);
1760 child_restart_task =
1761 GNUNET_SCHEDULER_add_with_priority(GNUNET_SCHEDULER_PRIORITY_IDLE,
1762 &delayed_restart_task,
1772 GNUNET_SCHEDULER_add_read_file(GNUNET_TIME_UNIT_FOREVER_REL,
1776 if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1778 else if (GNUNET_YES == in_shutdown)
1779 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
1780 "Delaying shutdown after child's death, still have %u children\n",
1781 list_count(running_head));
1786 * Signal handler called for SIGCHLD. Triggers the
1787 * respective handler by writing to the trigger pipe.
1790 sighandler_child_death()
1793 int old_errno = errno; /* back-up errno */
1797 GNUNET_DISK_file_write(GNUNET_DISK_pipe_handle(sigpipe,
1798 GNUNET_DISK_PIPE_END_WRITE),
1801 errno = old_errno; /* restore errno */
1806 * Setup our service record for the given section in the configuration file
1807 * (assuming the section is for a service).
1810 * @param section a section in the configuration file
1811 * @return #GNUNET_OK (continue)
1814 setup_service(void *cls, const char *section)
1816 struct ServiceList *sl;
1820 struct sockaddr **addrs;
1821 socklen_t *addr_lens;
1825 if (0 == strcasecmp(section, "arm"))
1828 GNUNET_CONFIGURATION_get_value_string(cfg, section, "BINARY", &binary))
1830 /* not a service section */
1834 GNUNET_CONFIGURATION_have_value(cfg, section, "RUN_PER_USER")) &&
1836 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "RUN_PER_USER")))
1838 if (GNUNET_NO == start_user)
1840 GNUNET_free(binary);
1841 return; /* user service, and we don't deal with those */
1846 if (GNUNET_NO == start_system)
1848 GNUNET_free(binary);
1849 return; /* system service, and we don't deal with those */
1852 sl = find_service(section);
1855 /* got the same section twice!? */
1857 GNUNET_free(binary);
1861 if (((GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(cfg,
1865 (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename(cfg,
1869 (0 != stat(config, &sbuf)))
1873 GNUNET_log_config_invalid(GNUNET_ERROR_TYPE_WARNING,
1877 GNUNET_free(config);
1881 sl = GNUNET_new(struct ServiceList);
1882 sl->name = GNUNET_strdup(section);
1883 sl->binary = binary;
1884 sl->config = config;
1885 sl->backoff = GNUNET_TIME_UNIT_MILLISECONDS;
1886 sl->restart_at = GNUNET_TIME_UNIT_FOREVER_ABS;
1888 sl->pipe_control = GNUNET_YES;
1890 if (GNUNET_CONFIGURATION_have_value(cfg, section, "PIPECONTROL"))
1892 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "PIPECONTROL");
1894 GNUNET_CONTAINER_DLL_insert(running_head, running_tail, sl);
1896 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "IMMEDIATE_START"))
1898 sl->force_start = GNUNET_YES;
1900 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "NOARMBIND"))
1906 GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "START_ON_DEMAND"))
1909 if (0 >= (ret = get_server_addresses(section, cfg, &addrs, &addr_lens)))
1911 /* this will free (or capture) addrs[i] */
1912 for (unsigned int i = 0; i < (unsigned int)ret; i++)
1913 create_listen_socket(addrs[i], addr_lens[i], sl);
1915 GNUNET_free(addr_lens);
1920 * A client connected, mark as a monitoring client.
1922 * @param cls closure
1923 * @param client identification of the client
1924 * @param mq queue to talk to @a client
1928 client_connect_cb(void *cls,
1929 struct GNUNET_SERVICE_Client *client,
1930 struct GNUNET_MQ_Handle *mq)
1932 /* All clients are considered to be of the "monitor" kind
1933 * (that is, they don't affect ARM shutdown).
1937 GNUNET_SERVICE_client_mark_monitor(client);
1943 * A client disconnected, clean up associated state.
1945 * @param cls closure
1946 * @param client identification of the client
1947 * @param app_ctx must match @a client
1950 client_disconnect_cb(void *cls,
1951 struct GNUNET_SERVICE_Client *client,
1955 GNUNET_assert(client == app_ctx);
1956 for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
1957 if (sl->killing_client == client)
1958 sl->killing_client = NULL;
1963 * Handle MONITOR-message.
1965 * @param cls identification of the client
1966 * @param message the actual message
1967 * @return #GNUNET_OK to keep the connection open,
1968 * #GNUNET_SYSERR to close it (signal serious error)
1971 handle_monitor(void *cls, const struct GNUNET_MessageHeader *message)
1973 struct GNUNET_SERVICE_Client *client = cls;
1976 /* FIXME: might want to start by letting monitor know about
1977 services that are already running */
1978 /* Removal is handled by the server implementation, internally. */
1979 GNUNET_notification_context_add(notifier,
1980 GNUNET_SERVICE_client_get_mq(client));
1981 broadcast_status("arm", GNUNET_ARM_SERVICE_MONITORING_STARTED, client);
1982 GNUNET_SERVICE_client_continue(client);
1987 * Process arm requests.
1989 * @param cls closure, NULL
1990 * @param serv the initialized service
1991 * @param c configuration to use
1995 const struct GNUNET_CONFIGURATION_Handle *c,
1996 struct GNUNET_SERVICE_Handle *serv)
1998 struct ServiceList *sl;
2003 GNUNET_SCHEDULER_add_shutdown(&shutdown_task, NULL);
2004 child_death_task = GNUNET_SCHEDULER_add_read_file(
2005 GNUNET_TIME_UNIT_FOREVER_REL,
2006 GNUNET_DISK_pipe_handle(sigpipe, GNUNET_DISK_PIPE_END_READ),
2011 GNUNET_CONFIGURATION_get_value_filename(cfg,
2013 "RESOURCE_DIAGNOSTICS",
2016 wait_file = fopen(wait_filename, "w");
2017 if (NULL == wait_file)
2019 GNUNET_log_strerror_file(GNUNET_ERROR_TYPE_ERROR,
2025 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg,
2029 prefix_command = GNUNET_strdup("");
2031 prefix_command = GNUNET_CONFIGURATION_expand_dollar(cfg, prefix_command);
2032 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string(cfg,
2036 final_option = GNUNET_strdup("");
2038 final_option = GNUNET_CONFIGURATION_expand_dollar(cfg, final_option);
2040 GNUNET_CONFIGURATION_get_value_yesno(cfg, "ARM", "START_USER_SERVICES");
2042 GNUNET_CONFIGURATION_get_value_yesno(cfg, "ARM", "START_SYSTEM_SERVICES");
2043 if ((GNUNET_NO == start_user) && (GNUNET_NO == start_system))
2046 GNUNET_ERROR_TYPE_ERROR,
2047 "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
2048 GNUNET_SCHEDULER_shutdown();
2052 GNUNET_CONFIGURATION_iterate_sections(cfg, &setup_service, NULL);
2054 /* start default services... */
2055 for (sl = running_head; NULL != sl; sl = sl->next)
2056 if (GNUNET_YES == sl->force_start)
2057 start_process(sl, NULL, 0);
2058 notifier = GNUNET_notification_context_create(MAX_NOTIFY_QUEUE);
2063 * The main function for the arm service.
2065 * @param argc number of arguments from the command line
2066 * @param argv command line arguments
2067 * @return 0 ok, 1 on error
2070 main(int argc, char *const *argv)
2072 struct GNUNET_SIGNAL_Context *shc_chld;
2073 struct GNUNET_MQ_MessageHandler handlers[] =
2074 { GNUNET_MQ_hd_var_size(start,
2075 GNUNET_MESSAGE_TYPE_ARM_START,
2076 struct GNUNET_ARM_Message,
2078 GNUNET_MQ_hd_var_size(stop,
2079 GNUNET_MESSAGE_TYPE_ARM_STOP,
2080 struct GNUNET_ARM_Message,
2082 GNUNET_MQ_hd_fixed_size(monitor,
2083 GNUNET_MESSAGE_TYPE_ARM_MONITOR,
2084 struct GNUNET_MessageHeader,
2086 GNUNET_MQ_hd_fixed_size(list,
2087 GNUNET_MESSAGE_TYPE_ARM_LIST,
2088 struct GNUNET_ARM_Message,
2090 GNUNET_MQ_hd_fixed_size(test,
2091 GNUNET_MESSAGE_TYPE_ARM_TEST,
2092 struct GNUNET_MessageHeader,
2094 GNUNET_MQ_handler_end() };
2096 sigpipe = GNUNET_DISK_pipe(GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_NO);
2097 GNUNET_assert(NULL != sigpipe);
2099 GNUNET_SIGNAL_handler_install(GNUNET_SIGCHLD, &sighandler_child_death);
2100 if (0 != GNUNET_SERVICE_run_(argc,
2103 GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN,
2106 &client_disconnect_cb,
2111 if (NULL != wait_file)
2116 if (NULL != wait_filename)
2118 GNUNET_free(wait_filename);
2119 wait_filename = NULL;
2122 GNUNET_SIGNAL_handler_uninstall(shc_chld);
2124 GNUNET_DISK_pipe_close(sigpipe);
2130 #if defined(LINUX) && defined(__GLIBC__)
2134 * MINIMIZE heap size (way below 128k) since this process doesn't need much.
2136 void __attribute__ ((constructor)) GNUNET_ARM_memory_init()
2138 mallopt(M_TRIM_THRESHOLD, 4 * 1024);
2139 mallopt(M_TOP_PAD, 1 * 1024);
2145 /* end of gnunet-service-arm.c */