GNUnet 0.27.0
 
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;
755
756 GNUNET_assert (NULL == sl->proc);
761 for (struct ServiceListeningInfo *sli = sl->listen_head;
762 NULL != sli;
763 sli = sli->next)
764 {
767 sl->proc,
769 GNUNET_NETWORK_get_fd (sli->listen_socket))));
770 if (NULL != sli->accept_task)
771 {
772 GNUNET_SCHEDULER_cancel (sli->accept_task);
773 sli->accept_task = NULL;
774 }
775 }
776
777 /* obtain configuration */
778 if (GNUNET_OK !=
780 sl->name,
781 "PREFIX",
782 &loprefix))
783 loprefix = GNUNET_strdup (prefix_command);
784 else
786 loprefix);
787 if (GNUNET_OK !=
789 sl->name,
790 "OPTIONS",
791 &options))
792 options = NULL;
793 else
795 {
796 char *new_options;
797 char *optpos;
798 char *fin_options;
799
800 fin_options = GNUNET_strdup (final_option);
801 /* replace '{}' with service name */
802 while (NULL != (optpos = strstr (fin_options, "{}")))
803 {
804 /* terminate string at opening parenthesis */
805 *optpos = 0;
806 GNUNET_asprintf (&new_options,
807 "%s%s%s",
808 fin_options,
809 sl->name,
810 optpos + 2);
811 GNUNET_free (fin_options);
812 fin_options = new_options;
813 }
814 if (NULL != options)
815 {
816 /* combine "fin_options" with "options" */
817 optpos = options;
819 "%s %s",
820 fin_options,
821 optpos);
822 GNUNET_free (fin_options);
823 GNUNET_free (optpos);
824 }
825 else
826 {
827 /* only have "fin_options", use that */
828 options = fin_options;
829 }
830 }
832 options);
834 sl->name,
835 "DEBUG");
836 {
837 const char *service_type = NULL;
838 const char *choices[] = {
839 "GNUNET",
840 "SIMPLE",
841 NULL
842 };
843
844 is_simple_service = false;
845 if ( (GNUNET_OK ==
847 sl->name,
848 "TYPE",
849 choices,
850 &service_type)) &&
851 (0 == strcasecmp (service_type,
852 "SIMPLE")) )
853 is_simple_service = true;
854 }
855
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);
864 "Starting simple service `%s' using binary `%s'\n",
865 sl->name,
866 sl->binary);
868 loprefix,
869 binary,
870 options,
871 NULL);
872 }
873 else
874 {
875 char *command;
876
877 /* actually start process */
879 "Starting service `%s' using binary `%s' and configuration `%s'\n",
880 sl->name,
881 sl->binary,
882 sl->config);
885 sl->binary);
886 GNUNET_asprintf (&command,
887 "%s%s%s%s%s%s%s%s",
888 loprefix,
889 (0 == strlen (loprefix)) ? "" : " ",
890 binary,
891 (use_debug) ? " -L DEBUG" : "",
892 (NULL == sl->config) ? "" : " -c ",
893 (NULL == sl->config) ? "" : sl->config,
894 (0 == strlen (options)) ? "" : " ",
895 options);
897 "Launching GNUnet service `%s'\n",
898 command);
900 sl->proc,
901 command);
902 GNUNET_free (command);
903 }
904
905 if (GNUNET_OK != ret)
906 {
907 GNUNET_break (0);
908 goto failure;
909 }
910
913 "Starting service `%s'\n",
914 sl->name);
917 NULL);
918 if (client)
919 signal_result (client,
920 sl->name,
921 request_id,
923 goto cleanup;
924failure:
925 if (NULL != sl->proc)
926 {
928 sl->proc = NULL;
929 }
931 "Failed to start service `%s'\n",
932 sl->name);
933 if (client)
934 signal_result (client,
935 sl->name,
936 request_id,
938cleanup:
939 GNUNET_free (binary);
940 GNUNET_free (loprefix);
942}
943
944
952static struct ServiceList *
953find_service (const char *name)
954{
955 struct ServiceList *sl;
956
957 sl = running_head;
958 while (sl != NULL)
959 {
960 if (0 == strcasecmp (sl->name, name))
961 return sl;
962 sl = sl->next;
963 }
964 return NULL;
965}
966
967
974static void
976{
977 struct ServiceListeningInfo *sli = cls;
978 struct ServiceList *sl = sli->sl;
979
980 sli->accept_task = NULL;
982 start_process (sl, NULL, 0);
983}
984
985
994static void
995create_listen_socket (struct sockaddr *sa,
996 socklen_t addr_len,
997 struct ServiceList *sl)
998{
999 static int on = 1;
1000 struct GNUNET_NETWORK_Handle *sock;
1001 struct ServiceListeningInfo *sli;
1002
1003 int match_uid;
1004 int match_gid;
1005
1006 switch (sa->sa_family)
1007 {
1008 case AF_INET:
1009 sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
1010 break;
1011
1012 case AF_INET6:
1013 sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1014 break;
1015
1016 case AF_UNIX:
1017 if (0 == strcmp (GNUNET_a2s (sa, addr_len),
1018 "@")) /* Do not bind to blank UNIX path! */
1019 return;
1020 sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
1021 break;
1022
1023 default:
1024 GNUNET_break (0);
1025 sock = NULL;
1026 errno = EAFNOSUPPORT;
1027 break;
1028 }
1029 if (NULL == sock)
1030 {
1032 _ ("Unable to create socket for service `%s': %s\n"),
1033 sl->name,
1034 strerror (errno));
1035 GNUNET_free (sa);
1036 return;
1037 }
1039 SOL_SOCKET,
1040 SO_REUSEADDR,
1041 &on,
1042 sizeof(on)))
1044 "setsockopt");
1045#ifdef IPV6_V6ONLY
1046 if ((sa->sa_family == AF_INET6) &&
1048 IPPROTO_IPV6,
1049 IPV6_V6ONLY,
1050 &on,
1051 sizeof(on))))
1053 "setsockopt");
1054#endif
1055 if (AF_UNIX == sa->sa_family)
1056 GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1057 if (GNUNET_OK !=
1058 GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
1059 {
1060 GNUNET_log (
1062 _ (
1063 "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1064 sl->name,
1065 GNUNET_a2s (sa, addr_len),
1066 strerror (errno));
1068 GNUNET_free (sa);
1069 return;
1070 }
1071 if ((AF_UNIX == sa->sa_family)
1072#ifdef __linux__
1073 /* Permission settings are not required when abstract sockets are used */
1074 && ('\0' != ((const struct sockaddr_un *) sa)->sun_path[0])
1075#endif
1076 )
1077 {
1078 match_uid =
1079 (GNUNET_YES ==
1081 sl->name,
1082 "UNIX_MATCH_UID"));
1083 match_gid =
1084 (GNUNET_YES ==
1086 sl->name,
1087 "UNIX_MATCH_GID"));
1088 GNUNET_DISK_fix_permissions (((const struct sockaddr_un *) sa)->sun_path,
1089 match_uid,
1090 match_gid);
1091 }
1092 if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1093 {
1096 GNUNET_free (sa);
1097 return;
1098 }
1100 _ ("ARM now monitors connections to service `%s' at `%s'\n"),
1101 sl->name,
1102 GNUNET_a2s (sa, addr_len));
1103 sli = GNUNET_new (struct ServiceListeningInfo);
1104 sli->service_addr = sa;
1105 sli->service_addr_len = addr_len;
1106 sli->listen_socket = sock;
1107 sli->sl = sl;
1108 sli->accept_task =
1110 sock,
1112 sli);
1114}
1115
1116
1123static void
1134
1135
1144static int
1145check_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1146{
1147 (void) cls;
1149 return GNUNET_OK;
1150}
1151
1152
1159static void
1160handle_start (void *cls, const struct GNUNET_ARM_Message *amsg)
1161{
1162 struct GNUNET_SERVICE_Client *client = cls;
1163 const char *servicename;
1164 struct ServiceList *sl;
1165 uint64_t request_id;
1166
1167 request_id = GNUNET_ntohll (amsg->request_id);
1168 servicename = (const char *) &amsg[1];
1170 if (GNUNET_YES == in_shutdown)
1171 {
1172 signal_result (client,
1173 servicename,
1174 request_id,
1176 return;
1177 }
1178 sl = find_service (servicename);
1179 if (NULL == sl)
1180 {
1181 signal_result (client,
1182 servicename,
1183 request_id,
1185 return;
1186 }
1187 sl->force_start = GNUNET_YES;
1188 if (NULL != sl->proc)
1189 {
1190 signal_result (client,
1191 servicename,
1192 request_id,
1194 return;
1195 }
1196 start_process (sl, client, request_id);
1197}
1198
1199
1205static void
1207{
1208 (void) cls;
1209 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1211}
1212
1213
1222static int
1223check_stop (void *cls,
1224 const struct GNUNET_ARM_Message *amsg)
1225{
1226 (void) cls;
1228 return GNUNET_OK;
1229}
1230
1231
1238static void
1239handle_stop (void *cls,
1240 const struct GNUNET_ARM_Message *amsg)
1241{
1242 struct GNUNET_SERVICE_Client *client = cls;
1243 struct ServiceList *sl;
1244 const char *servicename;
1245 uint64_t request_id;
1246
1247 request_id = GNUNET_ntohll (amsg->request_id);
1248 servicename = (const char *) &amsg[1];
1250 _ ("Preparing to stop `%s'\n"),
1251 servicename);
1253 if (0 == strcasecmp (servicename, "arm"))
1254 {
1255 broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1256 signal_result (client,
1257 servicename,
1258 request_id,
1262 return;
1263 }
1264 sl = find_service (servicename);
1265 if (NULL == sl)
1266 {
1267 signal_result (client,
1268 servicename,
1269 request_id,
1271 return;
1272 }
1273 sl->force_start = GNUNET_NO;
1274 if (GNUNET_YES == in_shutdown)
1275 {
1276 /* shutdown in progress */
1277 signal_result (client,
1278 servicename,
1279 request_id,
1281 return;
1282 }
1283 if (NULL != sl->killing_client)
1284 {
1285 /* killing already in progress */
1286 signal_result (client,
1287 servicename,
1288 request_id,
1290 return;
1291 }
1292 if (NULL == sl->proc)
1293 {
1294 /* process is down */
1295 signal_result (client,
1296 servicename,
1297 request_id,
1299 return;
1300 }
1302 "Sending kill signal to service `%s', waiting for process to die.\n",
1303 servicename);
1304 broadcast_status (servicename,
1306 NULL);
1307 /* no signal_start - only when it's STOPPED */
1309 if (GNUNET_OK !=
1313 "kill");
1314 sl->killing_client = client;
1315 sl->killing_client_request_id = request_id;
1316}
1317
1318
1330static int
1331pool_write (char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
1332{
1333 size_t next_pos = (*pool_pos) + strlen (str) + 1;
1334
1335 if (next_pos > pool_size)
1336 return GNUNET_SYSERR;
1337 memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1338 *pool_pos = next_pos;
1339 return GNUNET_OK;
1340}
1341
1342
1349static void
1350handle_list (void *cls, const struct GNUNET_ARM_Message *request)
1351{
1352 struct GNUNET_SERVICE_Client *client = cls;
1353 struct GNUNET_MQ_Envelope *env;
1355 size_t extra_size;
1356 struct ServiceList *sl;
1357 uint16_t count;
1358 size_t pool_size;
1359 size_t pool_pos;
1360 char *pool_start;
1362
1363 GNUNET_break_op (0 == ntohl (request->reserved));
1364 count = 0;
1365 pool_size = 0;
1366
1367 /* Do one pass over the list to compute the number of services
1368 * and the string pool size */
1369 for (sl = running_head; NULL != sl; sl = sl->next)
1370 {
1371 pool_size += strlen (sl->name) + 1;
1372 pool_size += strlen (sl->binary) + 1;
1373 count++;
1374 }
1375
1376 extra_size = pool_size + (count * sizeof (struct
1379 extra_size,
1381 msg->arm_msg.request_id = request->request_id;
1382 msg->count = htons (count);
1383
1384 ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1385 pool_start = (char *) (ssm + count);
1386 pool_pos = 0;
1387
1388 for (sl = running_head; NULL != sl; sl = sl->next)
1389 {
1390 ssm->name_index = htons ((uint16_t) pool_pos);
1391 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1392 sl->name));
1393 ssm->binary_index = htons ((uint16_t) pool_pos);
1394 GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1395 sl->binary));
1396 if (NULL == sl->proc)
1397 {
1398 if (0 == sl->last_started_at.abs_value_us)
1399 {
1400 /* Process never started */
1402 }
1403 else if (0 == sl->last_exit_status)
1404 {
1406 }
1407 else
1408 {
1410 ssm->last_exit_status = htons (sl->last_exit_status);
1411 }
1412 }
1413 else if ((NULL != sl->killing_client) || (GNUNET_YES == in_shutdown))
1414 {
1416 }
1417 else
1418 {
1420 }
1423 ssm++;
1424 }
1427}
1428
1429
1436static void
1437handle_test (void *cls, const struct GNUNET_MessageHeader *message)
1438{
1439 struct GNUNET_SERVICE_Client *client = cls;
1440 struct GNUNET_MQ_Envelope *env;
1441 struct GNUNET_MessageHeader *msg;
1442
1443 (void) message;
1447}
1448
1449
1454static void
1456{
1457 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1458 if (NULL != notifier)
1459 {
1461 notifier = NULL;
1462 }
1463 if (NULL != service)
1464 {
1466 service = NULL;
1467 }
1468 if (NULL != child_death_task)
1469 {
1471 child_death_task = NULL;
1472 }
1473}
1474
1475
1482static unsigned int
1483list_count (struct ServiceList *run_head)
1484{
1485 struct ServiceList *i;
1486 unsigned int res;
1487
1488 for (res = 0, i = run_head; NULL != i; i = i->next, res++)
1490 return res;
1491}
1492
1493
1499static void
1500shutdown_task (void *cls)
1501{
1502 struct ServiceList *pos;
1503 struct ServiceList *nxt;
1504 struct ServiceListeningInfo *sli;
1505
1506 (void) cls;
1507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1508 if (NULL != child_restart_task)
1509 {
1511 child_restart_task = NULL;
1512 }
1514 /* first, stop listening */
1515 for (pos = running_head; NULL != pos; pos = pos->next)
1516 {
1517 while (NULL != (sli = pos->listen_head))
1518 {
1520 pos->listen_tail,
1521 sli);
1522 if (NULL != sli->accept_task)
1523 {
1525 sli->accept_task = NULL;
1526 }
1530 GNUNET_free (sli);
1531 }
1532 }
1533 /* then, shutdown all existing service processes */
1534 nxt = running_head;
1535 while (NULL != (pos = nxt))
1536 {
1537 nxt = pos->next;
1538 if (NULL != pos->proc)
1539 {
1541 "Stopping service `%s'\n",
1542 pos->name);
1544 if (GNUNET_OK !=
1548 "kill");
1549 }
1550 else
1551 {
1552 free_service (pos);
1553 }
1554 }
1555 /* finally, should all service processes be already gone, terminate for real */
1556 if (NULL == running_head)
1557 do_shutdown ();
1558 else
1560 "Delaying shutdown, have %u children still running\n",
1562}
1563
1564
1570static void
1572
1573{
1574 struct ServiceList *sl;
1575 struct GNUNET_TIME_Relative lowestRestartDelay;
1576 struct ServiceListeningInfo *sli;
1577
1578 (void) cls;
1579 child_restart_task = NULL;
1581 lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1582
1583 /* check for services that need to be restarted due to
1584 * configuration changes or because the last restart failed */
1585 for (sl = running_head; NULL != sl; sl = sl->next)
1586 {
1587 if (NULL != sl->proc)
1588 continue;
1589 /* service is currently not running */
1591 {
1592 /* restart is now allowed */
1593 if (sl->force_start)
1594 {
1595 /* process should run by default, start immediately */
1597 _ ("Restarting service `%s'.\n"),
1598 sl->name);
1599 start_process (sl, NULL, 0);
1600 }
1601 else
1602 {
1603 /* process is run on-demand, ensure it is re-started if there is demand */
1604 for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1605 if (NULL == sli->accept_task)
1606 {
1607 /* accept was actually paused, so start it again */
1608 sli->accept_task =
1610 sli->listen_socket,
1612 sli);
1613 }
1614 }
1615 }
1616 else
1617 {
1618 /* update calculation for earliest time to reactivate a service */
1619 lowestRestartDelay =
1620 GNUNET_TIME_relative_min (lowestRestartDelay,
1622 sl->restart_at));
1623 }
1624 }
1625 if (lowestRestartDelay.rel_value_us !=
1626 GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1627 {
1629 "Will restart process in %s\n",
1630 GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1631 GNUNET_YES));
1636 NULL);
1637 }
1638}
1639
1640
1647static void
1649{
1650 struct ServiceList *pos;
1651 struct ServiceList *next;
1652 struct ServiceListeningInfo *sli;
1653 const char *statstr;
1654 int statcode;
1655 int ret;
1656 char c[16];
1657 enum GNUNET_OS_ProcessStatusType statusType;
1658 unsigned long statusCode;
1659 const struct GNUNET_DISK_FileHandle *pr;
1660
1661 (void) cls;
1664 child_death_task = NULL;
1665 /* consume the signal */
1666 GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
1667
1668 /* check for services that died (WAITPID) */
1669 next = running_head;
1670 while (NULL != (pos = next))
1671 {
1672 next = pos->next;
1673
1674 if (NULL == pos->proc)
1675 {
1676 if (GNUNET_YES == in_shutdown)
1677 free_service (pos);
1678 continue;
1679 }
1680#if HAVE_WAIT4
1681 if (NULL != wait_file)
1682 {
1683 /* need to use 'wait4()' to obtain and log performance data */
1684 struct rusage ru;
1685 int status;
1686 pid_t pid;
1687
1689 ret = wait4 (pid,
1690 &status,
1691 WNOHANG,
1692 &ru);
1693 if (ret <= 0)
1694 continue; /* no process done */
1695 if (WIFEXITED (status))
1696 {
1697 statusType = GNUNET_OS_PROCESS_EXITED;
1698 statusCode = WEXITSTATUS (status);
1699 }
1700 else if (WIFSIGNALED (status))
1701 {
1702 statusType = GNUNET_OS_PROCESS_SIGNALED;
1703 statusCode = WTERMSIG (status);
1704 }
1705 else if (WIFSTOPPED (status))
1706 {
1707 statusType = GNUNET_OS_PROCESS_SIGNALED;
1708 statusCode = WSTOPSIG (status);
1709 }
1710#ifdef WIFCONTINUED
1711 else if (WIFCONTINUED (status))
1712 {
1713 statusType = GNUNET_OS_PROCESS_RUNNING;
1714 statusCode = 0;
1715 }
1716#endif
1717 else
1718 {
1719 statusType = GNUNET_OS_PROCESS_UNKNOWN;
1720 statusCode = 0;
1721 }
1722 if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1723 (GNUNET_OS_PROCESS_SIGNALED == statusType))
1724 {
1725 double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1726 double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1727 fprintf (wait_file,
1728 "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1729 pos->binary,
1730 (unsigned int) pid,
1731 utime,
1732 stime,
1733 (unsigned long long) ru.ru_maxrss,
1734 (unsigned long long) ru.ru_inblock,
1735 (unsigned long long) ru.ru_oublock,
1736 (unsigned long long) ru.ru_nvcsw,
1737 (unsigned long long) ru.ru_nivcsw);
1738 }
1739 }
1740 else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1741#endif
1742 if ((GNUNET_SYSERR ==
1743 (ret = GNUNET_process_wait (pos->proc,
1744 false,
1745 &statusType,
1746 &statusCode))) ||
1747 (ret == GNUNET_NO) ||
1748 (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1749 (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1750 (statusType == GNUNET_OS_PROCESS_RUNNING))
1751 continue;
1752
1753 if (statusType == GNUNET_OS_PROCESS_EXITED)
1754 {
1755 statstr = _ (/* process termination method */ "exit");
1756 statcode = statusCode;
1757 }
1758 else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1759 {
1760 statstr = _ (/* process termination method */ "signal");
1761 statcode = statusCode;
1762 }
1763 else
1764 {
1765 statstr = _ (/* process termination method */ "unknown");
1766 statcode = 0;
1767 }
1768 if (0 != pos->killed_at.abs_value_us)
1769 {
1771 _ ("Service `%s' took %s to terminate\n"),
1772 pos->name,
1775 GNUNET_YES));
1776 }
1778 pos->proc = NULL;
1779 broadcast_status (pos->name,
1781 NULL);
1782 if (NULL != pos->killing_client)
1783 {
1785 pos->name,
1788 pos->killing_client = NULL;
1790 }
1791 if (GNUNET_YES != in_shutdown)
1792 {
1793 pos->last_exit_status = statcode;
1794 if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1795 {
1796 /* process terminated normally, allow restart at any time */
1797 pos->restart_at.abs_value_us = 0;
1798 GNUNET_log (
1800 _ ("Service `%s' terminated normally, will restart at any time\n"),
1801 pos->name);
1802 /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1803 for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1804 {
1805 GNUNET_break (NULL == sli->accept_task);
1806 sli->accept_task =
1808 sli->listen_socket,
1810 sli);
1811 }
1812 }
1813 else
1814 {
1815 GNUNET_log (
1817 _ ("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1818 pos->name,
1819 statstr,
1820 statcode,
1822 {
1823 /* Reduce backoff based on runtime of the process,
1824 so that there is a cool-down if a process actually
1825 runs for a while. */
1826 struct GNUNET_TIME_Relative runtime;
1827 unsigned int minutes;
1828
1830 minutes =
1831 runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1832 if (minutes > 31)
1834 else
1835 pos->backoff.rel_value_us >>= minutes;
1836 }
1837 /* schedule restart */
1840 if (NULL != child_restart_task)
1845 NULL);
1846 }
1847 }
1848 else
1849 {
1850 free_service (pos);
1851 }
1852 }
1855 pr,
1857 NULL);
1858 if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1859 do_shutdown ();
1860 else if (GNUNET_YES == in_shutdown)
1862 "Delaying shutdown after child's death, still have %u children\n",
1864}
1865
1866
1871static void
1873{
1874 static char c;
1875 int old_errno = errno; /* back-up errno */
1876
1877 GNUNET_break (
1878 1 ==
1881 ,
1882 &c,
1883 sizeof(c)));
1884 errno = old_errno; /* restore errno */
1885}
1886
1887
1896static void
1897setup_service (void *cls,
1898 const char *section)
1899{
1900 struct ServiceList *sl;
1901 char *binary;
1902 char *config;
1903 struct stat sbuf;
1904 struct sockaddr **addrs;
1905 socklen_t *addr_lens;
1906 int ret;
1907
1908 (void) cls;
1909 if (0 == strcasecmp (section, "arm"))
1910 return;
1911 if (GNUNET_OK !=
1913 section,
1914 "BINARY",
1915 &binary))
1916 {
1917 /* not a service section */
1918 return;
1919 }
1920 if (GNUNET_YES ==
1922 section,
1923 "RUN_PER_USER"))
1924 {
1925 if (GNUNET_NO == start_user)
1926 {
1927 GNUNET_free (binary);
1928 return; /* user service, and we don't deal with those */
1929 }
1930 }
1931 else
1932 {
1933 if (GNUNET_NO == start_system)
1934 {
1935 GNUNET_free (binary);
1936 return; /* system service, and we don't deal with those */
1937 }
1938 }
1939 sl = find_service (section);
1940 if (NULL != sl)
1941 {
1942 /* got the same section twice!? */
1943 GNUNET_break (0);
1944 GNUNET_free (binary);
1945 return;
1946 }
1947 config = NULL;
1948 if (((GNUNET_OK !=
1950 section,
1951 "CONFIG",
1952 &config)) &&
1953 (GNUNET_OK !=
1955 "PATHS",
1956 "DEFAULTCONFIG",
1957 &config))) ||
1958 (0 != stat (config,
1959 &sbuf)))
1960 {
1961 if (NULL != config)
1962 {
1964 section,
1965 "CONFIG",
1966 strerror (errno));
1968 config = NULL;
1969 }
1970 }
1971 sl = GNUNET_new (struct ServiceList);
1972 sl->name = GNUNET_strdup (section);
1973 sl->binary = binary;
1974 sl->config = config;
1977 sl->pipe_control =
1978 (GNUNET_YES ==
1980 section,
1981 "PIPECONTROL"));
1984 sl);
1985 if (GNUNET_YES ==
1987 section,
1988 "IMMEDIATE_START"))
1989 {
1990 sl->force_start = GNUNET_YES;
1991 if (GNUNET_YES ==
1993 section,
1994 "NOARMBIND"))
1995 return;
1996 }
1997 else
1998 {
1999 if (GNUNET_YES !=
2001 section,
2002 "START_ON_DEMAND"))
2003 return;
2004 }
2005 if (0 >= (ret = get_server_addresses (section,
2006 cfg,
2007 &addrs,
2008 &addr_lens)))
2009 return;
2010 /* this will free (or capture) addrs[i] */
2011 for (unsigned int i = 0; i < (unsigned int) ret; i++)
2012 create_listen_socket (addrs[i], addr_lens[i], sl);
2013 GNUNET_free (addrs);
2014 GNUNET_free (addr_lens);
2015}
2016
2017
2026static void *
2028 struct GNUNET_SERVICE_Client *client,
2029 struct GNUNET_MQ_Handle *mq)
2030{
2031 /* All clients are considered to be of the "monitor" kind
2032 * (that is, they don't affect ARM shutdown).
2033 */
2034 (void) cls;
2035 (void) mq;
2037 return client;
2038}
2039
2040
2048static void
2050 struct GNUNET_SERVICE_Client *client,
2051 void *app_ctx)
2052{
2053 (void) cls;
2054 GNUNET_assert (client == app_ctx);
2055 for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2056 if (sl->killing_client == client)
2057 sl->killing_client = NULL;
2058}
2059
2060
2069static void
2071 const struct GNUNET_MessageHeader *message)
2072{
2073 struct GNUNET_SERVICE_Client *client = cls;
2074
2075 (void) message;
2076 /* FIXME: might want to start by letting monitor know about
2077 services that are already running */
2078 /* Removal is handled by the server implementation, internally. */
2081 broadcast_status ("arm",
2083 client);
2085}
2086
2087
2095static void
2096run (void *cls,
2097 const struct GNUNET_CONFIGURATION_Handle *c,
2098 struct GNUNET_SERVICE_Handle *serv)
2099{
2100 struct ServiceList *sl;
2101 enum GNUNET_GenericReturnValue ret1;
2102 enum GNUNET_GenericReturnValue ret2;
2103
2104 (void) cls;
2105 cfg = c;
2106 service = serv;
2108 NULL);
2114 NULL);
2115#if HAVE_WAIT4
2116 if (GNUNET_OK ==
2118 "ARM",
2119 "RESOURCE_DIAGNOSTICS",
2120 &wait_filename))
2121 {
2122 wait_file = fopen (wait_filename, "w");
2123 if (NULL == wait_file)
2124 {
2126 "fopen",
2127 wait_filename);
2128 }
2129 }
2130#endif
2131 if (GNUNET_OK !=
2133 "ARM",
2134 "GLOBAL_PREFIX",
2137 else
2140 if (GNUNET_OK !=
2142 "ARM",
2143 "GLOBAL_POSTFIX",
2144 &final_option))
2146 else
2148 final_option);
2150 "ARM",
2151 "START_SYSTEM_SERVICES");
2153 "ARM",
2154 "START_USER_SERVICES");
2155 if ( (GNUNET_SYSERR == ret1) ||
2156 (GNUNET_SYSERR == ret2) )
2157 {
2158 /* invalid option */
2159 GNUNET_break (0);
2161 global_ret = 1;
2162 return;
2163 }
2165 "ARM",
2166 "START_SYSTEM_SERVICES"))
2167 ret1 = GNUNET_SYSERR;
2169 "ARM",
2170 "START_USER_SERVICES"))
2171 ret2 = GNUNET_SYSERR;
2172 start_system = (GNUNET_YES == ret1) ||
2173 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2174 start_user = (GNUNET_YES == ret2) ||
2175 ( (GNUNET_SYSERR == ret1) && (GNUNET_SYSERR == ret2) );
2176 if ( (GNUNET_NO == start_user) &&
2177 (GNUNET_NO == start_system) )
2178 {
2179 GNUNET_log (
2181 "Please enable either START_USER_SERVICES or START_SYSTEM_SERVICES\n");
2183 global_ret = 1;
2184 return;
2185 }
2188 NULL);
2189
2190 /* start default services... */
2191 for (sl = running_head; NULL != sl; sl = sl->next)
2192 if (GNUNET_YES == sl->force_start)
2193 start_process (sl, NULL, 0);
2195}
2196
2197
2205int
2206main (int argc, char *const *argv)
2207{
2212 struct GNUNET_ARM_Message,
2213 NULL),
2216 struct GNUNET_ARM_Message,
2217 NULL),
2220 struct GNUNET_MessageHeader,
2221 NULL),
2224 struct GNUNET_ARM_Message,
2225 NULL),
2228 struct GNUNET_MessageHeader,
2229 NULL),
2231 };
2232
2234 GNUNET_assert (NULL != sigpipe);
2235 shc_chld =
2238 if (0 !=
2240 argc,
2241 argv,
2242 "arm",
2245 &run,
2248 NULL,
2249 handlers))
2250 global_ret = 2;
2251#if HAVE_WAIT4
2252 if (NULL != wait_file)
2253 {
2254 fclose (wait_file);
2255 wait_file = NULL;
2256 }
2257 if (NULL != wait_filename)
2258 {
2259 GNUNET_free (wait_filename);
2260 wait_filename = NULL;
2261 }
2262#endif
2264 shc_chld = NULL;
2266 sigpipe = NULL;
2267 return global_ret;
2268}
2269
2270
2271#if defined(__linux__) && defined(__GLIBC__)
2272#include <malloc.h>
2273
2274void __attribute__ ((constructor))
2275GNUNET_ARM_memory_init (void);
2276
2280void __attribute__ ((constructor))
2281GNUNET_ARM_memory_init (void)
2282{
2283 mallopt (M_TRIM_THRESHOLD, 4 * 1024);
2284 mallopt (M_TOP_PAD, 1 * 1024);
2285 malloc_trim (0);
2286}
2287
2288
2289#endif
2290
2291
2292/* 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:1703
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:1524
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition disk.c:1671
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:1000
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:832
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:651
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:805
const struct GNUNET_OS_ProjectData * GNUNET_OS_project_data_gnunet(void)
Return default project data used by 'libgnunetutil' for GNUnet.
#define GNUNET_process_option_inherit_lsock(lsock)
Pass listen socket to child systemd-style.
enum GNUNET_GenericReturnValue GNUNET_process_run_command_va(struct GNUNET_Process *p, const char *filename,...)
Set the command and start a process.
Definition os_process.c:903
enum GNUNET_GenericReturnValue GNUNET_process_run_command(struct GNUNET_Process *p, const char *command)
Set the command and start a process.
Definition os_process.c:921
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:363
#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:356
enum GNUNET_GenericReturnValue GNUNET_process_kill(struct GNUNET_Process *proc, int sig)
Sends a signal to the process.
Definition os_process.c:307
struct GNUNET_Process * GNUNET_process_create(enum GNUNET_OS_InheritStdioFlags std_inheritance)
Create a process handle.
Definition os_process.c:462
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:2512
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:2022
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition service.c:2528
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition service.c:2538
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition service.c:2545
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition service.c:2434
@ 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