GNUnet 0.22.1
gnunet-service-arm.c
Go to the documentation of this file.
1/*
2 This file is part of GNUnet.
3 Copyright (C) 2009-2011, 2015, 2016 GNUnet e.V.
4
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.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
14
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/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
26#include "platform.h"
27#include "gnunet_util_lib.h"
28#include "gnunet_arm_service.h"
29#include "gnunet_protocols.h"
30#include "arm.h"
31
32#define LOG(kind, ...) GNUNET_log_from (kind, "util", __VA_ARGS__)
33
34#define LOG_STRERROR(kind, syscall) \
35 GNUNET_log_from_strerror (kind, "util", syscall)
36
37
38#if HAVE_WAIT4
42static char *wait_filename;
43
47static FILE *wait_file;
48#endif
49
50
56#define MAX_NOTIFY_QUEUE 1024
57
58
62struct ServiceList;
63
64
69{
74
79
83 struct sockaddr *service_addr;
84
88 struct ServiceList *sl;
89
94
99
104};
105
106
111{
116
121
126
131
135 char *name;
136
140 char *binary;
141
145 char *config;
146
152
157
162
167
172
177
183
190
196
201};
202
207
212
216static const struct GNUNET_CONFIGURATION_Handle *cfg;
217
221static char *prefix_command;
222
226static char *final_option;
227
232
238
243
247static int in_shutdown;
248
252static int global_ret;
253
258
263
275
280
281
292static void
293add_unixpath (struct sockaddr **saddrs,
294 socklen_t *saddrlens,
295 const char *unixpath,
296 int abstract)
297{
298#ifdef AF_UNIX
299 struct sockaddr_un *un;
300
301 un = GNUNET_new (struct sockaddr_un);
302 un->sun_family = AF_UNIX;
303 GNUNET_strlcpy (un->sun_path, unixpath, sizeof(un->sun_path));
304#ifdef __linux__
305 if (GNUNET_YES == abstract)
306 un->sun_path[0] = '\0';
307#endif
308#if HAVE_SOCKADDR_UN_SUN_LEN
309 un->sun_len = (u_char) sizeof(struct sockaddr_un);
310#endif
311 *saddrs = (struct sockaddr *) un;
312 *saddrlens = sizeof(struct sockaddr_un);
313#else
314 /* this function should never be called
315 * unless AF_UNIX is defined! */
316 GNUNET_assert (0);
317#endif
318}
319
320
341static int
343 const struct GNUNET_CONFIGURATION_Handle *cfg_,
344 struct sockaddr ***addrs,
345 socklen_t **addr_lens)
346{
347 int disablev6;
348 struct GNUNET_NETWORK_Handle *desc;
349 unsigned long long port;
350 char *unixpath;
351 struct addrinfo hints;
352 struct addrinfo *res;
353 struct addrinfo *pos;
354 struct addrinfo *next;
355 unsigned int i;
356 int resi;
357 int ret;
358 int abstract;
359 struct sockaddr **saddrs;
360 socklen_t *saddrlens;
361 char *hostname;
362
363 *addrs = NULL;
364 *addr_lens = NULL;
365 desc = NULL;
366 disablev6 = GNUNET_NO;
367 if (GNUNET_SYSERR ==
368 (disablev6 = GNUNET_CONFIGURATION_get_value_yesno (cfg_,
370 "DISABLEV6")))
371 return GNUNET_SYSERR;
372 if (! disablev6)
373 {
374 /* probe IPv6 support */
375 desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
376 if (NULL == desc)
377 {
378 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
379 (EACCES == errno))
380 {
382 return GNUNET_SYSERR;
383 }
385 _ (
386 "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
388 strerror (errno));
389 disablev6 = GNUNET_YES;
390 }
391 else
392 {
394 }
395 }
396
397 port = 0;
399 {
400 if (GNUNET_OK !=
403 "PORT",
404 &port))
405 {
407 _ ("Require valid port number for service `%s' in configuration!\n"),
409 }
410 if (port > 65535)
411 {
413 _ ("Require valid port number for service `%s' in configuration!\n"),
415 return GNUNET_SYSERR;
416 }
417 }
418
419 hostname = NULL;
423 "BINDTO",
424 &hostname));
425 unixpath = NULL;
426 abstract = GNUNET_NO;
427#ifdef AF_UNIX
428 if ( (GNUNET_OK ==
431 "UNIXPATH",
432 &unixpath)) &&
433 (0 < strlen (unixpath)) )
434 {
435 /* probe UNIX support */
436 struct sockaddr_un s_un;
437
438 if (strlen (unixpath) >= sizeof(s_un.sun_path))
439 {
441 _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
442 unixpath,
443 (unsigned long long) sizeof(s_un.sun_path));
444 unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
445 LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
446 }
447#ifdef __linux__
449 "TESTING",
450 "USE_ABSTRACT_SOCKETS");
451 if (GNUNET_SYSERR == abstract)
452 abstract = GNUNET_NO;
453#endif
454 if ((GNUNET_YES != abstract) &&
457 }
458 if (NULL != unixpath)
459 {
460 desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
461 if (NULL == desc)
462 {
463 if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
464 (EACCES == errno))
465 {
467 GNUNET_free (hostname);
468 GNUNET_free (unixpath);
469 return GNUNET_SYSERR;
470 }
472 _ (
473 "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
475 strerror (errno));
476 GNUNET_free (unixpath);
477 unixpath = NULL;
478 }
479 else
480 {
482 desc = NULL;
483 }
484 }
485#endif
486
487 if ((0 == port) && (NULL == unixpath))
488 {
489 if (GNUNET_YES ==
492 "START_ON_DEMAND"))
494 _ (
495 "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
497 GNUNET_free (hostname);
498 return GNUNET_SYSERR;
499 }
500 if (0 == port)
501 {
502 saddrs = GNUNET_new_array (2, struct sockaddr *);
503 saddrlens = GNUNET_new_array (2, socklen_t);
504 add_unixpath (saddrs, saddrlens, unixpath, abstract);
505 GNUNET_free (unixpath);
506 GNUNET_free (hostname);
507 *addrs = saddrs;
508 *addr_lens = saddrlens;
509 return 1;
510 }
511
512 if (NULL != hostname)
513 {
515 "Resolving `%s' since that is where `%s' will bind to.\n",
516 hostname,
518 memset (&hints, 0, sizeof(struct addrinfo));
519 if (disablev6)
520 hints.ai_family = AF_INET;
521 hints.ai_protocol = IPPROTO_TCP;
522 if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
523 (NULL == res))
524 {
526 _ ("Failed to resolve `%s': %s\n"),
527 hostname,
528 gai_strerror (ret));
529 GNUNET_free (hostname);
530 GNUNET_free (unixpath);
531 return GNUNET_SYSERR;
532 }
533 next = res;
534 i = 0;
535 while (NULL != (pos = next))
536 {
537 next = pos->ai_next;
538 if ((disablev6) && (pos->ai_family == AF_INET6))
539 continue;
540 i++;
541 }
542 if (0 == i)
543 {
545 _ ("Failed to find %saddress for `%s'.\n"),
546 disablev6 ? "IPv4 " : "",
547 hostname);
548 freeaddrinfo (res);
549 GNUNET_free (hostname);
550 GNUNET_free (unixpath);
551 return GNUNET_SYSERR;
552 }
553 resi = i;
554 if (NULL != unixpath)
555 resi++;
556 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
557 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
558 i = 0;
559 if (NULL != unixpath)
560 {
561 add_unixpath (saddrs, saddrlens, unixpath, abstract);
562 i++;
563 }
564 next = res;
565 while (NULL != (pos = next))
566 {
567 next = pos->ai_next;
568 if ((disablev6) && (AF_INET6 == pos->ai_family))
569 continue;
570 if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
571 continue; /* not TCP */
572 if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
573 continue; /* huh? */
575 "Service `%s' will bind to `%s'\n",
577 GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
578 if (AF_INET == pos->ai_family)
579 {
580 GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
581 saddrlens[i] = pos->ai_addrlen;
582 saddrs[i] = GNUNET_malloc (saddrlens[i]);
583 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
584 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
585 }
586 else
587 {
588 GNUNET_assert (AF_INET6 == pos->ai_family);
589 GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
590 saddrlens[i] = pos->ai_addrlen;
591 saddrs[i] = GNUNET_malloc (saddrlens[i]);
592 GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
593 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
594 }
595 i++;
596 }
597 GNUNET_free (hostname);
598 freeaddrinfo (res);
599 resi = i;
600 }
601 else
602 {
603 /* will bind against everything, just set port */
604 if (disablev6)
605 {
606 /* V4-only */
607 resi = 1;
608 if (NULL != unixpath)
609 resi++;
610 i = 0;
611 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
612 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
613 if (NULL != unixpath)
614 {
615 add_unixpath (saddrs, saddrlens, unixpath, abstract);
616 i++;
617 }
618 saddrlens[i] = sizeof(struct sockaddr_in);
619 saddrs[i] = GNUNET_malloc (saddrlens[i]);
620#if HAVE_SOCKADDR_IN_SIN_LEN
621 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
622#endif
623 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
624 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
625 }
626 else
627 {
628 /* dual stack */
629 resi = 2;
630 if (NULL != unixpath)
631 resi++;
632 saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
633 saddrlens = GNUNET_new_array (resi + 1, socklen_t);
634 i = 0;
635 if (NULL != unixpath)
636 {
637 add_unixpath (saddrs, saddrlens, unixpath, abstract);
638 i++;
639 }
640 saddrlens[i] = sizeof(struct sockaddr_in6);
641 saddrs[i] = GNUNET_malloc (saddrlens[i]);
642#if HAVE_SOCKADDR_IN_SIN_LEN
643 ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
644#endif
645 ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
646 ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
647 i++;
648 saddrlens[i] = sizeof(struct sockaddr_in);
649 saddrs[i] = GNUNET_malloc (saddrlens[i]);
650#if HAVE_SOCKADDR_IN_SIN_LEN
651 ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
652#endif
653 ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
654 ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
655 }
656 }
657 GNUNET_free (unixpath);
658 *addrs = saddrs;
659 *addr_lens = saddrlens;
660 return resi;
661}
662
663
674static void
676 const char *name,
677 uint64_t request_id,
679{
680 struct GNUNET_MQ_Envelope *env;
682
683 (void) name;
685 msg->result = htonl (result);
686 msg->arm_msg.request_id = GNUNET_htonll (request_id);
688}
689
690
699static void
702 struct GNUNET_SERVICE_Client *unicast)
703{
704 struct GNUNET_MQ_Envelope *env;
706 size_t namelen;
707
709 "Sending status %u of service `%s' to client\n",
710 (unsigned int) status,
711 name);
712 namelen = strlen (name) + 1;
714 namelen,
716 msg->status = htonl ((uint32_t) (status));
717 GNUNET_memcpy ((char *) &msg[1],
718 name,
719 namelen);
720 if (NULL == unicast)
721 {
722 if (NULL != notifier)
724 &msg->header,
725 GNUNET_YES);
727 }
728 else
729 {
731 env);
732 }
733}
734
735
744static void
746 struct GNUNET_SERVICE_Client *client,
747 uint64_t request_id)
748{
749 char *loprefix;
750 char *options;
751 enum GNUNET_GenericReturnValue use_debug;
752 bool is_simple_service;
753 int *lsocks;
754 unsigned int ls;
755 char *binary;
756 char *quotedbinary;
757
758 /* calculate listen socket list */
759 lsocks = NULL;
760 ls = 0;
761 for (struct ServiceListeningInfo *sli = sl->listen_head;
762 NULL != sli;
763 sli = sli->next)
764 {
765 GNUNET_array_append (lsocks,
766 ls,
767 GNUNET_NETWORK_get_fd (sli->listen_socket));
768 if (NULL != sli->accept_task)
769 {
770 GNUNET_SCHEDULER_cancel (sli->accept_task);
771 sli->accept_task = NULL;
772 }
773 }
774
775 GNUNET_array_append (lsocks,
776 ls,
777 -1);
778
779 /* obtain configuration */
780 if (GNUNET_OK !=
782 sl->name,
783 "PREFIX",
784 &loprefix))
785 loprefix = GNUNET_strdup (prefix_command);
786 else
788 loprefix);
789 if (GNUNET_OK !=
791 sl->name,
792 "OPTIONS",
793 &options))
794 options = NULL;
795 else
797 {
798 char *new_options;
799 char *optpos;
800 char *fin_options;
801
802 fin_options = GNUNET_strdup (final_option);
803 /* replace '{}' with service name */
804 while (NULL != (optpos = strstr (fin_options, "{}")))
805 {
806 /* terminate string at opening parenthesis */
807 *optpos = 0;
808 GNUNET_asprintf (&new_options,
809 "%s%s%s",
810 fin_options,
811 sl->name,
812 optpos + 2);
813 GNUNET_free (fin_options);
814 fin_options = new_options;
815 }
816 if (NULL != options)
817 {
818 /* combine "fin_options" with "options" */
819 optpos = options;
820 GNUNET_asprintf (&options, "%s %s", fin_options, optpos);
821 GNUNET_free (fin_options);
822 GNUNET_free (optpos);
823 }
824 else
825 {
826 /* only have "fin_options", use that */
827 options = fin_options;
828 }
829 }
831 options);
833 sl->name,
834 "DEBUG");
835 {
836 const char *service_type = NULL;
837 const char *choices[] = {
838 "GNUNET",
839 "SIMPLE",
840 NULL
841 };
842
843 is_simple_service = false;
844 if ( (GNUNET_OK ==
846 sl->name,
847 "TYPE",
848 choices,
849 &service_type)) &&
850 (0 == strcasecmp (service_type,
851 "SIMPLE")))
852 is_simple_service = true;
853 }
854
855 GNUNET_assert (NULL == sl->proc);
856 if (is_simple_service)
857 {
858 /* A simple service will receive no GNUnet specific
859 command line options. */
860 binary = GNUNET_strdup (sl->binary);
862 binary);
863 GNUNET_asprintf (&quotedbinary,
864 "\"%s\"",
865 sl->binary);
867 "Starting simple service `%s' using binary `%s'\n",
868 sl->name,
869 sl->binary);
870 /* FIXME: dollar expansion should only be done outside
871 * of ''-quoted strings, escaping should be considered. */
872 if (NULL != options)
874 options);
879 lsocks,
880 loprefix,
881 quotedbinary,
882 options,
883 NULL);
884 }
885 else
886 {
887 /* actually start process */
889 "Starting service `%s' using binary `%s' and configuration `%s'\n",
890 sl->name,
891 sl->binary,
892 sl->config);
894 GNUNET_asprintf (&quotedbinary,
895 "\"%s\"",
896 binary);
897
898 if (GNUNET_YES == use_debug)
899 {
900 if (NULL == sl->config)
902 sl->pipe_control
906 lsocks,
907 loprefix,
908 quotedbinary,
909 "-L",
910 "DEBUG",
911 options,
912 NULL);
913 else
915 sl->pipe_control
919 lsocks,
920 loprefix,
921 quotedbinary,
922 "-c",
923 sl->config,
924 "-L",
925 "DEBUG",
926 options,
927 NULL);
928 }
929 else
930 {
931 if (NULL == sl->config)
933 sl->pipe_control
937 lsocks,
938 loprefix,
939 quotedbinary,
940 options,
941 NULL);
942 else
944 sl->pipe_control
948 lsocks,
949 loprefix,
950 quotedbinary,
951 "-c",
952 sl->config,
953 options,
954 NULL);
955 }
956 }
957 GNUNET_free (binary);
958 GNUNET_free (quotedbinary);
960 if (NULL == sl->proc)
961 {
963 "Failed to start service `%s'\n",
964 sl->name);
965 if (client)
966 signal_result (client,
967 sl->name,
968 request_id,
970 }
971 else
972 {
974 "Starting service `%s'\n",
975 sl->name);
978 NULL);
979 if (client)
980 signal_result (client,
981 sl->name,
982 request_id,
984 }
985 /* clean up */
986 GNUNET_free (loprefix);
988 GNUNET_array_grow (lsocks,
989 ls,
990 0);
991}
992
993
1001static struct ServiceList *
1002find_service (const char *name)
1003{
1004 struct ServiceList *sl;
1005
1006 sl = running_head;
1007 while (sl != NULL)
1008 {
1009 if (0 == strcasecmp (sl->name, name))
1010 return sl;
1011 sl = sl->next;
1012 }
1013 return NULL;
1014}
1015
1016
1023static void
1025{
1026 struct ServiceListeningInfo *sli = cls;
1027 struct ServiceList *sl = sli->sl;
1028
1029 sli->accept_task = NULL;
1031 start_process (sl, NULL, 0);
1032}
1033
1034
1043static void
1044create_listen_socket (struct sockaddr *sa,
1045 socklen_t addr_len,
1046 struct ServiceList *sl)
1047{
1048 static int on = 1;
1049 struct GNUNET_NETWORK_Handle *sock;
1050 struct ServiceListeningInfo *sli;
1051
1052 int match_uid;
1053 int match_gid;
1054
1055 switch (sa->sa_family)
1056 {
1057 case AF_INET:
1058 sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
1059 break;
1060
1061 case AF_INET6:
1062 sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1063 break;
1064
1065 case AF_UNIX:
1066 if (0 == strcmp (GNUNET_a2s (sa, addr_len),
1067 "@")) /* Do not bind to blank UNIX path! */
1068 return;
1069 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
1070 break;
1071
1072 default:
1073 GNUNET_break (0);
1074 sock = NULL;
1075 errno = EAFNOSUPPORT;
1076 break;
1077 }
1078 if (NULL == sock)
1079 {
1081 _ ("Unable to create socket for service `%s': %s\n"),
1082 sl->name,
1083 strerror (errno));
1084 GNUNET_free (sa);
1085 return;
1086 }
1088 SOL_SOCKET,
1089 SO_REUSEADDR,
1090 &on,
1091 sizeof(on)))
1093 "setsockopt");
1094#ifdef IPV6_V6ONLY
1095 if ((sa->sa_family == AF_INET6) &&
1097 IPPROTO_IPV6,
1098 IPV6_V6ONLY,
1099 &on,
1100 sizeof(on))))
1102 "setsockopt");
1103#endif
1104 if (AF_UNIX == sa->sa_family)
1105 GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1106 if (GNUNET_OK !=
1107 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
1108 {
1109 GNUNET_log (
1111 _ (
1112 "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1113 sl->name,
1114 GNUNET_a2s (sa, addr_len),
1115 strerror (errno));
1117 GNUNET_free (sa);
1118 return;
1119 }
1120 if ((AF_UNIX == sa->sa_family)
1121#ifdef __linux__
1122 /* Permission settings are not required when abstract sockets are used */
1123 && ('\0' != ((const struct sockaddr_un *) sa)->sun_path[0])
1124#endif
1125 )
1126 {
1127 match_uid =
1128 (GNUNET_YES ==
1130 sl->name,
1131 "UNIX_MATCH_UID"));
1132 match_gid =
1133 (GNUNET_YES ==
1135 sl->name,
1136 "UNIX_MATCH_GID"));
1137 GNUNET_DISK_fix_permissions (((const struct sockaddr_un *) sa)->sun_path,
1138 match_uid,
1139 match_gid);
1140 }
1141 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1142 {
1145 GNUNET_free (sa);
1146 return;
1147 }
1149 _ ("ARM now monitors connections to service `%s' at `%s'\n"),
1150 sl->name,
1151 GNUNET_a2s (sa, addr_len));
1152 sli = GNUNET_new (struct ServiceListeningInfo);
1153 sli->service_addr = sa;
1154 sli->service_addr_len = addr_len;
1155 sli->listen_socket = sock;
1156 sli->sl = sl;
1157 sli->accept_task =
1159 sock,
1161 sli);
1163}
1164
1165
1172static void
1174{
1177 GNUNET_assert (NULL == sl->listen_head);
1180 GNUNET_free (sl->name);
1181 GNUNET_free (sl);
1182}
1183
1184
1193static int
1194check_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1195{
1196 (void) cls;
1198 return GNUNET_OK;
1199}
1200
1201
1208static void
1209handle_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1210{
1211 struct GNUNET_SERVICE_Client *client = cls;
1212 const char *servicename;
1213 struct ServiceList *sl;
1214 uint64_t request_id;
1215
1216 request_id = GNUNET_ntohll (amsg->request_id);
1217 servicename = (const char *) &amsg[1];
1219 if (GNUNET_YES == in_shutdown)
1220 {
1221 signal_result (client,
1222 servicename,
1223 request_id,
1225 return;
1226 }
1227 sl = find_service (servicename);
1228 if (NULL == sl)
1229 {
1230 signal_result (client,
1231 servicename,
1232 request_id,
1234 return;
1235 }
1236 sl->force_start = GNUNET_YES;
1237 if (NULL != sl->proc)
1238 {
1239 signal_result (client,
1240 servicename,
1241 request_id,
1243 return;
1244 }
1245 start_process (sl, client, request_id);
1246}
1247
1248
1254static void
1256{
1257 (void) cls;
1258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1260}
1261
1262
1271static int
1272check_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
1273{
1274 (void) cls;
1276 return GNUNET_OK;
1277}
1278
1279
1286static void
1287handle_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
1288{
1289 struct GNUNET_SERVICE_Client *client = cls;
1290 struct ServiceList *sl;
1291 const char *servicename;
1292 uint64_t request_id;
1293
1294 request_id = GNUNET_ntohll (amsg->request_id);
1295 servicename = (const char *) &amsg[1];
1297 _ ("Preparing to stop `%s'\n"),
1298 servicename);
1300 if (0 == strcasecmp (servicename, "arm"))
1301 {
1302 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1303 signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1306 return;
1307 }
1308 sl = find_service (servicename);
1309 if (NULL == sl)
1310 {
1311 signal_result (client,
1312 servicename,
1313 request_id,
1315 return;
1316 }
1317 sl->force_start = GNUNET_NO;
1318 if (GNUNET_YES == in_shutdown)
1319 {
1320 /* shutdown in progress */
1321 signal_result (client,
1322 servicename,
1323 request_id,
1325 return;
1326 }
1327 if (NULL != sl->killing_client)
1328 {
1329 /* killing already in progress */
1330 signal_result (client,
1331 servicename,
1332 request_id,
1334 return;
1335 }
1336 if (NULL == sl->proc)
1337 {
1338 /* process is down */
1339 signal_result (client,
1340 servicename,
1341 request_id,
1343 return;
1344 }
1346 "Sending kill signal to service `%s', waiting for process to die.\n",
1347 servicename);
1348 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1349 /* no signal_start - only when it's STOPPED */
1353 sl->killing_client = client;
1354 sl->killing_client_request_id = request_id;
1355}
1356
1357
1369static int
1370pool_write (char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
1371{
1372 size_t next_pos = (*pool_pos) + strlen (str) + 1;
1373
1374 if (next_pos > pool_size)
1375 return GNUNET_SYSERR;
1376 memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1377 *pool_pos = next_pos;
1378 return GNUNET_OK;
1379}
1380
1381
1388static void
1389handle_list (void *cls, const struct GNUNET_ARM_Message *request)
1390{
1391 struct GNUNET_SERVICE_Client *client = cls;
1392 struct GNUNET_MQ_Envelope *env;
1394 size_t extra_size;
1395 struct ServiceList *sl;
1396 uint16_t count;
1397 size_t pool_size;
1398 size_t pool_pos;
1399 char *pool_start;
1401
1402 GNUNET_break_op (0 == ntohl (request->reserved));
1403 count = 0;
1404 pool_size = 0;
1405
1406 /* Do one pass over the list to compute the number of services
1407 * and the string pool size */
1408 for (sl = running_head; NULL != sl; sl = sl->next)
1409 {
1410 pool_size += strlen (sl->name) + 1;
1411 pool_size += strlen (sl->binary) + 1;
1412 count++;
1413 }
1414
1415 extra_size = pool_size + (count * sizeof (struct
1418 extra_size,
1420 msg->arm_msg.request_id = request->request_id;
1421 msg->count = htons (count);
1422
1423 ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1424 pool_start = (char *) (ssm + count);
1425 pool_pos = 0;
1426
1427 for (sl = running_head; NULL != sl; sl = sl->next)
1428 {
1429 ssm->name_index = htons ((uint16_t) pool_pos);
1430 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1431 sl->name));
1432 ssm->binary_index = htons ((uint16_t) pool_pos);
1433 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1434 sl->binary));
1435 if (NULL == sl->proc)
1436 {
1437 if (0 == sl->last_started_at.abs_value_us)
1438 {
1439 /* Process never started */
1441 }
1442 else if (0 == sl->last_exit_status)
1443 {
1445 }
1446 else
1447 {
1449 ssm->last_exit_status = htons (sl->last_exit_status);
1450 }
1451 }
1452 else if ((NULL != sl->killing_client) || (GNUNET_YES == in_shutdown))
1453 {
1455 }
1456 else
1457 {
1459 }
1462 ssm++;
1463 }
1466}
1467
1468
1475static void
1476handle_test (void *cls, const struct GNUNET_MessageHeader *message)
1477{
1478 struct GNUNET_SERVICE_Client *client = cls;
1479 struct GNUNET_MQ_Envelope *env;
1480 struct GNUNET_MessageHeader *msg;
1481
1482 (void) message;
1486}
1487
1488
1493static void
1495{
1496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1497 if (NULL != notifier)
1498 {
1500 notifier = NULL;
1501 }
1502 if (NULL != service)
1503 {
1505 service = NULL;
1506 }
1507 if (NULL != child_death_task)
1508 {
1510 child_death_task = NULL;
1511 }
1512}
1513
1514
1521static unsigned int
1522list_count (struct ServiceList *run_head)
1523{
1524 struct ServiceList *i;
1525 unsigned int res;
1526
1527 for (res = 0, i = run_head; NULL != i; i = i->next, res++)
1529 return res;
1530}
1531
1532
1538static void
1539shutdown_task (void *cls)
1540{
1541 struct ServiceList *pos;
1542 struct ServiceList *nxt;
1543 struct ServiceListeningInfo *sli;
1544
1545 (void) cls;
1546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1547 if (NULL != child_restart_task)
1548 {
1550 child_restart_task = NULL;
1551 }
1553 /* first, stop listening */
1554 for (pos = running_head; NULL != pos; pos = pos->next)
1555 {
1556 while (NULL != (sli = pos->listen_head))
1557 {
1559 if (NULL != sli->accept_task)
1560 {
1562 sli->accept_task = NULL;
1563 }
1567 GNUNET_free (sli);
1568 }
1569 }
1570 /* then, shutdown all existing service processes */
1571 nxt = running_head;
1572 while (NULL != (pos = nxt))
1573 {
1574 nxt = pos->next;
1575 if (NULL != pos->proc)
1576 {
1577 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1581 }
1582 else
1583 {
1584 free_service (pos);
1585 }
1586 }
1587 /* finally, should all service processes be already gone, terminate for real */
1588 if (NULL == running_head)
1589 do_shutdown ();
1590 else
1592 "Delaying shutdown, have %u children still running\n",
1594}
1595
1596
1602static void
1604
1605{
1606 struct ServiceList *sl;
1607 struct GNUNET_TIME_Relative lowestRestartDelay;
1608 struct ServiceListeningInfo *sli;
1609
1610 (void) cls;
1611 child_restart_task = NULL;
1613 lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1614
1615 /* check for services that need to be restarted due to
1616 * configuration changes or because the last restart failed */
1617 for (sl = running_head; NULL != sl; sl = sl->next)
1618 {
1619 if (NULL != sl->proc)
1620 continue;
1621 /* service is currently not running */
1623 {
1624 /* restart is now allowed */
1625 if (sl->force_start)
1626 {
1627 /* process should run by default, start immediately */
1629 _ ("Restarting service `%s'.\n"),
1630 sl->name);
1631 start_process (sl, NULL, 0);
1632 }
1633 else
1634 {
1635 /* process is run on-demand, ensure it is re-started if there is demand */
1636 for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1637 if (NULL == sli->accept_task)
1638 {
1639 /* accept was actually paused, so start it again */
1640 sli->accept_task =
1642 sli->listen_socket,
1644 sli);
1645 }
1646 }
1647 }
1648 else
1649 {
1650 /* update calculation for earliest time to reactivate a service */
1651 lowestRestartDelay =
1652 GNUNET_TIME_relative_min (lowestRestartDelay,
1654 sl->restart_at));
1655 }
1656 }
1657 if (lowestRestartDelay.rel_value_us !=
1658 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1659 {
1661 "Will restart process in %s\n",
1662 GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1663 GNUNET_YES));
1668 NULL);
1669 }
1670}
1671
1672
1679static void
1681{
1682 struct ServiceList *pos;
1683 struct ServiceList *next;
1684 struct ServiceListeningInfo *sli;
1685 const char *statstr;
1686 int statcode;
1687 int ret;
1688 char c[16];
1689 enum GNUNET_OS_ProcessStatusType statusType;
1690 unsigned long statusCode;
1691 const struct GNUNET_DISK_FileHandle *pr;
1692
1693 (void) cls;
1695 child_death_task = NULL;
1696 /* consume the signal */
1697 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
1698
1699 /* check for services that died (WAITPID) */
1700 next = running_head;
1701 while (NULL != (pos = next))
1702 {
1703 next = pos->next;
1704
1705 if (NULL == pos->proc)
1706 {
1707 if (GNUNET_YES == in_shutdown)
1708 free_service (pos);
1709 continue;
1710 }
1711#if HAVE_WAIT4
1712 if (NULL != wait_file)
1713 {
1714 /* need to use 'wait4()' to obtain and log performance data */
1715 struct rusage ru;
1716 int status;
1717 pid_t pid;
1718
1720 ret = wait4 (pid, &status, WNOHANG, &ru);
1721 if (ret <= 0)
1722 continue; /* no process done */
1723 if (WIFEXITED (status))
1724 {
1725 statusType = GNUNET_OS_PROCESS_EXITED;
1726 statusCode = WEXITSTATUS (status);
1727 }
1728 else if (WIFSIGNALED (status))
1729 {
1730 statusType = GNUNET_OS_PROCESS_SIGNALED;
1731 statusCode = WTERMSIG (status);
1732 }
1733 else if (WIFSTOPPED (status))
1734 {
1735 statusType = GNUNET_OS_PROCESS_SIGNALED;
1736 statusCode = WSTOPSIG (status);
1737 }
1738#ifdef WIFCONTINUED
1739 else if (WIFCONTINUED (status))
1740 {
1741 statusType = GNUNET_OS_PROCESS_RUNNING;
1742 statusCode = 0;
1743 }
1744#endif
1745 else
1746 {
1747 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1748 statusCode = 0;
1749 }
1750 if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1751 (GNUNET_OS_PROCESS_SIGNALED == statusType))
1752 {
1753 double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1754 double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1755 fprintf (wait_file,
1756 "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1757 pos->binary,
1758 (unsigned int) pid,
1759 utime,
1760 stime,
1761 (unsigned long long) ru.ru_maxrss,
1762 (unsigned long long) ru.ru_inblock,
1763 (unsigned long long) ru.ru_oublock,
1764 (unsigned long long) ru.ru_nvcsw,
1765 (unsigned long long) ru.ru_nivcsw);
1766 }
1767 }
1768 else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1769#endif
1771 &statusType,
1772 &statusCode))) ||
1773 (ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1774 (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1775 (statusType == GNUNET_OS_PROCESS_RUNNING))
1776 continue;
1777
1778 if (statusType == GNUNET_OS_PROCESS_EXITED)
1779 {
1780 statstr = _ (/* process termination method */ "exit");
1781 statcode = statusCode;
1782 }
1783 else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1784 {
1785 statstr = _ (/* process termination method */ "signal");
1786 statcode = statusCode;
1787 }
1788 else
1789 {
1790 statstr = _ (/* process termination method */ "unknown");
1791 statcode = 0;
1792 }
1793 if (0 != pos->killed_at.abs_value_us)
1794 {
1796 _ ("Service `%s' took %s to terminate\n"),
1797 pos->name,
1800 GNUNET_YES));
1801 }
1803 pos->proc = NULL;
1805 if (NULL != pos->killing_client)
1806 {
1808 pos->name,
1811 pos->killing_client = NULL;
1813 }
1814 if (GNUNET_YES != in_shutdown)
1815 {
1816 pos->last_exit_status = statcode;
1817 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1818 {
1819 /* process terminated normally, allow restart at any time */
1820 pos->restart_at.abs_value_us = 0;
1821 GNUNET_log (
1823 _ ("Service `%s' terminated normally, will restart at any time\n"),
1824 pos->name);
1825 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1826 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1827 {
1828 GNUNET_break (NULL == sli->accept_task);
1829 sli->accept_task =
1831 sli->listen_socket,
1833 sli);
1834 }
1835 }
1836 else
1837 {
1838 GNUNET_log (
1840 _ ("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1841 pos->name,
1842 statstr,
1843 statcode,
1845 {
1846 /* Reduce backoff based on runtime of the process,
1847 so that there is a cool-down if a process actually
1848 runs for a while. */
1849 struct GNUNET_TIME_Relative runtime;
1850 unsigned int minutes;
1851
1853 minutes =
1854 runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1855 if (minutes > 31)
1857 else
1858 pos->backoff.rel_value_us >>= minutes;
1859 }
1860 /* schedule restart */
1863 if (NULL != child_restart_task)
1868 NULL);
1869 }
1870 }
1871 else
1872 {
1873 free_service (pos);
1874 }
1875 }
1878 pr,
1880 NULL);
1881 if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1882 do_shutdown ();
1883 else if (GNUNET_YES == in_shutdown)
1885 "Delaying shutdown after child's death, still have %u children\n",
1887}
1888
1889
1894static void
1896{
1897 static char c;
1898 int old_errno = errno; /* back-up errno */
1899
1900 GNUNET_break (
1901 1 ==
1904 ,
1905 &c,
1906 sizeof(c)));
1907 errno = old_errno; /* restore errno */
1908}
1909
1910
1919static void
1920setup_service (void *cls, const char *section)
1921{
1922 struct ServiceList *sl;
1923 char *binary;
1924 char *config;
1925 struct stat sbuf;
1926 struct sockaddr **addrs;
1927 socklen_t *addr_lens;
1928 int ret;
1929
1930 (void) cls;
1931 if (0 == strcasecmp (section, "arm"))
1932 return;
1933 if (GNUNET_OK !=
1934 GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary))
1935 {
1936 /* not a service section */
1937 return;
1938 }
1939 if (GNUNET_YES ==
1941 section,
1942 "RUN_PER_USER"))
1943 {
1944 if (GNUNET_NO == start_user)
1945 {
1946 GNUNET_free (binary);
1947 return; /* user service, and we don't deal with those */
1948 }
1949 }
1950 else
1951 {
1952 if (GNUNET_NO == start_system)
1953 {
1954 GNUNET_free (binary);
1955 return; /* system service, and we don't deal with those */
1956 }
1957 }
1958 sl = find_service (section);
1959 if (NULL != sl)
1960 {
1961 /* got the same section twice!? */
1962 GNUNET_break (0);
1963 GNUNET_free (binary);
1964 return;
1965 }
1966 config = NULL;
1967 if (((GNUNET_OK !=
1969 section,
1970 "CONFIG",
1971 &config)) &&
1972 (GNUNET_OK !=
1974 "PATHS",
1975 "DEFAULTCONFIG",
1976 &config))) ||
1977 (0 != stat (config,
1978 &sbuf)))
1979 {
1980 if (NULL != config)
1981 {
1983 section,
1984 "CONFIG",
1985 strerror (errno));
1987 config = NULL;
1988 }
1989 }
1990 sl = GNUNET_new (struct ServiceList);
1991 sl->name = GNUNET_strdup (section);
1992 sl->binary = binary;
1993 sl->config = config;
1996 sl->pipe_control =
1997 (GNUNET_YES ==
1999 section,
2000 "PIPECONTROL"));
2003 sl);
2004 if (GNUNET_YES ==
2006 section,
2007 "IMMEDIATE_START"))
2008 {
2009 sl->force_start = GNUNET_YES;
2010 if (GNUNET_YES ==
2012 section,
2013 "NOARMBIND"))
2014 return;
2015 }
2016 else
2017 {
2018 if (GNUNET_YES !=
2020 section,
2021 "START_ON_DEMAND"))
2022 return;
2023 }
2024 if (0 >= (ret = get_server_addresses (section,
2025 cfg,
2026 &addrs,
2027 &addr_lens)))
2028 return;
2029 /* this will free (or capture) addrs[i] */
2030 for (unsigned int i = 0; i < (unsigned int) ret; i++)
2031 create_listen_socket (addrs[i], addr_lens[i], sl);
2032 GNUNET_free (addrs);
2033 GNUNET_free (addr_lens);
2034}
2035
2036
2045static void *
2047 struct GNUNET_SERVICE_Client *client,
2048 struct GNUNET_MQ_Handle *mq)
2049{
2050 /* All clients are considered to be of the "monitor" kind
2051 * (that is, they don't affect ARM shutdown).
2052 */
2053 (void) cls;
2054 (void) mq;
2056 return client;
2057}
2058
2059
2067static void
2069 struct GNUNET_SERVICE_Client *client,
2070 void *app_ctx)
2071{
2072 (void) cls;
2073 GNUNET_assert (client == app_ctx);
2074 for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2075 if (sl->killing_client == client)
2076 sl->killing_client = NULL;
2077}
2078
2079
2088static void
2089handle_monitor (void *cls, const struct GNUNET_MessageHeader *message)
2090{
2091 struct GNUNET_SERVICE_Client *client = cls;
2092
2093 (void) message;
2094 /* FIXME: might want to start by letting monitor know about
2095 services that are already running */
2096 /* Removal is handled by the server implementation, internally. */
2101}
2102
2103
2111static void
2112run (void *cls,
2113 const struct GNUNET_CONFIGURATION_Handle *c,
2114 struct GNUNET_SERVICE_Handle *serv)
2115{
2116 struct ServiceList *sl;
2117 enum GNUNET_GenericReturnValue ret1;
2118 enum GNUNET_GenericReturnValue ret2;
2119
2120 (void) cls;
2121 cfg = c;
2122 service = serv;
2129 NULL);
2130#if HAVE_WAIT4
2131 if (GNUNET_OK ==
2133 "ARM",
2134 "RESOURCE_DIAGNOSTICS",
2135 &wait_filename))
2136 {
2137 wait_file = fopen (wait_filename, "w");
2138 if (NULL == wait_file)
2139 {
2141 "fopen",
2142 wait_filename);
2143 }
2144 }
2145#endif
2146 if (GNUNET_OK !=
2148 "ARM",
2149 "GLOBAL_PREFIX",
2152 else
2154 if (GNUNET_OK !=
2156 "ARM",
2157 "GLOBAL_POSTFIX",
2158 &final_option))
2160 else
2163 "ARM",
2164 "START_SYSTEM_SERVICES");
2166 "ARM",
2167 "START_USER_SERVICES");
2168 if ( (GNUNET_SYSERR == ret1) ||
2169 (GNUNET_SYSERR == ret2) )
2170 {
2171 /* invalid option */
2172 GNUNET_break (0);
2174 global_ret = 1;
2175 return;
2176 }
2178 "ARM",
2179 "START_SYSTEM_SERVICES"))
2180 ret1 = GNUNET_SYSERR;
2182 "ARM",
2183 "START_USER_SERVICES"))
2184 ret2 = GNUNET_SYSERR;
2185 start_system = (GNUNET_YES == ret1) ||
2186 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2187 start_user = (GNUNET_YES == ret2) ||
2188 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2189 if ( (GNUNET_NO == start_user) &&
2190 (GNUNET_NO == start_system) )
2191 {
2192 GNUNET_log (
2194 "Please enable either START_USER_SERVICES or START_SYSTEM_SERVICES\n");
2196 global_ret = 1;
2197 return;
2198 }
2201 NULL);
2202
2203 /* start default services... */
2204 for (sl = running_head; NULL != sl; sl = sl->next)
2205 if (GNUNET_YES == sl->force_start)
2206 start_process (sl, NULL, 0);
2208}
2209
2210
2218int
2219main (int argc, char *const *argv)
2220{
2225 struct GNUNET_ARM_Message,
2226 NULL),
2229 struct GNUNET_ARM_Message,
2230 NULL),
2233 struct GNUNET_MessageHeader,
2234 NULL),
2237 struct GNUNET_ARM_Message,
2238 NULL),
2241 struct GNUNET_MessageHeader,
2242 NULL),
2244 };
2245
2247 GNUNET_assert (NULL != sigpipe);
2248 shc_chld =
2251 if (0 != GNUNET_SERVICE_run_ (argc,
2252 argv,
2253 "arm",
2256 &run,
2259 NULL,
2260 handlers))
2261 global_ret = 2;
2262#if HAVE_WAIT4
2263 if (NULL != wait_file)
2264 {
2265 fclose (wait_file);
2266 wait_file = NULL;
2267 }
2268 if (NULL != wait_filename)
2269 {
2270 GNUNET_free (wait_filename);
2271 wait_filename = NULL;
2272 }
2273#endif
2275 shc_chld = NULL;
2277 sigpipe = NULL;
2278 return global_ret;
2279}
2280
2281
2282#if defined(__linux__) && defined(__GLIBC__)
2283#include <malloc.h>
2284
2285void __attribute__ ((constructor))
2286GNUNET_ARM_memory_init (void);
2287
2291void __attribute__ ((constructor))
2292GNUNET_ARM_memory_init (void)
2293{
2294 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
2295 mallopt (M_TOP_PAD, 1 * 1024);
2296 malloc_trim (0);
2297}
2298
2299
2300#endif
2301
2302
2303/* end of gnunet-service-arm.c */
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
struct GNUNET_MQ_MessageHandlers handlers[]
Definition: 003.c:1
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static struct GNUNET_SIGNAL_Context * shc_chld
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:38
static int monitor
Monitor ARM activity.
Definition: gnunet-arm.c:63
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:68
static int ret
Final status code.
Definition: gnunet-arm.c:93
static uint16_t port
Port number.
Definition: gnunet-bcd.c:146
const struct GNUNET_CONFIGURATION_Handle * config
static char * name
Name (label) of the records to list.
static char * res
Currently read line or NULL on EOF.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
static int status
The program status; 0 for success.
Definition: gnunet-nse.c:39
static int result
Global testing status.
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
static void delayed_restart_task(void *cls)
Task run whenever it is time to restart a child that died.
static struct ServiceList * running_head
List of running services.
static void trigger_shutdown(void *cls)
Start a shutdown sequence.
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
Process arm requests.
static void broadcast_status(const char *name, enum GNUNET_ARM_ServiceMonitorStatus status, struct GNUNET_SERVICE_Client *unicast)
Tell all clients about status change of a service.
static void free_service(struct ServiceList *sl)
Remove and free an entry in the service list.
#define MAX_NOTIFY_QUEUE
How many messages do we queue up at most for optional notifications to a client? (this can cause noti...
static char * prefix_command
Command to prepend to each actual command.
static void handle_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
Handle STOP-message.
static char * final_option
Option to append to each actual command.
static void add_unixpath(struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath, int abstract)
Add the given UNIX domain path as an address to the list (as the first entry).
static int global_ret
Return value from main.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static int start_user
Are we starting user services?
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
static unsigned int list_count(struct ServiceList *run_head)
Count how many services are still active.
static struct GNUNET_SCHEDULER_Task * child_death_task
ID of task called whenever we get a SIGCHILD.
static int start_system
Are we starting system services?
static int check_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
Check STOP-message.
static int in_shutdown
Are we in shutdown mode?
static void shutdown_task(void *cls)
Task run for shutdown.
static void handle_test(void *cls, const struct GNUNET_MessageHeader *message)
Handle TEST-message by sending back TEST.
static void setup_service(void *cls, const char *section)
Setup our service record for the given section in the configuration file (assuming the section is for...
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected, mark as a monitoring client.
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
static int get_server_addresses(const char *service_name, const struct GNUNET_CONFIGURATION_Handle *cfg_, struct sockaddr ***addrs, socklen_t **addr_lens)
Get the list of addresses that a server for the given service should bind to.
static void sighandler_child_death()
Signal handler called for SIGCHLD.
static void accept_connection(void *cls)
First connection has come to the listening socket associated with the service, create the service in ...
static void handle_start(void *cls, const struct GNUNET_ARM_Message *amsg)
Handle START-message.
static void do_shutdown()
We are done with everything.
static struct ServiceList * running_tail
List of running services.
static void handle_list(void *cls, const struct GNUNET_ARM_Message *request)
Handle LIST-message.
static void create_listen_socket(struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl)
Creating a listening socket for each of the service's addresses and wait for the first incoming conne...
#define LOG(kind,...)
int main(int argc, char *const *argv)
The main function for the arm service.
static void handle_monitor(void *cls, const struct GNUNET_MessageHeader *message)
Handle MONITOR-message.
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
#define LOG_STRERROR(kind, syscall)
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up associated state.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
static int pool_write(char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
Write a string to a string pool.
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
static int check_start(void *cls, const struct GNUNET_ARM_Message *amsg)
Check START-message.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
struct GNUNET_PQ_ResultSpec __attribute__
Constants for network protocols.
GNUNET_ARM_ServiceMonitorStatus
Statuses of services.
GNUNET_ARM_Result
Replies to ARM requests.
@ GNUNET_ARM_SERVICE_STATUS_FINISHED
The service was started, but then exited normally.
@ GNUNET_ARM_SERVICE_STATUS_FAILED
The service has previously failed, and will be restarted.
@ GNUNET_ARM_SERVICE_STATUS_STOPPED
Service is stopped.
@ GNUNET_ARM_SERVICE_STATUS_STOPPING
The service was started, and we're currently waiting for it to be stopped.
@ GNUNET_ARM_SERVICE_STATUS_STARTED
Service has been started and is currently running.
@ GNUNET_ARM_SERVICE_STOPPING
Service stopping was initiated.
@ GNUNET_ARM_SERVICE_STOPPED
Service was stopped.
@ GNUNET_ARM_SERVICE_STARTING
Service starting was initiated.
@ GNUNET_ARM_SERVICE_MONITORING_STARTED
Dummy message.
@ GNUNET_ARM_RESULT_IS_NOT_KNOWN
Asked to start or stop a service, but it's not known.
@ GNUNET_ARM_RESULT_IS_STOPPED_ALREADY
Asked to stop it, but it's already stopped.
@ GNUNET_ARM_RESULT_STARTING
Service starting was initiated.
@ GNUNET_ARM_RESULT_IS_STARTED_ALREADY
Asked to start it, but it's already started.
@ GNUNET_ARM_RESULT_STOPPING
ARM stopping was initiated (there's no "stopped" for ARM itself).
@ GNUNET_ARM_RESULT_IS_STOPPING_ALREADY
Asked to stop it, but it's already stopping.
@ GNUNET_ARM_RESULT_STOPPED
Service was stopped (never sent for ARM itself).
@ GNUNET_ARM_RESULT_START_FAILED
Tried to start a service, but that failed for some reason.
@ GNUNET_ARM_RESULT_IN_SHUTDOWN
Asked to start something, but ARM is shutting down and can't comply.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_SectionIterator iter, void *iter_cls)
Iterate over all sections in the configuration.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
char * GNUNET_CONFIGURATION_expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1618
void GNUNET_DISK_fix_permissions(const char *fn, int require_uid_match, int require_gid_match)
Update POSIX permissions mask of a file on disk.
Definition: disk.c:321
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:687
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1445
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1588
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:583
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:623
@ GNUNET_DISK_PF_NONE
No special options, use non-blocking read/write operations.
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define GNUNET_log(kind,...)
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
GNUNET_GenericReturnValue
Named constants for return values.
@ GNUNET_SCHEDULER_PRIORITY_IDLE
Run when otherwise idle.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
#define GNUNET_free(ptr)
Wrapper around free.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:138
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:305
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:285
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:122
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition: nc.c:190
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:161
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:508
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1001
char * GNUNET_NETWORK_shorten_unixpath(char *unixpath)
Given a unixpath that is too long (larger than UNIX_PATH_MAX), shorten it to an acceptable length whi...
Definition: network.c:143
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:439
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:652
void GNUNET_NETWORK_unix_precheck(const struct sockaddr_un *un)
If services crash, they can leave a unix domain socket file on the disk.
Definition: network.c:178
int GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len)
Set socket option.
Definition: network.c:806
char * GNUNET_OS_get_libexec_binary_path(const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
struct GNUNET_OS_Process * GNUNET_OS_start_process_s(enum GNUNET_OS_InheritStdioFlags std_inheritance, const int *lsocks, const char *filename,...)
Start a process.
Definition: os_priority.c:666
pid_t GNUNET_OS_process_get_pid(struct GNUNET_OS_Process *proc)
Get the pid of the process in question.
Definition: os_priority.c:253
GNUNET_OS_ProcessStatusType
Process status types.
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:260
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:210
enum GNUNET_GenericReturnValue GNUNET_OS_process_status(struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Retrieve the status of a process.
Definition: os_priority.c:860
@ GNUNET_OS_INHERIT_STD_OUT_AND_ERR
When these flags are set, the child process will inherit stdout and stderr of the parent.
@ GNUNET_OS_USE_PIPE_CONTROL
Should a pipe be used to send signals to the child?
@ GNUNET_OS_PROCESS_SIGNALED
The process was killed by a signal.
@ GNUNET_OS_PROCESS_EXITED
The process exited with a return code.
@ GNUNET_OS_PROCESS_UNKNOWN
The process is not known to the OS (or at least not one of our children).
@ GNUNET_OS_PROCESS_STOPPED
The process is paused (but could be resumed).
@ GNUNET_OS_PROCESS_RUNNING
The process is still running.
#define GNUNET_MESSAGE_TYPE_ARM_STOP
Request to ARM to stop a service.
#define GNUNET_MESSAGE_TYPE_ARM_RESULT
Response from ARM.
#define GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
Response from ARM for listing currently running services.
#define GNUNET_MESSAGE_TYPE_ARM_TEST
Test if ARM service is online.
#define GNUNET_MESSAGE_TYPE_ARM_STATUS
Status update from ARM.
#define GNUNET_MESSAGE_TYPE_ARM_START
Request to ARM to start a service.
#define GNUNET_MESSAGE_TYPE_ARM_LIST
Request to ARM to list all currently running services.
#define GNUNET_MESSAGE_TYPE_ARM_MONITOR
Request to ARM to notify client of service status changes.
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:566
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1510
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1660
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received,...
Definition: scheduler.c:1338
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:979
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_now(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run as soon as possible.
Definition: scheduler.c:1303
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed_with_priority(struct GNUNET_TIME_Relative delay, enum GNUNET_SCHEDULER_Priority priority, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1206
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1230
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2426
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2442
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2452
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2459
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2348
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.
Definition: service.c:1965
@ GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
@ GNUNET_SERVICE_OPTION_CLOSE_LSOCKS
Instead of listening on lsocks passed by the parent, close them after opening our own listen socket(s...
struct GNUNET_SIGNAL_Context * GNUNET_SIGNAL_handler_install(int signal, GNUNET_SIGNAL_Handler handler)
Install a signal handler that will be run if the given signal is received.
Definition: signal.c:52
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal handler.
Definition: signal.c:78
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:137
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:344
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:438
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:406
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:579
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:316
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:640
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_SIGCHLD
Definition: platform.h:42
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:234
Reply from ARM to client for the GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count '\0' terminat...
Definition: arm.h:145
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
Reply from ARM to client.
Definition: arm.h:87
struct GNUNET_TIME_AbsoluteNBO last_started_at
Time when the service was first started, if applicable.
Definition: arm.h:135
uint16_t binary_index
String pool index for the service's binary.
Definition: arm.h:109
struct GNUNET_TIME_AbsoluteNBO restart_at
Time when the service will be restarted, if applicable to the current status.
Definition: arm.h:130
uint32_t status
Status from the 'enum GNUNET_ARM_ServiceStatus'.
Definition: arm.h:124
int16_t last_exit_status
Last process exit status.
Definition: arm.h:114
uint16_t name_index
String pool index for the service's name.
Definition: arm.h:104
Status update from ARM to client.
Definition: arm.h:42
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:69
Handle to a message queue.
Definition: mq.c:87
Message handler for a specific message type.
Header for all communications.
handle to a socket
Definition: network.c:53
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:77
Entry in list of pending tasks.
Definition: scheduler.c:135
Handle to a client that is connected to a service.
Definition: service.c:245
Handle to a service.
Definition: service.c:116
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.
uint64_t request_id
non-zero if this request has been sent to the service.
Definition: vpn_api.c:127
List of our services.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
struct ServiceListeningInfo * listen_tail
Linked list of listen sockets associated with this service.
char * binary
Name of the binary used.
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze).
char * config
Name of the configuration file used.
int last_exit_status
Last exit status of the process.
struct ServiceList * next
This is a doubly-linked list.
struct GNUNET_TIME_Absolute last_started_at
Absolute time at which the process was (re-)started last.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process.
struct GNUNET_TIME_Relative backoff
Process exponential backoff time.
struct ServiceList * prev
This is a doubly-linked list.
char * name
Name of the service.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)?...
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate).
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).
Record with information about a listen socket we have open.
struct ServiceListeningInfo * prev
This is a linked list.
struct ServiceListeningInfo * next
This is a linked list.
struct sockaddr * service_addr
Address this socket is listening on.
struct ServiceList * sl
Service this listen socket is for.
socklen_t service_addr_len
Number of bytes in service_addr.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.