GNUnet  0.11.x
Data Structures | Macros | Functions | Variables
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.

Referenced by get_server_addresses().

◆ LOG_STRERROR

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

◆ 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.

Referenced by run().

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.

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

Referenced by get_server_addresses().

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 }
#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.
#define GNUNET_YES
Definition: gnunet_common.h:77
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:219
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.

References _, add_unixpath(), 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_free_non_null, 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, ServiceListeningInfo::next, port, res, and ret.

Referenced by setup_service().

346 {
347  int disablev6;
348  struct GNUNET_NETWORK_Handle *desc;
349  unsigned long long port;
350  char *unixpath;
351  struct addrinfo hints;
352  struct addrinfo *res;
353  struct addrinfo *pos;
354  struct addrinfo *next;
355  unsigned int i;
356  int resi;
357  int ret;
358  int abstract;
359  struct sockaddr **saddrs;
360  socklen_t *saddrlens;
361  char *hostname;
362 
363  *addrs = NULL;
364  *addr_lens = NULL;
365  desc = NULL;
366  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "DISABLEV6"))
367  {
368  if (GNUNET_SYSERR ==
369  (disablev6 = GNUNET_CONFIGURATION_get_value_yesno (cfg,
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 
424  if (GNUNET_CONFIGURATION_have_value (cfg, service_name, "BINDTO"))
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 ==
439  GNUNET_CONFIGURATION_have_value (cfg, service_name, "UNIXPATH")) &&
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
459  abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
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  {
478  GNUNET_free_non_null (hostname);
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);
507  GNUNET_free_non_null (hostname);
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_non_null (unixpath);
516  GNUNET_free_non_null (hostname);
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));
539  GNUNET_free (hostname);
540  GNUNET_free_non_null (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);
559  GNUNET_free (hostname);
560  GNUNET_free_non_null (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  }
607  GNUNET_free (hostname);
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_non_null (unixpath);
668  *addrs = saddrs;
669  *addr_lens = saddrlens;
670  return resi;
671 }
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:684
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define LOG(kind,...)
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
int GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
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)...
static int res
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static char * hostname
Our hostname; we give this to all the peers we start.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
#define LOG_STRERROR(kind, syscall)
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
handle to a socket
Definition: network.c:52
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:158
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
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).
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
#define GNUNET_malloc(size)
Wrapper around malloc.
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:912
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.

References GNUNET_ARM_ResultMessage::arm_msg, env, GNUNET_htonll(), GNUNET_MESSAGE_TYPE_ARM_RESULT, GNUNET_MQ_msg, GNUNET_MQ_send(), GNUNET_SERVICE_client_get_mq(), msg, GNUNET_ARM_Message::request_id, and GNUNET_ARM_ResultMessage::result.

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

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
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
#define GNUNET_MESSAGE_TYPE_ARM_RESULT
Response from ARM.
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_RESULT, with an ID.
Definition: arm.h:91
uint32_t result
Result from the enum GNUNET_ARM_Result
Definition: arm.h:96
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:35
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Reply from ARM to client.
Definition: arm.h:86
const char * name
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:353
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.

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, and GNUNET_ARM_StatusMessage::status.

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

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);
732  GNUNET_MQ_discard (env);
733  }
734  else
735  {
737  }
738 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_MESSAGE_TYPE_ARM_STATUS
Status update from ARM.
Status update from ARM to client.
Definition: arm.h:41
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct GNUNET_MessageHeader header
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_STATUS.
Definition: arm.h:46
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
uint16_t status
See PRISM_STATUS_*-constants.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:321
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
uint32_t status
Status from the &#39;enum GNUNET_ARM_ServiceStatus&#39;.
Definition: arm.h:51
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:189
const char * name
#define GNUNET_log(kind,...)
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
#define GNUNET_YES
Definition: gnunet_common.h:77
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:353
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.

References _, ServiceListeningInfo::accept_task, ServiceList::binary, broadcast_status(), 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_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, and signal_result().

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

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
795  options = GNUNET_CONFIGURATION_expand_dollar (cfg, options);
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  }
829  options = GNUNET_CONFIGURATION_expand_dollar (cfg, options);
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)
860  options = GNUNET_CONFIGURATION_expand_dollar (cfg, options);
863  lsocks,
864  loprefix,
865  quotedbinary,
866  options,
867  NULL);
868  }
869  else
870  {
871  /* actually start process */
873  "Starting service `%s' using binary `%s' and configuration `%s'\n",
874  sl->name,
875  sl->binary,
876  sl->config);
878  GNUNET_asprintf (&quotedbinary, "\"%s\"", binary);
879 
880  if (GNUNET_YES == use_debug)
881  {
882  if (NULL == sl->config)
885  lsocks,
886  loprefix,
887  quotedbinary,
888  "-L",
889  "DEBUG",
890  options,
891  NULL);
892  else
895  lsocks,
896  loprefix,
897  quotedbinary,
898  "-c",
899  sl->config,
900  "-L",
901  "DEBUG",
902  options,
903  NULL);
904  }
905  else
906  {
907  if (NULL == sl->config)
910  lsocks,
911  loprefix,
912  quotedbinary,
913  options,
914  NULL);
915  else
918  lsocks,
919  loprefix,
920  quotedbinary,
921  "-c",
922  sl->config,
923  options,
924  NULL);
925  }
926  }
927  GNUNET_free (binary);
928  GNUNET_free (quotedbinary);
930  if (NULL == sl->proc)
931  {
933  _ ("Failed to start service `%s'\n"),
934  sl->name);
935  if (client)
936  signal_result (client,
937  sl->name,
938  request_id,
940  }
941  else
942  {
944  _ ("Starting service `%s'\n"),
945  sl->name);
947  if (client)
948  signal_result (client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING);
949  }
950  /* clean up */
951  GNUNET_free (loprefix);
952  GNUNET_free (options);
953  GNUNET_array_grow (lsocks, ls, 0);
954 }
struct GNUNET_TIME_Absolute last_started_at
Absolute time at which the process was (re-)started last.
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1080
char * config
Name of the configuration file used.
static char * prefix_command
Command to prepend to each actual command.
struct GNUNET_GETOPT_CommandLineOption options[]
Definition: 002.c:5
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...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze)...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
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.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
Tried to start a service, but that failed for some reason.
Service starting was initiated.
Record with information about a listen socket we have open.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
When these flags are set, the child process will inherit stdout and stderr of the parent...
Definition: gnunet_os_lib.h:97
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
Service starting was initiated.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static struct GNUNET_NETWORK_Handle * ls
Listen socket for STUN processing.
Definition: gnunet-nat.c:85
static char * final_option
Option to append to each actual command.
#define GNUNET_array_append(arr, size, element)
Append an element to a list (growing the list by one).
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
char * binary
Name of the binary used.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
struct GNUNET_OS_Process * GNUNET_OS_start_process_s(int pipe_control, unsigned int std_inheritance, const int *lsocks, const char *filename,...)
Start a process.
Definition: os_priority.c:762
#define GNUNET_log(kind,...)
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 ...
#define GNUNET_YES
Definition: gnunet_common.h:77
char * name
Name of the service.
struct ServiceListeningInfo * next
This is a linked list.
int GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_free(ptr)
Wrapper around free.
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.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
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 965 of file gnunet-service-arm.c.

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

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

966 {
967  struct ServiceList *sl;
968 
969  sl = running_head;
970  while (sl != NULL)
971  {
972  if (0 == strcasecmp (sl->name, name))
973  return sl;
974  sl = sl->next;
975  }
976  return NULL;
977 }
static struct ServiceList * running_head
List of running services.
struct ServiceList * next
This is a doubly-linked list.
List of our services.
const char * name
char * name
Name of the 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 987 of file gnunet-service-arm.c.

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().

988 {
989  struct ServiceListeningInfo *sli = cls;
990  struct ServiceList *sl = sli->sl;
991 
992  sli->accept_task = NULL;
994  start_process (sl, NULL, 0);
995 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
List of our services.
Record with information about a listen socket we have open.
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?
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 1007 of file gnunet-service-arm.c.

References _, accept_connection(), ServiceListeningInfo::accept_task, 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().

1010 {
1011  static int on = 1;
1012  struct GNUNET_NETWORK_Handle *sock;
1013  struct ServiceListeningInfo *sli;
1014 
1015  int match_uid;
1016  int match_gid;
1017 
1018  switch (sa->sa_family)
1019  {
1020  case AF_INET:
1021  sock = GNUNET_NETWORK_socket_create (PF_INET, SOCK_STREAM, 0);
1022  break;
1023 
1024  case AF_INET6:
1025  sock = GNUNET_NETWORK_socket_create (PF_INET6, SOCK_STREAM, 0);
1026  break;
1027 
1028  case AF_UNIX:
1029  if (0 == strcmp (GNUNET_a2s (sa, addr_len),
1030  "@")) /* Do not bind to blank UNIX path! */
1031  return;
1032  sock = GNUNET_NETWORK_socket_create (PF_UNIX, SOCK_STREAM, 0);
1033  break;
1034 
1035  default:
1036  GNUNET_break (0);
1037  sock = NULL;
1038  errno = EAFNOSUPPORT;
1039  break;
1040  }
1041  if (NULL == sock)
1042  {
1044  _ ("Unable to create socket for service `%s': %s\n"),
1045  sl->name,
1046  strerror (errno));
1047  GNUNET_free (sa);
1048  return;
1049  }
1051  SOL_SOCKET,
1052  SO_REUSEADDR,
1053  &on,
1054  sizeof(on)))
1056  "setsockopt");
1057 #ifdef IPV6_V6ONLY
1058  if ((sa->sa_family == AF_INET6) &&
1060  IPPROTO_IPV6,
1061  IPV6_V6ONLY,
1062  &on,
1063  sizeof(on))))
1065  "setsockopt");
1066 #endif
1067  if (AF_UNIX == sa->sa_family)
1068  GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1069  if (GNUNET_OK !=
1070  GNUNET_NETWORK_socket_bind (sock, (const struct sockaddr *) sa, addr_len))
1071  {
1072  GNUNET_log (
1074  _ (
1075  "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1076  sl->name,
1077  GNUNET_a2s (sa, addr_len),
1078  strerror (errno));
1080  GNUNET_free (sa);
1081  return;
1082  }
1083  if ((AF_UNIX == sa->sa_family)
1084 #ifdef LINUX
1085  /* Permission settings are not required when abstract sockets are used */
1086  && ('\0' != ((const struct sockaddr_un *) sa)->sun_path[0])
1087 #endif
1088  )
1089  {
1090  match_uid =
1091  GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "UNIX_MATCH_UID");
1092  match_gid =
1093  GNUNET_CONFIGURATION_get_value_yesno (cfg, sl->name, "UNIX_MATCH_GID");
1094  GNUNET_DISK_fix_permissions (((const struct sockaddr_un *) sa)->sun_path,
1095  match_uid,
1096  match_gid);
1097  }
1098  if (GNUNET_OK != GNUNET_NETWORK_socket_listen (sock, 5))
1099  {
1102  GNUNET_free (sa);
1103  return;
1104  }
1106  _ ("ARM now monitors connections to service `%s' at `%s'\n"),
1107  sl->name,
1108  GNUNET_a2s (sa, addr_len));
1109  sli = GNUNET_new (struct ServiceListeningInfo);
1110  sli->service_addr = sa;
1111  sli->service_addr_len = addr_len;
1112  sli->listen_socket = sock;
1113  sli->sl = sl;
1114  sli->accept_task =
1116  sock,
1118  sli);
1120 }
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:708
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:883
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:485
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
socklen_t service_addr_len
Number of bytes in service_addr.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Record with information about a listen socket we have open.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
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:379
handle to a socket
Definition: network.c:52
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:1486
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:202
char * name
Name of the service.
struct ServiceListeningInfo * listen_tail
Linked list of listen sockets associated with this service.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
#define GNUNET_free(ptr)
Wrapper around free.
struct GNUNET_NETWORK_Handle * GNUNET_NETWORK_socket_create(int domain, int type, int protocol)
Create a new socket.
Definition: network.c:912
struct sockaddr * service_addr
Address this socket is listening on.
static void accept_connection(void *cls)
First connection has come to the listening socket associated with the service, create the service in ...
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 1130 of file gnunet-service-arm.c.

References ServiceList::binary, ServiceList::config, GNUNET_assert, GNUNET_CONTAINER_DLL_remove, GNUNET_free, GNUNET_free_non_null, GNUNET_YES, in_shutdown, ServiceList::listen_head, and ServiceList::name.

Referenced by maint_child_death(), and shutdown_task().

1131 {
1134  GNUNET_assert (NULL == sl->listen_head);
1137  GNUNET_free (sl->name);
1138  GNUNET_free (sl);
1139 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct ServiceList * running_head
List of running services.
char * config
Name of the configuration file used.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static struct ServiceList * running_tail
List of running services.
char * binary
Name of the binary used.
static int in_shutdown
Are we in shutdown mode?
#define GNUNET_YES
Definition: gnunet_common.h:77
char * name
Name of the service.
#define GNUNET_free(ptr)
Wrapper around free.
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 1151 of file gnunet-service-arm.c.

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

1152 {
1153  (void) cls;
1155  return GNUNET_OK;
1156 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...

◆ 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 1166 of file gnunet-service-arm.c.

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(), ServiceListeningInfo::sl, and start_process().

1167 {
1168  struct GNUNET_SERVICE_Client *client = cls;
1169  const char *servicename;
1170  struct ServiceList *sl;
1171  uint64_t request_id;
1172 
1173  request_id = GNUNET_ntohll (amsg->request_id);
1174  servicename = (const char *) &amsg[1];
1176  if (GNUNET_YES == in_shutdown)
1177  {
1178  signal_result (client,
1179  servicename,
1180  request_id,
1182  return;
1183  }
1184  sl = find_service (servicename);
1185  if (NULL == sl)
1186  {
1187  signal_result (client,
1188  servicename,
1189  request_id,
1191  return;
1192  }
1193  sl->force_start = GNUNET_YES;
1194  if (NULL != sl->proc)
1195  {
1196  signal_result (client,
1197  servicename,
1198  request_id,
1200  return;
1201  }
1202  start_process (sl, client, request_id);
1203 }
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
Asked to start it, but it&#39;s already started.
Handle to a client that is connected to a service.
Definition: service.c:250
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
List of our services.
Asked to start something, but ARM is shutting down and can&#39;t comply.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
Asked to start or stop a service, but it&#39;s not known.
static int in_shutdown
Are we in shutdown mode?
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
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 1212 of file gnunet-service-arm.c.

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and GNUNET_SCHEDULER_shutdown().

Referenced by handle_stop().

1213 {
1214  (void) cls;
1215  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1217 }
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:526
#define GNUNET_log(kind,...)
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 1229 of file gnunet-service-arm.c.

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

1230 {
1231  (void) cls;
1233  return GNUNET_OK;
1234 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_MQ_check_zero_termination(m)
Insert code for a "check_" function that verifies that a given variable-length message received over ...

◆ 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 1244 of file gnunet-service-arm.c.

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(), ServiceListeningInfo::sl, and trigger_shutdown().

1245 {
1246  struct GNUNET_SERVICE_Client *client = cls;
1247  struct ServiceList *sl;
1248  const char *servicename;
1249  uint64_t request_id;
1250 
1251  request_id = GNUNET_ntohll (amsg->request_id);
1252  servicename = (const char *) &amsg[1];
1254  _ ("Preparing to stop `%s'\n"),
1255  servicename);
1257  if (0 == strcasecmp (servicename, "arm"))
1258  {
1259  broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1260  signal_result (client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1263  return;
1264  }
1265  sl = find_service (servicename);
1266  if (NULL == sl)
1267  {
1268  signal_result (client,
1269  servicename,
1270  request_id,
1272  return;
1273  }
1274  sl->force_start = GNUNET_NO;
1275  if (GNUNET_YES == in_shutdown)
1276  {
1277  /* shutdown in progress */
1278  signal_result (client,
1279  servicename,
1280  request_id,
1282  return;
1283  }
1284  if (NULL != sl->killing_client)
1285  {
1286  /* killing already in progress */
1287  signal_result (client,
1288  servicename,
1289  request_id,
1291  return;
1292  }
1293  if (NULL == sl->proc)
1294  {
1295  /* process is down */
1296  signal_result (client,
1297  servicename,
1298  request_id,
1300  return;
1301  }
1303  "Sending kill signal to service `%s', waiting for process to die.\n",
1304  servicename);
1305  broadcast_status (servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1306  /* no signal_start - only when it's STOPPED */
1310  sl->killing_client = client;
1311  sl->killing_client_request_id = request_id;
1312 }
ARM stopping was initiated (there&#39;s no "stopped" for ARM itself).
Service stopping was initiated.
Asked to stop it, but it&#39;s already stopping.
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
#define GNUNET_NO
Definition: gnunet_common.h:78
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Handle to a client that is connected to a service.
Definition: service.c:250
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
List of our services.
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:1280
static void trigger_shutdown(void *cls)
Start a shutdown sequence.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
Asked to start something, but ARM is shutting down and can&#39;t comply.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
Asked to stop it, but it&#39;s already stopped.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
#define GNUNET_log(kind,...)
Asked to start or stop a service, but it&#39;s not known.
static int in_shutdown
Are we in shutdown mode?
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate)...
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:242
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process...
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:48
void GNUNET_SERVICE_client_persist(struct GNUNET_SERVICE_Client *c)
Set the persist option on this client.
Definition: service.c:2424
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.
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:225
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 1327 of file gnunet-service-arm.c.

References GNUNET_OK, and GNUNET_SYSERR.

Referenced by handle_list().

1328 {
1329  size_t next_pos = (*pool_pos) + strlen (str) + 1;
1330 
1331  if (next_pos > pool_size)
1332  return GNUNET_SYSERR;
1333  memcpy (pool_start + *pool_pos, str, strlen (str) + 1);
1334  *pool_pos = next_pos;
1335  return GNUNET_OK;
1336 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
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
messagethe actual message

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

References GNUNET_TIME_Absolute::abs_value_us, GNUNET_ARM_ListResultMessage::arm_msg, ServiceList::binary, GNUNET_ARM_ServiceInfoMessage::binary_index, GNUNET_ARM_ListResultMessage::count, 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, GNUNET_ARM_Message::request_id, GNUNET_ARM_Message::reserved, GNUNET_ARM_ServiceInfoMessage::restart_at, ServiceList::restart_at, ServiceListeningInfo::sl, and GNUNET_ARM_ServiceInfoMessage::status.

1347 {
1348  struct GNUNET_SERVICE_Client *client = cls;
1349  struct GNUNET_MQ_Envelope *env;
1351  size_t extra_size;
1352  struct ServiceList *sl;
1353  uint16_t count;
1354  size_t pool_size;
1355  size_t pool_pos;
1356  char *pool_start;
1357  struct GNUNET_ARM_ServiceInfoMessage *ssm;
1358 
1359  GNUNET_break_op (0 == ntohl (request->reserved));
1360  count = 0;
1361  pool_size = 0;
1362 
1363  /* Do one pass over the list to compute the number of services
1364  * and the string pool size */
1365  for (sl = running_head; NULL != sl; sl = sl->next)
1366  {
1367  pool_size += strlen (sl->name) + 1;
1368  pool_size += strlen (sl->binary) + 1;
1369  count++;
1370  }
1371 
1372  extra_size = pool_size + (count * sizeof (struct
1374  env = GNUNET_MQ_msg_extra (msg,
1375  extra_size,
1377  msg->arm_msg.request_id = request->request_id;
1378  msg->count = htons (count);
1379 
1380  ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &msg[1];
1381  pool_start = (char *) (ssm + count);
1382  pool_pos = 0;
1383 
1384  for (sl = running_head; NULL != sl; sl = sl->next)
1385  {
1386  ssm->name_index = htons ((uint16_t) pool_pos);
1387  GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1388  sl->name));
1389  ssm->binary_index = htons ((uint16_t) pool_pos);
1390  GNUNET_assert (GNUNET_OK == pool_write (pool_start, pool_size, &pool_pos,
1391  sl->binary));
1392  if (NULL == sl->proc)
1393  {
1394  if (0 == sl->last_started_at.abs_value_us)
1395  {
1396  /* Process never started */
1398  }
1399  else if (0 == sl->last_exit_status)
1400  {
1402  }
1403  else
1404  {
1406  ssm->last_exit_status = htons (sl->last_exit_status);
1407  }
1408  }
1409  else if ((NULL != sl->killing_client) || (GNUNET_YES == in_shutdown))
1410  {
1412  }
1413  else
1414  {
1416  }
1419  ssm++;
1420  }
1423 }
struct GNUNET_TIME_Absolute last_started_at
Absolute time at which the process was (re-)started last.
The service has previously failed, and will be restarted.
static struct ServiceList * running_head
List of running services.
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
Response from ARM for listing currently running services.
The service was started, but then exited normally.
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, with an ID.
Definition: arm.h:150
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
uint32_t reserved
For alignment.
Definition: arm.h:70
uint64_t abs_value_us
The actual value.
uint16_t count
Number of &#39;struct GNUNET_ARM_ServiceInfoMessage&#39; that are at the end of this message.
Definition: arm.h:156
The service was started, and we&#39;re currently waiting for it to be stopped.
struct ServiceList * next
This is a doubly-linked list.
Handle to a client that is connected to a service.
Definition: service.c:250
List of our services.
int last_exit_status
Last exit status of the process.
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
uint16_t name_index
String pool index for the service&#39;s name.
Definition: arm.h:104
Service has been started and is currently running.
int16_t last_exit_status
Last process exit status.
Definition: arm.h:114
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Reply from ARM to client for the GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count &#39;\0&#39; terminat...
Definition: arm.h:144
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
struct GNUNET_TIME_AbsoluteNBO last_started_at
Time when the sevice was first started, if applicable.
Definition: arm.h:135
char * binary
Name of the binary used.
uint32_t status
Status from the &#39;enum GNUNET_ARM_ServiceStatus&#39;.
Definition: arm.h:124
static int in_shutdown
Are we in shutdown mode?
#define GNUNET_YES
Definition: gnunet_common.h:77
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:353
char * name
Name of the service.
struct GNUNET_TIME_AbsoluteNBO GNUNET_TIME_absolute_hton(struct GNUNET_TIME_Absolute a)
Convert absolute time to network byte order.
Definition: time.c:657
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process...
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
struct GNUNET_TIME_AbsoluteNBO restart_at
Time when the sevice will be restarted, if applicable to the current status.
Definition: arm.h:130
uint16_t binary_index
String pool index for the service&#39;s binary.
Definition: arm.h:109
static int pool_write(char *pool_start, size_t pool_size, size_t *pool_pos, char *str)
Write a string to a string pool.
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 1433 of file gnunet-service-arm.c.

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

1434 {
1435  struct GNUNET_SERVICE_Client *client = cls;
1436  struct GNUNET_MQ_Envelope *env;
1437  struct GNUNET_MessageHeader *msg;
1438 
1439  (void) message;
1443 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
Handle to a client that is connected to a service.
Definition: service.c:250
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
#define GNUNET_MESSAGE_TYPE_ARM_TEST
Test if ARM service is online.
Header for all communications.
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:353
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
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 1451 of file gnunet-service-arm.c.

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, GNUNET_notification_context_destroy(), GNUNET_SCHEDULER_cancel(), and GNUNET_SERVICE_shutdown().

Referenced by maint_child_death(), and shutdown_task().

1452 {
1453  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1454  if (NULL != notifier)
1455  {
1457  notifier = NULL;
1458  }
1459  if (NULL != service)
1460  {
1462  service = NULL;
1463  }
1464  if (NULL != child_death_task)
1465  {
1467  child_death_task = NULL;
1468  }
1469 }
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static struct GNUNET_SCHEDULER_Task * child_death_task
ID of task called whenever we get a SIGCHILD.
#define GNUNET_log(kind,...)
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
void GNUNET_notification_context_destroy(struct GNUNET_NotificationContext *nc)
Destroy the context, force disconnect for all subscribers.
Definition: nc.c:137
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2383
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
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 1479 of file gnunet-service-arm.c.

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

Referenced by maint_child_death(), and shutdown_task().

1480 {
1481  struct ServiceList *i;
1482  unsigned int res;
1483 
1484  for (res = 0, i = running_head; NULL != i; i = i->next, res++)
1485  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s\n", i->name);
1486  return res;
1487 }
struct ServiceList * next
This is a doubly-linked list.
List of our services.
static int res
#define GNUNET_log(kind,...)
char * name
Name of the service.
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 1496 of file gnunet-service-arm.c.

References ServiceListeningInfo::accept_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().

1497 {
1498  struct ServiceList *pos;
1499  struct ServiceList *nxt;
1500  struct ServiceListeningInfo *sli;
1501 
1502  (void) cls;
1503  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1504  if (NULL != child_restart_task)
1505  {
1507  child_restart_task = NULL;
1508  }
1510  /* first, stop listening */
1511  for (pos = running_head; NULL != pos; pos = pos->next)
1512  {
1513  while (NULL != (sli = pos->listen_head))
1514  {
1516  if (NULL != sli->accept_task)
1517  {
1519  sli->accept_task = NULL;
1520  }
1523  GNUNET_free (sli->service_addr);
1524  GNUNET_free (sli);
1525  }
1526  }
1527  /* then, shutdown all existing service processes */
1528  nxt = running_head;
1529  while (NULL != (pos = nxt))
1530  {
1531  nxt = pos->next;
1532  if (NULL != pos->proc)
1533  {
1534  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1536  if (0 != GNUNET_OS_process_kill (pos->proc, GNUNET_TERM_SIG))
1538  }
1539  else
1540  {
1541  free_service (pos);
1542  }
1543  }
1544  /* finally, should all service processes be already gone, terminate for real */
1545  if (NULL == running_head)
1546  do_shutdown ();
1547  else
1549  "Delaying shutdown, have %u childs still running\n",
1551 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct ServiceList * running_head
List of running services.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
static unsigned int list_count(struct ServiceList *running_head)
Count how many services are still active.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
struct ServiceList * next
This is a doubly-linked list.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
List of our services.
Record with information about a listen socket we have open.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static void free_service(struct ServiceList *sl)
Remove and free an entry in the service list.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
static int in_shutdown
Are we in shutdown mode?
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
#define GNUNET_YES
Definition: gnunet_common.h:77
char * name
Name of the service.
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate)...
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:242
struct ServiceListeningInfo * listen_tail
Linked list of listen sockets associated with this service.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:560
static void do_shutdown()
We are done with everything.
#define GNUNET_free(ptr)
Wrapper around free.
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:225
struct sockaddr * service_addr
Address this socket is listening on.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
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 1560 of file gnunet-service-arm.c.

References _, accept_connection(), ServiceListeningInfo::accept_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, ServiceListeningInfo::sl, and start_process().

Referenced by maint_child_death().

1562 {
1563  struct ServiceList *sl;
1564  struct GNUNET_TIME_Relative lowestRestartDelay;
1565  struct ServiceListeningInfo *sli;
1566 
1567  (void) cls;
1568  child_restart_task = NULL;
1570  lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1571 
1572  /* check for services that need to be restarted due to
1573  * configuration changes or because the last restart failed */
1574  for (sl = running_head; NULL != sl; sl = sl->next)
1575  {
1576  if (NULL != sl->proc)
1577  continue;
1578  /* service is currently not running */
1580  {
1581  /* restart is now allowed */
1582  if (sl->force_start)
1583  {
1584  /* process should run by default, start immediately */
1586  _ ("Restarting service `%s'.\n"),
1587  sl->name);
1588  start_process (sl, NULL, 0);
1589  }
1590  else
1591  {
1592  /* process is run on-demand, ensure it is re-started if there is demand */
1593  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1594  if (NULL == sli->accept_task)
1595  {
1596  /* accept was actually paused, so start it again */
1597  sli->accept_task =
1599  sli->listen_socket,
1601  sli);
1602  }
1603  }
1604  }
1605  else
1606  {
1607  /* update calculation for earliest time to reactivate a service */
1608  lowestRestartDelay =
1609  GNUNET_TIME_relative_min (lowestRestartDelay,
1611  sl->restart_at));
1612  }
1613  }
1614  if (lowestRestartDelay.rel_value_us !=
1615  GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1616  {
1618  "Will restart process in %s\n",
1619  GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1620  GNUNET_YES));
1622  GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
1625  NULL);
1626  }
1627 }
static struct ServiceList * running_head
List of running services.
uint64_t rel_value_us
The actual value.
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:1183
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct ServiceList * next
This is a doubly-linked list.
List of our services.
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:687
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Record with information about a listen socket we have open.
static void delayed_restart_task(void *cls)
Task run whenever it is time to restart a child that died.
Run when otherwise idle.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
static int in_shutdown
Are we in shutdown mode?
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1486
char * name
Name of the service.
struct ServiceListeningInfo * next
This is a linked list.
Time for relative time used by GNUnet, in microseconds.
static void accept_connection(void *cls)
First connection has come to the listening socket associated with the service, create the service in ...
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 1637 of file gnunet-service-arm.c.

References _, GNUNET_TIME_Absolute::abs_value_us, accept_connection(), ServiceListeningInfo::accept_task, ServiceList::backoff, ServiceList::binary, broadcast_status(), 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(), and status.

Referenced by run().

1638 {
1639  struct ServiceList *pos;
1640  struct ServiceList *next;
1641  struct ServiceListeningInfo *sli;
1642  const char *statstr;
1643  int statcode;
1644  int ret;
1645  char c[16];
1646  enum GNUNET_OS_ProcessStatusType statusType;
1647  unsigned long statusCode;
1648  const struct GNUNET_DISK_FileHandle *pr;
1649 
1650  (void) cls;
1652  child_death_task = NULL;
1653  /* consume the signal */
1654  GNUNET_break (0 < GNUNET_DISK_file_read (pr, &c, sizeof(c)));
1655 
1656  /* check for services that died (WAITPID) */
1657  next = running_head;
1658  while (NULL != (pos = next))
1659  {
1660  next = pos->next;
1661 
1662  if (NULL == pos->proc)
1663  {
1664  if (GNUNET_YES == in_shutdown)
1665  free_service (pos);
1666  continue;
1667  }
1668 #if HAVE_WAIT4
1669  if (NULL != wait_file)
1670  {
1671  /* need to use 'wait4()' to obtain and log performance data */
1672  struct rusage ru;
1673  int status;
1674  pid_t pid;
1675 
1676  pid = GNUNET_OS_process_get_pid (pos->proc);
1677  ret = wait4 (pid, &status, WNOHANG, &ru);
1678  if (ret <= 0)
1679  continue; /* no process done */
1680  if (WIFEXITED (status))
1681  {
1682  statusType = GNUNET_OS_PROCESS_EXITED;
1683  statusCode = WEXITSTATUS (status);
1684  }
1685  else if (WIFSIGNALED (status))
1686  {
1687  statusType = GNUNET_OS_PROCESS_SIGNALED;
1688  statusCode = WTERMSIG (status);
1689  }
1690  else if (WIFSTOPPED (status))
1691  {
1692  statusType = GNUNET_OS_PROCESS_SIGNALED;
1693  statusCode = WSTOPSIG (status);
1694  }
1695 #ifdef WIFCONTINUED
1696  else if (WIFCONTINUED (status))
1697  {
1698  statusType = GNUNET_OS_PROCESS_RUNNING;
1699  statusCode = 0;
1700  }
1701 #endif
1702  else
1703  {
1704  statusType = GNUNET_OS_PROCESS_UNKNOWN;
1705  statusCode = 0;
1706  }
1707  if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1708  (GNUNET_OS_PROCESS_SIGNALED == statusType))
1709  {
1710  double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1711  double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1712  fprintf (wait_file,
1713  "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1714  pos->binary,
1715  (unsigned int) pid,
1716  utime,
1717  stime,
1718  (unsigned long long) ru.ru_maxrss,
1719  (unsigned long long) ru.ru_inblock,
1720  (unsigned long long) ru.ru_oublock,
1721  (unsigned long long) ru.ru_nvcsw,
1722  (unsigned long long) ru.ru_nivcsw);
1723  }
1724  }
1725  else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1726 #endif
1727  if ((GNUNET_SYSERR == (ret = GNUNET_OS_process_status (pos->proc,
1728  &statusType,
1729  &statusCode))) ||
1730  (ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1731  (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1732  (statusType == GNUNET_OS_PROCESS_RUNNING))
1733  continue;
1734 
1735  if (statusType == GNUNET_OS_PROCESS_EXITED)
1736  {
1737  statstr = _ (/* process termination method */ "exit");
1738  statcode = statusCode;
1739  }
1740  else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1741  {
1742  statstr = _ (/* process termination method */ "signal");
1743  statcode = statusCode;
1744  }
1745  else
1746  {
1747  statstr = _ (/* process termination method */ "unknown");
1748  statcode = 0;
1749  }
1750  if (0 != pos->killed_at.abs_value_us)
1751  {
1753  _ ("Service `%s' took %s to terminate\n"),
1754  pos->name,
1757  GNUNET_YES));
1758  }
1760  pos->proc = NULL;
1762  if (NULL != pos->killing_client)
1763  {
1765  pos->name,
1768  pos->killing_client = NULL;
1769  pos->killing_client_request_id = 0;
1770  }
1771  if (GNUNET_YES != in_shutdown)
1772  {
1773  pos->last_exit_status = statcode;
1774  if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1775  {
1776  /* process terminated normally, allow restart at any time */
1777  pos->restart_at.abs_value_us = 0;
1778  GNUNET_log (
1780  _ ("Service `%s' terminated normally, will restart at any time\n"),
1781  pos->name);
1782  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1783  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1784  {
1785  GNUNET_break (NULL == sli->accept_task);
1786  sli->accept_task =
1788  sli->listen_socket,
1790  sli);
1791  }
1792  }
1793  else
1794  {
1795  GNUNET_log (
1797  _ ("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1798  pos->name,
1799  statstr,
1800  statcode,
1802  {
1803  /* Reduce backoff based on runtime of the process,
1804  so that there is a cool-down if a process actually
1805  runs for a while. */
1806  struct GNUNET_TIME_Relative runtime;
1807  unsigned int minutes;
1808 
1810  minutes =
1811  runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1812  if (minutes > 31)
1814  else
1815  pos->backoff.rel_value_us <<= minutes;
1816  }
1817  /* schedule restart */
1819  pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
1820  if (NULL != child_restart_task)
1825  NULL);
1826  }
1827  }
1828  else
1829  {
1830  free_service (pos);
1831  }
1832  }
1835  pr,
1837  NULL);
1838  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1839  do_shutdown ();
1840  else if (GNUNET_YES == in_shutdown)
1842  "Delaying shutdown after child's death, still have %u children\n",
1844 }
static struct ServiceList * running_head
List of running services.
pid_t GNUNET_OS_process_get_pid(struct GNUNET_OS_Process *proc)
Get the pid of the process in question.
Definition: os_priority.c:274
uint64_t rel_value_us
The actual value.
static struct GNUNET_SCHEDULER_Task * child_death_task
ID of task called whenever we get a SIGCHILD.
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:287
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:732
int GNUNET_OS_process_status(struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Retrieve the status of a process, waiting on it if dead.
Definition: os_priority.c:963
#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:246
struct GNUNET_TIME_Relative backoff
Process exponential backoff time.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
static unsigned int list_count(struct ServiceList *running_head)
Count how many services are still active.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1636
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1753
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct ServiceList * next
This is a doubly-linked list.
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.
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).
List of our services.
int last_exit_status
Last exit status of the process.
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:1207
GNUNET_OS_ProcessStatusType
Process status types.
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:687
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Record with information about a listen socket we have open.
The reading-end of a pipe.
The process exited with a return code.
static void delayed_restart_task(void *cls)
Task run whenever it is time to restart a child that died.
Run when otherwise idle.
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
Service was stopped.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
The process was killed by a signal.
static void free_service(struct ServiceList *sl)
Remove and free an entry in the service list.
#define GNUNET_TIME_UNIT_ZERO
Relative time zero.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
char * binary
Name of the binary used.
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:375
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
The process is still running.
static int in_shutdown
Are we in shutdown mode?
The process is not known to the OS (or at least not one of our children).
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1486
char * name
Name of the service.
struct ServiceListeningInfo * next
This is a linked list.
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate)...
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
Service was stopped (never sent for ARM itself).
Handle used to access files (and pipes).
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process...
The process is paused (but could be resumed).
static void do_shutdown()
We are done with everything.
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.
Time for relative time used by GNUnet, in microseconds.
static void accept_connection(void *cls)
First connection has come to the listening socket associated with the service, create the service in ...
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:966
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sighandler_child_death()

static void sighandler_child_death ( )
static

Signal handler called for SIGCHLD.

Triggers the respective handler by writing to the trigger pipe.

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

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

Referenced by main().

1853 {
1854  static char c;
1855  int old_errno = errno; /* back-up errno */
1856 
1857  GNUNET_break (
1858  1 ==
1861  &c,
1862  sizeof(c)));
1863  errno = old_errno; /* restore errno */
1864 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1753
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:820
The writing-end of a pipe.
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
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 1876 of file gnunet-service-arm.c.

References ServiceList::backoff, ServiceList::binary, config, ServiceList::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, ServiceList::name, ServiceList::pipe_control, ServiceList::restart_at, ret, ServiceListeningInfo::sl, start_system, and start_user.

Referenced by run().

1877 {
1878  struct ServiceList *sl;
1879  char *binary;
1880  char *config;
1881  struct stat sbuf;
1882  struct sockaddr **addrs;
1883  socklen_t *addr_lens;
1884  int ret;
1885 
1886  (void) cls;
1887  if (0 == strcasecmp (section, "arm"))
1888  return;
1889  if (GNUNET_OK !=
1890  GNUNET_CONFIGURATION_get_value_string (cfg, section, "BINARY", &binary))
1891  {
1892  /* not a service section */
1893  return;
1894  }
1895  if ((GNUNET_YES ==
1896  GNUNET_CONFIGURATION_have_value (cfg, section, "RUN_PER_USER")) &&
1897  (GNUNET_YES ==
1898  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "RUN_PER_USER")))
1899  {
1900  if (GNUNET_NO == start_user)
1901  {
1902  GNUNET_free (binary);
1903  return; /* user service, and we don't deal with those */
1904  }
1905  }
1906  else
1907  {
1908  if (GNUNET_NO == start_system)
1909  {
1910  GNUNET_free (binary);
1911  return; /* system service, and we don't deal with those */
1912  }
1913  }
1914  sl = find_service (section);
1915  if (NULL != sl)
1916  {
1917  /* got the same section twice!? */
1918  GNUNET_break (0);
1919  GNUNET_free (binary);
1920  return;
1921  }
1922  config = NULL;
1924  section,
1925  "CONFIG",
1926  &config)) &&
1928  "PATHS",
1929  "DEFAULTCONFIG",
1930  &config))) ||
1931  (0 != stat (config, &sbuf)))
1932  {
1933  if (NULL != config)
1934  {
1936  section,
1937  "CONFIG",
1938  strerror (errno));
1939  GNUNET_free (config);
1940  config = NULL;
1941  }
1942  }
1943  sl = GNUNET_new (struct ServiceList);
1944  sl->name = GNUNET_strdup (section);
1945  sl->binary = binary;
1946  sl->config = config;
1949  if (GNUNET_CONFIGURATION_have_value (cfg, section, "PIPECONTROL"))
1950  sl->pipe_control =
1953  if (GNUNET_YES ==
1954  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "IMMEDIATE_START"))
1955  {
1956  sl->force_start = GNUNET_YES;
1957  if (GNUNET_YES ==
1959  return;
1960  }
1961  else
1962  {
1963  if (GNUNET_YES !=
1964  GNUNET_CONFIGURATION_get_value_yesno (cfg, section, "START_ON_DEMAND"))
1965  return;
1966  }
1967  if (0 >= (ret = get_server_addresses (section, cfg, &addrs, &addr_lens)))
1968  return;
1969  /* this will free (or capture) addrs[i] */
1970  for (unsigned int i = 0; i < (unsigned int) ret; i++)
1971  create_listen_socket (addrs[i], addr_lens[i], sl);
1972  GNUNET_free (addrs);
1973  GNUNET_free (addr_lens);
1974 }
static struct ServiceList * running_head
List of running services.
char * config
Name of the configuration file used.
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct GNUNET_TIME_Relative backoff
Process exponential backoff time.
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze)...
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
static void create_listen_socket(struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl)
Creating a listening socket for each of the service&#39;s addresses and wait for the first incoming conne...
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static int start_user
Are we starting user services?
#define GNUNET_TIME_UNIT_FOREVER_ABS
Constant used to specify "forever".
static char * section
Name of the section.
Definition: gnunet-config.c:33
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
List of our services.
int GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
static const struct GNUNET_CONFIGURATION_Handle * config
static struct ServiceList * running_tail
List of running services.
#define GNUNET_TIME_UNIT_MILLISECONDS
One millisecond.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static 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.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
char * binary
Name of the binary used.
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
#define GNUNET_YES
Definition: gnunet_common.h:77
char * name
Name of the service.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_free(ptr)
Wrapper around free.
static int start_system
Are we starting system services?
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 1986 of file gnunet-service-arm.c.

References GNUNET_SERVICE_client_mark_monitor().

Referenced by main().

1989 {
1990  /* All clients are considered to be of the "monitor" kind
1991  * (that is, they don't affect ARM shutdown).
1992  */
1993  (void) cls;
1994  (void) mq;
1996  return client;
1997 }
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2407
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 2008 of file gnunet-service-arm.c.

References GNUNET_assert, ServiceList::killing_client, ServiceList::next, and ServiceListeningInfo::sl.

Referenced by main().

2011 {
2012  (void) cls;
2013  GNUNET_assert (client == app_ctx);
2014  for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2015  if (sl->killing_client == client)
2016  sl->killing_client = NULL;
2017 }
static struct ServiceList * running_head
List of running services.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ServiceList * next
This is a doubly-linked list.
List of our services.
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 2029 of file gnunet-service-arm.c.

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

2030 {
2031  struct GNUNET_SERVICE_Client *client = cls;
2032 
2033  (void) message;
2034  /* FIXME: might want to start by letting monitor know about
2035  services that are already running */
2036  /* Removal is handled by the server implementation, internally. */
2038  GNUNET_SERVICE_client_get_mq (client));
2041 }
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2437
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:160
Handle to a client that is connected to a service.
Definition: service.c:250
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2243
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.
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 2052 of file gnunet-service-arm.c.

References 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, prefix_command, setup_service(), shutdown_task(), ServiceListeningInfo::sl, start_process(), start_system, and start_user.

Referenced by main().

2055 {
2056  struct ServiceList *sl;
2057 
2058  (void) cls;
2059  cfg = c;
2060  service = serv;
2066  NULL);
2067 #if HAVE_WAIT4
2068  if (GNUNET_OK ==
2070  "ARM",
2071  "RESOURCE_DIAGNOSTICS",
2072  &wait_filename))
2073  {
2074  wait_file = fopen (wait_filename, "w");
2075  if (NULL == wait_file)
2076  {
2078  "fopen",
2079  wait_filename);
2080  }
2081  }
2082 #endif
2084  "ARM",
2085  "GLOBAL_PREFIX",
2086  &prefix_command))
2088  else
2091  "ARM",
2092  "GLOBAL_POSTFIX",
2093  &final_option))
2094  final_option = GNUNET_strdup ("");
2095  else
2097  start_user =
2098  GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "START_USER_SERVICES");
2099  start_system =
2100  GNUNET_CONFIGURATION_get_value_yesno (cfg, "ARM", "START_SYSTEM_SERVICES");
2101  if ((GNUNET_NO == start_user) && (GNUNET_NO == start_system))
2102  {
2103  GNUNET_log (
2105  "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
2107  global_ret = 1;
2108  return;
2109  }
2111 
2112  /* start default services... */
2113  for (sl = running_head; NULL != sl; sl = sl->next)
2114  if (GNUNET_YES == sl->force_start)
2115  start_process (sl, NULL, 0);
2117 }
static struct ServiceList * running_head
List of running services.
static struct GNUNET_SERVICE_Handle * service
Handle to our service instance.
static char * prefix_command
Command to prepend to each actual command.
static struct GNUNET_SCHEDULER_Task * child_death_task
ID of task called whenever we get a SIGCHILD.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_shutdown(GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run on shutdown, that is when a CTRL-C signal is received, or when GNUNET_SCHEDULER_shutdown() is being invoked.
Definition: scheduler.c:1300
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...
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1636
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:526
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
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:1753
static int start_user
Are we starting user services?
struct ServiceList * next
This is a doubly-linked list.
List of our services.
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define MAX_NOTIFY_QUEUE
How many messages do we queue up at most for optional notifications to a client? (this can cause noti...
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
The reading-end of a pipe.
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
static void shutdown_task(void *cls)
Task run for shutdown.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
static char * final_option
Option to append to each actual command.
struct GNUNET_NotificationContext * GNUNET_notification_context_create(unsigned int queue_length)
Create a new notification context.
Definition: nc.c:121
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls)
Iterate over all sections in the configuration.
#define GNUNET_log(kind,...)
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static int global_ret
Return value from main.
static void setup_service(void *cls, const char *section)
Setup our service record for the given section in the configuration file (assuming the section is for...
static int start_system
Are we starting system services?
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 2128 of file gnunet-service-arm.c.

References __attribute__, client_connect_cb(), client_disconnect_cb(), global_ret, GNUNET_assert, 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_NO, GNUNET_SERVICE_OPTION_CLOSE_LSOCKS, GNUNET_SERVICE_OPTION_MANUAL_SHUTDOWN, GNUNET_SERVICE_run_(), GNUNET_SIGCHLD, GNUNET_SIGNAL_handler_install(), GNUNET_SIGNAL_handler_uninstall(), list, monitor, run(), sighandler_child_death(), and start.

2129 {
2130  struct GNUNET_SIGNAL_Context *shc_chld;
2131  struct GNUNET_MQ_MessageHandler handlers[] = {
2134  struct GNUNET_ARM_Message,
2135  NULL),
2136  GNUNET_MQ_hd_var_size (stop,
2138  struct GNUNET_ARM_Message,
2139  NULL),
2142  struct GNUNET_MessageHeader,
2143  NULL),
2146  struct GNUNET_ARM_Message,
2147  NULL),
2150  struct GNUNET_MessageHeader,
2151  NULL),
2153  };
2154 
2156  GNUNET_assert (NULL != sigpipe);
2157  shc_chld =
2160  if (0 != GNUNET_SERVICE_run_ (argc,
2161  argv,
2162  "arm",
2165  &run,
2168  NULL,
2169  handlers))
2170  global_ret = 2;
2171 #if HAVE_WAIT4
2172  if (NULL != wait_file)
2173  {
2174  fclose (wait_file);
2175  wait_file = NULL;
2176  }
2177  if (NULL != wait_filename)
2178  {
2179  GNUNET_free (wait_filename);
2180  wait_filename = NULL;
2181  }
2182 #endif
2184  shc_chld = NULL;
2186  sigpipe = NULL;
2187  return global_ret;
2188 }
#define GNUNET_SIGCHLD
Definition: platform.h:42
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up associated state.
#define GNUNET_MESSAGE_TYPE_ARM_START
Request to ARM to start a service.
#define GNUNET_MESSAGE_TYPE_ARM_STOP
Request to ARM to stop a service.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_NO
Definition: gnunet_common.h:78
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:77
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 struct GNUNET_CADET_MessageHandler handlers[]
Handlers, for diverse services.
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
Message handler for a specific message type.
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(int blocking_read, int blocking_write, int inherit_read, int inherit_write)
Creates an interprocess channel.
Definition: disk.c:1526
static struct GNUNET_DISK_PipeHandle * sigpipe
Pipe used to communicate shutdown via signal.
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:51
Instead of listening on lsocks passed by the parent, close them after opening our own listen socket(s...
#define GNUNET_MESSAGE_TYPE_ARM_LIST
Request to ARM to list all currently running services.
int GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1715
#define GNUNET_MESSAGE_TYPE_ARM_TEST
Test if ARM service is online.
#define GNUNET_MESSAGE_TYPE_ARM_MONITOR
Request to ARM to notify client of service status changes.
static int monitor
Monitor ARM activity.
Definition: gnunet-arm.c:64
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:1966
Header for all communications.
static void * client_connect_cb(void *cls, struct GNUNET_SERVICE_Client *client, struct GNUNET_MQ_Handle *mq)
A client connected, mark as a monitoring client.
static int global_ret
Return value from main.
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
static int list
Set if we should print a list of currently running services.
Definition: gnunet-arm.c:69
#define GNUNET_free(ptr)
Wrapper around free.
Here is the call graph for this function:

Variable Documentation

◆ running_head

struct ServiceList* running_head
static

List of running services.

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

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

◆ running_tail

struct ServiceList* running_tail
static

List of running services.

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

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

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

◆ 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.

◆ 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.

◆ sigpipe

struct GNUNET_DISK_PipeHandle* sigpipe
static

Pipe used to communicate shutdown via signal.

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

◆ 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 check_get(), check_set(), check_statistics_value(), check_watch(), free_service_record(), gns_string_to_value(), GST_connection_pool_get_handle(), handle_get(), handle_init(), handle_set(), handle_statistics_value(), handle_watch(), libgnunet_plugin_transport_tcp_init(), parse_shared_services(), run(), and shutdown_task().

◆ 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.