GNUnet  0.10.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_ServiceStatus 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 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 55 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 283 of file gnunet-service-arm.c.

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

Referenced by get_server_addresses().

287 {
288 #ifdef AF_UNIX
289  struct sockaddr_un *un;
290 
291  un = GNUNET_new (struct sockaddr_un);
292  un->sun_family = AF_UNIX;
293  GNUNET_strlcpy (un->sun_path, unixpath, sizeof (un->sun_path));
294 #ifdef LINUX
295  if (GNUNET_YES == abstract)
296  un->sun_path[0] = '\0';
297 #endif
298 #if HAVE_SOCKADDR_UN_SUN_LEN
299  un->sun_len = (u_char) sizeof (struct sockaddr_un);
300 #endif
301  *saddrs = (struct sockaddr *) un;
302  *saddrlens = sizeof (struct sockaddr_un);
303 #else
304  /* this function should never be called
305  * unless AF_UNIX is defined! */
306  GNUNET_assert (0);
307 #endif
308 }
#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:80
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
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 332 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, ret, and STRERROR.

Referenced by setup_service().

336 {
337  int disablev6;
338  struct GNUNET_NETWORK_Handle *desc;
339  unsigned long long port;
340  char *unixpath;
341  struct addrinfo hints;
342  struct addrinfo *res;
343  struct addrinfo *pos;
344  struct addrinfo *next;
345  unsigned int i;
346  int resi;
347  int ret;
348  int abstract;
349  struct sockaddr **saddrs;
350  socklen_t *saddrlens;
351  char *hostname;
352 
353  *addrs = NULL;
354  *addr_lens = NULL;
355  desc = NULL;
357  service_name,
358  "DISABLEV6"))
359  {
360  if (GNUNET_SYSERR ==
361  (disablev6 =
363  service_name,
364  "DISABLEV6")))
365  return GNUNET_SYSERR;
366  }
367  else
368  disablev6 = GNUNET_NO;
369 
370  if (! disablev6)
371  {
372  /* probe IPv6 support */
373  desc = GNUNET_NETWORK_socket_create (PF_INET6,
374  SOCK_STREAM,
375  0);
376  if (NULL == desc)
377  {
378  if ( (ENOBUFS == errno) ||
379  (ENOMEM == errno) ||
380  (ENFILE == errno) ||
381  (EACCES == errno) )
382  {
384  "socket");
385  return GNUNET_SYSERR;
386  }
388  _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
389  service_name,
390  STRERROR (errno));
391  disablev6 = GNUNET_YES;
392  }
393  else
394  {
396  desc = NULL;
397  }
398  }
399 
400  port = 0;
402  service_name,
403  "PORT"))
404  {
405  if (GNUNET_OK !=
407  service_name,
408  "PORT",
409  &port))
410  {
412  _("Require valid port number for service `%s' in configuration!\n"),
413  service_name);
414  }
415  if (port > 65535)
416  {
418  _("Require valid port number for service `%s' in configuration!\n"),
419  service_name);
420  return GNUNET_SYSERR;
421  }
422  }
423 
425  service_name,
426  "BINDTO"))
427  {
430  service_name,
431  "BINDTO",
432  &hostname));
433  }
434  else
435  hostname = NULL;
436 
437  unixpath = NULL;
438  abstract = GNUNET_NO;
439 #ifdef AF_UNIX
440  if ((GNUNET_YES ==
442  service_name,
443  "UNIXPATH")) &&
444  (GNUNET_OK ==
446  service_name,
447  "UNIXPATH",
448  &unixpath)) &&
449  (0 < strlen (unixpath)))
450  {
451  /* probe UNIX support */
452  struct sockaddr_un s_un;
453 
454  if (strlen (unixpath) >= sizeof (s_un.sun_path))
455  {
457  _("UNIXPATH `%s' too long, maximum length is %llu\n"),
458  unixpath,
459  (unsigned long long) sizeof (s_un.sun_path));
460  unixpath = GNUNET_NETWORK_shorten_unixpath (unixpath);
462  _("Using `%s' instead\n"),
463  unixpath);
464  }
465 #ifdef LINUX
466  abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg,
467  "TESTING",
468  "USE_ABSTRACT_SOCKETS");
469  if (GNUNET_SYSERR == abstract)
470  abstract = GNUNET_NO;
471 #endif
472  if ( (GNUNET_YES != abstract) &&
473  (GNUNET_OK !=
476  "mkdir",
477  unixpath);
478  }
479  if (NULL != unixpath)
480  {
481  desc = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
482  if (NULL == desc)
483  {
484  if ( (ENOBUFS == errno) ||
485  (ENOMEM == errno) ||
486  (ENFILE == errno) ||
487  (EACCES == errno) )
488  {
490  GNUNET_free_non_null (hostname);
491  GNUNET_free (unixpath);
492  return GNUNET_SYSERR;
493  }
495  _("Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
496  service_name,
497  STRERROR (errno));
498  GNUNET_free (unixpath);
499  unixpath = NULL;
500  }
501  else
502  {
504  desc = NULL;
505  }
506  }
507 #endif
508 
509  if ( (0 == port) &&
510  (NULL == unixpath) )
511  {
512  if (GNUNET_YES ==
514  service_name,
515  "START_ON_DEMAND"))
517  _("Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
518  service_name);
519  GNUNET_free_non_null (hostname);
520  return GNUNET_SYSERR;
521  }
522  if (0 == port)
523  {
524  saddrs = GNUNET_new_array (2,
525  struct sockaddr *);
526  saddrlens = GNUNET_new_array (2,
527  socklen_t);
528  add_unixpath (saddrs,
529  saddrlens,
530  unixpath,
531  abstract);
532  GNUNET_free_non_null (unixpath);
533  GNUNET_free_non_null (hostname);
534  *addrs = saddrs;
535  *addr_lens = saddrlens;
536  return 1;
537  }
538 
539  if (NULL != hostname)
540  {
542  "Resolving `%s' since that is where `%s' will bind to.\n",
543  hostname,
544  service_name);
545  memset (&hints, 0, sizeof (struct addrinfo));
546  if (disablev6)
547  hints.ai_family = AF_INET;
548  hints.ai_protocol = IPPROTO_TCP;
549  if ((0 != (ret = getaddrinfo (hostname,
550  NULL,
551  &hints,
552  &res))) ||
553  (NULL == res))
554  {
556  _("Failed to resolve `%s': %s\n"),
557  hostname,
558  gai_strerror (ret));
559  GNUNET_free (hostname);
560  GNUNET_free_non_null (unixpath);
561  return GNUNET_SYSERR;
562  }
563  next = res;
564  i = 0;
565  while (NULL != (pos = next))
566  {
567  next = pos->ai_next;
568  if ((disablev6) && (pos->ai_family == AF_INET6))
569  continue;
570  i++;
571  }
572  if (0 == i)
573  {
575  _("Failed to find %saddress for `%s'.\n"),
576  disablev6 ? "IPv4 " : "",
577  hostname);
578  freeaddrinfo (res);
579  GNUNET_free (hostname);
580  GNUNET_free_non_null (unixpath);
581  return GNUNET_SYSERR;
582  }
583  resi = i;
584  if (NULL != unixpath)
585  resi++;
586  saddrs = GNUNET_new_array (resi + 1,
587  struct sockaddr *);
588  saddrlens = GNUNET_new_array (resi + 1,
589  socklen_t);
590  i = 0;
591  if (NULL != unixpath)
592  {
593  add_unixpath (saddrs, saddrlens, unixpath, abstract);
594  i++;
595  }
596  next = res;
597  while (NULL != (pos = next))
598  {
599  next = pos->ai_next;
600  if ((disablev6) && (AF_INET6 == pos->ai_family))
601  continue;
602  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
603  continue; /* not TCP */
604  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
605  continue; /* huh? */
606  LOG (GNUNET_ERROR_TYPE_DEBUG, "Service `%s' will bind to `%s'\n",
607  service_name, GNUNET_a2s (pos->ai_addr, pos->ai_addrlen));
608  if (AF_INET == pos->ai_family)
609  {
610  GNUNET_assert (sizeof (struct sockaddr_in) == pos->ai_addrlen);
611  saddrlens[i] = pos->ai_addrlen;
612  saddrs[i] = GNUNET_malloc (saddrlens[i]);
613  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
614  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
615  }
616  else
617  {
618  GNUNET_assert (AF_INET6 == pos->ai_family);
619  GNUNET_assert (sizeof (struct sockaddr_in6) == pos->ai_addrlen);
620  saddrlens[i] = pos->ai_addrlen;
621  saddrs[i] = GNUNET_malloc (saddrlens[i]);
622  GNUNET_memcpy (saddrs[i], pos->ai_addr, saddrlens[i]);
623  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
624  }
625  i++;
626  }
627  GNUNET_free (hostname);
628  freeaddrinfo (res);
629  resi = i;
630  }
631  else
632  {
633  /* will bind against everything, just set port */
634  if (disablev6)
635  {
636  /* V4-only */
637  resi = 1;
638  if (NULL != unixpath)
639  resi++;
640  i = 0;
641  saddrs = GNUNET_new_array (resi + 1,
642  struct sockaddr *);
643  saddrlens = GNUNET_new_array (resi + 1,
644  socklen_t);
645  if (NULL != unixpath)
646  {
647  add_unixpath (saddrs, saddrlens, unixpath, abstract);
648  i++;
649  }
650  saddrlens[i] = sizeof (struct sockaddr_in);
651  saddrs[i] = GNUNET_malloc (saddrlens[i]);
652 #if HAVE_SOCKADDR_IN_SIN_LEN
653  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[i];
654 #endif
655  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
656  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
657  }
658  else
659  {
660  /* dual stack */
661  resi = 2;
662  if (NULL != unixpath)
663  resi++;
664  saddrs = GNUNET_new_array (resi + 1,
665  struct sockaddr *);
666  saddrlens = GNUNET_new_array (resi + 1,
667  socklen_t);
668  i = 0;
669  if (NULL != unixpath)
670  {
671  add_unixpath (saddrs,
672  saddrlens,
673  unixpath,
674  abstract);
675  i++;
676  }
677  saddrlens[i] = sizeof (struct sockaddr_in6);
678  saddrs[i] = GNUNET_malloc (saddrlens[i]);
679 #if HAVE_SOCKADDR_IN_SIN_LEN
680  ((struct sockaddr_in6 *) saddrs[i])->sin6_len = saddrlens[0];
681 #endif
682  ((struct sockaddr_in6 *) saddrs[i])->sin6_family = AF_INET6;
683  ((struct sockaddr_in6 *) saddrs[i])->sin6_port = htons (port);
684  i++;
685  saddrlens[i] = sizeof (struct sockaddr_in);
686  saddrs[i] = GNUNET_malloc (saddrlens[i]);
687 #if HAVE_SOCKADDR_IN_SIN_LEN
688  ((struct sockaddr_in *) saddrs[i])->sin_len = saddrlens[1];
689 #endif
690  ((struct sockaddr_in *) saddrs[i])->sin_family = AF_INET;
691  ((struct sockaddr_in *) saddrs[i])->sin_port = htons (port);
692  }
693  }
694  GNUNET_free_non_null (unixpath);
695  *addrs = saddrs;
696  *addr_lens = saddrlens;
697  return resi;
698 }
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 STRERROR(i)
Definition: plibc.h:676
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:833
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define LOG(kind,...)
static int ret
Final status code.
Definition: gnunet-arm.c:89
#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:208
#define GNUNET_memcpy(dst, src, n)
#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:79
static char * hostname
Our hostname; we give this to all the peers we start.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:79
#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:46
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:157
#define GNUNET_YES
Definition: gnunet_common.h:80
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:604
#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:1037
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 712 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().

716 {
717  struct GNUNET_MQ_Envelope *env;
719 
720  (void) name;
721  env = GNUNET_MQ_msg (msg,
723  msg->result = htonl (result);
724  msg->arm_msg.request_id = GNUNET_htonll (request_id);
726  env);
727 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:78
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2734
#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:93
uint32_t result
Result from the enum GNUNET_ARM_Result
Definition: arm.h:98
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
const char * name
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Reply from ARM to client.
Definition: arm.h:87
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_ServiceStatus  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 739 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().

742 {
743  struct GNUNET_MQ_Envelope *env;
745  size_t namelen;
746 
748  "Sending status %u of service `%s' to client\n",
749  (unsigned int) status,
750  name);
751  namelen = strlen (name) + 1;
752  env = GNUNET_MQ_msg_extra (msg,
753  namelen,
755  msg->status = htonl ((uint32_t) (status));
756  GNUNET_memcpy ((char *) &msg[1],
757  name,
758  namelen);
759  if (NULL == unicast)
760  {
761  if (NULL != notifier)
763  &msg->header,
764  GNUNET_YES);
765  GNUNET_MQ_discard (env);
766  }
767  else
768  {
770  env);
771  }
772 }
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:2734
struct GNUNET_MessageHeader header
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_STATUS.
Definition: arm.h:47
#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_memcpy(dst, src, n)
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
const char * name
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
uint32_t status
Status from the &#39;enum GNUNET_ARM_ServiceStatus&#39;.
Definition: arm.h:52
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:192
#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:80
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 784 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_YES, INVALID_SOCKET, ServiceList::listen_head, ServiceListeningInfo::listen_socket, ls, ServiceList::name, ServiceListeningInfo::next, options, ServiceList::pipe_control, prefix_command, ServiceList::proc, signal_result(), and SOCKTYPE.

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

787 {
788  char *loprefix;
789  char *options;
790  int use_debug;
791  int is_simple_service;
792  struct ServiceListeningInfo *sli;
793  SOCKTYPE *lsocks;
794  unsigned int ls;
795  char *binary;
796  char *quotedbinary;
797 
798  /* calculate listen socket list */
799  lsocks = NULL;
800  ls = 0;
801  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
802  {
803  GNUNET_array_append (lsocks, ls,
805  if (NULL != sli->accept_task)
806  {
808  sli->accept_task = NULL;
809  }
810  }
811 #if WINDOWS
812  GNUNET_array_append (lsocks,
813  ls,
815 #else
816  GNUNET_array_append (lsocks,
817  ls,
818  -1);
819 #endif
820 
821  /* obtain configuration */
822  if (GNUNET_OK !=
824  sl->name,
825  "PREFIX",
826  &loprefix))
827  loprefix = GNUNET_strdup (prefix_command);
828  else
830  loprefix);
831  if (GNUNET_OK !=
833  sl->name,
834  "OPTIONS",
835  &options))
836  options = NULL;
837  else
839  options);
840  {
841  char *new_options;
842  char *optpos;
843  char *fin_options;
844 
845  fin_options = GNUNET_strdup (final_option);
846  /* replace '{}' with service name */
847  while (NULL != (optpos = strstr (fin_options,
848  "{}")))
849  {
850  /* terminate string at opening parenthesis */
851  *optpos = 0;
852  GNUNET_asprintf (&new_options,
853  "%s%s%s",
854  fin_options,
855  sl->name,
856  optpos + 2);
857  GNUNET_free (fin_options);
858  fin_options = new_options;
859  }
860  if (NULL != options)
861  {
862  /* combine "fin_options" with "options" */
863  optpos = options;
864  GNUNET_asprintf (&options,
865  "%s %s",
866  fin_options,
867  optpos);
868  GNUNET_free (fin_options);
869  GNUNET_free (optpos);
870  }
871  else
872  {
873  /* only have "fin_options", use that */
874  options = fin_options;
875  }
876  }
878  options);
880  sl->name,
881  "DEBUG");
882  {
883  const char *service_type = NULL;
884  const char *choices[] = { "GNUNET", "SIMPLE", NULL };
885 
886  is_simple_service = GNUNET_NO;
887  if ( (GNUNET_OK ==
889  sl->name,
890  "TYPE",
891  choices,
892  &service_type)) &&
893  (0 == strcasecmp (service_type, "SIMPLE")) )
894  is_simple_service = GNUNET_YES;
895  }
896 
897  GNUNET_assert (NULL == sl->proc);
898  if (GNUNET_YES == is_simple_service)
899  {
900  /* A simple service will receive no GNUnet specific
901  command line options. */
902  binary = GNUNET_strdup (sl->binary);
903  binary = GNUNET_CONFIGURATION_expand_dollar (cfg, binary);
904  GNUNET_asprintf (&quotedbinary,
905  "\"%s\"",
906  sl->binary);
908  "Starting simple service `%s' using binary `%s'\n",
909  sl->name, sl->binary);
910  /* FIXME: dollar expansion should only be done outside
911  * of ''-quoted strings, escaping should be considered. */
912  if (NULL != options)
913  options = GNUNET_CONFIGURATION_expand_dollar (cfg, options);
914  sl->proc =
917  lsocks,
918  loprefix,
919  quotedbinary,
920  options,
921  NULL);
922  }
923  else
924  {
925  /* actually start process */
927  "Starting service `%s' using binary `%s' and configuration `%s'\n",
928  sl->name, sl->binary, sl->config);
930  GNUNET_asprintf (&quotedbinary,
931  "\"%s\"",
932  binary);
933 
934  if (GNUNET_YES == use_debug)
935  {
936  if (NULL == sl->config)
937  sl->proc =
940  lsocks,
941  loprefix,
942  quotedbinary,
943  "-L", "DEBUG",
944  options,
945  NULL);
946  else
947  sl->proc =
950  lsocks,
951  loprefix,
952  quotedbinary,
953  "-c", sl->config,
954  "-L", "DEBUG",
955  options,
956  NULL);
957  }
958  else
959  {
960  if (NULL == sl->config)
961  sl->proc =
964  lsocks,
965  loprefix,
966  quotedbinary,
967  options,
968  NULL);
969  else
970  sl->proc =
973  lsocks,
974  loprefix,
975  quotedbinary,
976  "-c", sl->config,
977  options,
978  NULL);
979  }
980  }
981  GNUNET_free (binary);
982  GNUNET_free (quotedbinary);
983  if (NULL == sl->proc)
984  {
986  _("Failed to start service `%s'\n"),
987  sl->name);
988  if (client)
989  signal_result (client,
990  sl->name,
991  request_id,
993  }
994  else
995  {
997  _("Starting service `%s'\n"),
998  sl->name);
999  broadcast_status (sl->name,
1001  NULL);
1002  if (client)
1003  signal_result (client,
1004  sl->name,
1005  request_id,
1007  }
1008  /* clean up */
1009  GNUNET_free (loprefix);
1010  GNUNET_free (options);
1011  GNUNET_array_grow (lsocks,
1012  ls,
1013  0);
1014 }
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1268
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
#define SOCKTYPE
Definition: platform.h:276
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.
struct GNUNET_OS_Process * GNUNET_OS_start_process_s(int pipe_control, unsigned int std_inheritance, const SOCKTYPE *lsocks, const char *filename,...)
Start a process.
Definition: os_priority.c:1474
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
Service starting was initiated.
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze)...
#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:208
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.
#define INVALID_SOCKET
Definition: network.c:39
Record with information about a listen socket we have open.
When these flags are set, the child process will inherit stdout and stderr of the parent...
Definition: gnunet_os_lib.h:98
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 void broadcast_status(const char *name, enum GNUNET_ARM_ServiceStatus status, struct GNUNET_SERVICE_Client *unicast)
Tell all clients about status change of a service.
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.
#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:80
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.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
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 1025 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().

1026 {
1027  struct ServiceList *sl;
1028 
1029  sl = running_head;
1030  while (sl != NULL)
1031  {
1032  if (0 == strcasecmp (sl->name, name))
1033  return sl;
1034  sl = sl->next;
1035  }
1036  return NULL;
1037 }
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 1047 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().

1048 {
1049  struct ServiceListeningInfo *sli = cls;
1050  struct ServiceList *sl = sli->sl;
1051 
1052  sli->accept_task = NULL;
1054  start_process (sl, NULL, 0);
1055 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:81
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 1067 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, ServiceListeningInfo::sl, and STRERROR.

Referenced by setup_service().

1070 {
1071  static int on = 1;
1072  struct GNUNET_NETWORK_Handle *sock;
1073  struct ServiceListeningInfo *sli;
1074 #ifndef WINDOWS
1075  int match_uid;
1076  int match_gid;
1077 #endif
1078 
1079  switch (sa->sa_family)
1080  {
1081  case AF_INET:
1082  sock = GNUNET_NETWORK_socket_create (PF_INET,
1083  SOCK_STREAM,
1084  0);
1085  break;
1086  case AF_INET6:
1087  sock = GNUNET_NETWORK_socket_create (PF_INET6,
1088  SOCK_STREAM,
1089  0);
1090  break;
1091  case AF_UNIX:
1092  if (0 == strcmp (GNUNET_a2s (sa,
1093  addr_len),
1094  "@")) /* Do not bind to blank UNIX path! */
1095  return;
1096  sock = GNUNET_NETWORK_socket_create (PF_UNIX,
1097  SOCK_STREAM,
1098  0);
1099  break;
1100  default:
1101  GNUNET_break (0);
1102  sock = NULL;
1103  errno = EAFNOSUPPORT;
1104  break;
1105  }
1106  if (NULL == sock)
1107  {
1109  _("Unable to create socket for service `%s': %s\n"),
1110  sl->name,
1111  STRERROR (errno));
1112  GNUNET_free (sa);
1113  return;
1114  }
1115  if (GNUNET_OK !=
1117  SOL_SOCKET,
1118  SO_REUSEADDR,
1119  &on,
1120  sizeof (on)))
1122  "setsockopt");
1123 #ifdef IPV6_V6ONLY
1124  if ( (sa->sa_family == AF_INET6) &&
1125  (GNUNET_OK !=
1127  IPPROTO_IPV6,
1128  IPV6_V6ONLY,
1129  &on,
1130  sizeof (on))) )
1132  "setsockopt");
1133 #endif
1134 #ifndef WINDOWS
1135  if (AF_UNIX == sa->sa_family)
1136  GNUNET_NETWORK_unix_precheck ((struct sockaddr_un *) sa);
1137 #endif
1138  if (GNUNET_OK !=
1140  (const struct sockaddr *) sa,
1141  addr_len))
1142  {
1144  _("Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1145  sl->name,
1146  GNUNET_a2s (sa,
1147  addr_len),
1148  STRERROR (errno));
1151  GNUNET_free (sa);
1152  return;
1153  }
1154 #ifndef WINDOWS
1155  if ((AF_UNIX == sa->sa_family)
1156 #ifdef LINUX
1157  /* Permission settings are not required when abstract sockets are used */
1158  && ('\0' != ((const struct sockaddr_un *)sa)->sun_path[0])
1159 #endif
1160  )
1161  {
1162  match_uid =
1164  sl->name,
1165  "UNIX_MATCH_UID");
1166  match_gid =
1168  sl->name,
1169  "UNIX_MATCH_GID");
1170  GNUNET_DISK_fix_permissions (((const struct sockaddr_un *)sa)->sun_path,
1171  match_uid,
1172  match_gid);
1173 
1174  }
1175 #endif
1176  if (GNUNET_OK !=
1177  GNUNET_NETWORK_socket_listen (sock, 5))
1178  {
1180  "listen");
1183  GNUNET_free (sa);
1184  return;
1185  }
1187  _("ARM now monitors connections to service `%s' at `%s'\n"),
1188  sl->name,
1189  GNUNET_a2s (sa,
1190  addr_len));
1191  sli = GNUNET_new (struct ServiceListeningInfo);
1192  sli->service_addr = sa;
1193  sli->service_addr_len = addr_len;
1194  sli->listen_socket = sock;
1195  sli->sl = sl;
1196  sli->accept_task
1198  sock,
1199  &accept_connection, sli);
1201  sl->listen_tail,
1202  sli);
1203 }
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:796
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:1005
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
#define STRERROR(i)
Definition: plibc.h:676
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:522
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
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:208
#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:498
handle to a socket
Definition: network.c:46
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:1478
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:201
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:604
#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:1037
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 1213 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().

1214 {
1217  running_tail,
1218  sl);
1219  GNUNET_assert (NULL == sl->listen_head);
1222  GNUNET_free (sl->name);
1223  GNUNET_free (sl);
1224 }
#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:80
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 1236 of file gnunet-service-arm.c.

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

1238 {
1239  (void) cls;
1241  return GNUNET_OK;
1242 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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 1252 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().

1254 {
1255  struct GNUNET_SERVICE_Client *client = cls;
1256  const char *servicename;
1257  struct ServiceList *sl;
1258  uint64_t request_id;
1259 
1260  request_id = GNUNET_ntohll (amsg->request_id);
1261  servicename = (const char *) &amsg[1];
1263  if (GNUNET_YES == in_shutdown)
1264  {
1265  signal_result (client,
1266  servicename,
1267  request_id,
1269  return;
1270  }
1271  sl = find_service (servicename);
1272  if (NULL == sl)
1273  {
1274  signal_result (client,
1275  servicename,
1276  request_id,
1278  return;
1279  }
1280  sl->force_start = GNUNET_YES;
1281  if (NULL != sl->proc)
1282  {
1283  signal_result (client,
1284  servicename,
1285  request_id,
1287  return;
1288  }
1289  start_process (sl,
1290  client,
1291  request_id);
1292 }
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:78
Asked to start it, but it&#39;s already started.
Handle to a client that is connected to a service.
Definition: service.c:249
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:80
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2533
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 1301 of file gnunet-service-arm.c.

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and GNUNET_SCHEDULER_shutdown().

Referenced by handle_stop().

1302 {
1303  (void) cls;
1305  "Triggering shutdown\n");
1307 }
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
#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 1319 of file gnunet-service-arm.c.

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

1321 {
1322  (void) cls;
1324  return GNUNET_OK;
1325 }
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
#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 1335 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().

1337 {
1338  struct GNUNET_SERVICE_Client *client = cls;
1339  struct ServiceList *sl;
1340  const char *servicename;
1341  uint64_t request_id;
1342 
1343  request_id = GNUNET_ntohll (amsg->request_id);
1344  servicename = (const char *) &amsg[1];
1346  _("Preparing to stop `%s'\n"),
1347  servicename);
1349  if (0 == strcasecmp (servicename,
1350  "arm"))
1351  {
1352  broadcast_status (servicename,
1354  NULL);
1355  signal_result (client,
1356  servicename,
1357  request_id,
1361  NULL);
1362  return;
1363  }
1364  sl = find_service (servicename);
1365  if (NULL == sl)
1366  {
1367  signal_result (client,
1368  servicename,
1369  request_id,
1371  return;
1372  }
1373  sl->force_start = GNUNET_NO;
1374  if (GNUNET_YES == in_shutdown)
1375  {
1376  /* shutdown in progress */
1377  signal_result (client,
1378  servicename,
1379  request_id,
1381  return;
1382  }
1383  if (NULL != sl->killing_client)
1384  {
1385  /* killing already in progress */
1386  signal_result (client,
1387  servicename,
1388  request_id,
1390  return;
1391  }
1392  if (NULL == sl->proc)
1393  {
1394  /* process is down */
1395  signal_result (client,
1396  servicename,
1397  request_id,
1399  return;
1400  }
1402  "Sending kill signal to service `%s', waiting for process to die.\n",
1403  servicename);
1404  broadcast_status (servicename,
1406  NULL);
1407  /* no signal_start - only when it's STOPPED */
1409  if (0 != GNUNET_OS_process_kill (sl->proc,
1410  GNUNET_TERM_SIG))
1412  "kill");
1413  sl->killing_client = client;
1414  sl->killing_client_request_id = request_id;
1415 }
ARM stopping was initiated (there&#39;s no "stopped" for ARM itself).
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:78
#define GNUNET_NO
Definition: gnunet_common.h:81
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
Handle to a client that is connected to a service.
Definition: service.c:249
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:1273
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)...
static void broadcast_status(const char *name, enum GNUNET_ARM_ServiceStatus status, struct GNUNET_SERVICE_Client *unicast)
Tell all clients about status change of a service.
Asked to stop it, but it&#39;s already stopped.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
Service stopping was initiated.
#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:80
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:282
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:2533
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:2721
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:251
Here is the call 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 1425 of file gnunet-service-arm.c.

References GNUNET_ARM_ListResultMessage::arm_msg, ServiceList::binary, GNUNET_ARM_ListResultMessage::count, env, GNUNET_break, GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, GNUNET_MQ_msg_extra, GNUNET_MQ_send(), GNUNET_SERVICE_client_continue(), GNUNET_SERVICE_client_get_mq(), GNUNET_snprintf(), msg, ServiceList::name, ServiceList::next, ServiceList::proc, GNUNET_ARM_Message::request_id, GNUNET_ARM_Message::reserved, and ServiceListeningInfo::sl.

1427 {
1428  struct GNUNET_SERVICE_Client *client = cls;
1429  struct GNUNET_MQ_Envelope *env;
1431  size_t string_list_size;
1432  struct ServiceList *sl;
1433  uint16_t count;
1434  char *pos;
1435 
1436  GNUNET_break (0 == ntohl (request->reserved));
1437  count = 0;
1438  string_list_size = 0;
1439 
1440  /* first count the running processes get their name's size */
1441  for (sl = running_head; NULL != sl; sl = sl->next)
1442  {
1443  if (NULL != sl->proc)
1444  {
1445  string_list_size += strlen (sl->name);
1446  string_list_size += strlen (sl->binary);
1447  string_list_size += 4;
1448  count++;
1449  }
1450  }
1451 
1452  env = GNUNET_MQ_msg_extra (msg,
1453  string_list_size,
1455  msg->arm_msg.request_id = request->request_id;
1456  msg->count = htons (count);
1457 
1458  pos = (char *) &msg[1];
1459  for (sl = running_head; NULL != sl; sl = sl->next)
1460  {
1461  if (NULL != sl->proc)
1462  {
1463  size_t s = strlen (sl->name) + strlen (sl->binary) + 4;
1464  GNUNET_snprintf (pos,
1465  s,
1466  "%s (%s)",
1467  sl->name,
1468  sl->binary);
1469  pos += s;
1470  }
1471  }
1473  env);
1475 }
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.
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:78
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2734
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, with an ID.
Definition: arm.h:113
uint32_t reserved
For alignment.
Definition: arm.h:71
uint16_t count
Number of &#39;\0&#39; terminated strings that follow this message.
Definition: arm.h:119
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct ServiceList * next
This is a doubly-linked list.
Handle to a client that is connected to a service.
Definition: service.c:249
List of our services.
#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
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:107
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
char * binary
Name of the binary used.
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.
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2533
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 1485 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.

1487 {
1488  struct GNUNET_SERVICE_Client *client = cls;
1489  struct GNUNET_MQ_Envelope *env;
1490  struct GNUNET_MessageHeader *msg;
1491 
1492  (void) message;
1493  env = GNUNET_MQ_msg (msg,
1496  env);
1498 }
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:2734
#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:249
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:2533
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 1506 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().

1507 {
1509  "Last shutdown phase\n");
1510  if (NULL != notifier)
1511  {
1513  notifier = NULL;
1514  }
1515  if (NULL != service)
1516  {
1518  service = NULL;
1519  }
1520  if (NULL != child_death_task)
1521  {
1523  child_death_task = NULL;
1524  }
1525 }
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:141
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2679
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:965
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 1535 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().

1536 {
1537  struct ServiceList *i;
1538  unsigned int res;
1539 
1540  for (res = 0, i = running_head; NULL != i; i = i->next, res++)
1542  "%s\n",
1543  i->name);
1544  return res;
1545 }
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 1554 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().

1555 {
1556  struct ServiceList *pos;
1557  struct ServiceList *nxt;
1558  struct ServiceListeningInfo *sli;
1559 
1560  (void) cls;
1562  "First shutdown phase\n");
1563  if (NULL != child_restart_task)
1564  {
1566  child_restart_task = NULL;
1567  }
1569  /* first, stop listening */
1570  for (pos = running_head; NULL != pos; pos = pos->next)
1571  {
1572  while (NULL != (sli = pos->listen_head))
1573  {
1575  pos->listen_tail,
1576  sli);
1577  if (NULL != sli->accept_task)
1578  {
1580  sli->accept_task = NULL;
1581  }
1584  GNUNET_free (sli->service_addr);
1585  GNUNET_free (sli);
1586  }
1587  }
1588  /* then, shutdown all existing service processes */
1589  nxt = running_head;
1590  while (NULL != (pos = nxt))
1591  {
1592  nxt = pos->next;
1593  if (NULL != pos->proc)
1594  {
1596  "Stopping service `%s'\n",
1597  pos->name);
1599  if (0 != GNUNET_OS_process_kill (pos->proc,
1600  GNUNET_TERM_SIG))
1602  "kill");
1603  }
1604  else
1605  {
1606  free_service (pos);
1607  }
1608  }
1609  /* finally, should all service processes be already gone, terminate for real */
1610  if (NULL == running_head)
1611  do_shutdown ();
1612  else
1614  "Delaying shutdown, have %u childs still running\n",
1616 }
#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:78
#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:80
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:282
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:604
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:251
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:965
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 1625 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().

1627 {
1628  struct ServiceList *sl;
1629  struct GNUNET_TIME_Relative lowestRestartDelay;
1630  struct ServiceListeningInfo *sli;
1631 
1632  (void) cls;
1633  child_restart_task = NULL;
1635  lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1636 
1637  /* check for services that need to be restarted due to
1638  * configuration changes or because the last restart failed */
1639  for (sl = running_head; NULL != sl; sl = sl->next)
1640  {
1641  if (NULL != sl->proc)
1642  continue;
1643  /* service is currently not running */
1645  {
1646  /* restart is now allowed */
1647  if (sl->force_start)
1648  {
1649  /* process should run by default, start immediately */
1651  _("Restarting service `%s'.\n"),
1652  sl->name);
1653  start_process (sl,
1654  NULL,
1655  0);
1656  }
1657  else
1658  {
1659  /* process is run on-demand, ensure it is re-started if there is demand */
1660  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1661  if (NULL == sli->accept_task)
1662  {
1663  /* accept was actually paused, so start it again */
1664  sli->accept_task
1666  sli->listen_socket,
1668  sli);
1669  }
1670  }
1671  }
1672  else
1673  {
1674  /* update calculation for earliest time to reactivate a service */
1675  lowestRestartDelay =
1676  GNUNET_TIME_relative_min (lowestRestartDelay,
1678  (sl->restart_at));
1679  }
1680  }
1681  if (lowestRestartDelay.rel_value_us != GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1682  {
1684  "Will restart process in %s\n",
1685  GNUNET_STRINGS_relative_time_to_string (lowestRestartDelay,
1686  GNUNET_YES));
1688  GNUNET_SCHEDULER_add_delayed_with_priority (lowestRestartDelay,
1691  NULL);
1692  }
1693 }
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:1178
#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:81
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:208
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:727
#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:271
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:80
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:1478
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 1703 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_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, 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().

1704 {
1705  struct ServiceList *pos;
1706  struct ServiceList *next;
1707  struct ServiceListeningInfo *sli;
1708  const char *statstr;
1709  int statcode;
1710  int ret;
1711  char c[16];
1712  enum GNUNET_OS_ProcessStatusType statusType;
1713  unsigned long statusCode;
1714  const struct GNUNET_DISK_FileHandle *pr;
1715 
1716  (void) cls;
1719  child_death_task = NULL;
1720  /* consume the signal */
1722  &c,
1723  sizeof (c)));
1724 
1725  /* check for services that died (WAITPID) */
1726  next = running_head;
1727  while (NULL != (pos = next))
1728  {
1729  next = pos->next;
1730 
1731  if (NULL == pos->proc)
1732  {
1733  if (GNUNET_YES == in_shutdown)
1734  free_service (pos);
1735  continue;
1736  }
1737 #if HAVE_WAIT4
1738  if (NULL != wait_file)
1739  {
1740  /* need to use 'wait4()' to obtain and log performance data */
1741  struct rusage ru;
1742  int status;
1743  pid_t pid;
1744 
1745  pid = GNUNET_OS_process_get_pid (pos->proc);
1746  ret = wait4 (pid,
1747  &status,
1748  WNOHANG,
1749  &ru);
1750  if (ret <= 0)
1751  continue; /* no process done */
1752  if (WIFEXITED (status))
1753  {
1754  statusType = GNUNET_OS_PROCESS_EXITED;
1755  statusCode = WEXITSTATUS (status);
1756  }
1757  else if (WIFSIGNALED (status))
1758  {
1759  statusType = GNUNET_OS_PROCESS_SIGNALED;
1760  statusCode = WTERMSIG (status);
1761  }
1762  else if (WIFSTOPPED (status))
1763  {
1764  statusType = GNUNET_OS_PROCESS_SIGNALED;
1765  statusCode = WSTOPSIG (status);
1766  }
1767 #ifdef WIFCONTINUED
1768  else if (WIFCONTINUED (status))
1769  {
1770  statusType = GNUNET_OS_PROCESS_RUNNING;
1771  statusCode = 0;
1772  }
1773 #endif
1774  else
1775  {
1776  statusType = GNUNET_OS_PROCESS_UNKNOWN;
1777  statusCode = 0;
1778  }
1779  if ( (GNUNET_OS_PROCESS_EXITED == statusType) ||
1780  (GNUNET_OS_PROCESS_SIGNALED == statusType) )
1781  {
1782  double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1783  double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1784  fprintf (wait_file,
1785  "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1786  pos->binary,
1787  (unsigned int) pid,
1788  utime,
1789  stime,
1790  (unsigned long long) ru.ru_maxrss,
1791  (unsigned long long) ru.ru_inblock,
1792  (unsigned long long) ru.ru_oublock,
1793  (unsigned long long) ru.ru_nvcsw,
1794  (unsigned long long) ru.ru_nivcsw);
1795  }
1796  }
1797  else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1798 #endif
1799  if ( (GNUNET_SYSERR ==
1800  (ret =
1802  &statusType,
1803  &statusCode))) ||
1804  (ret == GNUNET_NO) ||
1805  (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1806  (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1807  (statusType == GNUNET_OS_PROCESS_RUNNING) )
1808  continue;
1809 
1810  if (statusType == GNUNET_OS_PROCESS_EXITED)
1811  {
1812  statstr = _( /* process termination method */ "exit");
1813  statcode = statusCode;
1814  }
1815  else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1816  {
1817  statstr = _( /* process termination method */ "signal");
1818  statcode = statusCode;
1819  }
1820  else
1821  {
1822  statstr = _( /* process termination method */ "unknown");
1823  statcode = 0;
1824  }
1825  if (0 != pos->killed_at.abs_value_us)
1826  {
1828  _("Service `%s' took %s to terminate\n"),
1829  pos->name,
1831  GNUNET_YES));
1832  }
1834  pos->proc = NULL;
1835  broadcast_status (pos->name,
1837  NULL);
1838  if (NULL != pos->killing_client)
1839  {
1840  signal_result (pos->killing_client, pos->name,
1843  pos->killing_client = NULL;
1844  pos->killing_client_request_id = 0;
1845  }
1846  if (GNUNET_YES != in_shutdown)
1847  {
1848  if ( (statusType == GNUNET_OS_PROCESS_EXITED) &&
1849  (statcode == 0) )
1850  {
1851  /* process terminated normally, allow restart at any time */
1852  pos->restart_at.abs_value_us = 0;
1854  _("Service `%s' terminated normally, will restart at any time\n"),
1855  pos->name);
1856  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1857  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1858  {
1859  GNUNET_break (NULL == sli->accept_task);
1860  sli->accept_task =
1862  sli->listen_socket,
1864  sli);
1865  }
1866  }
1867  else
1868  {
1870  _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1871  pos->name,
1872  statstr,
1873  statcode,
1875  GNUNET_YES));
1876  {
1877  /* Reduce backoff based on runtime of the process,
1878  so that there is a cool-down if a process actually
1879  runs for a while. */
1880  struct GNUNET_TIME_Relative runtime;
1881  unsigned int minutes;
1882 
1884  minutes = runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1885  if (minutes > 31)
1887  else
1888  pos->backoff.rel_value_us <<= minutes;
1889  }
1890  /* schedule restart */
1892  pos->backoff = GNUNET_TIME_STD_BACKOFF (pos->backoff);
1893  if (NULL != child_restart_task)
1898  NULL);
1899  }
1900  }
1901  else
1902  {
1903  free_service (pos);
1904  }
1905  }
1908  pr,
1909  &maint_child_death, NULL);
1910  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1911  do_shutdown ();
1912  else if (GNUNET_YES == in_shutdown)
1914  "Delaying shutdown after child's death, still have %u children\n",
1916 
1917 }
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:351
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:364
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:881
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:1719
#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:245
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 void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
#define GNUNET_NO
Definition: gnunet_common.h:81
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:1643
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
static int ret
Final status code.
Definition: gnunet-arm.c:89
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:2641
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:208
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.
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:1200
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:727
uint16_t status
See PRISM_STATUS_*-constants.
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Service was stopped.
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.
#define GNUNET_SYSERR
Definition: gnunet_common.h:79
static void broadcast_status(const char *name, enum GNUNET_ARM_ServiceStatus status, struct GNUNET_SERVICE_Client *unicast)
Tell all clients about status change of a service.
#define GNUNET_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:373
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:80
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:1478
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.
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:965
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 1925 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().

1926 {
1927  static char c;
1928  int old_errno = errno; /* back-up errno */
1929 
1930  GNUNET_break (1 ==
1933  &c,
1934  sizeof (c)));
1935  errno = old_errno; /* restore errno */
1936 }
#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:2641
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:1049
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 1948 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, start_user, STAT, and STRERROR.

Referenced by run().

1950 {
1951  struct ServiceList *sl;
1952  char *binary;
1953  char *config;
1954  struct stat sbuf;
1955  struct sockaddr **addrs;
1956  socklen_t *addr_lens;
1957  int ret;
1958 
1959  (void) cls;
1960  if (0 == strcasecmp (section,
1961  "arm"))
1962  return;
1963  if (GNUNET_OK !=
1965  section,
1966  "BINARY",
1967  &binary))
1968  {
1969  /* not a service section */
1970  return;
1971  }
1972  if ((GNUNET_YES ==
1974  section,
1975  "RUN_PER_USER")) &&
1976  (GNUNET_YES ==
1978  section,
1979  "RUN_PER_USER")))
1980  {
1981  if (GNUNET_NO == start_user)
1982  {
1983  GNUNET_free (binary);
1984  return; /* user service, and we don't deal with those */
1985  }
1986  }
1987  else
1988  {
1989  if (GNUNET_NO == start_system)
1990  {
1991  GNUNET_free (binary);
1992  return; /* system service, and we don't deal with those */
1993  }
1994  }
1995  sl = find_service (section);
1996  if (NULL != sl)
1997  {
1998  /* got the same section twice!? */
1999  GNUNET_break (0);
2000  GNUNET_free (binary);
2001  return;
2002  }
2003  config = NULL;
2004  if (( (GNUNET_OK !=
2006  section,
2007  "CONFIG",
2008  &config)) &&
2009  (GNUNET_OK !=
2011  "PATHS",
2012  "DEFAULTCONFIG",
2013  &config)) ) ||
2014  (0 != STAT (config, &sbuf)))
2015  {
2016  if (NULL != config)
2017  {
2019  section, "CONFIG",
2020  STRERROR (errno));
2021  GNUNET_free (config);
2022  config = NULL;
2023  }
2024  }
2025  sl = GNUNET_new (struct ServiceList);
2026  sl->name = GNUNET_strdup (section);
2027  sl->binary = binary;
2028  sl->config = config;
2031 #if WINDOWS
2032  sl->pipe_control = GNUNET_YES;
2033 #else
2035  section,
2036  "PIPECONTROL"))
2038  section,
2039  "PIPECONTROL");
2040 #endif
2042  running_tail,
2043  sl);
2044  if (GNUNET_YES ==
2046  section,
2047  "IMMEDIATE_START"))
2048  {
2049  sl->force_start = GNUNET_YES;
2050  if (GNUNET_YES ==
2052  section,
2053  "NOARMBIND"))
2054  return;
2055  }
2056  else
2057  {
2058  if (GNUNET_YES !=
2060  section,
2061  "START_ON_DEMAND"))
2062  return;
2063  }
2064  if (0 >= (ret = get_server_addresses (section,
2065  cfg,
2066  &addrs,
2067  &addr_lens)))
2068  return;
2069  /* this will free (or capture) addrs[i] */
2070  for (unsigned int i = 0; i < (unsigned int) ret; i++)
2071  create_listen_socket (addrs[i],
2072  addr_lens[i],
2073  sl);
2074  GNUNET_free (addrs);
2075  GNUNET_free (addr_lens);
2076 }
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.
#define STRERROR(i)
Definition: plibc.h:676
#define GNUNET_NO
Definition: gnunet_common.h:81
#define GNUNET_OK
Named constants for return values.
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.
#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.
#define STAT(p, b)
Definition: plibc.h:663
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...
static int ret
Final status code.
Definition: gnunet-arm.c:89
#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:80
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 2088 of file gnunet-service-arm.c.

References GNUNET_SERVICE_client_mark_monitor().

Referenced by main().

2091 {
2092  /* All clients are considered to be of the "monitor" kind
2093  * (that is, they don't affect ARM shutdown).
2094  */
2095  (void) cls;
2096  (void) mq;
2098  return client;
2099 }
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2704
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 2110 of file gnunet-service-arm.c.

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

Referenced by main().

2113 {
2114  (void) cls;
2115  GNUNET_assert (client == app_ctx);
2116  for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
2117  if (sl->killing_client == client)
2118  sl->killing_client = NULL;
2119 }
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 2131 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().

2133 {
2134  struct GNUNET_SERVICE_Client *client = cls;
2135 
2136  (void) message;
2137  /* FIXME: might want to start by letting monitor know about
2138  services that are already running */
2139  /* Removal is handled by the server implementation, internally. */
2141  GNUNET_SERVICE_client_get_mq (client));
2142  broadcast_status ("arm",
2144  client);
2146 }
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2734
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:164
Handle to a client that is connected to a service.
Definition: service.c:249
static void broadcast_status(const char *name, enum GNUNET_ARM_ServiceStatus status, struct GNUNET_SERVICE_Client *unicast)
Tell all clients about status change of a service.
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:2533
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 2157 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().

2160 {
2161  struct ServiceList *sl;
2162 
2163  (void) cls;
2164  cfg = c;
2165  service = serv;
2167  NULL);
2173  NULL);
2174 #if HAVE_WAIT4
2175  if (GNUNET_OK ==
2177  "ARM",
2178  "RESOURCE_DIAGNOSTICS",
2179  &wait_filename))
2180  {
2181  wait_file = fopen (wait_filename,
2182  "w");
2183  if (NULL == wait_file)
2184  {
2186  "fopen",
2187  wait_filename);
2188  }
2189  }
2190 #endif
2191  if (GNUNET_OK !=
2193  "ARM",
2194  "GLOBAL_PREFIX",
2195  &prefix_command))
2197  else
2199  prefix_command);
2200  if (GNUNET_OK !=
2202  "ARM",
2203  "GLOBAL_POSTFIX",
2204  &final_option))
2205  final_option = GNUNET_strdup ("");
2206  else
2208  final_option);
2210  "ARM",
2211  "START_USER_SERVICES");
2213  "ARM",
2214  "START_SYSTEM_SERVICES");
2215  if ( (GNUNET_NO == start_user) &&
2216  (GNUNET_NO == start_system) )
2217  {
2219  "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
2221  global_ret = 1;
2222  return;
2223  }
2225  &setup_service,
2226  NULL);
2227 
2228  /* start default services... */
2229  for (sl = running_head; NULL != sl; sl = sl->next)
2230  if (GNUNET_YES == sl->force_start)
2231  start_process (sl,
2232  NULL,
2233  0);
2235 }
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:1293
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:81
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:1643
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:524
#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:2641
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:125
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:80
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 2246 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_OK, 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.

2248 {
2249  struct GNUNET_SIGNAL_Context *shc_chld;
2250  struct GNUNET_MQ_MessageHandler handlers[] = {
2253  struct GNUNET_ARM_Message,
2254  NULL),
2255  GNUNET_MQ_hd_var_size (stop,
2257  struct GNUNET_ARM_Message,
2258  NULL),
2261  struct GNUNET_MessageHeader,
2262  NULL),
2265  struct GNUNET_ARM_Message,
2266  NULL),
2269  struct GNUNET_MessageHeader,
2270  NULL),
2272  };
2273 
2275  GNUNET_NO,
2276  GNUNET_NO,
2277  GNUNET_NO);
2278  GNUNET_assert (NULL != sigpipe);
2279  shc_chld =
2282  if ( GNUNET_OK != GNUNET_SERVICE_run_ (argc,
2283  argv,
2284  "arm",
2286  &run,
2289  NULL,
2290  handlers))
2291  global_ret = 2;
2292 #if HAVE_WAIT4
2293  if (NULL != wait_file)
2294  {
2295  fclose (wait_file);
2296  wait_file = NULL;
2297  }
2298  if (NULL != wait_filename)
2299  {
2300  GNUNET_free (wait_filename);
2301  wait_filename = NULL;
2302  }
2303 #endif
2305  shc_chld = NULL;
2307  sigpipe = NULL;
2308  return global_ret;
2309 }
#define GNUNET_SIGCHLD
Definition: platform.h:46
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:81
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:78
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:99
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:2289
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:59
#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:2603
#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:59
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:2248
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:64
#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 196 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 201 of file gnunet-service-arm.c.

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

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

◆ prefix_command

char* prefix_command
static

Command to prepend to each actual command.

Definition at line 211 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 216 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 221 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 227 of file gnunet-service-arm.c.

◆ sigpipe

struct GNUNET_DISK_PipeHandle* sigpipe
static

Pipe used to communicate shutdown via signal.

Definition at line 232 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 242 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 247 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 252 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 264 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 269 of file gnunet-service-arm.c.