GNUnet 0.26.2-32-gd298f7855
 
Loading...
Searching...
No Matches
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
105
106
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 char *binary;
754 char *quotedbinary;
756
757 GNUNET_assert (NULL == sl->proc);
761 sl->proc,
763 sl->pipe_control
767 for (struct ServiceListeningInfo *sli = sl->listen_head;
768 NULL != sli;
769 sli = sli->next)
770 {
773 sl->proc,
775 GNUNET_NETWORK_get_fd (sli->listen_socket))));
776 if (NULL != sli->accept_task)
777 {
778 GNUNET_SCHEDULER_cancel (sli->accept_task);
779 sli->accept_task = NULL;
780 }
781 }
782
783 /* obtain configuration */
784 if (GNUNET_OK !=
786 sl->name,
787 "PREFIX",
788 &loprefix))
789 loprefix = GNUNET_strdup (prefix_command);
790 else
792 loprefix);
793 if (GNUNET_OK !=
795 sl->name,
796 "OPTIONS",
797 &options))
798 options = NULL;
799 else
801 {
802 char *new_options;
803 char *optpos;
804 char *fin_options;
805
806 fin_options = GNUNET_strdup (final_option);
807 /* replace '{}' with service name */
808 while (NULL != (optpos = strstr (fin_options, "{}")))
809 {
810 /* terminate string at opening parenthesis */
811 *optpos = 0;
812 GNUNET_asprintf (&new_options,
813 "%s%s%s",
814 fin_options,
815 sl->name,
816 optpos + 2);
817 GNUNET_free (fin_options);
818 fin_options = new_options;
819 }
820 if (NULL != options)
821 {
822 /* combine "fin_options" with "options" */
823 optpos = options;
825 "%s %s",
826 fin_options,
827 optpos);
828 GNUNET_free (fin_options);
829 GNUNET_free (optpos);
830 }
831 else
832 {
833 /* only have "fin_options", use that */
834 options = fin_options;
835 }
836 }
838 options);
840 sl->name,
841 "DEBUG");
842 {
843 const char *service_type = NULL;
844 const char *choices[] = {
845 "GNUNET",
846 "SIMPLE",
847 NULL
848 };
849
850 is_simple_service = false;
851 if ( (GNUNET_OK ==
853 sl->name,
854 "TYPE",
855 choices,
856 &service_type)) &&
857 (0 == strcasecmp (service_type,
858 "SIMPLE")) )
859 is_simple_service = true;
860 }
861
862 if (is_simple_service)
863 {
864 /* A simple service will receive no GNUnet specific
865 command line options. */
866 binary = GNUNET_strdup (sl->binary);
868 binary);
869 GNUNET_asprintf (&quotedbinary,
870 "\"%s\"",
871 sl->binary);
873 "Starting simple service `%s' using binary `%s'\n",
874 sl->name,
875 sl->binary);
876 /* FIXME: dollar expansion should only be done outside
877 * of ''-quoted strings, escaping should be considered. */
878 if (NULL != options)
880 options);
882 loprefix,
883 quotedbinary,
884 options,
885 NULL);
886 }
887 else
888 {
889 /* actually start process */
891 "Starting service `%s' using binary `%s' and configuration `%s'\n",
892 sl->name,
893 sl->binary,
894 sl->config);
897 sl->binary);
898 GNUNET_asprintf (&quotedbinary,
899 "\"%s\"",
900 binary);
901 if (GNUNET_YES == use_debug)
902 {
903 if (NULL == sl->config)
905 sl->proc,
906 loprefix,
907 quotedbinary,
908 "-L",
909 "DEBUG",
910 options,
911 NULL);
912 else
914 sl->proc,
915 loprefix,
916 quotedbinary,
917 "-c",
918 sl->config,
919 "-L",
920 "DEBUG",
921 options,
922 NULL);
923 }
924 else
925 {
926 if (NULL == sl->config)
928 sl->proc,
929 loprefix,
930 quotedbinary,
931 options,
932 NULL);
933 else
935 sl->proc,
936 loprefix,
937 quotedbinary,
938 "-c",
939 sl->config,
940 options,
941 NULL);
942 }
943 }
944
945 if (GNUNET_OK != ret)
946 {
947 GNUNET_break (0);
948 goto failure;
949 }
950
953 "Starting service `%s'\n",
954 sl->name);
957 NULL);
958 if (client)
959 signal_result (client,
960 sl->name,
961 request_id,
963 goto cleanup;
964failure:
965 if (NULL != sl->proc)
966 {
968 sl->proc = NULL;
969 }
971 "Failed to start service `%s'\n",
972 sl->name);
973 if (client)
974 signal_result (client,
975 sl->name,
976 request_id,
978cleanup:
979 GNUNET_free (binary);
980 GNUNET_free (quotedbinary);
981 GNUNET_free (loprefix);
983}
984
985
993static struct ServiceList *
994find_service (const char *name)
995{
996 struct ServiceList *sl;
997
998 sl = running_head;
999 while (sl != NULL)
1000 {
1001 if (0 == strcasecmp (sl->name, name))
1002 return sl;
1003 sl = sl->next;
1004 }
1005 return NULL;
1006}
1007
1008
1015static void
1017{
1018 struct ServiceListeningInfo *sli = cls;
1019 struct ServiceList *sl = sli->sl;
1020
1021 sli->accept_task = NULL;
1023 start_process (sl, NULL, 0);
1024}
1025
1026
1035static void
1036create_listen_socket (struct sockaddr *sa,
1037 socklen_t addr_len,
1038 struct ServiceList *sl)
1039{
1040 static int on = 1;
1041 struct GNUNET_NETWORK_Handle *sock;
1042 struct ServiceListeningInfo *sli;
1043
1044 int match_uid;
1045 int match_gid;
1046
1047 switch (sa->sa_family)
1048 {
1049 case AF_INET:
1050 sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
1051 break;
1052
1053 case AF_INET6:
1054 sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1055 break;
1056
1057 case AF_UNIX:
1058 if (0 == strcmp (GNUNET_a2s (sa, addr_len),
1059 "@")) /* Do not bind to blank UNIX path! */
1060 return;
1061 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
1062 break;
1063
1064 default:
1065 GNUNET_break (0);
1066 sock = NULL;
1067 errno = EAFNOSUPPORT;
1068 break;
1069 }
1070 if (NULL == sock)
1071 {
1073 _ ("Unable to create socket for service `%s': %s\n"),
1074 sl->name,
1075 strerror (errno));
1076 GNUNET_free (sa);
1077 return;
1078 }
1080 SOL_SOCKET,
1081 SO_REUSEADDR,
1082 &on,
1083 sizeof(on)))
1085 "setsockopt");
1086#ifdef IPV6_V6ONLY
1087 if ((sa->sa_family == AF_INET6) &&
1089 IPPROTO_IPV6,
1090 IPV6_V6ONLY,
1091 &on,
1092 sizeof(on))))
1094 "setsockopt");
1095#endif
1096 if (AF_UNIX == sa->sa_family)
1097 GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1098 if (GNUNET_OK !=
1099 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
1100 {
1101 GNUNET_log (
1103 _ (
1104 "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1105 sl->name,
1106 GNUNET_a2s (sa, addr_len),
1107 strerror (errno));
1109 GNUNET_free (sa);
1110 return;
1111 }
1112 if ((AF_UNIX == sa->sa_family)
1113#ifdef __linux__
1114 /* Permission settings are not required when abstract sockets are used */
1115 && ('\0' != ((const struct sockaddr_un *) sa)->sun_path[0])
1116#endif
1117 )
1118 {
1119 match_uid =
1120 (GNUNET_YES ==
1122 sl->name,
1123 "UNIX_MATCH_UID"));
1124 match_gid =
1125 (GNUNET_YES ==
1127 sl->name,
1128 "UNIX_MATCH_GID"));
1129 GNUNET_DISK_fix_permissions (((const struct sockaddr_un *) sa)->sun_path,
1130 match_uid,
1131 match_gid);
1132 }
1133 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1134 {
1137 GNUNET_free (sa);
1138 return;
1139 }
1141 _ ("ARM now monitors connections to service `%s' at `%s'\n"),
1142 sl->name,
1143 GNUNET_a2s (sa, addr_len));
1144 sli = GNUNET_new (struct ServiceListeningInfo);
1145 sli->service_addr = sa;
1146 sli->service_addr_len = addr_len;
1147 sli->listen_socket = sock;
1148 sli->sl = sl;
1149 sli->accept_task =
1151 sock,
1153 sli);
1155}
1156
1157
1164static void
1175
1176
1185static int
1186check_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1187{
1188 (void) cls;
1190 return GNUNET_OK;
1191}
1192
1193
1200static void
1201handle_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1202{
1203 struct GNUNET_SERVICE_Client *client = cls;
1204 const char *servicename;
1205 struct ServiceList *sl;
1206 uint64_t request_id;
1207
1208 request_id = GNUNET_ntohll (amsg->request_id);
1209 servicename = (const char *) &amsg[1];
1211 if (GNUNET_YES == in_shutdown)
1212 {
1213 signal_result (client,
1214 servicename,
1215 request_id,
1217 return;
1218 }
1219 sl = find_service (servicename);
1220 if (NULL == sl)
1221 {
1222 signal_result (client,
1223 servicename,
1224 request_id,
1226 return;
1227 }
1228 sl->force_start = GNUNET_YES;
1229 if (NULL != sl->proc)
1230 {
1231 signal_result (client,
1232 servicename,
1233 request_id,
1235 return;
1236 }
1237 start_process (sl, client, request_id);
1238}
1239
1240
1246static void
1248{
1249 (void) cls;
1250 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1252}
1253
1254
1263static int
1264check_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
1265{
1266 (void) cls;
1268 return GNUNET_OK;
1269}
1270
1271
1278static void
1279handle_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
1280{
1281 struct GNUNET_SERVICE_Client *client = cls;
1282 struct ServiceList *sl;
1283 const char *servicename;
1284 uint64_t request_id;
1285
1286 request_id = GNUNET_ntohll (amsg->request_id);
1287 servicename = (const char *) &amsg[1];
1289 _ ("Preparing to stop `%s'\n"),
1290 servicename);
1292 if (0 == strcasecmp (servicename, "arm"))
1293 {
1294 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1295 signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1298 return;
1299 }
1300 sl = find_service (servicename);
1301 if (NULL == sl)
1302 {
1303 signal_result (client,
1304 servicename,
1305 request_id,
1307 return;
1308 }
1309 sl->force_start = GNUNET_NO;
1310 if (GNUNET_YES == in_shutdown)
1311 {
1312 /* shutdown in progress */
1313 signal_result (client,
1314 servicename,
1315 request_id,
1317 return;
1318 }
1319 if (NULL != sl->killing_client)
1320 {
1321 /* killing already in progress */
1322 signal_result (client,
1323 servicename,
1324 request_id,
1326 return;
1327 }
1328 if (NULL == sl->proc)
1329 {
1330 /* process is down */
1331 signal_result (client,
1332 servicename,
1333 request_id,
1335 return;
1336 }
1338 "Sending kill signal to service `%s', waiting for process to die.\n",
1339 servicename);
1340 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1341 /* no signal_start - only when it's STOPPED */
1343 if (GNUNET_OK !=
1347 "kill");
1348 sl->killing_client = client;
1349 sl->killing_client_request_id = request_id;
1350}
1351
1352
1364static int
1365pool_write (char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
1366{
1367 size_t next_pos = (*pool_pos) + strlen (str) + 1;
1368
1369 if (next_pos > pool_size)
1370 return GNUNET_SYSERR;
1371 memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1372 *pool_pos = next_pos;
1373 return GNUNET_OK;
1374}
1375
1376
1383static void
1384handle_list (void *cls, const struct GNUNET_ARM_Message *request)
1385{
1386 struct GNUNET_SERVICE_Client *client = cls;
1387 struct GNUNET_MQ_Envelope *env;
1389 size_t extra_size;
1390 struct ServiceList *sl;
1391 uint16_t count;
1392 size_t pool_size;
1393 size_t pool_pos;
1394 char *pool_start;
1396
1397 GNUNET_break_op (0 == ntohl (request->reserved));
1398 count = 0;
1399 pool_size = 0;
1400
1401 /* Do one pass over the list to compute the number of services
1402 * and the string pool size */
1403 for (sl = running_head; NULL != sl; sl = sl->next)
1404 {
1405 pool_size += strlen (sl->name) + 1;
1406 pool_size += strlen (sl->binary) + 1;
1407 count++;
1408 }
1409
1410 extra_size = pool_size + (count * sizeof (struct
1413 extra_size,
1415 msg->arm_msg.request_id = request->request_id;
1416 msg->count = htons (count);
1417
1418 ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1419 pool_start = (char *) (ssm + count);
1420 pool_pos = 0;
1421
1422 for (sl = running_head; NULL != sl; sl = sl->next)
1423 {
1424 ssm->name_index = htons ((uint16_t) pool_pos);
1425 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1426 sl->name));
1427 ssm->binary_index = htons ((uint16_t) pool_pos);
1428 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1429 sl->binary));
1430 if (NULL == sl->proc)
1431 {
1432 if (0 == sl->last_started_at.abs_value_us)
1433 {
1434 /* Process never started */
1436 }
1437 else if (0 == sl->last_exit_status)
1438 {
1440 }
1441 else
1442 {
1444 ssm->last_exit_status = htons (sl->last_exit_status);
1445 }
1446 }
1447 else if ((NULL != sl->killing_client) || (GNUNET_YES == in_shutdown))
1448 {
1450 }
1451 else
1452 {
1454 }
1457 ssm++;
1458 }
1461}
1462
1463
1470static void
1471handle_test (void *cls, const struct GNUNET_MessageHeader *message)
1472{
1473 struct GNUNET_SERVICE_Client *client = cls;
1474 struct GNUNET_MQ_Envelope *env;
1475 struct GNUNET_MessageHeader *msg;
1476
1477 (void) message;
1481}
1482
1483
1488static void
1490{
1491 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1492 if (NULL != notifier)
1493 {
1495 notifier = NULL;
1496 }
1497 if (NULL != service)
1498 {
1500 service = NULL;
1501 }
1502 if (NULL != child_death_task)
1503 {
1505 child_death_task = NULL;
1506 }
1507}
1508
1509
1516static unsigned int
1517list_count (struct ServiceList *run_head)
1518{
1519 struct ServiceList *i;
1520 unsigned int res;
1521
1522 for (res = 0, i = run_head; NULL != i; i = i->next, res++)
1524 return res;
1525}
1526
1527
1533static void
1534shutdown_task (void *cls)
1535{
1536 struct ServiceList *pos;
1537 struct ServiceList *nxt;
1538 struct ServiceListeningInfo *sli;
1539
1540 (void) cls;
1541 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1542 if (NULL != child_restart_task)
1543 {
1545 child_restart_task = NULL;
1546 }
1548 /* first, stop listening */
1549 for (pos = running_head; NULL != pos; pos = pos->next)
1550 {
1551 while (NULL != (sli = pos->listen_head))
1552 {
1554 if (NULL != sli->accept_task)
1555 {
1557 sli->accept_task = NULL;
1558 }
1562 GNUNET_free (sli);
1563 }
1564 }
1565 /* then, shutdown all existing service processes */
1566 nxt = running_head;
1567 while (NULL != (pos = nxt))
1568 {
1569 nxt = pos->next;
1570 if (NULL != pos->proc)
1571 {
1573 "Stopping service `%s'\n",
1574 pos->name);
1576 if (GNUNET_OK !=
1580 "kill");
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,
1721 &status,
1722 WNOHANG,
1723 &ru);
1724 if (ret <= 0)
1725 continue; /* no process done */
1726 if (WIFEXITED (status))
1727 {
1728 statusType = GNUNET_OS_PROCESS_EXITED;
1729 statusCode = WEXITSTATUS (status);
1730 }
1731 else if (WIFSIGNALED (status))
1732 {
1733 statusType = GNUNET_OS_PROCESS_SIGNALED;
1734 statusCode = WTERMSIG (status);
1735 }
1736 else if (WIFSTOPPED (status))
1737 {
1738 statusType = GNUNET_OS_PROCESS_SIGNALED;
1739 statusCode = WSTOPSIG (status);
1740 }
1741#ifdef WIFCONTINUED
1742 else if (WIFCONTINUED (status))
1743 {
1744 statusType = GNUNET_OS_PROCESS_RUNNING;
1745 statusCode = 0;
1746 }
1747#endif
1748 else
1749 {
1750 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1751 statusCode = 0;
1752 }
1753 if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1754 (GNUNET_OS_PROCESS_SIGNALED == statusType))
1755 {
1756 double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1757 double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1758 fprintf (wait_file,
1759 "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1760 pos->binary,
1761 (unsigned int) pid,
1762 utime,
1763 stime,
1764 (unsigned long long) ru.ru_maxrss,
1765 (unsigned long long) ru.ru_inblock,
1766 (unsigned long long) ru.ru_oublock,
1767 (unsigned long long) ru.ru_nvcsw,
1768 (unsigned long long) ru.ru_nivcsw);
1769 }
1770 }
1771 else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1772#endif
1773 if ((GNUNET_SYSERR ==
1774 (ret = GNUNET_process_wait (pos->proc,
1775 true,
1776 &statusType,
1777 &statusCode))) ||
1778 (ret == GNUNET_NO) ||
1779 (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1780 (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1781 (statusType == GNUNET_OS_PROCESS_RUNNING))
1782 continue;
1783
1784 if (statusType == GNUNET_OS_PROCESS_EXITED)
1785 {
1786 statstr = _ (/* process termination method */ "exit");
1787 statcode = statusCode;
1788 }
1789 else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1790 {
1791 statstr = _ (/* process termination method */ "signal");
1792 statcode = statusCode;
1793 }
1794 else
1795 {
1796 statstr = _ (/* process termination method */ "unknown");
1797 statcode = 0;
1798 }
1799 if (0 != pos->killed_at.abs_value_us)
1800 {
1802 _ ("Service `%s' took %s to terminate\n"),
1803 pos->name,
1806 GNUNET_YES));
1807 }
1809 pos->proc = NULL;
1810 broadcast_status (pos->name,
1812 NULL);
1813 if (NULL != pos->killing_client)
1814 {
1816 pos->name,
1819 pos->killing_client = NULL;
1821 }
1822 if (GNUNET_YES != in_shutdown)
1823 {
1824 pos->last_exit_status = statcode;
1825 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1826 {
1827 /* process terminated normally, allow restart at any time */
1828 pos->restart_at.abs_value_us = 0;
1829 GNUNET_log (
1831 _ ("Service `%s' terminated normally, will restart at any time\n"),
1832 pos->name);
1833 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1834 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1835 {
1836 GNUNET_break (NULL == sli->accept_task);
1837 sli->accept_task =
1839 sli->listen_socket,
1841 sli);
1842 }
1843 }
1844 else
1845 {
1846 GNUNET_log (
1848 _ ("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1849 pos->name,
1850 statstr,
1851 statcode,
1853 {
1854 /* Reduce backoff based on runtime of the process,
1855 so that there is a cool-down if a process actually
1856 runs for a while. */
1857 struct GNUNET_TIME_Relative runtime;
1858 unsigned int minutes;
1859
1861 minutes =
1862 runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1863 if (minutes > 31)
1865 else
1866 pos->backoff.rel_value_us >>= minutes;
1867 }
1868 /* schedule restart */
1871 if (NULL != child_restart_task)
1876 NULL);
1877 }
1878 }
1879 else
1880 {
1881 free_service (pos);
1882 }
1883 }
1886 pr,
1888 NULL);
1889 if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1890 do_shutdown ();
1891 else if (GNUNET_YES == in_shutdown)
1893 "Delaying shutdown after child's death, still have %u children\n",
1895}
1896
1897
1902static void
1904{
1905 static char c;
1906 int old_errno = errno; /* back-up errno */
1907
1908 GNUNET_break (
1909 1 ==
1912 ,
1913 &c,
1914 sizeof(c)));
1915 errno = old_errno; /* restore errno */
1916}
1917
1918
1927static void
1928setup_service (void *cls, const char *section)
1929{
1930 struct ServiceList *sl;
1931 char *binary;
1932 char *config;
1933 struct stat sbuf;
1934 struct sockaddr **addrs;
1935 socklen_t *addr_lens;
1936 int ret;
1937
1938 (void) cls;
1939 if (0 == strcasecmp (section, "arm"))
1940 return;
1941 if (GNUNET_OK !=
1942 GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary))
1943 {
1944 /* not a service section */
1945 return;
1946 }
1947 if (GNUNET_YES ==
1949 section,
1950 "RUN_PER_USER"))
1951 {
1952 if (GNUNET_NO == start_user)
1953 {
1954 GNUNET_free (binary);
1955 return; /* user service, and we don't deal with those */
1956 }
1957 }
1958 else
1959 {
1960 if (GNUNET_NO == start_system)
1961 {
1962 GNUNET_free (binary);
1963 return; /* system service, and we don't deal with those */
1964 }
1965 }
1966 sl = find_service (section);
1967 if (NULL != sl)
1968 {
1969 /* got the same section twice!? */
1970 GNUNET_break (0);
1971 GNUNET_free (binary);
1972 return;
1973 }
1974 config = NULL;
1975 if (((GNUNET_OK !=
1977 section,
1978 "CONFIG",
1979 &config)) &&
1980 (GNUNET_OK !=
1982 "PATHS",
1983 "DEFAULTCONFIG",
1984 &config))) ||
1985 (0 != stat (config,
1986 &sbuf)))
1987 {
1988 if (NULL != config)
1989 {
1991 section,
1992 "CONFIG",
1993 strerror (errno));
1995 config = NULL;
1996 }
1997 }
1998 sl = GNUNET_new (struct ServiceList);
1999 sl->name = GNUNET_strdup (section);
2000 sl->binary = binary;
2001 sl->config = config;
2004 sl->pipe_control =
2005 (GNUNET_YES ==
2007 section,
2008 "PIPECONTROL"));
2011 sl);
2012 if (GNUNET_YES ==
2014 section,
2015 "IMMEDIATE_START"))
2016 {
2017 sl->force_start = GNUNET_YES;
2018 if (GNUNET_YES ==
2020 section,
2021 "NOARMBIND"))
2022 return;
2023 }
2024 else
2025 {
2026 if (GNUNET_YES !=
2028 section,
2029 "START_ON_DEMAND"))
2030 return;
2031 }
2032 if (0 >= (ret = get_server_addresses (section,
2033 cfg,
2034 &addrs,
2035 &addr_lens)))
2036 return;
2037 /* this will free (or capture) addrs[i] */
2038 for (unsigned int i = 0; i < (unsigned int) ret; i++)
2039 create_listen_socket (addrs[i], addr_lens[i], sl);
2040 GNUNET_free (addrs);
2041 GNUNET_free (addr_lens);
2042}
2043
2044
2053static void *
2055 struct GNUNET_SERVICE_Client *client,
2056 struct GNUNET_MQ_Handle *mq)
2057{
2058 /* All clients are considered to be of the "monitor" kind
2059 * (that is, they don't affect ARM shutdown).
2060 */
2061 (void) cls;
2062 (void) mq;
2064 return client;
2065}
2066
2067
2075static void
2077 struct GNUNET_SERVICE_Client *client,
2078 void *app_ctx)
2079{
2080 (void) cls;
2081 GNUNET_assert (client == app_ctx);
2082 for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2083 if (sl->killing_client == client)
2084 sl->killing_client = NULL;
2085}
2086
2087
2096static void
2097handle_monitor (void *cls, const struct GNUNET_MessageHeader *message)
2098{
2099 struct GNUNET_SERVICE_Client *client = cls;
2100
2101 (void) message;
2102 /* FIXME: might want to start by letting monitor know about
2103 services that are already running */
2104 /* Removal is handled by the server implementation, internally. */
2109}
2110
2111
2119static void
2120run (void *cls,
2121 const struct GNUNET_CONFIGURATION_Handle *c,
2122 struct GNUNET_SERVICE_Handle *serv)
2123{
2124 struct ServiceList *sl;
2125 enum GNUNET_GenericReturnValue ret1;
2126 enum GNUNET_GenericReturnValue ret2;
2127
2128 (void) cls;
2129 cfg = c;
2130 service = serv;
2137 NULL);
2138#if HAVE_WAIT4
2139 if (GNUNET_OK ==
2141 "ARM",
2142 "RESOURCE_DIAGNOSTICS",
2143 &wait_filename))
2144 {
2145 wait_file = fopen (wait_filename, "w");
2146 if (NULL == wait_file)
2147 {
2149 "fopen",
2150 wait_filename);
2151 }
2152 }
2153#endif
2154 if (GNUNET_OK !=
2156 "ARM",
2157 "GLOBAL_PREFIX",
2160 else
2162 if (GNUNET_OK !=
2164 "ARM",
2165 "GLOBAL_POSTFIX",
2166 &final_option))
2168 else
2171 "ARM",
2172 "START_SYSTEM_SERVICES");
2174 "ARM",
2175 "START_USER_SERVICES");
2176 if ( (GNUNET_SYSERR == ret1) ||
2177 (GNUNET_SYSERR == ret2) )
2178 {
2179 /* invalid option */
2180 GNUNET_break (0);
2182 global_ret = 1;
2183 return;
2184 }
2186 "ARM",
2187 "START_SYSTEM_SERVICES"))
2188 ret1 = GNUNET_SYSERR;
2190 "ARM",
2191 "START_USER_SERVICES"))
2192 ret2 = GNUNET_SYSERR;
2193 start_system = (GNUNET_YES == ret1) ||
2194 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2195 start_user = (GNUNET_YES == ret2) ||
2196 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2197 if ( (GNUNET_NO == start_user) &&
2198 (GNUNET_NO == start_system) )
2199 {
2200 GNUNET_log (
2202 "Please enable either START_USER_SERVICES or START_SYSTEM_SERVICES\n");
2204 global_ret = 1;
2205 return;
2206 }
2209 NULL);
2210
2211 /* start default services... */
2212 for (sl = running_head; NULL != sl; sl = sl->next)
2213 if (GNUNET_YES == sl->force_start)
2214 start_process (sl, NULL, 0);
2216}
2217
2218
2226int
2227main (int argc, char *const *argv)
2228{
2233 struct GNUNET_ARM_Message,
2234 NULL),
2237 struct GNUNET_ARM_Message,
2238 NULL),
2241 struct GNUNET_MessageHeader,
2242 NULL),
2245 struct GNUNET_ARM_Message,
2246 NULL),
2249 struct GNUNET_MessageHeader,
2250 NULL),
2252 };
2253
2255 GNUNET_assert (NULL != sigpipe);
2256 shc_chld =
2260 argc,
2261 argv,
2262 "arm",
2265 &run,
2268 NULL,
2269 handlers))
2270 global_ret = 2;
2271#if HAVE_WAIT4
2272 if (NULL != wait_file)
2273 {
2274 fclose (wait_file);
2275 wait_file = NULL;
2276 }
2277 if (NULL != wait_filename)
2278 {
2279 GNUNET_free (wait_filename);
2280 wait_filename = NULL;
2281 }
2282#endif
2284 shc_chld = NULL;
2286 sigpipe = NULL;
2287 return global_ret;
2288}
2289
2290
2291#if defined(__linux__) && defined(__GLIBC__)
2292#include <malloc.h>
2293
2294void __attribute__ ((constructor))
2295GNUNET_ARM_memory_init (void);
2296
2300void __attribute__ ((constructor))
2301GNUNET_ARM_memory_init (void)
2302{
2303 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
2304 mallopt (M_TOP_PAD, 1 * 1024);
2305 malloc_trim (0);
2306}
2307
2308
2309#endif
2310
2311
2312/* 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_MessageHeader * msg
Definition 005.c:2
struct GNUNET_MQ_Envelope * env
Definition 005.c:1
static struct GNUNET_SIGNAL_Context * shc_chld
int main()
Program to simulate results from GCP_get_desirability_of_path() for various plausible inputs.
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
struct GNUNET_SCHEDULER_Task * shutdown_task
static char * name
Name (label) of the records to list.
static char * res
Currently read line or NULL on EOF.
static int status
The program status; 0 for success.
Definition gnunet-nse.c:39
static void start_process()
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 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 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,...)
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 void cleanup()
Cleanup task.
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:1702
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:334
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:745
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition disk.c:1523
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition disk.c:1670
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition disk.c:664
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:704
@ 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.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
#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_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_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.
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.
#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_Process * GNUNET_process_create(void)
Create a process handle.
Definition os_process.c:446
#define GNUNET_process_option_inherit_lsock(lsock)
Pass listen socket to child systemd-style.
enum GNUNET_GenericReturnValue GNUNET_process_wait(struct GNUNET_Process *proc, bool blocking, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Wait for a process to terminate.
void GNUNET_process_destroy(struct GNUNET_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition os_process.c:350
#define GNUNET_process_option_std_inheritance(flags)
Set flags about standard inheritance options.
enum GNUNET_GenericReturnValue GNUNET_process_set_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command to start a process.
Definition os_process.c:907
#define GNUNET_process_set_options(proc,...)
Set the requested options for the process.
GNUNET_OS_ProcessStatusType
Process status types.
pid_t GNUNET_process_get_pid(const struct GNUNET_Process *proc)
Get the pid of the process in question.
Definition os_process.c:343
enum GNUNET_GenericReturnValue GNUNET_process_kill(struct GNUNET_Process *proc, int sig)
Sends a signal to the process.
Definition os_process.c:302
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:572
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:1517
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:1667
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:1345
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition scheduler.c:986
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:1310
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:1213
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:1237
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition service.c:2511
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:2021
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2527
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition service.c:2537
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition service.c:2544
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2433
@ 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:604
#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:636
#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:179
#define GNUNET_SIGCHLD
Definition platform.h:42
#define GNUNET_TERM_SIG
The termination signal.
Definition platform.h:235
static struct GNUNET_MQ_Handle * mq
Our connection to the resolver service, created on-demand, but then persists until error or shutdown.
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:141
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).
struct GNUNET_Process * proc
Process structure pointer of the child.
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_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.
const char * str
Definition time.c:1252