GNUnet 0.22.2
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 ,
895 sl->binary);
896 GNUNET_asprintf (&quotedbinary,
897 "\"%s\"",
898 binary);
899
900 if (GNUNET_YES == use_debug)
901 {
902 if (NULL == sl->config)
904 sl->pipe_control
908 lsocks,
909 loprefix,
910 quotedbinary,
911 "-L",
912 "DEBUG",
913 options,
914 NULL);
915 else
917 sl->pipe_control
921 lsocks,
922 loprefix,
923 quotedbinary,
924 "-c",
925 sl->config,
926 "-L",
927 "DEBUG",
928 options,
929 NULL);
930 }
931 else
932 {
933 if (NULL == sl->config)
935 sl->pipe_control
939 lsocks,
940 loprefix,
941 quotedbinary,
942 options,
943 NULL);
944 else
946 sl->pipe_control
950 lsocks,
951 loprefix,
952 quotedbinary,
953 "-c",
954 sl->config,
955 options,
956 NULL);
957 }
958 }
959 GNUNET_free (binary);
960 GNUNET_free (quotedbinary);
962 if (NULL == sl->proc)
963 {
965 "Failed to start service `%s'\n",
966 sl->name);
967 if (client)
968 signal_result (client,
969 sl->name,
970 request_id,
972 }
973 else
974 {
976 "Starting service `%s'\n",
977 sl->name);
980 NULL);
981 if (client)
982 signal_result (client,
983 sl->name,
984 request_id,
986 }
987 /* clean up */
988 GNUNET_free (loprefix);
990 GNUNET_array_grow (lsocks,
991 ls,
992 0);
993}
994
995
1003static struct ServiceList *
1004find_service (const char *name)
1005{
1006 struct ServiceList *sl;
1007
1008 sl = running_head;
1009 while (sl != NULL)
1010 {
1011 if (0 == strcasecmp (sl->name, name))
1012 return sl;
1013 sl = sl->next;
1014 }
1015 return NULL;
1016}
1017
1018
1025static void
1027{
1028 struct ServiceListeningInfo *sli = cls;
1029 struct ServiceList *sl = sli->sl;
1030
1031 sli->accept_task = NULL;
1033 start_process (sl, NULL, 0);
1034}
1035
1036
1045static void
1046create_listen_socket (struct sockaddr *sa,
1047 socklen_t addr_len,
1048 struct ServiceList *sl)
1049{
1050 static int on = 1;
1051 struct GNUNET_NETWORK_Handle *sock;
1052 struct ServiceListeningInfo *sli;
1053
1054 int match_uid;
1055 int match_gid;
1056
1057 switch (sa->sa_family)
1058 {
1059 case AF_INET:
1060 sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
1061 break;
1062
1063 case AF_INET6:
1064 sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1065 break;
1066
1067 case AF_UNIX:
1068 if (0 == strcmp (GNUNET_a2s (sa, addr_len),
1069 "@")) /* Do not bind to blank UNIX path! */
1070 return;
1071 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
1072 break;
1073
1074 default:
1075 GNUNET_break (0);
1076 sock = NULL;
1077 errno = EAFNOSUPPORT;
1078 break;
1079 }
1080 if (NULL == sock)
1081 {
1083 _ ("Unable to create socket for service `%s': %s\n"),
1084 sl->name,
1085 strerror (errno));
1086 GNUNET_free (sa);
1087 return;
1088 }
1090 SOL_SOCKET,
1091 SO_REUSEADDR,
1092 &on,
1093 sizeof(on)))
1095 "setsockopt");
1096#ifdef IPV6_V6ONLY
1097 if ((sa->sa_family == AF_INET6) &&
1099 IPPROTO_IPV6,
1100 IPV6_V6ONLY,
1101 &on,
1102 sizeof(on))))
1104 "setsockopt");
1105#endif
1106 if (AF_UNIX == sa->sa_family)
1107 GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1108 if (GNUNET_OK !=
1109 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
1110 {
1111 GNUNET_log (
1113 _ (
1114 "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1115 sl->name,
1116 GNUNET_a2s (sa, addr_len),
1117 strerror (errno));
1119 GNUNET_free (sa);
1120 return;
1121 }
1122 if ((AF_UNIX == sa->sa_family)
1123#ifdef __linux__
1124 /* Permission settings are not required when abstract sockets are used */
1125 && ('\0' != ((const struct sockaddr_un *) sa)->sun_path[0])
1126#endif
1127 )
1128 {
1129 match_uid =
1130 (GNUNET_YES ==
1132 sl->name,
1133 "UNIX_MATCH_UID"));
1134 match_gid =
1135 (GNUNET_YES ==
1137 sl->name,
1138 "UNIX_MATCH_GID"));
1139 GNUNET_DISK_fix_permissions (((const struct sockaddr_un *) sa)->sun_path,
1140 match_uid,
1141 match_gid);
1142 }
1143 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1144 {
1147 GNUNET_free (sa);
1148 return;
1149 }
1151 _ ("ARM now monitors connections to service `%s' at `%s'\n"),
1152 sl->name,
1153 GNUNET_a2s (sa, addr_len));
1154 sli = GNUNET_new (struct ServiceListeningInfo);
1155 sli->service_addr = sa;
1156 sli->service_addr_len = addr_len;
1157 sli->listen_socket = sock;
1158 sli->sl = sl;
1159 sli->accept_task =
1161 sock,
1163 sli);
1165}
1166
1167
1174static void
1176{
1179 GNUNET_assert (NULL == sl->listen_head);
1182 GNUNET_free (sl->name);
1183 GNUNET_free (sl);
1184}
1185
1186
1195static int
1196check_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1197{
1198 (void) cls;
1200 return GNUNET_OK;
1201}
1202
1203
1210static void
1211handle_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1212{
1213 struct GNUNET_SERVICE_Client *client = cls;
1214 const char *servicename;
1215 struct ServiceList *sl;
1216 uint64_t request_id;
1217
1218 request_id = GNUNET_ntohll (amsg->request_id);
1219 servicename = (const char *) &amsg[1];
1221 if (GNUNET_YES == in_shutdown)
1222 {
1223 signal_result (client,
1224 servicename,
1225 request_id,
1227 return;
1228 }
1229 sl = find_service (servicename);
1230 if (NULL == sl)
1231 {
1232 signal_result (client,
1233 servicename,
1234 request_id,
1236 return;
1237 }
1238 sl->force_start = GNUNET_YES;
1239 if (NULL != sl->proc)
1240 {
1241 signal_result (client,
1242 servicename,
1243 request_id,
1245 return;
1246 }
1247 start_process (sl, client, request_id);
1248}
1249
1250
1256static void
1258{
1259 (void) cls;
1260 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1262}
1263
1264
1273static int
1274check_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
1275{
1276 (void) cls;
1278 return GNUNET_OK;
1279}
1280
1281
1288static void
1289handle_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
1290{
1291 struct GNUNET_SERVICE_Client *client = cls;
1292 struct ServiceList *sl;
1293 const char *servicename;
1294 uint64_t request_id;
1295
1296 request_id = GNUNET_ntohll (amsg->request_id);
1297 servicename = (const char *) &amsg[1];
1299 _ ("Preparing to stop `%s'\n"),
1300 servicename);
1302 if (0 == strcasecmp (servicename, "arm"))
1303 {
1304 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1305 signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1308 return;
1309 }
1310 sl = find_service (servicename);
1311 if (NULL == sl)
1312 {
1313 signal_result (client,
1314 servicename,
1315 request_id,
1317 return;
1318 }
1319 sl->force_start = GNUNET_NO;
1320 if (GNUNET_YES == in_shutdown)
1321 {
1322 /* shutdown in progress */
1323 signal_result (client,
1324 servicename,
1325 request_id,
1327 return;
1328 }
1329 if (NULL != sl->killing_client)
1330 {
1331 /* killing already in progress */
1332 signal_result (client,
1333 servicename,
1334 request_id,
1336 return;
1337 }
1338 if (NULL == sl->proc)
1339 {
1340 /* process is down */
1341 signal_result (client,
1342 servicename,
1343 request_id,
1345 return;
1346 }
1348 "Sending kill signal to service `%s', waiting for process to die.\n",
1349 servicename);
1350 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1351 /* no signal_start - only when it's STOPPED */
1355 sl->killing_client = client;
1356 sl->killing_client_request_id = request_id;
1357}
1358
1359
1371static int
1372pool_write (char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
1373{
1374 size_t next_pos = (*pool_pos) + strlen (str) + 1;
1375
1376 if (next_pos > pool_size)
1377 return GNUNET_SYSERR;
1378 memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1379 *pool_pos = next_pos;
1380 return GNUNET_OK;
1381}
1382
1383
1390static void
1391handle_list (void *cls, const struct GNUNET_ARM_Message *request)
1392{
1393 struct GNUNET_SERVICE_Client *client = cls;
1394 struct GNUNET_MQ_Envelope *env;
1396 size_t extra_size;
1397 struct ServiceList *sl;
1398 uint16_t count;
1399 size_t pool_size;
1400 size_t pool_pos;
1401 char *pool_start;
1403
1404 GNUNET_break_op (0 == ntohl (request->reserved));
1405 count = 0;
1406 pool_size = 0;
1407
1408 /* Do one pass over the list to compute the number of services
1409 * and the string pool size */
1410 for (sl = running_head; NULL != sl; sl = sl->next)
1411 {
1412 pool_size += strlen (sl->name) + 1;
1413 pool_size += strlen (sl->binary) + 1;
1414 count++;
1415 }
1416
1417 extra_size = pool_size + (count * sizeof (struct
1420 extra_size,
1422 msg->arm_msg.request_id = request->request_id;
1423 msg->count = htons (count);
1424
1425 ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1426 pool_start = (char *) (ssm + count);
1427 pool_pos = 0;
1428
1429 for (sl = running_head; NULL != sl; sl = sl->next)
1430 {
1431 ssm->name_index = htons ((uint16_t) pool_pos);
1432 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1433 sl->name));
1434 ssm->binary_index = htons ((uint16_t) pool_pos);
1435 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1436 sl->binary));
1437 if (NULL == sl->proc)
1438 {
1439 if (0 == sl->last_started_at.abs_value_us)
1440 {
1441 /* Process never started */
1443 }
1444 else if (0 == sl->last_exit_status)
1445 {
1447 }
1448 else
1449 {
1451 ssm->last_exit_status = htons (sl->last_exit_status);
1452 }
1453 }
1454 else if ((NULL != sl->killing_client) || (GNUNET_YES == in_shutdown))
1455 {
1457 }
1458 else
1459 {
1461 }
1464 ssm++;
1465 }
1468}
1469
1470
1477static void
1478handle_test (void *cls, const struct GNUNET_MessageHeader *message)
1479{
1480 struct GNUNET_SERVICE_Client *client = cls;
1481 struct GNUNET_MQ_Envelope *env;
1482 struct GNUNET_MessageHeader *msg;
1483
1484 (void) message;
1488}
1489
1490
1495static void
1497{
1498 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1499 if (NULL != notifier)
1500 {
1502 notifier = NULL;
1503 }
1504 if (NULL != service)
1505 {
1507 service = NULL;
1508 }
1509 if (NULL != child_death_task)
1510 {
1512 child_death_task = NULL;
1513 }
1514}
1515
1516
1523static unsigned int
1524list_count (struct ServiceList *run_head)
1525{
1526 struct ServiceList *i;
1527 unsigned int res;
1528
1529 for (res = 0, i = run_head; NULL != i; i = i->next, res++)
1531 return res;
1532}
1533
1534
1540static void
1541shutdown_task (void *cls)
1542{
1543 struct ServiceList *pos;
1544 struct ServiceList *nxt;
1545 struct ServiceListeningInfo *sli;
1546
1547 (void) cls;
1548 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1549 if (NULL != child_restart_task)
1550 {
1552 child_restart_task = NULL;
1553 }
1555 /* first, stop listening */
1556 for (pos = running_head; NULL != pos; pos = pos->next)
1557 {
1558 while (NULL != (sli = pos->listen_head))
1559 {
1561 if (NULL != sli->accept_task)
1562 {
1564 sli->accept_task = NULL;
1565 }
1569 GNUNET_free (sli);
1570 }
1571 }
1572 /* then, shutdown all existing service processes */
1573 nxt = running_head;
1574 while (NULL != (pos = nxt))
1575 {
1576 nxt = pos->next;
1577 if (NULL != pos->proc)
1578 {
1579 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1583 }
1584 else
1585 {
1586 free_service (pos);
1587 }
1588 }
1589 /* finally, should all service processes be already gone, terminate for real */
1590 if (NULL == running_head)
1591 do_shutdown ();
1592 else
1594 "Delaying shutdown, have %u children still running\n",
1596}
1597
1598
1604static void
1606
1607{
1608 struct ServiceList *sl;
1609 struct GNUNET_TIME_Relative lowestRestartDelay;
1610 struct ServiceListeningInfo *sli;
1611
1612 (void) cls;
1613 child_restart_task = NULL;
1615 lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1616
1617 /* check for services that need to be restarted due to
1618 * configuration changes or because the last restart failed */
1619 for (sl = running_head; NULL != sl; sl = sl->next)
1620 {
1621 if (NULL != sl->proc)
1622 continue;
1623 /* service is currently not running */
1625 {
1626 /* restart is now allowed */
1627 if (sl->force_start)
1628 {
1629 /* process should run by default, start immediately */
1631 _ ("Restarting service `%s'.\n"),
1632 sl->name);
1633 start_process (sl, NULL, 0);
1634 }
1635 else
1636 {
1637 /* process is run on-demand, ensure it is re-started if there is demand */
1638 for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1639 if (NULL == sli->accept_task)
1640 {
1641 /* accept was actually paused, so start it again */
1642 sli->accept_task =
1644 sli->listen_socket,
1646 sli);
1647 }
1648 }
1649 }
1650 else
1651 {
1652 /* update calculation for earliest time to reactivate a service */
1653 lowestRestartDelay =
1654 GNUNET_TIME_relative_min (lowestRestartDelay,
1656 sl->restart_at));
1657 }
1658 }
1659 if (lowestRestartDelay.rel_value_us !=
1660 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1661 {
1663 "Will restart process in %s\n",
1664 GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1665 GNUNET_YES));
1670 NULL);
1671 }
1672}
1673
1674
1681static void
1683{
1684 struct ServiceList *pos;
1685 struct ServiceList *next;
1686 struct ServiceListeningInfo *sli;
1687 const char *statstr;
1688 int statcode;
1689 int ret;
1690 char c[16];
1691 enum GNUNET_OS_ProcessStatusType statusType;
1692 unsigned long statusCode;
1693 const struct GNUNET_DISK_FileHandle *pr;
1694
1695 (void) cls;
1697 child_death_task = NULL;
1698 /* consume the signal */
1699 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
1700
1701 /* check for services that died (WAITPID) */
1702 next = running_head;
1703 while (NULL != (pos = next))
1704 {
1705 next = pos->next;
1706
1707 if (NULL == pos->proc)
1708 {
1709 if (GNUNET_YES == in_shutdown)
1710 free_service (pos);
1711 continue;
1712 }
1713#if HAVE_WAIT4
1714 if (NULL != wait_file)
1715 {
1716 /* need to use 'wait4()' to obtain and log performance data */
1717 struct rusage ru;
1718 int status;
1719 pid_t pid;
1720
1722 ret = wait4 (pid, &status, WNOHANG, &ru);
1723 if (ret <= 0)
1724 continue; /* no process done */
1725 if (WIFEXITED (status))
1726 {
1727 statusType = GNUNET_OS_PROCESS_EXITED;
1728 statusCode = WEXITSTATUS (status);
1729 }
1730 else if (WIFSIGNALED (status))
1731 {
1732 statusType = GNUNET_OS_PROCESS_SIGNALED;
1733 statusCode = WTERMSIG (status);
1734 }
1735 else if (WIFSTOPPED (status))
1736 {
1737 statusType = GNUNET_OS_PROCESS_SIGNALED;
1738 statusCode = WSTOPSIG (status);
1739 }
1740#ifdef WIFCONTINUED
1741 else if (WIFCONTINUED (status))
1742 {
1743 statusType = GNUNET_OS_PROCESS_RUNNING;
1744 statusCode = 0;
1745 }
1746#endif
1747 else
1748 {
1749 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1750 statusCode = 0;
1751 }
1752 if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1753 (GNUNET_OS_PROCESS_SIGNALED == statusType))
1754 {
1755 double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1756 double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1757 fprintf (wait_file,
1758 "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1759 pos->binary,
1760 (unsigned int) pid,
1761 utime,
1762 stime,
1763 (unsigned long long) ru.ru_maxrss,
1764 (unsigned long long) ru.ru_inblock,
1765 (unsigned long long) ru.ru_oublock,
1766 (unsigned long long) ru.ru_nvcsw,
1767 (unsigned long long) ru.ru_nivcsw);
1768 }
1769 }
1770 else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1771#endif
1773 &statusType,
1774 &statusCode))) ||
1775 (ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1776 (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1777 (statusType == GNUNET_OS_PROCESS_RUNNING))
1778 continue;
1779
1780 if (statusType == GNUNET_OS_PROCESS_EXITED)
1781 {
1782 statstr = _ (/* process termination method */ "exit");
1783 statcode = statusCode;
1784 }
1785 else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1786 {
1787 statstr = _ (/* process termination method */ "signal");
1788 statcode = statusCode;
1789 }
1790 else
1791 {
1792 statstr = _ (/* process termination method */ "unknown");
1793 statcode = 0;
1794 }
1795 if (0 != pos->killed_at.abs_value_us)
1796 {
1798 _ ("Service `%s' took %s to terminate\n"),
1799 pos->name,
1802 GNUNET_YES));
1803 }
1805 pos->proc = NULL;
1807 if (NULL != pos->killing_client)
1808 {
1810 pos->name,
1813 pos->killing_client = NULL;
1815 }
1816 if (GNUNET_YES != in_shutdown)
1817 {
1818 pos->last_exit_status = statcode;
1819 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1820 {
1821 /* process terminated normally, allow restart at any time */
1822 pos->restart_at.abs_value_us = 0;
1823 GNUNET_log (
1825 _ ("Service `%s' terminated normally, will restart at any time\n"),
1826 pos->name);
1827 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1828 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1829 {
1830 GNUNET_break (NULL == sli->accept_task);
1831 sli->accept_task =
1833 sli->listen_socket,
1835 sli);
1836 }
1837 }
1838 else
1839 {
1840 GNUNET_log (
1842 _ ("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1843 pos->name,
1844 statstr,
1845 statcode,
1847 {
1848 /* Reduce backoff based on runtime of the process,
1849 so that there is a cool-down if a process actually
1850 runs for a while. */
1851 struct GNUNET_TIME_Relative runtime;
1852 unsigned int minutes;
1853
1855 minutes =
1856 runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1857 if (minutes > 31)
1859 else
1860 pos->backoff.rel_value_us >>= minutes;
1861 }
1862 /* schedule restart */
1865 if (NULL != child_restart_task)
1870 NULL);
1871 }
1872 }
1873 else
1874 {
1875 free_service (pos);
1876 }
1877 }
1880 pr,
1882 NULL);
1883 if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1884 do_shutdown ();
1885 else if (GNUNET_YES == in_shutdown)
1887 "Delaying shutdown after child's death, still have %u children\n",
1889}
1890
1891
1896static void
1898{
1899 static char c;
1900 int old_errno = errno; /* back-up errno */
1901
1902 GNUNET_break (
1903 1 ==
1906 ,
1907 &c,
1908 sizeof(c)));
1909 errno = old_errno; /* restore errno */
1910}
1911
1912
1921static void
1922setup_service (void *cls, const char *section)
1923{
1924 struct ServiceList *sl;
1925 char *binary;
1926 char *config;
1927 struct stat sbuf;
1928 struct sockaddr **addrs;
1929 socklen_t *addr_lens;
1930 int ret;
1931
1932 (void) cls;
1933 if (0 == strcasecmp (section, "arm"))
1934 return;
1935 if (GNUNET_OK !=
1936 GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary))
1937 {
1938 /* not a service section */
1939 return;
1940 }
1941 if (GNUNET_YES ==
1943 section,
1944 "RUN_PER_USER"))
1945 {
1946 if (GNUNET_NO == start_user)
1947 {
1948 GNUNET_free (binary);
1949 return; /* user service, and we don't deal with those */
1950 }
1951 }
1952 else
1953 {
1954 if (GNUNET_NO == start_system)
1955 {
1956 GNUNET_free (binary);
1957 return; /* system service, and we don't deal with those */
1958 }
1959 }
1960 sl = find_service (section);
1961 if (NULL != sl)
1962 {
1963 /* got the same section twice!? */
1964 GNUNET_break (0);
1965 GNUNET_free (binary);
1966 return;
1967 }
1968 config = NULL;
1969 if (((GNUNET_OK !=
1971 section,
1972 "CONFIG",
1973 &config)) &&
1974 (GNUNET_OK !=
1976 "PATHS",
1977 "DEFAULTCONFIG",
1978 &config))) ||
1979 (0 != stat (config,
1980 &sbuf)))
1981 {
1982 if (NULL != config)
1983 {
1985 section,
1986 "CONFIG",
1987 strerror (errno));
1989 config = NULL;
1990 }
1991 }
1992 sl = GNUNET_new (struct ServiceList);
1993 sl->name = GNUNET_strdup (section);
1994 sl->binary = binary;
1995 sl->config = config;
1998 sl->pipe_control =
1999 (GNUNET_YES ==
2001 section,
2002 "PIPECONTROL"));
2005 sl);
2006 if (GNUNET_YES ==
2008 section,
2009 "IMMEDIATE_START"))
2010 {
2011 sl->force_start = GNUNET_YES;
2012 if (GNUNET_YES ==
2014 section,
2015 "NOARMBIND"))
2016 return;
2017 }
2018 else
2019 {
2020 if (GNUNET_YES !=
2022 section,
2023 "START_ON_DEMAND"))
2024 return;
2025 }
2026 if (0 >= (ret = get_server_addresses (section,
2027 cfg,
2028 &addrs,
2029 &addr_lens)))
2030 return;
2031 /* this will free (or capture) addrs[i] */
2032 for (unsigned int i = 0; i < (unsigned int) ret; i++)
2033 create_listen_socket (addrs[i], addr_lens[i], sl);
2034 GNUNET_free (addrs);
2035 GNUNET_free (addr_lens);
2036}
2037
2038
2047static void *
2049 struct GNUNET_SERVICE_Client *client,
2050 struct GNUNET_MQ_Handle *mq)
2051{
2052 /* All clients are considered to be of the "monitor" kind
2053 * (that is, they don't affect ARM shutdown).
2054 */
2055 (void) cls;
2056 (void) mq;
2058 return client;
2059}
2060
2061
2069static void
2071 struct GNUNET_SERVICE_Client *client,
2072 void *app_ctx)
2073{
2074 (void) cls;
2075 GNUNET_assert (client == app_ctx);
2076 for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2077 if (sl->killing_client == client)
2078 sl->killing_client = NULL;
2079}
2080
2081
2090static void
2091handle_monitor (void *cls, const struct GNUNET_MessageHeader *message)
2092{
2093 struct GNUNET_SERVICE_Client *client = cls;
2094
2095 (void) message;
2096 /* FIXME: might want to start by letting monitor know about
2097 services that are already running */
2098 /* Removal is handled by the server implementation, internally. */
2103}
2104
2105
2113static void
2114run (void *cls,
2115 const struct GNUNET_CONFIGURATION_Handle *c,
2116 struct GNUNET_SERVICE_Handle *serv)
2117{
2118 struct ServiceList *sl;
2119 enum GNUNET_GenericReturnValue ret1;
2120 enum GNUNET_GenericReturnValue ret2;
2121
2122 (void) cls;
2123 cfg = c;
2124 service = serv;
2131 NULL);
2132#if HAVE_WAIT4
2133 if (GNUNET_OK ==
2135 "ARM",
2136 "RESOURCE_DIAGNOSTICS",
2137 &wait_filename))
2138 {
2139 wait_file = fopen (wait_filename, "w");
2140 if (NULL == wait_file)
2141 {
2143 "fopen",
2144 wait_filename);
2145 }
2146 }
2147#endif
2148 if (GNUNET_OK !=
2150 "ARM",
2151 "GLOBAL_PREFIX",
2154 else
2156 if (GNUNET_OK !=
2158 "ARM",
2159 "GLOBAL_POSTFIX",
2160 &final_option))
2162 else
2165 "ARM",
2166 "START_SYSTEM_SERVICES");
2168 "ARM",
2169 "START_USER_SERVICES");
2170 if ( (GNUNET_SYSERR == ret1) ||
2171 (GNUNET_SYSERR == ret2) )
2172 {
2173 /* invalid option */
2174 GNUNET_break (0);
2176 global_ret = 1;
2177 return;
2178 }
2180 "ARM",
2181 "START_SYSTEM_SERVICES"))
2182 ret1 = GNUNET_SYSERR;
2184 "ARM",
2185 "START_USER_SERVICES"))
2186 ret2 = GNUNET_SYSERR;
2187 start_system = (GNUNET_YES == ret1) ||
2188 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2189 start_user = (GNUNET_YES == ret2) ||
2190 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2191 if ( (GNUNET_NO == start_user) &&
2192 (GNUNET_NO == start_system) )
2193 {
2194 GNUNET_log (
2196 "Please enable either START_USER_SERVICES or START_SYSTEM_SERVICES\n");
2198 global_ret = 1;
2199 return;
2200 }
2203 NULL);
2204
2205 /* start default services... */
2206 for (sl = running_head; NULL != sl; sl = sl->next)
2207 if (GNUNET_YES == sl->force_start)
2208 start_process (sl, NULL, 0);
2210}
2211
2212
2220int
2221main (int argc, char *const *argv)
2222{
2227 struct GNUNET_ARM_Message,
2228 NULL),
2231 struct GNUNET_ARM_Message,
2232 NULL),
2235 struct GNUNET_MessageHeader,
2236 NULL),
2239 struct GNUNET_ARM_Message,
2240 NULL),
2243 struct GNUNET_MessageHeader,
2244 NULL),
2246 };
2247
2249 GNUNET_assert (NULL != sigpipe);
2250 shc_chld =
2254 argc,
2255 argv,
2256 "arm",
2259 &run,
2262 NULL,
2263 handlers))
2264 global_ret = 2;
2265#if HAVE_WAIT4
2266 if (NULL != wait_file)
2267 {
2268 fclose (wait_file);
2269 wait_file = NULL;
2270 }
2271 if (NULL != wait_filename)
2272 {
2273 GNUNET_free (wait_filename);
2274 wait_filename = NULL;
2275 }
2276#endif
2278 shc_chld = NULL;
2280 sigpipe = NULL;
2281 return global_ret;
2282}
2283
2284
2285#if defined(__linux__) && defined(__GLIBC__)
2286#include <malloc.h>
2287
2288void __attribute__ ((constructor))
2289GNUNET_ARM_memory_init (void);
2290
2294void __attribute__ ((constructor))
2295GNUNET_ARM_memory_init (void)
2296{
2297 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
2298 mallopt (M_TOP_PAD, 1 * 1024);
2299 malloc_trim (0);
2300}
2301
2302
2303#endif
2304
2305
2306/* 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:1602
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:682
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1425
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1572
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:606
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:646
@ 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:61
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:76
#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
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
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:659
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:853
char * GNUNET_OS_get_libexec_binary_path(const struct GNUNET_OS_ProjectData *pd, const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
@ 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:567
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:1511
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:1661
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:1339
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:980
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:1304
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:1207
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:1231
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2467
int GNUNET_SERVICE_run_(const struct GNUNET_OS_ProjectData *pd, 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:1977
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2483
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2493
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2500
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2389
@ 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:136
Handle to a client that is connected to a service.
Definition: service.c:249
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.