GNUnet  0.10.x
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
39 
42 static char *wait_filename;
43 
47 static FILE *wait_file;
48 #endif
49 
50 
56 #define MAX_NOTIFY_QUEUE 1024
57 
58 
62 struct ServiceList;
63 
64 
73 
78 
82  struct sockaddr *service_addr;
83 
87  struct ServiceList *sl;
88 
92  socklen_t service_addr_len;
93 
98 
103 };
104 
105 
109 struct ServiceList {
113  struct ServiceList *next;
114 
118  struct ServiceList *prev;
119 
124 
129 
133  char *name;
134 
138  char *binary;
139 
143  char *config;
144 
150 
155 
160 
165 
169  struct GNUNET_TIME_Absolute restart_at;
170 
175  struct GNUNET_TIME_Absolute killed_at;
176 
183 
189 };
190 
194 static struct ServiceList *running_head;
195 
199 static struct ServiceList *running_tail;
200 
204 static const struct GNUNET_CONFIGURATION_Handle *cfg;
205 
209 static char *prefix_command;
210 
214 static char *final_option;
215 
220 
226 
231 
235 static int in_shutdown;
236 
240 static int global_ret;
241 
245 static int start_user = GNUNET_YES;
246 
251 
263 
268 
269 
280 static void
281 add_unixpath(struct sockaddr **saddrs,
282  socklen_t *saddrlens,
283  const char *unixpath,
284  int abstract)
285 {
286 #ifdef AF_UNIX
287  struct sockaddr_un *un;
288 
289  un = GNUNET_new(struct sockaddr_un);
290  un->sun_family = AF_UNIX;
291  GNUNET_strlcpy(un->sun_path, unixpath, sizeof(un->sun_path));
292 #ifdef LINUX
293  if (GNUNET_YES == abstract)
294  un->sun_path[0] = '\0';
295 #endif
296 #if HAVE_SOCKADDR_UN_SUN_LEN
297  un->sun_len = (u_char)sizeof(struct sockaddr_un);
298 #endif
299  *saddrs = (struct sockaddr *)un;
300  *saddrlens = sizeof(struct sockaddr_un);
301 #else
302  /* this function should never be called
303  * unless AF_UNIX is defined! */
304  GNUNET_assert(0);
305 #endif
306 }
307 
308 
329 static int
331  const struct GNUNET_CONFIGURATION_Handle *cfg,
332  struct sockaddr ***addrs,
333  socklen_t **addr_lens)
334 {
335  int disablev6;
336  struct GNUNET_NETWORK_Handle *desc;
337  unsigned long long port;
338  char *unixpath;
339  struct addrinfo hints;
340  struct addrinfo *res;
341  struct addrinfo *pos;
342  struct addrinfo *next;
343  unsigned int i;
344  int resi;
345  int ret;
346  int abstract;
347  struct sockaddr **saddrs;
348  socklen_t *saddrlens;
349  char *hostname;
350 
351  *addrs = NULL;
352  *addr_lens = NULL;
353  desc = NULL;
354  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "DISABLEV6"))
355  {
356  if (GNUNET_SYSERR ==
357  (disablev6 = GNUNET_CONFIGURATION_get_value_yesno(cfg,
358  service_name,
359  "DISABLEV6")))
360  return GNUNET_SYSERR;
361  }
362  else
363  disablev6 = GNUNET_NO;
364 
365  if (!disablev6)
366  {
367  /* probe IPv6 support */
368  desc = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
369  if (NULL == desc)
370  {
371  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
372  (EACCES == errno))
373  {
375  return GNUNET_SYSERR;
376  }
378  _(
379  "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
380  service_name,
381  strerror(errno));
382  disablev6 = GNUNET_YES;
383  }
384  else
385  {
387  desc = NULL;
388  }
389  }
390 
391  port = 0;
392  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "PORT"))
393  {
395  service_name,
396  "PORT",
397  &port))
398  {
400  _("Require valid port number for service `%s' in configuration!\n"),
401  service_name);
402  }
403  if (port > 65535)
404  {
406  _("Require valid port number for service `%s' in configuration!\n"),
407  service_name);
408  return GNUNET_SYSERR;
409  }
410  }
411 
412  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "BINDTO"))
413  {
416  service_name,
417  "BINDTO",
418  &hostname));
419  }
420  else
421  hostname = NULL;
422 
423  unixpath = NULL;
424  abstract = GNUNET_NO;
425 #ifdef AF_UNIX
426  if ((GNUNET_YES ==
427  GNUNET_CONFIGURATION_have_value(cfg, service_name, "UNIXPATH")) &&
429  service_name,
430  "UNIXPATH",
431  &unixpath)) &&
432  (0 < strlen(unixpath)))
433  {
434  /* probe UNIX support */
435  struct sockaddr_un s_un;
436 
437  if (strlen(unixpath) >= sizeof(s_un.sun_path))
438  {
440  _("UNIXPATH `%s' too long, maximum length is %llu\n"),
441  unixpath,
442  (unsigned long long)sizeof(s_un.sun_path));
443  unixpath = GNUNET_NETWORK_shorten_unixpath(unixpath);
444  LOG(GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath);
445  }
446 #ifdef LINUX
448  "TESTING",
449  "USE_ABSTRACT_SOCKETS");
450  if (GNUNET_SYSERR == abstract)
451  abstract = GNUNET_NO;
452 #endif
453  if ((GNUNET_YES != abstract) &&
456  }
457  if (NULL != unixpath)
458  {
459  desc = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_STREAM, 0);
460  if (NULL == desc)
461  {
462  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
463  (EACCES == errno))
464  {
466  GNUNET_free_non_null(hostname);
467  GNUNET_free(unixpath);
468  return GNUNET_SYSERR;
469  }
471  _(
472  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
473  service_name,
474  strerror(errno));
475  GNUNET_free(unixpath);
476  unixpath = NULL;
477  }
478  else
479  {
481  desc = NULL;
482  }
483  }
484 #endif
485 
486  if ((0 == port) && (NULL == unixpath))
487  {
489  service_name,
490  "START_ON_DEMAND"))
492  _(
493  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
494  service_name);
495  GNUNET_free_non_null(hostname);
496  return GNUNET_SYSERR;
497  }
498  if (0 == port)
499  {
500  saddrs = GNUNET_new_array(2, struct sockaddr *);
501  saddrlens = GNUNET_new_array(2, socklen_t);
502  add_unixpath(saddrs, saddrlens, unixpath, abstract);
503  GNUNET_free_non_null(unixpath);
504  GNUNET_free_non_null(hostname);
505  *addrs = saddrs;
506  *addr_lens = saddrlens;
507  return 1;
508  }
509 
510  if (NULL != hostname)
511  {
513  "Resolving `%s' since that is where `%s' will bind to.\n",
514  hostname,
515  service_name);
516  memset(&hints, 0, sizeof(struct addrinfo));
517  if (disablev6)
518  hints.ai_family = AF_INET;
519  hints.ai_protocol = IPPROTO_TCP;
520  if ((0 != (ret = getaddrinfo(hostname, NULL, &hints, &res))) ||
521  (NULL == res))
522  {
524  _("Failed to resolve `%s': %s\n"),
525  hostname,
526  gai_strerror(ret));
527  GNUNET_free(hostname);
528  GNUNET_free_non_null(unixpath);
529  return GNUNET_SYSERR;
530  }
531  next = res;
532  i = 0;
533  while (NULL != (pos = next))
534  {
535  next = pos->ai_next;
536  if ((disablev6) && (pos->ai_family == AF_INET6))
537  continue;
538  i++;
539  }
540  if (0 == i)
541  {
543  _("Failed to find %saddress for `%s'.\n"),
544  disablev6 ? "IPv4 " : "",
545  hostname);
546  freeaddrinfo(res);
547  GNUNET_free(hostname);
548  GNUNET_free_non_null(unixpath);
549  return GNUNET_SYSERR;
550  }
551  resi = i;
552  if (NULL != unixpath)
553  resi++;
554  saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
555  saddrlens = GNUNET_new_array(resi + 1, socklen_t);
556  i = 0;
557  if (NULL != unixpath)
558  {
559  add_unixpath(saddrs, saddrlens, unixpath, abstract);
560  i++;
561  }
562  next = res;
563  while (NULL != (pos = next))
564  {
565  next = pos->ai_next;
566  if ((disablev6) && (AF_INET6 == pos->ai_family))
567  continue;
568  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
569  continue; /* not TCP */
570  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
571  continue; /* huh? */
573  "Service `%s' will bind to `%s'\n",
574  service_name,
575  GNUNET_a2s(pos->ai_addr, pos->ai_addrlen));
576  if (AF_INET == pos->ai_family)
577  {
578  GNUNET_assert(sizeof(struct sockaddr_in) == pos->ai_addrlen);
579  saddrlens[i] = pos->ai_addrlen;
580  saddrs[i] = GNUNET_malloc(saddrlens[i]);
581  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
582  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
583  }
584  else
585  {
586  GNUNET_assert(AF_INET6 == pos->ai_family);
587  GNUNET_assert(sizeof(struct sockaddr_in6) == pos->ai_addrlen);
588  saddrlens[i] = pos->ai_addrlen;
589  saddrs[i] = GNUNET_malloc(saddrlens[i]);
590  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
591  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
592  }
593  i++;
594  }
595  GNUNET_free(hostname);
596  freeaddrinfo(res);
597  resi = i;
598  }
599  else
600  {
601  /* will bind against everything, just set port */
602  if (disablev6)
603  {
604  /* V4-only */
605  resi = 1;
606  if (NULL != unixpath)
607  resi++;
608  i = 0;
609  saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
610  saddrlens = GNUNET_new_array(resi + 1, socklen_t);
611  if (NULL != unixpath)
612  {
613  add_unixpath(saddrs, saddrlens, unixpath, abstract);
614  i++;
615  }
616  saddrlens[i] = sizeof(struct sockaddr_in);
617  saddrs[i] = GNUNET_malloc(saddrlens[i]);
618 #if HAVE_SOCKADDR_IN_SIN_LEN
619  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[i];
620 #endif
621  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
622  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
623  }
624  else
625  {
626  /* dual stack */
627  resi = 2;
628  if (NULL != unixpath)
629  resi++;
630  saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
631  saddrlens = GNUNET_new_array(resi + 1, socklen_t);
632  i = 0;
633  if (NULL != unixpath)
634  {
635  add_unixpath(saddrs, saddrlens, unixpath, abstract);
636  i++;
637  }
638  saddrlens[i] = sizeof(struct sockaddr_in6);
639  saddrs[i] = GNUNET_malloc(saddrlens[i]);
640 #if HAVE_SOCKADDR_IN_SIN_LEN
641  ((struct sockaddr_in6 *)saddrs[i])->sin6_len = saddrlens[0];
642 #endif
643  ((struct sockaddr_in6 *)saddrs[i])->sin6_family = AF_INET6;
644  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
645  i++;
646  saddrlens[i] = sizeof(struct sockaddr_in);
647  saddrs[i] = GNUNET_malloc(saddrlens[i]);
648 #if HAVE_SOCKADDR_IN_SIN_LEN
649  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[1];
650 #endif
651  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
652  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
653  }
654  }
655  GNUNET_free_non_null(unixpath);
656  *addrs = saddrs;
657  *addr_lens = saddrlens;
658  return resi;
659 }
660 
661 
672 static void
674  const char *name,
675  uint64_t request_id,
677 {
678  struct GNUNET_MQ_Envelope *env;
680 
681  (void)name;
683  msg->result = htonl(result);
684  msg->arm_msg.request_id = GNUNET_htonll(request_id);
686 }
687 
688 
697 static void
698 broadcast_status(const char *name,
701 {
702  struct GNUNET_MQ_Envelope *env;
704  size_t namelen;
705 
707  "Sending status %u of service `%s' to client\n",
708  (unsigned int)status,
709  name);
710  namelen = strlen(name) + 1;
712  msg->status = htonl((uint32_t)(status));
713  GNUNET_memcpy((char *)&msg[1], name, namelen);
714  if (NULL == unicast)
715  {
716  if (NULL != notifier)
718  &msg->header,
719  GNUNET_YES);
720  GNUNET_MQ_discard(env);
721  }
722  else
723  {
725  }
726 }
727 
728 
737 static void
739  struct GNUNET_SERVICE_Client *client,
740  uint64_t request_id)
741 {
742  char *loprefix;
743  char *options;
744  int use_debug;
745  int is_simple_service;
746  struct ServiceListeningInfo *sli;
747  SOCKTYPE *lsocks;
748  unsigned int ls;
749  char *binary;
750  char *quotedbinary;
751 
752  /* calculate listen socket list */
753  lsocks = NULL;
754  ls = 0;
755  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
756  {
757  GNUNET_array_append(lsocks,
758  ls,
760  if (NULL != sli->accept_task)
761  {
763  sli->accept_task = NULL;
764  }
765  }
766 
767  GNUNET_array_append(lsocks, ls, -1);
768 
769  /* obtain configuration */
771  sl->name,
772  "PREFIX",
773  &loprefix))
774  loprefix = GNUNET_strdup(prefix_command);
775  else
776  loprefix = GNUNET_CONFIGURATION_expand_dollar(cfg, loprefix);
778  sl->name,
779  "OPTIONS",
780  &options))
781  options = NULL;
782  else
783  options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
784  {
785  char *new_options;
786  char *optpos;
787  char *fin_options;
788 
789  fin_options = GNUNET_strdup(final_option);
790  /* replace '{}' with service name */
791  while (NULL != (optpos = strstr(fin_options, "{}")))
792  {
793  /* terminate string at opening parenthesis */
794  *optpos = 0;
795  GNUNET_asprintf(&new_options,
796  "%s%s%s",
797  fin_options,
798  sl->name,
799  optpos + 2);
800  GNUNET_free(fin_options);
801  fin_options = new_options;
802  }
803  if (NULL != options)
804  {
805  /* combine "fin_options" with "options" */
806  optpos = options;
807  GNUNET_asprintf(&options, "%s %s", fin_options, optpos);
808  GNUNET_free(fin_options);
809  GNUNET_free(optpos);
810  }
811  else
812  {
813  /* only have "fin_options", use that */
814  options = fin_options;
815  }
816  }
817  options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
818  use_debug = GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "DEBUG");
819  {
820  const char *service_type = NULL;
821  const char *choices[] = { "GNUNET", "SIMPLE", NULL };
822 
823  is_simple_service = GNUNET_NO;
825  sl->name,
826  "TYPE",
827  choices,
828  &service_type)) &&
829  (0 == strcasecmp(service_type, "SIMPLE")))
830  is_simple_service = GNUNET_YES;
831  }
832 
833  GNUNET_assert(NULL == sl->proc);
834  if (GNUNET_YES == is_simple_service)
835  {
836  /* A simple service will receive no GNUnet specific
837  command line options. */
838  binary = GNUNET_strdup(sl->binary);
839  binary = GNUNET_CONFIGURATION_expand_dollar(cfg, binary);
840  GNUNET_asprintf(&quotedbinary, "\"%s\"", sl->binary);
842  "Starting simple service `%s' using binary `%s'\n",
843  sl->name,
844  sl->binary);
845  /* FIXME: dollar expansion should only be done outside
846  * of ''-quoted strings, escaping should be considered. */
847  if (NULL != options)
848  options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
851  lsocks,
852  loprefix,
853  quotedbinary,
854  options,
855  NULL);
856  }
857  else
858  {
859  /* actually start process */
861  "Starting service `%s' using binary `%s' and configuration `%s'\n",
862  sl->name,
863  sl->binary,
864  sl->config);
866  GNUNET_asprintf(&quotedbinary, "\"%s\"", binary);
867 
868  if (GNUNET_YES == use_debug)
869  {
870  if (NULL == sl->config)
873  lsocks,
874  loprefix,
875  quotedbinary,
876  "-L",
877  "DEBUG",
878  options,
879  NULL);
880  else
883  lsocks,
884  loprefix,
885  quotedbinary,
886  "-c",
887  sl->config,
888  "-L",
889  "DEBUG",
890  options,
891  NULL);
892  }
893  else
894  {
895  if (NULL == sl->config)
898  lsocks,
899  loprefix,
900  quotedbinary,
901  options,
902  NULL);
903  else
906  lsocks,
907  loprefix,
908  quotedbinary,
909  "-c",
910  sl->config,
911  options,
912  NULL);
913  }
914  }
915  GNUNET_free(binary);
916  GNUNET_free(quotedbinary);
917  if (NULL == sl->proc)
918  {
920  _("Failed to start service `%s'\n"),
921  sl->name);
922  if (client)
923  signal_result(client,
924  sl->name,
925  request_id,
927  }
928  else
929  {
931  _("Starting service `%s'\n"),
932  sl->name);
934  if (client)
935  signal_result(client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING);
936  }
937  /* clean up */
938  GNUNET_free(loprefix);
939  GNUNET_free(options);
940  GNUNET_array_grow(lsocks, ls, 0);
941 }
942 
943 
951 static struct ServiceList *
952 find_service(const char *name)
953 {
954  struct ServiceList *sl;
955 
956  sl = running_head;
957  while (sl != NULL)
958  {
959  if (0 == strcasecmp(sl->name, name))
960  return sl;
961  sl = sl->next;
962  }
963  return NULL;
964 }
965 
966 
973 static void
975 {
976  struct ServiceListeningInfo *sli = cls;
977  struct ServiceList *sl = sli->sl;
978 
979  sli->accept_task = NULL;
981  start_process(sl, NULL, 0);
982 }
983 
984 
993 static void
994 create_listen_socket(struct sockaddr *sa,
995  socklen_t addr_len,
996  struct ServiceList *sl)
997 {
998  static int on = 1;
999  struct GNUNET_NETWORK_Handle *sock;
1000  struct ServiceListeningInfo *sli;
1001 
1002  int match_uid;
1003  int match_gid;
1004 
1005  switch (sa->sa_family)
1006  {
1007  case AF_INET:
1008  sock = GNUNET_NETWORK_socket_create(PF_INET, SOCK_STREAM, 0);
1009  break;
1010 
1011  case AF_INET6:
1012  sock = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
1013  break;
1014 
1015  case AF_UNIX:
1016  if (0 == strcmp(GNUNET_a2s(sa, addr_len),
1017  "@")) /* Do not bind to blank UNIX path! */
1018  return;
1019  sock = GNUNET_NETWORK_socket_create(PF_UNIX, SOCK_STREAM, 0);
1020  break;
1021 
1022  default:
1023  GNUNET_break(0);
1024  sock = NULL;
1025  errno = EAFNOSUPPORT;
1026  break;
1027  }
1028  if (NULL == sock)
1029  {
1031  _("Unable to create socket for service `%s': %s\n"),
1032  sl->name,
1033  strerror(errno));
1034  GNUNET_free(sa);
1035  return;
1036  }
1038  SOL_SOCKET,
1039  SO_REUSEADDR,
1040  &on,
1041  sizeof(on)))
1043  "setsockopt");
1044 #ifdef IPV6_V6ONLY
1045  if ((sa->sa_family == AF_INET6) &&
1047  IPPROTO_IPV6,
1048  IPV6_V6ONLY,
1049  &on,
1050  sizeof(on))))
1052  "setsockopt");
1053 #endif
1054  if (AF_UNIX == sa->sa_family)
1055  GNUNET_NETWORK_unix_precheck((struct sockaddr_un *)sa);
1056  if (GNUNET_OK !=
1057  GNUNET_NETWORK_socket_bind(sock, (const struct sockaddr *)sa, addr_len))
1058  {
1059  GNUNET_log(
1061  _(
1062  "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1063  sl->name,
1064  GNUNET_a2s(sa, addr_len),
1065  strerror(errno));
1067  GNUNET_free(sa);
1068  return;
1069  }
1070  if ((AF_UNIX == sa->sa_family)
1071 #ifdef LINUX
1072  /* Permission settings are not required when abstract sockets are used */
1073  && ('\0' != ((const struct sockaddr_un *)sa)->sun_path[0])
1074 #endif
1075  )
1076  {
1077  match_uid =
1078  GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "UNIX_MATCH_UID");
1079  match_gid =
1080  GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "UNIX_MATCH_GID");
1081  GNUNET_DISK_fix_permissions(((const struct sockaddr_un *)sa)->sun_path,
1082  match_uid,
1083  match_gid);
1084  }
1085  if (GNUNET_OK != GNUNET_NETWORK_socket_listen(sock, 5))
1086  {
1089  GNUNET_free(sa);
1090  return;
1091  }
1093  _("ARM now monitors connections to service `%s' at `%s'\n"),
1094  sl->name,
1095  GNUNET_a2s(sa, addr_len));
1096  sli = GNUNET_new(struct ServiceListeningInfo);
1097  sli->service_addr = sa;
1098  sli->service_addr_len = addr_len;
1099  sli->listen_socket = sock;
1100  sli->sl = sl;
1101  sli->accept_task =
1103  sock,
1105  sli);
1107 }
1108 
1109 
1116 static void
1118 {
1120  GNUNET_CONTAINER_DLL_remove(running_head, running_tail, sl);
1121  GNUNET_assert(NULL == sl->listen_head);
1124  GNUNET_free(sl->name);
1125  GNUNET_free(sl);
1126 }
1127 
1128 
1137 static int
1138 check_start(void *cls, const struct GNUNET_ARM_Message *amsg)
1139 {
1140  (void)cls;
1142  return GNUNET_OK;
1143 }
1144 
1145 
1152 static void
1153 handle_start(void *cls, const struct GNUNET_ARM_Message *amsg)
1154 {
1155  struct GNUNET_SERVICE_Client *client = cls;
1156  const char *servicename;
1157  struct ServiceList *sl;
1158  uint64_t request_id;
1159 
1160  request_id = GNUNET_ntohll(amsg->request_id);
1161  servicename = (const char *)&amsg[1];
1163  if (GNUNET_YES == in_shutdown)
1164  {
1165  signal_result(client,
1166  servicename,
1167  request_id,
1169  return;
1170  }
1171  sl = find_service(servicename);
1172  if (NULL == sl)
1173  {
1174  signal_result(client,
1175  servicename,
1176  request_id,
1178  return;
1179  }
1180  sl->force_start = GNUNET_YES;
1181  if (NULL != sl->proc)
1182  {
1183  signal_result(client,
1184  servicename,
1185  request_id,
1187  return;
1188  }
1189  start_process(sl, client, request_id);
1190 }
1191 
1192 
1198 static void
1200 {
1201  (void)cls;
1202  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1204 }
1205 
1206 
1215 static int
1216 check_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
1217 {
1218  (void)cls;
1220  return GNUNET_OK;
1221 }
1222 
1223 
1230 static void
1231 handle_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
1232 {
1233  struct GNUNET_SERVICE_Client *client = cls;
1234  struct ServiceList *sl;
1235  const char *servicename;
1236  uint64_t request_id;
1237 
1238  request_id = GNUNET_ntohll(amsg->request_id);
1239  servicename = (const char *)&amsg[1];
1241  _("Preparing to stop `%s'\n"),
1242  servicename);
1244  if (0 == strcasecmp(servicename, "arm"))
1245  {
1246  broadcast_status(servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1247  signal_result(client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1250  return;
1251  }
1252  sl = find_service(servicename);
1253  if (NULL == sl)
1254  {
1255  signal_result(client,
1256  servicename,
1257  request_id,
1259  return;
1260  }
1261  sl->force_start = GNUNET_NO;
1262  if (GNUNET_YES == in_shutdown)
1263  {
1264  /* shutdown in progress */
1265  signal_result(client,
1266  servicename,
1267  request_id,
1269  return;
1270  }
1271  if (NULL != sl->killing_client)
1272  {
1273  /* killing already in progress */
1274  signal_result(client,
1275  servicename,
1276  request_id,
1278  return;
1279  }
1280  if (NULL == sl->proc)
1281  {
1282  /* process is down */
1283  signal_result(client,
1284  servicename,
1285  request_id,
1287  return;
1288  }
1290  "Sending kill signal to service `%s', waiting for process to die.\n",
1291  servicename);
1292  broadcast_status(servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1293  /* no signal_start - only when it's STOPPED */
1297  sl->killing_client = client;
1298  sl->killing_client_request_id = request_id;
1299 }
1300 
1301 
1308 static void
1309 handle_list(void *cls, const struct GNUNET_ARM_Message *request)
1310 {
1311  struct GNUNET_SERVICE_Client *client = cls;
1312  struct GNUNET_MQ_Envelope *env;
1314  size_t string_list_size;
1315  struct ServiceList *sl;
1316  uint16_t count;
1317  char *pos;
1318 
1319  GNUNET_break(0 == ntohl(request->reserved));
1320  count = 0;
1321  string_list_size = 0;
1322 
1323  /* first count the running processes get their name's size */
1324  for (sl = running_head; NULL != sl; sl = sl->next)
1325  {
1326  if (NULL != sl->proc)
1327  {
1328  string_list_size += strlen(sl->name);
1329  string_list_size += strlen(sl->binary);
1330  string_list_size += 4;
1331  count++;
1332  }
1333  }
1334 
1335  env = GNUNET_MQ_msg_extra(msg,
1336  string_list_size,
1338  msg->arm_msg.request_id = request->request_id;
1339  msg->count = htons(count);
1340 
1341  pos = (char *)&msg[1];
1342  for (sl = running_head; NULL != sl; sl = sl->next)
1343  {
1344  if (NULL != sl->proc)
1345  {
1346  size_t s = strlen(sl->name) + strlen(sl->binary) + 4;
1347  GNUNET_snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
1348  pos += s;
1349  }
1350  }
1353 }
1354 
1355 
1362 static void
1363 handle_test(void *cls, const struct GNUNET_MessageHeader *message)
1364 {
1365  struct GNUNET_SERVICE_Client *client = cls;
1366  struct GNUNET_MQ_Envelope *env;
1367  struct GNUNET_MessageHeader *msg;
1368 
1369  (void)message;
1373 }
1374 
1375 
1380 static void
1382 {
1383  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1384  if (NULL != notifier)
1385  {
1387  notifier = NULL;
1388  }
1389  if (NULL != service)
1390  {
1391  GNUNET_SERVICE_shutdown(service);
1392  service = NULL;
1393  }
1394  if (NULL != child_death_task)
1395  {
1396  GNUNET_SCHEDULER_cancel(child_death_task);
1397  child_death_task = NULL;
1398  }
1399 }
1400 
1401 
1408 static unsigned int
1409 list_count(struct ServiceList *running_head)
1410 {
1411  struct ServiceList *i;
1412  unsigned int res;
1413 
1414  for (res = 0, i = running_head; NULL != i; i = i->next, res++)
1416  return res;
1417 }
1418 
1419 
1425 static void
1426 shutdown_task(void *cls)
1427 {
1428  struct ServiceList *pos;
1429  struct ServiceList *nxt;
1430  struct ServiceListeningInfo *sli;
1431 
1432  (void)cls;
1433  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1434  if (NULL != child_restart_task)
1435  {
1436  GNUNET_SCHEDULER_cancel(child_restart_task);
1437  child_restart_task = NULL;
1438  }
1440  /* first, stop listening */
1441  for (pos = running_head; NULL != pos; pos = pos->next)
1442  {
1443  while (NULL != (sli = pos->listen_head))
1444  {
1446  if (NULL != sli->accept_task)
1447  {
1449  sli->accept_task = NULL;
1450  }
1453  GNUNET_free(sli->service_addr);
1454  GNUNET_free(sli);
1455  }
1456  }
1457  /* then, shutdown all existing service processes */
1458  nxt = running_head;
1459  while (NULL != (pos = nxt))
1460  {
1461  nxt = pos->next;
1462  if (NULL != pos->proc)
1463  {
1464  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1468  }
1469  else
1470  {
1471  free_service(pos);
1472  }
1473  }
1474  /* finally, should all service processes be already gone, terminate for real */
1475  if (NULL == running_head)
1476  do_shutdown();
1477  else
1479  "Delaying shutdown, have %u childs still running\n",
1480  list_count(running_head));
1481 }
1482 
1483 
1489 static void
1491 
1492 {
1493  struct ServiceList *sl;
1494  struct GNUNET_TIME_Relative lowestRestartDelay;
1495  struct ServiceListeningInfo *sli;
1496 
1497  (void)cls;
1498  child_restart_task = NULL;
1500  lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1501 
1502  /* check for services that need to be restarted due to
1503  * configuration changes or because the last restart failed */
1504  for (sl = running_head; NULL != sl; sl = sl->next)
1505  {
1506  if (NULL != sl->proc)
1507  continue;
1508  /* service is currently not running */
1510  {
1511  /* restart is now allowed */
1512  if (sl->force_start)
1513  {
1514  /* process should run by default, start immediately */
1516  _("Restarting service `%s'.\n"),
1517  sl->name);
1518  start_process(sl, NULL, 0);
1519  }
1520  else
1521  {
1522  /* process is run on-demand, ensure it is re-started if there is demand */
1523  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1524  if (NULL == sli->accept_task)
1525  {
1526  /* accept was actually paused, so start it again */
1527  sli->accept_task =
1529  sli->listen_socket,
1531  sli);
1532  }
1533  }
1534  }
1535  else
1536  {
1537  /* update calculation for earliest time to reactivate a service */
1538  lowestRestartDelay =
1539  GNUNET_TIME_relative_min(lowestRestartDelay,
1541  sl->restart_at));
1542  }
1543  }
1544  if (lowestRestartDelay.rel_value_us !=
1545  GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1546  {
1548  "Will restart process in %s\n",
1549  GNUNET_STRINGS_relative_time_to_string(lowestRestartDelay,
1550  GNUNET_YES));
1551  child_restart_task =
1552  GNUNET_SCHEDULER_add_delayed_with_priority(lowestRestartDelay,
1555  NULL);
1556  }
1557 }
1558 
1559 
1566 static void
1568 {
1569  struct ServiceList *pos;
1570  struct ServiceList *next;
1571  struct ServiceListeningInfo *sli;
1572  const char *statstr;
1573  int statcode;
1574  int ret;
1575  char c[16];
1576  enum GNUNET_OS_ProcessStatusType statusType;
1577  unsigned long statusCode;
1578  const struct GNUNET_DISK_FileHandle *pr;
1579 
1580  (void)cls;
1582  child_death_task = NULL;
1583  /* consume the signal */
1584  GNUNET_break(0 < GNUNET_DISK_file_read(pr, &c, sizeof(c)));
1585 
1586  /* check for services that died (WAITPID) */
1587  next = running_head;
1588  while (NULL != (pos = next))
1589  {
1590  next = pos->next;
1591 
1592  if (NULL == pos->proc)
1593  {
1594  if (GNUNET_YES == in_shutdown)
1595  free_service(pos);
1596  continue;
1597  }
1598 #if HAVE_WAIT4
1599  if (NULL != wait_file)
1600  {
1601  /* need to use 'wait4()' to obtain and log performance data */
1602  struct rusage ru;
1603  int status;
1604  pid_t pid;
1605 
1606  pid = GNUNET_OS_process_get_pid(pos->proc);
1607  ret = wait4(pid, &status, WNOHANG, &ru);
1608  if (ret <= 0)
1609  continue; /* no process done */
1610  if (WIFEXITED(status))
1611  {
1612  statusType = GNUNET_OS_PROCESS_EXITED;
1613  statusCode = WEXITSTATUS(status);
1614  }
1615  else if (WIFSIGNALED(status))
1616  {
1617  statusType = GNUNET_OS_PROCESS_SIGNALED;
1618  statusCode = WTERMSIG(status);
1619  }
1620  else if (WIFSTOPPED(status))
1621  {
1622  statusType = GNUNET_OS_PROCESS_SIGNALED;
1623  statusCode = WSTOPSIG(status);
1624  }
1625 #ifdef WIFCONTINUED
1626  else if (WIFCONTINUED(status))
1627  {
1628  statusType = GNUNET_OS_PROCESS_RUNNING;
1629  statusCode = 0;
1630  }
1631 #endif
1632  else
1633  {
1634  statusType = GNUNET_OS_PROCESS_UNKNOWN;
1635  statusCode = 0;
1636  }
1637  if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1638  (GNUNET_OS_PROCESS_SIGNALED == statusType))
1639  {
1640  double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1641  double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1642  fprintf(wait_file,
1643  "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1644  pos->binary,
1645  (unsigned int)pid,
1646  utime,
1647  stime,
1648  (unsigned long long)ru.ru_maxrss,
1649  (unsigned long long)ru.ru_inblock,
1650  (unsigned long long)ru.ru_oublock,
1651  (unsigned long long)ru.ru_nvcsw,
1652  (unsigned long long)ru.ru_nivcsw);
1653  }
1654  }
1655  else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1656 #endif
1657  if ((GNUNET_SYSERR == (ret = GNUNET_OS_process_status(pos->proc,
1658  &statusType,
1659  &statusCode))) ||
1660  (ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1661  (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1662  (statusType == GNUNET_OS_PROCESS_RUNNING))
1663  continue;
1664 
1665  if (statusType == GNUNET_OS_PROCESS_EXITED)
1666  {
1667  statstr = _(/* process termination method */ "exit");
1668  statcode = statusCode;
1669  }
1670  else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1671  {
1672  statstr = _(/* process termination method */ "signal");
1673  statcode = statusCode;
1674  }
1675  else
1676  {
1677  statstr = _(/* process termination method */ "unknown");
1678  statcode = 0;
1679  }
1680  if (0 != pos->killed_at.abs_value_us)
1681  {
1683  _("Service `%s' took %s to terminate\n"),
1684  pos->name,
1687  GNUNET_YES));
1688  }
1690  pos->proc = NULL;
1692  if (NULL != pos->killing_client)
1693  {
1695  pos->name,
1698  pos->killing_client = NULL;
1699  pos->killing_client_request_id = 0;
1700  }
1701  if (GNUNET_YES != in_shutdown)
1702  {
1703  if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1704  {
1705  /* process terminated normally, allow restart at any time */
1706  pos->restart_at.abs_value_us = 0;
1707  GNUNET_log(
1709  _("Service `%s' terminated normally, will restart at any time\n"),
1710  pos->name);
1711  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1712  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1713  {
1714  GNUNET_break(NULL == sli->accept_task);
1715  sli->accept_task =
1717  sli->listen_socket,
1719  sli);
1720  }
1721  }
1722  else
1723  {
1724  GNUNET_log(
1726  _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1727  pos->name,
1728  statstr,
1729  statcode,
1731  {
1732  /* Reduce backoff based on runtime of the process,
1733  so that there is a cool-down if a process actually
1734  runs for a while. */
1735  struct GNUNET_TIME_Relative runtime;
1736  unsigned int minutes;
1737 
1739  minutes =
1740  runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1741  if (minutes > 31)
1743  else
1744  pos->backoff.rel_value_us <<= minutes;
1745  }
1746  /* schedule restart */
1749  if (NULL != child_restart_task)
1750  GNUNET_SCHEDULER_cancel(child_restart_task);
1751  child_restart_task =
1754  NULL);
1755  }
1756  }
1757  else
1758  {
1759  free_service(pos);
1760  }
1761  }
1762  child_death_task =
1764  pr,
1766  NULL);
1767  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1768  do_shutdown();
1769  else if (GNUNET_YES == in_shutdown)
1771  "Delaying shutdown after child's death, still have %u children\n",
1772  list_count(running_head));
1773 }
1774 
1775 
1780 static void
1782 {
1783  static char c;
1784  int old_errno = errno; /* back-up errno */
1785 
1786  GNUNET_break(
1787  1 ==
1790  &c,
1791  sizeof(c)));
1792  errno = old_errno; /* restore errno */
1793 }
1794 
1795 
1804 static void
1805 setup_service(void *cls, const char *section)
1806 {
1807  struct ServiceList *sl;
1808  char *binary;
1809  char *config;
1810  struct stat sbuf;
1811  struct sockaddr **addrs;
1812  socklen_t *addr_lens;
1813  int ret;
1814 
1815  (void)cls;
1816  if (0 == strcasecmp(section, "arm"))
1817  return;
1818  if (GNUNET_OK !=
1819  GNUNET_CONFIGURATION_get_value_string(cfg, section, "BINARY", &binary))
1820  {
1821  /* not a service section */
1822  return;
1823  }
1824  if ((GNUNET_YES ==
1825  GNUNET_CONFIGURATION_have_value(cfg, section, "RUN_PER_USER")) &&
1826  (GNUNET_YES ==
1827  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "RUN_PER_USER")))
1828  {
1829  if (GNUNET_NO == start_user)
1830  {
1831  GNUNET_free(binary);
1832  return; /* user service, and we don't deal with those */
1833  }
1834  }
1835  else
1836  {
1837  if (GNUNET_NO == start_system)
1838  {
1839  GNUNET_free(binary);
1840  return; /* system service, and we don't deal with those */
1841  }
1842  }
1843  sl = find_service(section);
1844  if (NULL != sl)
1845  {
1846  /* got the same section twice!? */
1847  GNUNET_break(0);
1848  GNUNET_free(binary);
1849  return;
1850  }
1851  config = NULL;
1853  section,
1854  "CONFIG",
1855  &config)) &&
1857  "PATHS",
1858  "DEFAULTCONFIG",
1859  &config))) ||
1860  (0 != stat(config, &sbuf)))
1861  {
1862  if (NULL != config)
1863  {
1865  section,
1866  "CONFIG",
1867  strerror(errno));
1868  GNUNET_free(config);
1869  config = NULL;
1870  }
1871  }
1872  sl = GNUNET_new(struct ServiceList);
1873  sl->name = GNUNET_strdup(section);
1874  sl->binary = binary;
1875  sl->config = config;
1878  if (GNUNET_CONFIGURATION_have_value(cfg, section, "PIPECONTROL"))
1879  sl->pipe_control =
1880  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "PIPECONTROL");
1881  GNUNET_CONTAINER_DLL_insert(running_head, running_tail, sl);
1882  if (GNUNET_YES ==
1883  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "IMMEDIATE_START"))
1884  {
1885  sl->force_start = GNUNET_YES;
1886  if (GNUNET_YES ==
1887  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "NOARMBIND"))
1888  return;
1889  }
1890  else
1891  {
1892  if (GNUNET_YES !=
1893  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "START_ON_DEMAND"))
1894  return;
1895  }
1896  if (0 >= (ret = get_server_addresses(section, cfg, &addrs, &addr_lens)))
1897  return;
1898  /* this will free (or capture) addrs[i] */
1899  for (unsigned int i = 0; i < (unsigned int)ret; i++)
1900  create_listen_socket(addrs[i], addr_lens[i], sl);
1901  GNUNET_free(addrs);
1902  GNUNET_free(addr_lens);
1903 }
1904 
1905 
1914 static void *
1916  struct GNUNET_SERVICE_Client *client,
1917  struct GNUNET_MQ_Handle *mq)
1918 {
1919  /* All clients are considered to be of the "monitor" kind
1920  * (that is, they don't affect ARM shutdown).
1921  */
1922  (void)cls;
1923  (void)mq;
1925  return client;
1926 }
1927 
1928 
1936 static void
1938  struct GNUNET_SERVICE_Client *client,
1939  void *app_ctx)
1940 {
1941  (void)cls;
1942  GNUNET_assert(client == app_ctx);
1943  for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
1944  if (sl->killing_client == client)
1945  sl->killing_client = NULL;
1946 }
1947 
1948 
1957 static void
1958 handle_monitor(void *cls, const struct GNUNET_MessageHeader *message)
1959 {
1960  struct GNUNET_SERVICE_Client *client = cls;
1961 
1962  (void)message;
1963  /* FIXME: might want to start by letting monitor know about
1964  services that are already running */
1965  /* Removal is handled by the server implementation, internally. */
1970 }
1971 
1972 
1980 static void
1981 run(void *cls,
1982  const struct GNUNET_CONFIGURATION_Handle *c,
1983  struct GNUNET_SERVICE_Handle *serv)
1984 {
1985  struct ServiceList *sl;
1986 
1987  (void)cls;
1988  cfg = c;
1989  service = serv;
1991  child_death_task = GNUNET_SCHEDULER_add_read_file(
1995  NULL);
1996 #if HAVE_WAIT4
1997  if (GNUNET_OK ==
1999  "ARM",
2000  "RESOURCE_DIAGNOSTICS",
2001  &wait_filename))
2002  {
2003  wait_file = fopen(wait_filename, "w");
2004  if (NULL == wait_file)
2005  {
2007  "fopen",
2008  wait_filename);
2009  }
2010  }
2011 #endif
2013  "ARM",
2014  "GLOBAL_PREFIX",
2015  &prefix_command))
2017  else
2020  "ARM",
2021  "GLOBAL_POSTFIX",
2022  &final_option))
2024  else
2026  start_user =
2027  GNUNET_CONFIGURATION_get_value_yesno(cfg, "ARM", "START_USER_SERVICES");
2028  start_system =
2029  GNUNET_CONFIGURATION_get_value_yesno(cfg, "ARM", "START_SYSTEM_SERVICES");
2030  if ((GNUNET_NO == start_user) && (GNUNET_NO == start_system))
2031  {
2032  GNUNET_log(
2034  "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
2036  global_ret = 1;
2037  return;
2038  }
2040 
2041  /* start default services... */
2042  for (sl = running_head; NULL != sl; sl = sl->next)
2043  if (GNUNET_YES == sl->force_start)
2044  start_process(sl, NULL, 0);
2046 }
2047 
2048 
2056 int
2057 main(int argc, char *const *argv)
2058 {
2059  struct GNUNET_SIGNAL_Context *shc_chld;
2060  struct GNUNET_MQ_MessageHandler handlers[] =
2063  struct GNUNET_ARM_Message,
2064  NULL),
2065  GNUNET_MQ_hd_var_size(stop,
2067  struct GNUNET_ARM_Message,
2068  NULL),
2071  struct GNUNET_MessageHeader,
2072  NULL),
2075  struct GNUNET_ARM_Message,
2076  NULL),
2079  struct GNUNET_MessageHeader,
2080  NULL),
2082 
2084  GNUNET_assert(NULL != sigpipe);
2085  shc_chld =
2087  if (0 != GNUNET_SERVICE_run_(argc,
2088  argv,
2089  "arm",
2091  &run,
2094  NULL,
2095  handlers))
2096  global_ret = 2;
2097 #if HAVE_WAIT4
2098  if (NULL != wait_file)
2099  {
2100  fclose(wait_file);
2101  wait_file = NULL;
2102  }
2103  if (NULL != wait_filename)
2104  {
2105  GNUNET_free(wait_filename);
2106  wait_filename = NULL;
2107  }
2108 #endif
2110  shc_chld = NULL;
2111  GNUNET_DISK_pipe_close(sigpipe);
2112  sigpipe = NULL;
2113  return global_ret;
2114 }
2115 
2116 
2117 #if defined(LINUX) && defined(__GLIBC__)
2118 #include <malloc.h>
2119 
2123 void __attribute__ ((constructor)) GNUNET_ARM_memory_init()
2124 {
2125  mallopt(M_TRIM_THRESHOLD, 4 * 1024);
2126  mallopt(M_TOP_PAD, 1 * 1024);
2127  malloc_trim(0);
2128 }
2129 #endif
2130 
2131 
2132 /* end of gnunet-service-arm.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:696
static void handle_start(void *cls, const struct GNUNET_ARM_Message *amsg)
Handle START-message.
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:871
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1068
static struct ServiceList * running_head
List of running services.
ARM stopping was initiated (there&#39;s no "stopped" for ARM itself).
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
pid_t GNUNET_OS_process_get_pid(struct GNUNET_OS_Process *proc)
Get the pid of the process in question.
Definition: os_priority.c:273
char * config
Name of the configuration file used.
The notification context is the key datastructure for a convenience API used for transmission of noti...
Definition: nc.c:74
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
static struct GNUNET_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:41
static char * prefix_command
Command to prepend to each actual command.
#define GNUNET_MESSAGE_TYPE_ARM_STATUS
Status update from ARM.
#define GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
Response from ARM for listing currently running services.
int 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.
uint64_t rel_value_us
The actual value.
static struct GNUNET_SCHEDULER_Task * child_death_task
ID of task called whenever we get a SIGCHILD.
struct ServiceList * prev
This is a doubly-linked list.
Asked to stop it, but it&#39;s already stopping.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:75
static struct GNUNET_TIME_Relative backoff
How long should we wait to reconnect?
Definition: resolver_api.c:81
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
#define SOCKTYPE
Definition: platform.h:237
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:286
Handle to a service.
Definition: service.c:114
Status update from ARM to client.
Definition: arm.h:41
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
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:1169
#define GNUNET_SIGCHLD
Definition: platform.h:42
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2424
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:729
int GNUNET_OS_process_status(struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Retrieve the status of a process, waiting on it if dead.
Definition: os_priority.c:963
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, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1284
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct ServiceListeningInfo * prev
This is a linked list.
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
#define GNUNET_MESSAGE_TYPE_ARM_RESULT
Response from ARM.
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:246
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...
struct GNUNET_TIME_Relative backoff
Process exponential backoff time.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up associated state.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
#define GNUNET_MESSAGE_TYPE_ARM_START
Request to ARM to start a service.
struct GNUNET_OS_Process * GNUNET_OS_start_process_s(int pipe_control, unsigned int std_inheritance, const SOCKTYPE *lsocks, const char *filename,...)
Start a process.
Definition: os_priority.c:762
#define GNUNET_MESSAGE_TYPE_ARM_STOP
Request to ARM to stop a service.
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, with an ID.
Definition: arm.h:107
int 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:474
int main(int argc, char *const *argv)
The main function for the arm service.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
static void handle_test(void *cls, const struct GNUNET_MessageHeader *message)
Handle TEST-message by sending back TEST.
static unsigned int list_count(struct ServiceList *running_head)
Count how many services are still active.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
#define GNUNET_NO
Definition: gnunet_common.h:78
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:1615
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:75
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
socklen_t service_addr_len
Number of bytes in service_addr.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
GNUNET_ARM_Result
Replies to ARM requests.
Service starting was initiated.
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze)...
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 LOG(kind,...)
Asked to start it, but it&#39;s already started.
static void create_listen_socket(struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl)
Creating a listening socket for each of the service&#39;s addresses and wait for the first incoming conne...
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
static int ret
Final status code.
Definition: gnunet-arm.c:89
uint32_t reserved
For alignment.
Definition: arm.h:68
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:158
uint64_t abs_value_us
The actual value.
uint16_t count
Number of &#39;\0&#39; terminated strings that follow this message.
Definition: arm.h:113
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
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:1744
struct ServiceList * sl
Service this listen socket is for.
static int start_user
Are we starting user services?
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static char * section
Name of the section.
Definition: gnunet-config.c:33
struct ServiceList * next
This is a doubly-linked list.
Handle to a client that is connected to a service.
Definition: service.c:246
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.
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
Process arm requests.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
List of our services.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
static void sighandler_child_death()
Signal handler called for SIGCHLD.
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:1191
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
static void handle_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
Handle STOP-message.
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_RESULT, with an ID.
Definition: arm.h:88
Tried to start a service, but that failed for some reason.
Service starting was initiated.
uint32_t result
Result from the enum GNUNET_ARM_Result
Definition: arm.h:93
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
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:817
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:1264
GNUNET_OS_ProcessStatusType
Process status types.
int 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.
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:686
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
#define MAX_NOTIFY_QUEUE
How many messages do we queue up at most for optional notifications to a client? (this can cause noti...
static const struct GNUNET_CONFIGURATION_Handle * config
static int result
Global testing status.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
The writing-end of a pipe.
Service was stopped.
Record with information about a listen socket we have open.
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)...
The reading-end of a pipe.
static struct ServiceList * running_tail
List of running services.
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2394
The process exited with a return code.
static void delayed_restart_task(void *cls)
Task run whenever it is time to restart a child that died.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
static void trigger_shutdown(void *cls)
Start a shutdown sequence.
Message handler for a specific message type.
static int res
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
When these flags are set, the child process will inherit stdout and stderr of the parent...
Definition: gnunet_os_lib.h:96
Asked to start something, but ARM is shutting down and can&#39;t comply.
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(int blocking_read, int blocking_write, int inherit_read, int inherit_write)
Creates an interprocess channel.
Definition: disk.c:1518
Run when otherwise idle.
int 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.
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:319
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 shutdown_task(void *cls)
Task run for shutdown.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:35
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:50
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
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:272
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static void handle_list(void *cls, const struct GNUNET_ARM_Message *request)
Handle LIST-message.
static void broadcast_status(const char *name, enum GNUNET_ARM_ServiceStatus status, struct GNUNET_SERVICE_Client *unicast)
Tell all clients about status change of a service.
#define GNUNET_MESSAGE_TYPE_ARM_LIST
Request to ARM to list all currently running services.
const char * name
static int check_stop(void *cls, const struct GNUNET_ARM_Message *amsg)
Check STOP-message.
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Reply from ARM to client for the GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count &#39;\0&#39; terminat...
Definition: arm.h:102
static void unicast(struct TransportClient *tc, const struct GNUNET_MessageHeader *msg, int may_drop)
Queue the given message for transmission to the given client.
static void handle_monitor(void *cls, const struct GNUNET_MessageHeader *message)
Handle MONITOR-message.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
The process was killed by a signal.
static void free_service(struct ServiceList *sl)
Remove and free an entry in the service list.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
static char * final_option
Option to append to each actual command.
Asked to stop it, but it&#39;s already stopped.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:119
Handle to a message queue.
Definition: mq.c:84
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1706
uint32_t status
Status from the &#39;enum GNUNET_ARM_ServiceStatus&#39;.
Definition: arm.h:50
GNUNET_ARM_ServiceStatus
Statuses of services.
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
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:187
enum RadiotapType __attribute__
#define GNUNET_MESSAGE_TYPE_ARM_TEST
Test if ARM service is online.
Reply from ARM to client.
Definition: arm.h:84
#define GNUNET_MESSAGE_TYPE_ARM_MONITOR
Request to ARM to notify client of service status changes.
static char * hostname
Our hostname; we give this to all the peers we start.
static int monitor
Monitor ARM activity.
Definition: gnunet-arm.c:59
char * binary
Name of the binary used.
int GNUNET_SERVICE_run_(int argc, char *const *argv, const char *service_name, enum GNUNET_SERVICE_Options options, GNUNET_SERVICE_InitCallback service_init_cb, GNUNET_SERVICE_ConnectHandler connect_cb, GNUNET_SERVICE_DisconnectHandler disconnect_cb, void *cls, const struct GNUNET_MQ_MessageHandler *handlers)
Creates the "main" function for a GNUnet service.
Definition: service.c:1962
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
configuration data
Definition: configuration.c:83
Service stopping was initiated.
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:373
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define LOG_STRERROR(kind, syscall)
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls)
Iterate over all sections in the configuration.
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
#define GNUNET_log(kind,...)
Entry in list of pending tasks.
Definition: scheduler.c:131
The process is still running.
Asked to start or stop a service, but it&#39;s not known.
int 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.
char * GNUNET_OS_get_libexec_binary_path(const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
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:376
static int in_shutdown
Are we in shutdown mode?
handle to a socket
Definition: network.c:46
The process is not known to the OS (or at least not one of our children).
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
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:331
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:151
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
Header for all communications.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:1467
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:135
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:351
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:194
char * name
Name of the service.
struct ServiceListeningInfo * next
This is a linked list.
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 int check_start(void *cls, const struct GNUNET_ARM_Message *amsg)
Check START-message.
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate)...
int 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.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:242
struct ServiceListeningInfo * listen_tail
Linked list of listen sockets associated with this service.
int 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".
Service was stopped (never sent for ARM itself).
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).
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:219
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:68
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process...
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
static int global_ret
Return value from main.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:64
#define GNUNET_malloc(size)
Wrapper around malloc.
The process is paused (but could be resumed).
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
static void do_shutdown()
We are done with everything.
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2411
#define GNUNET_free(ptr)
Wrapper around free.
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...
Time for relative time used by GNUnet, in microseconds.
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2370
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:900
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:224
struct sockaddr * service_addr
Address this socket is listening on.
static int start_system
Are we starting system services?
static void accept_connection(void *cls)
First connection has come to the listening socket associated with the service, create the service in ...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956