GNUnet  0.20.0
gnunet-service-arm.c File Reference

the automated restart manager service More...

#include "platform.h"
#include "gnunet_util_lib.h"
#include "gnunet_arm_service.h"
#include "gnunet_protocols.h"
#include "arm.h"
Include dependency graph for gnunet-service-arm.c:

Go to the source code of this file.

Data Structures

struct  ServiceListeningInfo
 Record with information about a listen socket we have open. More...
 
struct  ServiceList
 List of our services. More...
 

Macros

#define LOG(kind, ...)   GNUNET_log_from (kind, "util", __VA_ARGS__)
 
#define LOG_STRERROR(kind, syscall)    GNUNET_log_from_strerror (kind, "util", syscall)
 
#define MAX_NOTIFY_QUEUE   1024
 How many messages do we queue up at most for optional notifications to a client? (this can cause notifications about outgoing messages to be dropped). More...
 

Functions

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). More...
 
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. More...
 
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. More...
 
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. More...
 
static void start_process (struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
 Actually start the process for the given service. More...
 
static struct ServiceListfind_service (const char *name)
 Find the process with the given service name in the given list and return it. More...
 
static void accept_connection (void *cls)
 First connection has come to the listening socket associated with the service, create the service in order to relay the incoming connection to it. More...
 
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 connection to it. More...
 
static void free_service (struct ServiceList *sl)
 Remove and free an entry in the service list. More...
 
static int check_start (void *cls, const struct GNUNET_ARM_Message *amsg)
 Check START-message. More...
 
static void handle_start (void *cls, const struct GNUNET_ARM_Message *amsg)
 Handle START-message. More...
 
static void trigger_shutdown (void *cls)
 Start a shutdown sequence. More...
 
static int check_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
 Check STOP-message. More...
 
static void handle_stop (void *cls, const struct GNUNET_ARM_Message *amsg)
 Handle STOP-message. More...
 
static int pool_write (char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
 Write a string to a string pool. More...
 
static void handle_list (void *cls, const struct GNUNET_ARM_Message *request)
 Handle LIST-message. More...
 
static void handle_test (void *cls, const struct GNUNET_MessageHeader *message)
 Handle TEST-message by sending back TEST. More...
 
static void do_shutdown ()
 We are done with everything. More...
 
static unsigned int list_count (struct ServiceList *running_head)
 Count how many services are still active. More...
 
static void shutdown_task (void *cls)
 Task run for shutdown. More...
 
static void delayed_restart_task (void *cls)
 Task run whenever it is time to restart a child that died. More...
 
static void maint_child_death (void *cls)
 Task triggered whenever we receive a SIGCHLD (child process died). More...
 
static void sighandler_child_death ()
 Signal handler called for SIGCHLD. More...
 
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 a service). More...
 
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. More...
 
static void client_disconnect_cb (void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
 A client disconnected, clean up associated state. More...
 
static void handle_monitor (void *cls, const struct GNUNET_MessageHeader *message)
 Handle MONITOR-message. More...
 
static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
 Process arm requests. More...
 
int main (int argc, char *const *argv)
 The main function for the arm service. More...
 

Variables

static struct ServiceListrunning_head
 List of running services. More...
 
static struct ServiceListrunning_tail
 List of running services. More...
 
static const struct GNUNET_CONFIGURATION_Handlecfg
 Our configuration. More...
 
static char * prefix_command
 Command to prepend to each actual command. More...
 
static char * final_option
 Option to append to each actual command. More...
 
static struct GNUNET_SCHEDULER_Taskchild_death_task
 ID of task called whenever we get a SIGCHILD. More...
 
static struct GNUNET_SCHEDULER_Taskchild_restart_task
 ID of task called whenever the timeout for restarting a child expires. More...
 
static struct GNUNET_DISK_PipeHandlesigpipe
 Pipe used to communicate shutdown via signal. More...
 
static int in_shutdown
 Are we in shutdown mode? More...
 
static int global_ret
 Return value from main. More...
 
static int start_user = GNUNET_YES
 Are we starting user services? More...
 
static int start_system = GNUNET_YES
 Are we starting system services? More...
 
static struct GNUNET_SERVICE_Handleservice
 Handle to our service instance. More...
 
static struct GNUNET_NotificationContextnotifier
 Context for notifications we need to send to our clients. More...
 

Detailed Description

the automated restart manager service

Author
Christian Grothoff

Definition in file gnunet-service-arm.c.

Macro Definition Documentation

◆ LOG

#define LOG (   kind,
  ... 
)    GNUNET_log_from (kind, "util", __VA_ARGS__)

Definition at line 32 of file gnunet-service-arm.c.

◆ LOG_STRERROR

#define LOG_STRERROR (   kind,
  syscall 
)     GNUNET_log_from_strerror (kind, "util", syscall)

Definition at line 34 of file gnunet-service-arm.c.

◆ MAX_NOTIFY_QUEUE

#define MAX_NOTIFY_QUEUE   1024

How many messages do we queue up at most for optional notifications to a client? (this can cause notifications about outgoing messages to be dropped).

Definition at line 56 of file gnunet-service-arm.c.

Function Documentation

◆ add_unixpath()

static void add_unixpath ( struct sockaddr **  saddrs,
socklen_t *  saddrlens,
const char *  unixpath,
int  abstract 
)
static

Add the given UNIX domain path as an address to the list (as the first entry).

Parameters
saddrsarray to update
saddrlenswhere to store the address length
unixpathpath to add
abstractGNUNET_YES to add an abstract UNIX domain socket. This parameter is ignore on systems other than LINUX

Definition at line 293 of file gnunet-service-arm.c.

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 }
@ GNUNET_YES
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:138

References GNUNET_assert, GNUNET_new, GNUNET_strlcpy(), and GNUNET_YES.

Referenced by get_server_addresses().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_server_addresses()

static int get_server_addresses ( const char *  service_name,
const struct GNUNET_CONFIGURATION_Handle cfg,
struct sockaddr ***  addrs,
socklen_t **  addr_lens 
)
static

Get the list of addresses that a server for the given service should bind to.

Parameters
service_namename of the service
cfgconfiguration (which specifies the addresses)
addrsset (call by reference) to an array of pointers to the addresses the server should bind to and listen on; the array will be NULL-terminated (on success)
addr_lensset (call by reference) to an array of the lengths of the respective struct sockaddr struct in the addrs array (on success)
Returns
number of addresses found on success, GNUNET_SYSERR if the configuration did not specify reasonable finding information or if it specified a hostname that could not be resolved; GNUNET_NO if the number of addresses configured is zero (in this case, *addrs and *addr_lens will be set to NULL).

Definition at line 342 of file gnunet-service-arm.c.

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;
367  {
368  if (GNUNET_SYSERR ==
370  service_name,
371  "DISABLEV6")))
372  return GNUNET_SYSERR;
373  }
374  else
375  disablev6 = GNUNET_NO;
376 
377  if (! disablev6)
378  {
379  /* probe IPv6 support */
380  desc = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
381  if (NULL == desc)
382  {
383  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
384  (EACCES == errno))
385  {
387  return GNUNET_SYSERR;
388  }
390  _ (
391  "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
392  service_name,
393  strerror (errno));
394  disablev6 = GNUNET_YES;
395  }
396  else
397  {
399  desc = NULL;
400  }
401  }
402 
403  port = 0;
405  {
407  service_name,
408  "PORT",
409  &port))
410  {
412  _ ("Require valid port number for service `%s' in configuration!\n"),
413  service_name);
414  }
415  if (port > 65535)
416  {
418  _ ("Require valid port number for service `%s' in configuration!\n"),
419  service_name);
420  return GNUNET_SYSERR;
421  }
422  }
423 
425  {
428  service_name,
429  "BINDTO",
430  &hostname));
431  }
432  else
433  hostname = NULL;
434 
435  unixpath = NULL;
436  abstract = GNUNET_NO;
437 #ifdef AF_UNIX
438  if ((GNUNET_YES ==
441  service_name,
442  "UNIXPATH",
443  &unixpath)) &&
444  (0 < strlen (unixpath)))
445  {
446  /* probe UNIX support */
447  struct sockaddr_un s_un;
448 
449  if (strlen (unixpath) >= sizeof(s_un.sun_path))
450  {
452  _ ("UNIXPATH `%s' too long, maximum length is %llu\n"),
453  unixpath,
454  (unsigned long long) sizeof(s_un.sun_path));
455  unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
456  LOG (GNUNET_ERROR_TYPE_INFO, _ ("Using `%s' instead\n"), unixpath);
457  }
458 #ifdef __linux__
460  "TESTING",
461  "USE_ABSTRACT_SOCKETS");
462  if (GNUNET_SYSERR == abstract)
463  abstract = GNUNET_NO;
464 #endif
465  if ((GNUNET_YES != abstract) &&
468  }
469  if (NULL != unixpath)
470  {
471  desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
472  if (NULL == desc)
473  {
474  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
475  (EACCES == errno))
476  {
479  GNUNET_free (unixpath);
480  return GNUNET_SYSERR;
481  }
483  _ (
484  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
485  service_name,
486  strerror (errno));
487  GNUNET_free (unixpath);
488  unixpath = NULL;
489  }
490  else
491  {
493  desc = NULL;
494  }
495  }
496 #endif
497 
498  if ((0 == port) && (NULL == unixpath))
499  {
501  service_name,
502  "START_ON_DEMAND"))
504  _ (
505  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
506  service_name);
508  return GNUNET_SYSERR;
509  }
510  if (0 == port)
511  {
512  saddrs = GNUNET_new_array (2, struct sockaddr *);
513  saddrlens = GNUNET_new_array (2, socklen_t);
514  add_unixpath (saddrs, saddrlens, unixpath, abstract);
515  GNUNET_free (unixpath);
517  *addrs = saddrs;
518  *addr_lens = saddrlens;
519  return 1;
520  }
521 
522  if (NULL != hostname)
523  {
525  "Resolving `%s' since that is where `%s' will bind to.\n",
526  hostname,
527  service_name);
528  memset (&hints, 0, sizeof(struct addrinfo));
529  if (disablev6)
530  hints.ai_family = AF_INET;
531  hints.ai_protocol = IPPROTO_TCP;
532  if ((0 != (ret = getaddrinfo (hostname, NULL, &hints, &res))) ||
533  (NULL == res))
534  {
536  _ ("Failed to resolve `%s': %s\n"),
537  hostname,
538  gai_strerror (ret));
540  GNUNET_free (unixpath);
541  return GNUNET_SYSERR;
542  }
543  next = res;
544  i = 0;
545  while (NULL != (pos = next))
546  {
547  next = pos->ai_next;
548  if ((disablev6) && (pos->ai_family == AF_INET6))
549  continue;
550  i++;
551  }
552  if (0 == i)
553  {
555  _ ("Failed to find %saddress for `%s'.\n"),
556  disablev6 ? "IPv4 " : "",
557  hostname);
558  freeaddrinfo (res);
560  GNUNET_free (unixpath);
561  return GNUNET_SYSERR;
562  }
563  resi = i;
564  if (NULL != unixpath)
565  resi++;
566  saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
567  saddrlens = GNUNET_new_array (resi + 1, socklen_t);
568  i = 0;
569  if (NULL != unixpath)
570  {
571  add_unixpath (saddrs, saddrlens, unixpath, abstract);
572  i++;
573  }
574  next = res;
575  while (NULL != (pos = next))
576  {
577  next = pos->ai_next;
578  if ((disablev6) && (AF_INET6 == pos->ai_family))
579  continue;
580  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
581  continue; /* not TCP */
582  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
583  continue; /* huh? */
585  "Service `%s' will bind to `%s'\n",
586  service_name,
587  GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
588  if (AF_INET == pos->ai_family)
589  {
590  GNUNET_assert (sizeof(struct sockaddr_in) == pos->ai_addrlen);
591  saddrlens[i] = pos->ai_addrlen;
592  saddrs[i] = GNUNET_malloc (saddrlens[i]);
593  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
594  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
595  }
596  else
597  {
598  GNUNET_assert (AF_INET6 == pos->ai_family);
599  GNUNET_assert (sizeof(struct sockaddr_in6) == pos->ai_addrlen);
600  saddrlens[i] = pos->ai_addrlen;
601  saddrs[i] = GNUNET_malloc (saddrlens[i]);
602  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
603  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
604  }
605  i++;
606  }
608  freeaddrinfo (res);
609  resi = i;
610  }
611  else
612  {
613  /* will bind against everything, just set port */
614  if (disablev6)
615  {
616  /* V4-only */
617  resi = 1;
618  if (NULL != unixpath)
619  resi++;
620  i = 0;
621  saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
622  saddrlens = GNUNET_new_array (resi + 1, socklen_t);
623  if (NULL != unixpath)
624  {
625  add_unixpath (saddrs, saddrlens, unixpath, abstract);
626  i++;
627  }
628  saddrlens[i] = sizeof(struct sockaddr_in);
629  saddrs[i] = GNUNET_malloc (saddrlens[i]);
630 #if HAVE_SOCKADDR_IN_SIN_LEN
631  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
632 #endif
633  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
634  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
635  }
636  else
637  {
638  /* dual stack */
639  resi = 2;
640  if (NULL != unixpath)
641  resi++;
642  saddrs = GNUNET_new_array (resi + 1, struct sockaddr *);
643  saddrlens = GNUNET_new_array (resi + 1, socklen_t);
644  i = 0;
645  if (NULL != unixpath)
646  {
647  add_unixpath (saddrs, saddrlens, unixpath, abstract);
648  i++;
649  }
650  saddrlens[i] = sizeof(struct sockaddr_in6);
651  saddrs[i] = GNUNET_malloc (saddrlens[i]);
652 #if HAVE_SOCKADDR_IN_SIN_LEN
653  ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
654 #endif
655  ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
656  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
657  i++;
658  saddrlens[i] = sizeof(struct sockaddr_in);
659  saddrs[i] = GNUNET_malloc (saddrlens[i]);
660 #if HAVE_SOCKADDR_IN_SIN_LEN
661  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
662 #endif
663  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
664  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
665  }
666  }
667  GNUNET_free (unixpath);
668  *addrs = saddrs;
669  *addr_lens = saddrlens;
670  return resi;
671 }
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int res
static uint16_t port
Port number.
Definition: gnunet-bcd.c:147
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 const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
#define LOG(kind,...)
#define LOG_STRERROR(kind, syscall)
static char * hostname
Our hostname; we give this to all the peers we start.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:50
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.
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.
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_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
@ GNUNET_OK
@ GNUNET_NO
@ GNUNET_SYSERR
#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).
#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_DEBUG
@ GNUNET_ERROR_TYPE_INFO
#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.
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:509
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:833
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:144
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
handle to a socket
Definition: network.c:54

References _, add_unixpath(), cfg, GNUNET_a2s(), GNUNET_assert, GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_number(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_have_value(), GNUNET_DISK_directory_create_for_file(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_strerror_file, GNUNET_malloc, GNUNET_memcpy, GNUNET_NETWORK_shorten_unixpath(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_new_array, GNUNET_NO, GNUNET_OK, GNUNET_SYSERR, GNUNET_YES, hostname, LOG, LOG_STRERROR, port, res, ret, and service_name.

Referenced by setup_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ signal_result()

static void signal_result ( struct GNUNET_SERVICE_Client client,
const char *  name,
uint64_t  request_id,
enum GNUNET_ARM_Result  result 
)
static

Signal our client that we will start or stop the service.

Parameters
clientwho is being signalled
namename of the service
request_idid of the request that is being responded to.
resultmessage type to send
Returns
NULL if it was not found

Definition at line 685 of file gnunet-service-arm.c.

689 {
690  struct GNUNET_MQ_Envelope *env;
692 
693  (void) name;
695  msg->result = htonl (result);
696  msg->arm_msg.request_id = GNUNET_htonll (request_id);
698 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
static int result
Global testing status.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:37
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:304
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:78
#define GNUNET_MESSAGE_TYPE_ARM_RESULT
Response from ARM.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2443
const char * name
Reply from ARM to client.
Definition: arm.h:87

References env, GNUNET_htonll(), GNUNET_MESSAGE_TYPE_ARM_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_get_mq(), msg, name, and result.

Referenced by handle_start(), handle_stop(), maint_child_death(), and start_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ broadcast_status()

static void broadcast_status ( const char *  name,
enum GNUNET_ARM_ServiceMonitorStatus  status,
struct GNUNET_SERVICE_Client unicast 
)
static

Tell all clients about status change of a service.

Parameters
namename of the service
statusmessage type to send
unicastif not NULL, send to this client only. otherwise, send to all clients in the notifier

Definition at line 710 of file gnunet-service-arm.c.

713 {
714  struct GNUNET_MQ_Envelope *env;
716  size_t namelen;
717 
719  "Sending status %u of service `%s' to client\n",
720  (unsigned int) status,
721  name);
722  namelen = strlen (name) + 1;
724  msg->status = htonl ((uint32_t) (status));
725  GNUNET_memcpy ((char *) &msg[1], name, namelen);
726  if (NULL == unicast)
727  {
728  if (NULL != notifier)
730  &msg->header,
731  GNUNET_YES);
733  }
734  else
735  {
737  }
738 }
uint16_t status
See PRISM_STATUS_*-constants.
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
static void unicast(struct TransportClient *tc, const struct GNUNET_MessageHeader *msg, int may_drop)
Queue the given message for transmission to the given client.
#define GNUNET_log(kind,...)
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:285
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct.
Definition: gnunet_mq_lib.h:63
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_MESSAGE_TYPE_ARM_STATUS
Status update from ARM.
Status update from ARM to client.
Definition: arm.h:42

References env, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_memcpy, GNUNET_MESSAGE_TYPE_ARM_STATUS, GNUNET_MQ_discard(), GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_notification_context_broadcast(), GNUNET_SERVICE_client_get_mq(), GNUNET_YES, msg, name, notifier, status, and unicast().

Referenced by handle_monitor(), handle_stop(), maint_child_death(), and start_process().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ start_process()

static void start_process ( struct ServiceList sl,
struct GNUNET_SERVICE_Client client,
uint64_t  request_id 
)
static

Actually start the process for the given service.

Parameters
slidentifies service to start
clientthat asked to start the service (may be NULL)
request_idid of the request in response to which the process is being started. 0 if starting was not requested.

Definition at line 750 of file gnunet-service-arm.c.

753 {
754  char *loprefix;
755  char *options;
756  int use_debug;
757  int is_simple_service;
758  struct ServiceListeningInfo *sli;
759  int *lsocks;
760  unsigned int ls;
761  char *binary;
762  char *quotedbinary;
763 
764  /* calculate listen socket list */
765  lsocks = NULL;
766  ls = 0;
767  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
768  {
769  GNUNET_array_append (lsocks,
770  ls,
772  if (NULL != sli->accept_task)
773  {
775  sli->accept_task = NULL;
776  }
777  }
778 
779  GNUNET_array_append (lsocks, ls, -1);
780 
781  /* obtain configuration */
783  sl->name,
784  "PREFIX",
785  &loprefix))
786  loprefix = GNUNET_strdup (prefix_command);
787  else
788  loprefix = GNUNET_CONFIGURATION_expand_dollar (cfg, loprefix);
790  sl->name,
791  "OPTIONS",
792  &options))
793  options = NULL;
794  else
796  {
797  char *new_options;
798  char *optpos;
799  char *fin_options;
800 
801  fin_options = GNUNET_strdup (final_option);
802  /* replace '{}' with service name */
803  while (NULL != (optpos = strstr (fin_options, "{}")))
804  {
805  /* terminate string at opening parenthesis */
806  *optpos = 0;
807  GNUNET_asprintf (&new_options,
808  "%s%s%s",
809  fin_options,
810  sl->name,
811  optpos + 2);
812  GNUNET_free (fin_options);
813  fin_options = new_options;
814  }
815  if (NULL != options)
816  {
817  /* combine "fin_options" with "options" */
818  optpos = options;
819  GNUNET_asprintf (&options, "%s %s", fin_options, optpos);
820  GNUNET_free (fin_options);
821  GNUNET_free (optpos);
822  }
823  else
824  {
825  /* only have "fin_options", use that */
826  options = fin_options;
827  }
828  }
830  use_debug = GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "DEBUG");
831  {
832  const char *service_type = NULL;
833  const char *choices[] = { "GNUNET", "SIMPLE", NULL };
834 
835  is_simple_service = GNUNET_NO;
837  sl->name,
838  "TYPE",
839  choices,
840  &service_type)) &&
841  (0 == strcasecmp (service_type, "SIMPLE")))
842  is_simple_service = GNUNET_YES;
843  }
844 
845  GNUNET_assert (NULL == sl->proc);
846  if (GNUNET_YES == is_simple_service)
847  {
848  /* A simple service will receive no GNUnet specific
849  command line options. */
850  binary = GNUNET_strdup (sl->binary);
851  binary = GNUNET_CONFIGURATION_expand_dollar (cfg, binary);
852  GNUNET_asprintf (&quotedbinary, "\"%s\"", sl->binary);
854  "Starting simple service `%s' using binary `%s'\n",
855  sl->name,
856  sl->binary);
857  /* FIXME: dollar expansion should only be done outside
858  * of ''-quoted strings, escaping should be considered. */
859  if (NULL != options)
865  lsocks,
866  loprefix,
867  quotedbinary,
868  options,
869  NULL);
870  }
871  else
872  {
873  /* actually start process */
875  "Starting service `%s' using binary `%s' and configuration `%s'\n",
876  sl->name,
877  sl->binary,
878  sl->config);
880  GNUNET_asprintf (&quotedbinary, "\"%s\"", binary);
881 
882  if (GNUNET_YES == use_debug)
883  {
884  if (NULL == sl->config)
886  ?
889  :
891  lsocks,
892  loprefix,
893  quotedbinary,
894  "-L",
895  "DEBUG",
896  options,
897  NULL);
898  else
900  ?
903  :
905  lsocks,
906  loprefix,
907  quotedbinary,
908  "-c",
909  sl->config,
910  "-L",
911  "DEBUG",
912  options,
913  NULL);
914  }
915  else
916  {
917  if (NULL == sl->config)
919  ?
922  :
924  lsocks,
925  loprefix,
926  quotedbinary,
927  options,
928  NULL);
929  else
931  ?
934  :
936  lsocks,
937  loprefix,
938  quotedbinary,
939  "-c",
940  sl->config,
941  options,
942  NULL);
943  }
944  }
945  GNUNET_free (binary);
946  GNUNET_free (quotedbinary);
948  if (NULL == sl->proc)
949  {
951  _ ("Failed to start service `%s'\n"),
952  sl->name);
953  if (client)
954  signal_result (client,
955  sl->name,
956  request_id,
958  }
959  else
960  {
962  _ ("Starting service `%s'\n"),
963  sl->name);
965  if (client)
966  signal_result (client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING);
967  }
968  /* clean up */
969  GNUNET_free (loprefix);
971  GNUNET_array_grow (lsocks, ls, 0);
972 }
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
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 char * prefix_command
Command to prepend to each actual command.
static char * final_option
Option to append to each actual command.
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.
@ GNUNET_ARM_SERVICE_STARTING
Service starting was initiated.
@ GNUNET_ARM_RESULT_STARTING
Service starting was initiated.
@ GNUNET_ARM_RESULT_START_FAILED
Tried to start a service, but that failed for some reason.
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_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.
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
#define GNUNET_array_append(arr, len, element)
Append an element to an array (growing the array by one).
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1001
char * GNUNET_OS_get_libexec_binary_path(const char *progname)
Given the name of a gnunet-helper, gnunet-service or gnunet-daemon binary, try to prefix it with the ...
struct GNUNET_OS_Process * GNUNET_OS_start_process_s(enum GNUNET_OS_InheritStdioFlags std_inheritance, const int *lsocks, const char *filename,...)
Start a process.
Definition: os_priority.c:659
@ 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?
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:975
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
char * binary
Name of the binary used.
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze).
char * config
Name of the configuration file used.
struct GNUNET_TIME_Absolute last_started_at
Absolute time at which the process was (re-)started last.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
char * name
Name of the service.
Record with information about a listen socket we have open.
struct ServiceListeningInfo * next
This is a linked list.
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.

References _, ServiceListeningInfo::accept_task, ServiceList::binary, broadcast_status(), cfg, warningfilter::choices, ServiceList::config, final_option, GNUNET_ARM_RESULT_START_FAILED, GNUNET_ARM_RESULT_STARTING, GNUNET_ARM_SERVICE_STARTING, GNUNET_array_append, GNUNET_array_grow, GNUNET_asprintf(), GNUNET_assert, GNUNET_CONFIGURATION_expand_dollar(), GNUNET_CONFIGURATION_get_value_choice(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_free, GNUNET_log, GNUNET_NETWORK_get_fd(), GNUNET_NO, GNUNET_OK, GNUNET_OS_get_libexec_binary_path(), GNUNET_OS_INHERIT_STD_OUT_AND_ERR, GNUNET_OS_start_process_s(), GNUNET_OS_USE_PIPE_CONTROL, GNUNET_SCHEDULER_cancel(), GNUNET_strdup, GNUNET_TIME_absolute_get(), GNUNET_YES, ServiceList::last_started_at, ServiceList::listen_head, ServiceListeningInfo::listen_socket, ls, ServiceList::name, ServiceListeningInfo::next, options, ServiceList::pipe_control, prefix_command, ServiceList::proc, signal_result(), and ServiceListeningInfo::sl.

Referenced by accept_connection(), delayed_restart_task(), handle_start(), and run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_service()

static struct ServiceList* find_service ( const char *  name)
static

Find the process with the given service name in the given list and return it.

Parameters
namewhich service entry to look up
Returns
NULL if it was not found

Definition at line 983 of file gnunet-service-arm.c.

984 {
985  struct ServiceList *sl;
986 
987  sl = running_head;
988  while (sl != NULL)
989  {
990  if (0 == strcasecmp (sl->name, name))
991  return sl;
992  sl = sl->next;
993  }
994  return NULL;
995 }
static struct ServiceList * running_head
List of running services.
List of our services.
struct ServiceList * next
This is a doubly-linked list.

References name, ServiceList::name, ServiceList::next, and running_head.

Referenced by handle_start(), handle_stop(), and setup_service().

Here is the caller graph for this function:

◆ accept_connection()

static void accept_connection ( void *  cls)
static

First connection has come to the listening socket associated with the service, create the service in order to relay the incoming connection to it.

Parameters
clscallback data, struct ServiceListeningInfo describing a listen socket

Definition at line 1005 of file gnunet-service-arm.c.

1006 {
1007  struct ServiceListeningInfo *sli = cls;
1008  struct ServiceList *sl = sli->sl;
1009 
1010  sli->accept_task = NULL;
1012  start_process (sl, NULL, 0);
1013 }
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
static int in_shutdown
Are we in shutdown mode?

References ServiceListeningInfo::accept_task, GNUNET_assert, GNUNET_NO, in_shutdown, ServiceListeningInfo::sl, and start_process().

Referenced by create_listen_socket(), delayed_restart_task(), and maint_child_death().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_listen_socket()

static void create_listen_socket ( struct sockaddr *  sa,
socklen_t  addr_len,
struct ServiceList sl 
)
static

Creating a listening socket for each of the service's addresses and wait for the first incoming connection to it.

Parameters
saaddress associated with the service
addr_lenlength of sa
slservice entry for the service in question

Definition at line 1025 of file gnunet-service-arm.c.

1028 {
1029  static int on = 1;
1030  struct GNUNET_NETWORK_Handle *sock;
1031  struct ServiceListeningInfo *sli;
1032 
1033  int match_uid;
1034  int match_gid;
1035 
1036  switch (sa->sa_family)
1037  {
1038  case AF_INET:
1039  sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
1040  break;
1041 
1042  case AF_INET6:
1043  sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1044  break;
1045 
1046  case AF_UNIX:
1047  if (0 == strcmp (GNUNET_a2s (sa, addr_len),
1048  "@")) /* Do not bind to blank UNIX path! */
1049  return;
1050  sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
1051  break;
1052 
1053  default:
1054  GNUNET_break (0);
1055  sock = NULL;
1056  errno = EAFNOSUPPORT;
1057  break;
1058  }
1059  if (NULL == sock)
1060  {
1062  _ ("Unable to create socket for service `%s': %s\n"),
1063  sl->name,
1064  strerror (errno));
1065  GNUNET_free (sa);
1066  return;
1067  }
1069  SOL_SOCKET,
1070  SO_REUSEADDR,
1071  &on,
1072  sizeof(on)))
1074  "setsockopt");
1075 #ifdef IPV6_V6ONLY
1076  if ((sa->sa_family == AF_INET6) &&
1078  IPPROTO_IPV6,
1079  IPV6_V6ONLY,
1080  &on,
1081  sizeof(on))))
1083  "setsockopt");
1084 #endif
1085  if (AF_UNIX == sa->sa_family)
1086  GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1087  if (GNUNET_OK !=
1088  GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
1089  {
1090  GNUNET_log (
1092  _ (
1093  "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1094  sl->name,
1095  GNUNET_a2s (sa, addr_len),
1096  strerror (errno));
1098  GNUNET_free (sa);
1099  return;
1100  }
1101  if ((AF_UNIX == sa->sa_family)
1102 #ifdef __linux__
1103  /* Permission settings are not required when abstract sockets are used */
1104  && ('\0' != ((const struct sockaddr_un *) sa)->sun_path[0])
1105 #endif
1106  )
1107  {
1108  match_uid =
1109  GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "UNIX_MATCH_UID");
1110  match_gid =
1111  GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "UNIX_MATCH_GID");
1112  GNUNET_DISK_fix_permissions (((const struct sockaddr_un *) sa)->sun_path,
1113  match_uid,
1114  match_gid);
1115  }
1116  if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1117  {
1120  GNUNET_free (sa);
1121  return;
1122  }
1124  _ ("ARM now monitors connections to service `%s' at `%s'\n"),
1125  sl->name,
1126  GNUNET_a2s (sa, addr_len));
1127  sli = GNUNET_new (struct ServiceListeningInfo);
1128  sli->service_addr = sa;
1129  sli->service_addr_len = addr_len;
1130  sli->listen_socket = sock;
1131  sli->sl = sl;
1132  sli->accept_task =
1134  sock,
1136  sli);
1138 }
static void accept_connection(void *cls)
First connection has come to the listening socket associated with the service, create the service in ...
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:320
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#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...
@ GNUNET_ERROR_TYPE_BULK
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:440
enum GNUNET_GenericReturnValue GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:652
void GNUNET_NETWORK_unix_precheck(const struct sockaddr_un *un)
If services crash, they can leave a unix domain socket file on the disk.
Definition: network.c:179
int GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len)
Set socket option.
Definition: network.c:806
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:1506
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
struct ServiceListeningInfo * listen_tail
Linked list of listen sockets associated with this service.
struct sockaddr * service_addr
Address this socket is listening on.
socklen_t service_addr_len
Number of bytes in service_addr.

References _, accept_connection(), ServiceListeningInfo::accept_task, cfg, GNUNET_a2s(), GNUNET_break, GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONTAINER_DLL_insert, GNUNET_DISK_fix_permissions(), GNUNET_ERROR_TYPE_BULK, GNUNET_ERROR_TYPE_ERROR, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_bind(), GNUNET_NETWORK_socket_close(), GNUNET_NETWORK_socket_create(), GNUNET_NETWORK_socket_listen(), GNUNET_NETWORK_socket_setsockopt(), GNUNET_NETWORK_unix_precheck(), GNUNET_new, GNUNET_OK, GNUNET_SCHEDULER_add_read_net(), GNUNET_TIME_UNIT_FOREVER_REL, ServiceList::listen_head, ServiceListeningInfo::listen_socket, ServiceList::listen_tail, ServiceList::name, ServiceListeningInfo::service_addr, ServiceListeningInfo::service_addr_len, and ServiceListeningInfo::sl.

Referenced by setup_service().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ free_service()

static void free_service ( struct ServiceList sl)
static

Remove and free an entry in the service list.

Listen sockets must have already been cleaned up. Only to be called during shutdown.

Parameters
slentry to free

Definition at line 1148 of file gnunet-service-arm.c.

1149 {
1152  GNUNET_assert (NULL == sl->listen_head);
1153  GNUNET_free (sl->config);
1154  GNUNET_free (sl->binary);
1155  GNUNET_free (sl->name);
1156  GNUNET_free (sl);
1157 }
static struct ServiceList * running_tail
List of running services.
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.

References ServiceList::binary, ServiceList::config, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_YES, in_shutdown, ServiceList::listen_head, ServiceList::name, running_head, running_tail, and ServiceListeningInfo::sl.

Referenced by maint_child_death(), and shutdown_task().

Here is the caller graph for this function:

◆ check_start()

static int check_start ( void *  cls,
const struct GNUNET_ARM_Message amsg 
)
static

Check START-message.

Parameters
clsidentification of the client
amsgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1169 of file gnunet-service-arm.c.

1170 {
1171  (void) cls;
1173  return GNUNET_OK;
1174 }
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

◆ handle_start()

static void handle_start ( void *  cls,
const struct GNUNET_ARM_Message amsg 
)
static

Handle START-message.

Parameters
clsidentification of the client
amsgthe actual message

Definition at line 1184 of file gnunet-service-arm.c.

1185 {
1186  struct GNUNET_SERVICE_Client *client = cls;
1187  const char *servicename;
1188  struct ServiceList *sl;
1189  uint64_t request_id;
1190 
1191  request_id = GNUNET_ntohll (amsg->request_id);
1192  servicename = (const char *) &amsg[1];
1194  if (GNUNET_YES == in_shutdown)
1195  {
1196  signal_result (client,
1197  servicename,
1198  request_id,
1200  return;
1201  }
1202  sl = find_service (servicename);
1203  if (NULL == sl)
1204  {
1205  signal_result (client,
1206  servicename,
1207  request_id,
1209  return;
1210  }
1211  sl->force_start = GNUNET_YES;
1212  if (NULL != sl->proc)
1213  {
1214  signal_result (client,
1215  servicename,
1216  request_id,
1218  return;
1219  }
1220  start_process (sl, client, request_id);
1221 }
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
@ GNUNET_ARM_RESULT_IS_NOT_KNOWN
Asked to start or stop a service, but it's not known.
@ GNUNET_ARM_RESULT_IS_STARTED_ALREADY
Asked to start it, but it's already started.
@ GNUNET_ARM_RESULT_IN_SHUTDOWN
Asked to start something, but ARM is shutting down and can't comply.
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:54
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2249
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
Handle to a client that is connected to a service.
Definition: service.c:252
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)?...

References find_service(), ServiceList::force_start, GNUNET_ARM_RESULT_IN_SHUTDOWN, GNUNET_ARM_RESULT_IS_NOT_KNOWN, GNUNET_ARM_RESULT_IS_STARTED_ALREADY, GNUNET_ntohll(), GNUNET_SERVICE_client_continue(), GNUNET_YES, in_shutdown, ServiceList::proc, GNUNET_ARM_Message::request_id, signal_result(), and start_process().

Here is the call graph for this function:

◆ trigger_shutdown()

static void trigger_shutdown ( void *  cls)
static

Start a shutdown sequence.

Parameters
clsclosure (refers to service)

Definition at line 1230 of file gnunet-service-arm.c.

1231 {
1232  (void) cls;
1233  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1235 }
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:562

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and GNUNET_SCHEDULER_shutdown().

Referenced by handle_stop().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ check_stop()

static int check_stop ( void *  cls,
const struct GNUNET_ARM_Message amsg 
)
static

Check STOP-message.

Parameters
clsidentification of the client
amsgthe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 1247 of file gnunet-service-arm.c.

1248 {
1249  (void) cls;
1251  return GNUNET_OK;
1252 }

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

◆ handle_stop()

static void handle_stop ( void *  cls,
const struct GNUNET_ARM_Message amsg 
)
static

Handle STOP-message.

Parameters
clsidentification of the client
amsgthe actual message

Definition at line 1262 of file gnunet-service-arm.c.

1263 {
1264  struct GNUNET_SERVICE_Client *client = cls;
1265  struct ServiceList *sl;
1266  const char *servicename;
1267  uint64_t request_id;
1268 
1269  request_id = GNUNET_ntohll (amsg->request_id);
1270  servicename = (const char *) &amsg[1];
1272  _ ("Preparing to stop `%s'\n"),
1273  servicename);
1275  if (0 == strcasecmp (servicename, "arm"))
1276  {
1277  broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1278  signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1281  return;
1282  }
1283  sl = find_service (servicename);
1284  if (NULL == sl)
1285  {
1286  signal_result (client,
1287  servicename,
1288  request_id,
1290  return;
1291  }
1292  sl->force_start = GNUNET_NO;
1293  if (GNUNET_YES == in_shutdown)
1294  {
1295  /* shutdown in progress */
1296  signal_result (client,
1297  servicename,
1298  request_id,
1300  return;
1301  }
1302  if (NULL != sl->killing_client)
1303  {
1304  /* killing already in progress */
1305  signal_result (client,
1306  servicename,
1307  request_id,
1309  return;
1310  }
1311  if (NULL == sl->proc)
1312  {
1313  /* process is down */
1314  signal_result (client,
1315  servicename,
1316  request_id,
1318  return;
1319  }
1321  "Sending kill signal to service `%s', waiting for process to die.\n",
1322  servicename);
1323  broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1324  /* no signal_start - only when it's STOPPED */
1328  sl->killing_client = client;
1329  sl->killing_client_request_id = request_id;
1330 }
static void trigger_shutdown(void *cls)
Start a shutdown sequence.
@ GNUNET_ARM_SERVICE_STOPPING
Service stopping was initiated.
@ GNUNET_ARM_RESULT_IS_STOPPED_ALREADY
Asked to stop it, but it's already stopped.
@ 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.
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:210
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:1299
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2430
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:234
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process.
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate).
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).

References _, broadcast_status(), find_service(), ServiceList::force_start, GNUNET_ARM_RESULT_IN_SHUTDOWN, GNUNET_ARM_RESULT_IS_NOT_KNOWN, GNUNET_ARM_RESULT_IS_STOPPED_ALREADY, GNUNET_ARM_RESULT_IS_STOPPING_ALREADY, GNUNET_ARM_RESULT_STOPPING, GNUNET_ARM_SERVICE_STOPPING, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_log_strerror, GNUNET_NO, GNUNET_ntohll(), GNUNET_OS_process_kill(), GNUNET_SCHEDULER_add_now(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_persist(), GNUNET_TERM_SIG, GNUNET_TIME_absolute_get(), GNUNET_YES, in_shutdown, ServiceList::killed_at, ServiceList::killing_client, ServiceList::killing_client_request_id, ServiceList::proc, GNUNET_ARM_Message::request_id, signal_result(), and trigger_shutdown().

Here is the call graph for this function:

◆ pool_write()

static int pool_write ( char *  pool_start,
size_t  pool_size,
size_t *  pool_pos,
char *  str 
)
static

Write a string to a string pool.

Parameters
pool_startpointer to the start of the string pool
pool_sizesize of the string pool
[in,out]pool_poscurrent position index in the string pool, will be updated
strstring to write to the string pool
Returns
GNUNET_OK if the string fits into the pool, GNUNET_SYSERR otherwise

Definition at line 1345 of file gnunet-service-arm.c.

1346 {
1347  size_t next_pos = (*pool_pos) + strlen (str) + 1;
1348 
1349  if (next_pos > pool_size)
1350  return GNUNET_SYSERR;
1351  memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1352  *pool_pos = next_pos;
1353  return GNUNET_OK;
1354 }

References GNUNET_OK, and GNUNET_SYSERR.

Referenced by handle_list().

Here is the caller graph for this function:

◆ handle_list()

static void handle_list ( void *  cls,
const struct GNUNET_ARM_Message request 
)
static

Handle LIST-message.

Parameters
clsidentification of the client
requestthe actual message

Definition at line 1364 of file gnunet-service-arm.c.

1365 {
1366  struct GNUNET_SERVICE_Client *client = cls;
1367  struct GNUNET_MQ_Envelope *env;
1369  size_t extra_size;
1370  struct ServiceList *sl;
1371  uint16_t count;
1372  size_t pool_size;
1373  size_t pool_pos;
1374  char *pool_start;
1375  struct GNUNET_ARM_ServiceInfoMessage *ssm;
1376 
1377  GNUNET_break_op (0 == ntohl (request->reserved));
1378  count = 0;
1379  pool_size = 0;
1380 
1381  /* Do one pass over the list to compute the number of services
1382  * and the string pool size */
1383  for (sl = running_head; NULL != sl; sl = sl->next)
1384  {
1385  pool_size += strlen (sl->name) + 1;
1386  pool_size += strlen (sl->binary) + 1;
1387  count++;
1388  }
1389 
1390  extra_size = pool_size + (count * sizeof (struct
1393  extra_size,
1395  msg->arm_msg.request_id = request->request_id;
1396  msg->count = htons (count);
1397 
1398  ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1399  pool_start = (char *) (ssm + count);
1400  pool_pos = 0;
1401 
1402  for (sl = running_head; NULL != sl; sl = sl->next)
1403  {
1404  ssm->name_index = htons ((uint16_t) pool_pos);
1405  GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1406  sl->name));
1407  ssm->binary_index = htons ((uint16_t) pool_pos);
1408  GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1409  sl->binary));
1410  if (NULL == sl->proc)
1411  {
1412  if (0 == sl->last_started_at.abs_value_us)
1413  {
1414  /* Process never started */
1416  }
1417  else if (0 == sl->last_exit_status)
1418  {
1420  }
1421  else
1422  {
1424  ssm->last_exit_status = htons (sl->last_exit_status);
1425  }
1426  }
1427  else if ((NULL != sl->killing_client) || (GNUNET_YES == in_shutdown))
1428  {
1430  }
1431  else
1432  {
1434  }
1437  ssm++;
1438  }
1441 }
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_VPN_RedirectionRequest * request
Opaque redirection request handle.
Definition: gnunet-vpn.c:40
@ 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.
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
#define GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
Response from ARM for listing currently running services.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:638
Reply from ARM to client for the GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count '\0' terminat...
Definition: arm.h:145
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
uint64_t abs_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
int last_exit_status
Last exit status of the process.
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.

References GNUNET_TIME_Absolute::abs_value_us, ServiceList::binary, GNUNET_ARM_ServiceInfoMessage::binary_index, env, GNUNET_ARM_SERVICE_STATUS_FAILED, GNUNET_ARM_SERVICE_STATUS_FINISHED, GNUNET_ARM_SERVICE_STATUS_STARTED, GNUNET_ARM_SERVICE_STATUS_STOPPED, GNUNET_ARM_SERVICE_STATUS_STOPPING, GNUNET_assert, GNUNET_break_op, GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_OK, GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), GNUNET_TIME_absolute_hton(), GNUNET_YES, in_shutdown, ServiceList::killing_client, GNUNET_ARM_ServiceInfoMessage::last_exit_status, ServiceList::last_exit_status, GNUNET_ARM_ServiceInfoMessage::last_started_at, ServiceList::last_started_at, msg, ServiceList::name, GNUNET_ARM_ServiceInfoMessage::name_index, ServiceList::next, pool_write(), ServiceList::proc, request, GNUNET_VPN_RedirectionRequest::request_id, GNUNET_ARM_ServiceInfoMessage::restart_at, ServiceList::restart_at, running_head, and GNUNET_ARM_ServiceInfoMessage::status.

Here is the call graph for this function:

◆ handle_test()

static void handle_test ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle TEST-message by sending back TEST.

Parameters
clsidentification of the client
messagethe actual message

Definition at line 1451 of file gnunet-service-arm.c.

1452 {
1453  struct GNUNET_SERVICE_Client *client = cls;
1454  struct GNUNET_MQ_Envelope *env;
1455  struct GNUNET_MessageHeader *msg;
1456 
1457  (void) message;
1461 }
#define GNUNET_MESSAGE_TYPE_ARM_TEST
Test if ARM service is online.
Header for all communications.

References env, GNUNET_MESSAGE_TYPE_ARM_TEST, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), and msg.

Here is the call graph for this function:

◆ do_shutdown()

static void do_shutdown ( )
static

We are done with everything.

Stop remaining tasks, signal handler and the server.

Definition at line 1469 of file gnunet-service-arm.c.

1470 {
1471  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1472  if (NULL != notifier)
1473  {
1475  notifier = NULL;
1476  }
1477  if (NULL != service)
1478  {
1480  service = NULL;
1481  }
1482  if (NULL != child_death_task)
1483  {
1485  child_death_task = NULL;
1486  }
1487 }
static struct GNUNET_SCHEDULER_Task * child_death_task
ID of task called whenever we get a SIGCHILD.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:138
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2389

References child_death_task, GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_notification_context_destroy(), GNUNET_SCHEDULER_cancel(), GNUNET_SERVICE_shutdown(), notifier, and service.

Referenced by maint_child_death(), and shutdown_task().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ list_count()

static unsigned int list_count ( struct ServiceList running_head)
static

Count how many services are still active.

Parameters
running_headlist of services
Returns
number of active services found

Definition at line 1497 of file gnunet-service-arm.c.

1498 {
1499  struct ServiceList *i;
1500  unsigned int res;
1501 
1502  for (res = 0, i = running_head; NULL != i; i = i->next, res++)
1503  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", i->name);
1504  return res;
1505 }

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, ServiceList::name, ServiceList::next, res, and running_head.

Referenced by maint_child_death(), and shutdown_task().

Here is the caller graph for this function:

◆ shutdown_task()

static void shutdown_task ( void *  cls)
static

Task run for shutdown.

Parameters
clsclosure, NULL if we need to self-restart

Definition at line 1514 of file gnunet-service-arm.c.

1515 {
1516  struct ServiceList *pos;
1517  struct ServiceList *nxt;
1518  struct ServiceListeningInfo *sli;
1519 
1520  (void) cls;
1521  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1522  if (NULL != child_restart_task)
1523  {
1525  child_restart_task = NULL;
1526  }
1528  /* first, stop listening */
1529  for (pos = running_head; NULL != pos; pos = pos->next)
1530  {
1531  while (NULL != (sli = pos->listen_head))
1532  {
1534  if (NULL != sli->accept_task)
1535  {
1537  sli->accept_task = NULL;
1538  }
1541  GNUNET_free (sli->service_addr);
1542  GNUNET_free (sli);
1543  }
1544  }
1545  /* then, shutdown all existing service processes */
1546  nxt = running_head;
1547  while (NULL != (pos = nxt))
1548  {
1549  nxt = pos->next;
1550  if (NULL != pos->proc)
1551  {
1552  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1554  if (0 != GNUNET_OS_process_kill (pos->proc, GNUNET_TERM_SIG))
1556  }
1557  else
1558  {
1559  free_service (pos);
1560  }
1561  }
1562  /* finally, should all service processes be already gone, terminate for real */
1563  if (NULL == running_head)
1564  do_shutdown ();
1565  else
1567  "Delaying shutdown, have %u children still running\n",
1569 }
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
static void free_service(struct ServiceList *sl)
Remove and free an entry in the service list.
static unsigned int list_count(struct ServiceList *running_head)
Count how many services are still active.
static void do_shutdown()
We are done with everything.

References ServiceListeningInfo::accept_task, child_restart_task, do_shutdown(), free_service(), GNUNET_break, GNUNET_CONTAINER_DLL_remove, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log, GNUNET_log_strerror, GNUNET_NETWORK_socket_close(), GNUNET_OK, GNUNET_OS_process_kill(), GNUNET_SCHEDULER_cancel(), GNUNET_TERM_SIG, GNUNET_TIME_absolute_get(), GNUNET_YES, in_shutdown, ServiceList::killed_at, list_count(), ServiceList::listen_head, ServiceListeningInfo::listen_socket, ServiceList::listen_tail, ServiceList::name, ServiceList::next, ServiceList::proc, running_head, and ServiceListeningInfo::service_addr.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ delayed_restart_task()

static void delayed_restart_task ( void *  cls)
static

Task run whenever it is time to restart a child that died.

Parameters
clsclosure, always NULL

Definition at line 1578 of file gnunet-service-arm.c.

1580 {
1581  struct ServiceList *sl;
1582  struct GNUNET_TIME_Relative lowestRestartDelay;
1583  struct ServiceListeningInfo *sli;
1584 
1585  (void) cls;
1586  child_restart_task = NULL;
1588  lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1589 
1590  /* check for services that need to be restarted due to
1591  * configuration changes or because the last restart failed */
1592  for (sl = running_head; NULL != sl; sl = sl->next)
1593  {
1594  if (NULL != sl->proc)
1595  continue;
1596  /* service is currently not running */
1598  {
1599  /* restart is now allowed */
1600  if (sl->force_start)
1601  {
1602  /* process should run by default, start immediately */
1604  _ ("Restarting service `%s'.\n"),
1605  sl->name);
1606  start_process (sl, NULL, 0);
1607  }
1608  else
1609  {
1610  /* process is run on-demand, ensure it is re-started if there is demand */
1611  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1612  if (NULL == sli->accept_task)
1613  {
1614  /* accept was actually paused, so start it again */
1615  sli->accept_task =
1617  sli->listen_socket,
1619  sli);
1620  }
1621  }
1622  }
1623  else
1624  {
1625  /* update calculation for earliest time to reactivate a service */
1626  lowestRestartDelay =
1627  GNUNET_TIME_relative_min (lowestRestartDelay,
1629  sl->restart_at));
1630  }
1631  }
1632  if (lowestRestartDelay.rel_value_us !=
1633  GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1634  {
1636  "Will restart process in %s\n",
1637  GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1638  GNUNET_YES));
1640  GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
1643  NULL);
1644  }
1645 }
static void delayed_restart_task(void *cls)
Task run whenever it is time to restart a child that died.
@ GNUNET_SCHEDULER_PRIORITY_IDLE
Run when otherwise idle.
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:1202
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:343
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:405
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:569
Time for relative time used by GNUnet, in microseconds.
uint64_t rel_value_us
The actual value.

References _, accept_connection(), ServiceListeningInfo::accept_task, child_restart_task, ServiceList::force_start, GNUNET_assert, GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_log, GNUNET_NO, GNUNET_SCHEDULER_add_delayed_with_priority(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_PRIORITY_IDLE, GNUNET_STRINGS_relative_time_to_string(), GNUNET_TIME_absolute_get_remaining(), GNUNET_TIME_relative_min(), GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, in_shutdown, ServiceList::listen_head, ServiceListeningInfo::listen_socket, ServiceList::name, ServiceListeningInfo::next, ServiceList::next, ServiceList::proc, GNUNET_TIME_Relative::rel_value_us, ServiceList::restart_at, running_head, ServiceListeningInfo::sl, and start_process().

Referenced by maint_child_death().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ maint_child_death()

static void maint_child_death ( void *  cls)
static

Task triggered whenever we receive a SIGCHLD (child process died).

Parameters
clsclosure, NULL

Definition at line 1655 of file gnunet-service-arm.c.

1656 {
1657  struct ServiceList *pos;
1658  struct ServiceList *next;
1659  struct ServiceListeningInfo *sli;
1660  const char *statstr;
1661  int statcode;
1662  int ret;
1663  char c[16];
1664  enum GNUNET_OS_ProcessStatusType statusType;
1665  unsigned long statusCode;
1666  const struct GNUNET_DISK_FileHandle *pr;
1667 
1668  (void) cls;
1670  child_death_task = NULL;
1671  /* consume the signal */
1672  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
1673 
1674  /* check for services that died (WAITPID) */
1675  next = running_head;
1676  while (NULL != (pos = next))
1677  {
1678  next = pos->next;
1679 
1680  if (NULL == pos->proc)
1681  {
1682  if (GNUNET_YES == in_shutdown)
1683  free_service (pos);
1684  continue;
1685  }
1686 #if HAVE_WAIT4
1687  if (NULL != wait_file)
1688  {
1689  /* need to use 'wait4()' to obtain and log performance data */
1690  struct rusage ru;
1691  int status;
1692  pid_t pid;
1693 
1695  ret = wait4 (pid, &status, WNOHANG, &ru);
1696  if (ret <= 0)
1697  continue; /* no process done */
1698  if (WIFEXITED (status))
1699  {
1700  statusType = GNUNET_OS_PROCESS_EXITED;
1701  statusCode = WEXITSTATUS (status);
1702  }
1703  else if (WIFSIGNALED (status))
1704  {
1705  statusType = GNUNET_OS_PROCESS_SIGNALED;
1706  statusCode = WTERMSIG (status);
1707  }
1708  else if (WIFSTOPPED (status))
1709  {
1710  statusType = GNUNET_OS_PROCESS_SIGNALED;
1711  statusCode = WSTOPSIG (status);
1712  }
1713 #ifdef WIFCONTINUED
1714  else if (WIFCONTINUED (status))
1715  {
1716  statusType = GNUNET_OS_PROCESS_RUNNING;
1717  statusCode = 0;
1718  }
1719 #endif
1720  else
1721  {
1722  statusType = GNUNET_OS_PROCESS_UNKNOWN;
1723  statusCode = 0;
1724  }
1725  if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1726  (GNUNET_OS_PROCESS_SIGNALED == statusType))
1727  {
1728  double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1729  double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1730  fprintf (wait_file,
1731  "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1732  pos->binary,
1733  (unsigned int) pid,
1734  utime,
1735  stime,
1736  (unsigned long long) ru.ru_maxrss,
1737  (unsigned long long) ru.ru_inblock,
1738  (unsigned long long) ru.ru_oublock,
1739  (unsigned long long) ru.ru_nvcsw,
1740  (unsigned long long) ru.ru_nivcsw);
1741  }
1742  }
1743  else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1744 #endif
1746  &statusType,
1747  &statusCode))) ||
1748  (ret == GNUNET_NO) || (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;
1780  if (NULL != pos->killing_client)
1781  {
1783  pos->name,
1786  pos->killing_client = NULL;
1787  pos->killing_client_request_id = 0;
1788  }
1789  if (GNUNET_YES != in_shutdown)
1790  {
1791  pos->last_exit_status = statcode;
1792  if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1793  {
1794  /* process terminated normally, allow restart at any time */
1795  pos->restart_at.abs_value_us = 0;
1796  GNUNET_log (
1798  _ ("Service `%s' terminated normally, will restart at any time\n"),
1799  pos->name);
1800  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1801  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1802  {
1803  GNUNET_break (NULL == sli->accept_task);
1804  sli->accept_task =
1806  sli->listen_socket,
1808  sli);
1809  }
1810  }
1811  else
1812  {
1813  GNUNET_log (
1815  _ ("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1816  pos->name,
1817  statstr,
1818  statcode,
1820  {
1821  /* Reduce backoff based on runtime of the process,
1822  so that there is a cool-down if a process actually
1823  runs for a while. */
1824  struct GNUNET_TIME_Relative runtime;
1825  unsigned int minutes;
1826 
1828  minutes =
1829  runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1830  if (minutes > 31)
1832  else
1833  pos->backoff.rel_value_us <<= minutes;
1834  }
1835  /* schedule restart */
1837  pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
1838  if (NULL != child_restart_task)
1843  NULL);
1844  }
1845  }
1846  else
1847  {
1848  free_service (pos);
1849  }
1850  }
1853  pr,
1855  NULL);
1856  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1857  do_shutdown ();
1858  else if (GNUNET_YES == in_shutdown)
1860  "Delaying shutdown after child's death, still have %u children\n",
1862 }
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
@ GNUNET_ARM_SERVICE_STOPPED
Service was stopped.
@ GNUNET_ARM_RESULT_STOPPED
Service was stopped (never sent for ARM itself).
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:622
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:1617
@ GNUNET_DISK_PIPE_END_READ
The reading-end of a pipe.
pid_t GNUNET_OS_process_get_pid(struct GNUNET_OS_Process *proc)
Get the pid of the process in question.
Definition: os_priority.c:253
GNUNET_OS_ProcessStatusType
Process status types.
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:260
enum GNUNET_GenericReturnValue GNUNET_OS_process_status(struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Retrieve the status of a process.
Definition: os_priority.c:853
@ 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.
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:1656
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:1226
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:436
#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.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
Handle used to access files (and pipes).
struct GNUNET_TIME_Relative backoff
Process exponential backoff time.

References _, GNUNET_TIME_Absolute::abs_value_us, accept_connection(), ServiceListeningInfo::accept_task, ServiceList::backoff, ServiceList::binary, broadcast_status(), child_death_task, child_restart_task, delayed_restart_task(), do_shutdown(), free_service(), GNUNET_ARM_RESULT_STOPPED, GNUNET_ARM_SERVICE_STOPPED, GNUNET_break, GNUNET_DISK_file_read(), GNUNET_DISK_PIPE_END_READ, GNUNET_DISK_pipe_handle(), GNUNET_ERROR_TYPE_DEBUG, GNUNET_ERROR_TYPE_INFO, GNUNET_ERROR_TYPE_WARNING, GNUNET_log, GNUNET_NO, GNUNET_OS_process_destroy(), GNUNET_OS_PROCESS_EXITED, GNUNET_OS_process_get_pid(), GNUNET_OS_PROCESS_RUNNING, GNUNET_OS_PROCESS_SIGNALED, GNUNET_OS_process_status(), GNUNET_OS_PROCESS_STOPPED, GNUNET_OS_PROCESS_UNKNOWN, GNUNET_SCHEDULER_add_read_file(), GNUNET_SCHEDULER_add_read_net(), GNUNET_SCHEDULER_add_with_priority(), GNUNET_SCHEDULER_cancel(), GNUNET_SCHEDULER_PRIORITY_IDLE, GNUNET_STRINGS_relative_time_to_string(), GNUNET_SYSERR, GNUNET_TIME_absolute_get_duration(), GNUNET_TIME_relative_to_absolute(), GNUNET_TIME_STD_BACKOFF, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_TIME_UNIT_MINUTES, GNUNET_TIME_UNIT_ZERO, GNUNET_YES, in_shutdown, ServiceList::killed_at, ServiceList::killing_client, ServiceList::killing_client_request_id, ServiceList::last_exit_status, list_count(), ServiceList::listen_head, ServiceListeningInfo::listen_socket, ServiceList::name, ServiceListeningInfo::next, ServiceList::next, pid, ServiceList::proc, GNUNET_TIME_Relative::rel_value_us, ServiceList::restart_at, ret, running_head, signal_result(), sigpipe, and status.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sighandler_child_death()

static void sighandler_child_death ( void  )
static

Signal handler called for SIGCHLD.

Triggers the respective handler by writing to the trigger pipe.

Definition at line 1870 of file gnunet-service-arm.c.

1871 {
1872  static char c;
1873  int old_errno = errno; /* back-up errno */
1874 
1875  GNUNET_break (
1876  1 ==
1879  &c,
1880  sizeof(c)));
1881  errno = old_errno; /* restore errno */
1882 }
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:686
@ GNUNET_DISK_PIPE_END_WRITE
The writing-end of a pipe.

References GNUNET_break, GNUNET_DISK_file_write(), GNUNET_DISK_PIPE_END_WRITE, GNUNET_DISK_pipe_handle(), and sigpipe.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ setup_service()

static void setup_service ( void *  cls,
const char *  section 
)
static

Setup our service record for the given section in the configuration file (assuming the section is for a service).

Parameters
clsunused
sectiona section in the configuration file
Returns
GNUNET_OK (continue)

Definition at line 1894 of file gnunet-service-arm.c.

1895 {
1896  struct ServiceList *sl;
1897  char *binary;
1898  char *config;
1899  struct stat sbuf;
1900  struct sockaddr **addrs;
1901  socklen_t *addr_lens;
1902  int ret;
1903 
1904  (void) cls;
1905  if (0 == strcasecmp (section, "arm"))
1906  return;
1907  if (GNUNET_OK !=
1908  GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary))
1909  {
1910  /* not a service section */
1911  return;
1912  }
1913  if ((GNUNET_YES ==
1914  GNUNET_CONFIGURATION_have_value (cfg, section, "RUN_PER_USER")) &&
1915  (GNUNET_YES ==
1916  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "RUN_PER_USER")))
1917  {
1918  if (GNUNET_NO == start_user)
1919  {
1920  GNUNET_free (binary);
1921  return; /* user service, and we don't deal with those */
1922  }
1923  }
1924  else
1925  {
1926  if (GNUNET_NO == start_system)
1927  {
1928  GNUNET_free (binary);
1929  return; /* system service, and we don't deal with those */
1930  }
1931  }
1932  sl = find_service (section);
1933  if (NULL != sl)
1934  {
1935  /* got the same section twice!? */
1936  GNUNET_break (0);
1937  GNUNET_free (binary);
1938  return;
1939  }
1940  config = NULL;
1942  section,
1943  "CONFIG",
1944  &config)) &&
1946  "PATHS",
1947  "DEFAULTCONFIG",
1948  &config))) ||
1949  (0 != stat (config, &sbuf)))
1950  {
1951  if (NULL != config)
1952  {
1954  section,
1955  "CONFIG",
1956  strerror (errno));
1957  GNUNET_free (config);
1958  config = NULL;
1959  }
1960  }
1961  sl = GNUNET_new (struct ServiceList);
1962  sl->name = GNUNET_strdup (section);
1963  sl->binary = binary;
1964  sl->config = config;
1967  if (GNUNET_CONFIGURATION_have_value (cfg, section, "PIPECONTROL"))
1968  sl->pipe_control =
1969  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "PIPECONTROL");
1971  if (GNUNET_YES ==
1972  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "IMMEDIATE_START"))
1973  {
1974  sl->force_start = GNUNET_YES;
1975  if (GNUNET_YES ==
1976  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "NOARMBIND"))
1977  return;
1978  }
1979  else
1980  {
1981  if (GNUNET_YES !=
1982  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "START_ON_DEMAND"))
1983  return;
1984  }
1985  if (0 >= (ret = get_server_addresses (section, cfg, &addrs, &addr_lens)))
1986  return;
1987  /* this will free (or capture) addrs[i] */
1988  for (unsigned int i = 0; i < (unsigned int) ret; i++)
1989  create_listen_socket (addrs[i], addr_lens[i], sl);
1990  GNUNET_free (addrs);
1991  GNUNET_free (addr_lens);
1992 }
static int start_user
Are we starting user services?
static int start_system
Are we starting system services?
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 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...
static const struct GNUNET_CONFIGURATION_Handle * config
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_TIME_UNIT_MILLISECONDS
One millisecond.
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".

References ServiceList::backoff, ServiceList::binary, cfg, ServiceList::config, config, create_listen_socket(), find_service(), ServiceList::force_start, get_server_addresses(), GNUNET_break, GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_have_value(), GNUNET_CONTAINER_DLL_insert, GNUNET_ERROR_TYPE_WARNING, GNUNET_free, GNUNET_log_config_invalid(), GNUNET_new, GNUNET_NO, GNUNET_OK, GNUNET_strdup, GNUNET_TIME_UNIT_FOREVER_ABS, GNUNET_TIME_UNIT_MILLISECONDS, GNUNET_YES, consensus-simulation::int, ServiceList::name, ServiceList::pipe_control, ServiceList::restart_at, ret, running_head, running_tail, start_system, and start_user.

Referenced by run().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

static void* client_connect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
struct GNUNET_MQ_Handle mq 
)
static

A client connected, mark as a monitoring client.

Parameters
clsclosure
clientidentification of the client
mqqueue to talk to client
Returns
client

Definition at line 2004 of file gnunet-service-arm.c.

2007 {
2008  /* All clients are considered to be of the "monitor" kind
2009  * (that is, they don't affect ARM shutdown).
2010  */
2011  (void) cls;
2012  (void) mq;
2014  return client;
2015 }
struct GNUNET_MQ_Handle * mq
Definition: 003.c:5
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the 'monitor' flag on this client.
Definition: service.c:2413

References GNUNET_SERVICE_client_mark_monitor(), and mq.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_disconnect_cb()

static void client_disconnect_cb ( void *  cls,
struct GNUNET_SERVICE_Client client,
void *  app_ctx 
)
static

A client disconnected, clean up associated state.

Parameters
clsclosure
clientidentification of the client
app_ctxmust match client

Definition at line 2026 of file gnunet-service-arm.c.

2029 {
2030  (void) cls;
2031  GNUNET_assert (client == app_ctx);
2032  for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2033  if (sl->killing_client == client)
2034  sl->killing_client = NULL;
2035 }

References GNUNET_assert, ServiceList::next, and running_head.

Referenced by main().

Here is the caller graph for this function:

◆ handle_monitor()

static void handle_monitor ( void *  cls,
const struct GNUNET_MessageHeader message 
)
static

Handle MONITOR-message.

Parameters
clsidentification of the client
messagethe actual message
Returns
GNUNET_OK to keep the connection open, GNUNET_SYSERR to close it (signal serious error)

Definition at line 2047 of file gnunet-service-arm.c.

2048 {
2049  struct GNUNET_SERVICE_Client *client = cls;
2050 
2051  (void) message;
2052  /* FIXME: might want to start by letting monitor know about
2053  services that are already running */
2054  /* Removal is handled by the server implementation, internally. */
2056  GNUNET_SERVICE_client_get_mq (client));
2059 }
@ GNUNET_ARM_SERVICE_MONITORING_STARTED
Dummy message.
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

References broadcast_status(), GNUNET_ARM_SERVICE_MONITORING_STARTED, GNUNET_notification_context_add(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), and notifier.

Here is the call graph for this function:

◆ run()

static void run ( void *  cls,
const struct GNUNET_CONFIGURATION_Handle c,
struct GNUNET_SERVICE_Handle serv 
)
static

Process arm requests.

Parameters
clsclosure, NULL
servthe initialized service
cconfiguration to use

Definition at line 2070 of file gnunet-service-arm.c.

2073 {
2074  struct ServiceList *sl;
2075 
2076  (void) cls;
2077  cfg = c;
2078  service = serv;
2084  NULL);
2085 #if HAVE_WAIT4
2086  if (GNUNET_OK ==
2088  "ARM",
2089  "RESOURCE_DIAGNOSTICS",
2090  &wait_filename))
2091  {
2092  wait_file = fopen (wait_filename, "w");
2093  if (NULL == wait_file)
2094  {
2096  "fopen",
2097  wait_filename);
2098  }
2099  }
2100 #endif
2102  "ARM",
2103  "GLOBAL_PREFIX",
2104  &prefix_command))
2106  else
2109  "ARM",
2110  "GLOBAL_POSTFIX",
2111  &final_option))
2112  final_option = GNUNET_strdup ("");
2113  else
2115  start_user =
2116  GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "START_USER_SERVICES");
2117  start_system =
2118  GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "START_SYSTEM_SERVICES");
2119  if ((GNUNET_NO == start_user) && (GNUNET_NO == start_system))
2120  {
2121  GNUNET_log (
2123  "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
2125  global_ret = 1;
2126  return;
2127  }
2129 
2130  /* start default services... */
2131  for (sl = running_head; NULL != sl; sl = sl->next)
2132  if (GNUNET_YES == sl->force_start)
2133  start_process (sl, NULL, 0);
2135 }
#define MAX_NOTIFY_QUEUE
How many messages do we queue up at most for optional notifications to a client? (this can cause noti...
static int global_ret
Return value from main.
static void shutdown_task(void *cls)
Task run for shutdown.
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...
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.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:122
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:1334

References cfg, child_death_task, final_option, ServiceList::force_start, global_ret, GNUNET_CONFIGURATION_expand_dollar(), GNUNET_CONFIGURATION_get_value_filename(), GNUNET_CONFIGURATION_get_value_string(), GNUNET_CONFIGURATION_get_value_yesno(), GNUNET_CONFIGURATION_iterate_sections(), GNUNET_DISK_PIPE_END_READ, GNUNET_DISK_pipe_handle(), GNUNET_ERROR_TYPE_ERROR, GNUNET_log, GNUNET_log_strerror_file, GNUNET_NO, GNUNET_notification_context_create(), GNUNET_OK, GNUNET_SCHEDULER_add_read_file(), GNUNET_SCHEDULER_add_shutdown(), GNUNET_SCHEDULER_shutdown(), GNUNET_strdup, GNUNET_TIME_UNIT_FOREVER_REL, GNUNET_YES, maint_child_death(), MAX_NOTIFY_QUEUE, ServiceList::next, notifier, prefix_command, running_head, service, setup_service(), shutdown_task(), sigpipe, start_process(), start_system, and start_user.

Referenced by main().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char *const *  argv 
)

The main function for the arm service.

Parameters
argcnumber of arguments from the command line
argvcommand line arguments
Returns
0 ok, 1 on error

Definition at line 2146 of file gnunet-service-arm.c.

2147 {
2149  struct GNUNET_MQ_MessageHandler handlers[] = {
2152  struct GNUNET_ARM_Message,
2153  NULL),
2154  GNUNET_MQ_hd_var_size (stop,
2156  struct GNUNET_ARM_Message,
2157  NULL),
2160  struct GNUNET_MessageHeader,
2161  NULL),
2164  struct GNUNET_ARM_Message,
2165  NULL),
2168  struct GNUNET_MessageHeader,
2169  NULL),
2171  };
2172 
2174  GNUNET_assert (NULL != sigpipe);
2175  shc_chld =
2178  if (0 != GNUNET_SERVICE_run_ (argc,
2179  argv,
2180  "arm",
2183  &run,
2186  NULL,
2187  handlers))
2188  global_ret = 2;
2189 #if HAVE_WAIT4
2190  if (NULL != wait_file)
2191  {
2192  fclose (wait_file);
2193  wait_file = NULL;
2194  }
2195  if (NULL != wait_filename)
2196  {
2197  GNUNET_free (wait_filename);
2198  wait_filename = NULL;
2199  }
2200 #endif
2202  shc_chld = NULL;
2204  sigpipe = NULL;
2205  return global_ret;
2206 }
static struct GNUNET_SIGNAL_Context * shc_chld
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int monitor
Monitor ARM activity.
Definition: gnunet-arm.c:64
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
static struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
static void run(void *cls, const struct GNUNET_CONFIGURATION_Handle *c, struct GNUNET_SERVICE_Handle *serv)
Process arm requests.
static void sighandler_child_death()
Signal handler called for SIGCHLD.
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 void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up associated state.
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1587
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1444
@ GNUNET_DISK_PF_NONE
No special options, use non-blocking read/write operations.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_MESSAGE_TYPE_ARM_STOP
Request to ARM to stop a service.
#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.
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:1968
@ 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
#define GNUNET_SIGCHLD
Definition: platform.h:42
Message handler for a specific message type.

References client_connect_cb(), client_disconnect_cb(), global_ret, GNUNET_assert, GNUNET_DISK_PF_NONE, GNUNET_DISK_pipe(), GNUNET_DISK_pipe_close(), GNUNET_free, GNUNET_MESSAGE_TYPE_ARM_LIST, GNUNET_MESSAGE_TYPE_ARM_MONITOR, GNUNET_MESSAGE_TYPE_ARM_START, GNUNET_MESSAGE_TYPE_ARM_STOP, GNUNET_MESSAGE_TYPE_ARM_TEST, GNUNET_MQ_handler_end, GNUNET_MQ_hd_fixed_size, GNUNET_MQ_hd_var_size, GNUNET_SERVICE_OPTION_CLOSE_LSOCKS, GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, GNUNET_SERVICE_run_(), GNUNET_SIGCHLD, GNUNET_SIGNAL_handler_install(), GNUNET_SIGNAL_handler_uninstall(), handlers, list, monitor, run(), shc_chld, sighandler_child_death(), sigpipe, and start.

Here is the call graph for this function:

Variable Documentation

◆ running_head

struct ServiceList* running_head
static

◆ running_tail

struct ServiceList* running_tail
static

List of running services.

Definition at line 211 of file gnunet-service-arm.c.

Referenced by free_service(), and setup_service().

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

Definition at line 216 of file gnunet-service-arm.c.

Referenced by create_listen_socket(), get_server_addresses(), run(), setup_service(), and start_process().

◆ prefix_command

char* prefix_command
static

Command to prepend to each actual command.

Definition at line 221 of file gnunet-service-arm.c.

Referenced by run(), and start_process().

◆ final_option

char* final_option
static

Option to append to each actual command.

Definition at line 226 of file gnunet-service-arm.c.

Referenced by run(), and start_process().

◆ child_death_task

struct GNUNET_SCHEDULER_Task* child_death_task
static

ID of task called whenever we get a SIGCHILD.

Definition at line 231 of file gnunet-service-arm.c.

Referenced by do_shutdown(), maint_child_death(), and run().

◆ child_restart_task

struct GNUNET_SCHEDULER_Task* child_restart_task
static

ID of task called whenever the timeout for restarting a child expires.

Definition at line 237 of file gnunet-service-arm.c.

Referenced by delayed_restart_task(), maint_child_death(), and shutdown_task().

◆ sigpipe

struct GNUNET_DISK_PipeHandle* sigpipe
static

Pipe used to communicate shutdown via signal.

Definition at line 242 of file gnunet-service-arm.c.

Referenced by main(), maint_child_death(), run(), and sighandler_child_death().

◆ in_shutdown

int in_shutdown
static

◆ global_ret

int global_ret
static

Return value from main.

Definition at line 252 of file gnunet-service-arm.c.

Referenced by main(), and run().

◆ start_user

int start_user = GNUNET_YES
static

Are we starting user services?

Definition at line 257 of file gnunet-service-arm.c.

Referenced by run(), and setup_service().

◆ start_system

int start_system = GNUNET_YES
static

Are we starting system services?

Definition at line 262 of file gnunet-service-arm.c.

Referenced by run(), and setup_service().

◆ service

struct GNUNET_SERVICE_Handle* service
static

Handle to our service instance.

Our service is a bit special in that its service is not immediately stopped once we get a shutdown request (since we need to continue service until all of our child processes are dead). This handle is used to shut down the service (and thus trigger process termination) once all child processes are also dead. A special option in the ARM configuration modifies the behaviour of the service implementation to not do the shutdown immediately.

Definition at line 274 of file gnunet-service-arm.c.

Referenced by add_service_handle(), callback_shutdown_service(), check_get(), check_manage_peer_service(), check_set(), check_statistics_value(), check_watch(), close_service_room(), create_message_peer(), create_service(), create_srv_handle(), destroy_service(), do_shutdown(), entry_service_room(), find_subsystem_entry(), free_service_record(), get_service_contact_store(), get_service_ego_store(), get_service_peer_identity(), get_service_room(), gns_string_to_value(), GST_connection_pool_get_handle(), handle_get(), handle_init(), handle_manage_peer_service(), handle_service_message(), handle_set(), handle_statistics_value(), handle_watch(), libgnunet_plugin_transport_tcp_init(), open_service_room(), parse_shared_services(), peer_connect_notify_cb(), remove_service_handle(), run(), shutdown_task(), srv_status(), and store_service().

◆ notifier

struct GNUNET_NotificationContext* notifier
static

Context for notifications we need to send to our clients.

Definition at line 279 of file gnunet-service-arm.c.

Referenced by broadcast_status(), do_shutdown(), handle_monitor(), and run().