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

Referenced by run().

Function Documentation

◆ add_unixpath()

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

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

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

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

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

Referenced by get_server_addresses().

285 {
286 #ifdef AF_UNIX
287  struct sockaddr_un *un;
288 
289  un = GNUNET_new(struct sockaddr_un);
290  un->sun_family = AF_UNIX;
291  GNUNET_strlcpy(un->sun_path, unixpath, sizeof(un->sun_path));
292 #ifdef LINUX
293  if (GNUNET_YES == abstract)
294  un->sun_path[0] = '\0';
295 #endif
296 #if HAVE_SOCKADDR_UN_SUN_LEN
297  un->sun_len = (u_char)sizeof(struct sockaddr_un);
298 #endif
299  *saddrs = (struct sockaddr *)un;
300  *saddrlens = sizeof(struct sockaddr_un);
301 #else
302  /* this function should never be called
303  * unless AF_UNIX is defined! */
304  GNUNET_assert(0);
305 #endif
306 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_YES
Definition: gnunet_common.h:77
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:219
Here is the call graph for this function:
Here is the caller graph for this function:

◆ get_server_addresses()

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

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

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

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

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

Referenced by setup_service().

334 {
335  int disablev6;
336  struct GNUNET_NETWORK_Handle *desc;
337  unsigned long long port;
338  char *unixpath;
339  struct addrinfo hints;
340  struct addrinfo *res;
341  struct addrinfo *pos;
342  struct addrinfo *next;
343  unsigned int i;
344  int resi;
345  int ret;
346  int abstract;
347  struct sockaddr **saddrs;
348  socklen_t *saddrlens;
349  char *hostname;
350 
351  *addrs = NULL;
352  *addr_lens = NULL;
353  desc = NULL;
354  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "DISABLEV6"))
355  {
356  if (GNUNET_SYSERR ==
357  (disablev6 = GNUNET_CONFIGURATION_get_value_yesno(cfg,
358  service_name,
359  "DISABLEV6")))
360  return GNUNET_SYSERR;
361  }
362  else
363  disablev6 = GNUNET_NO;
364 
365  if (!disablev6)
366  {
367  /* probe IPv6 support */
368  desc = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
369  if (NULL == desc)
370  {
371  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
372  (EACCES == errno))
373  {
375  return GNUNET_SYSERR;
376  }
378  _(
379  "Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
380  service_name,
381  strerror(errno));
382  disablev6 = GNUNET_YES;
383  }
384  else
385  {
387  desc = NULL;
388  }
389  }
390 
391  port = 0;
393  {
395  service_name,
396  "PORT",
397  &port))
398  {
400  _("Require valid port number for service `%s' in configuration!\n"),
401  service_name);
402  }
403  if (port > 65535)
404  {
406  _("Require valid port number for service `%s' in configuration!\n"),
407  service_name);
408  return GNUNET_SYSERR;
409  }
410  }
411 
412  if (GNUNET_CONFIGURATION_have_value(cfg, service_name, "BINDTO"))
413  {
416  service_name,
417  "BINDTO",
418  &hostname));
419  }
420  else
421  hostname = NULL;
422 
423  unixpath = NULL;
424  abstract = GNUNET_NO;
425 #ifdef AF_UNIX
426  if ((GNUNET_YES ==
427  GNUNET_CONFIGURATION_have_value(cfg, service_name, "UNIXPATH")) &&
429  service_name,
430  "UNIXPATH",
431  &unixpath)) &&
432  (0 < strlen(unixpath)))
433  {
434  /* probe UNIX support */
435  struct sockaddr_un s_un;
436 
437  if (strlen(unixpath) >= sizeof(s_un.sun_path))
438  {
440  _("UNIXPATH `%s' too long, maximum length is %llu\n"),
441  unixpath,
442  (unsigned long long)sizeof(s_un.sun_path));
443  unixpath = GNUNET_NETWORK_shorten_unixpath(unixpath);
444  LOG(GNUNET_ERROR_TYPE_INFO, _("Using `%s' instead\n"), unixpath);
445  }
446 #ifdef LINUX
448  "TESTING",
449  "USE_ABSTRACT_SOCKETS");
450  if (GNUNET_SYSERR == abstract)
451  abstract = GNUNET_NO;
452 #endif
453  if ((GNUNET_YES != abstract) &&
456  }
457  if (NULL != unixpath)
458  {
459  desc = GNUNET_NETWORK_socket_create(AF_UNIX, SOCK_STREAM, 0);
460  if (NULL == desc)
461  {
462  if ((ENOBUFS == errno) || (ENOMEM == errno) || (ENFILE == errno) ||
463  (EACCES == errno))
464  {
466  GNUNET_free_non_null(hostname);
467  GNUNET_free(unixpath);
468  return GNUNET_SYSERR;
469  }
471  _(
472  "Disabling UNIX domain socket support for service `%s', failed to create UNIX domain socket: %s\n"),
473  service_name,
474  strerror(errno));
475  GNUNET_free(unixpath);
476  unixpath = NULL;
477  }
478  else
479  {
481  desc = NULL;
482  }
483  }
484 #endif
485 
486  if ((0 == port) && (NULL == unixpath))
487  {
489  service_name,
490  "START_ON_DEMAND"))
492  _(
493  "Have neither PORT nor UNIXPATH for service `%s', but one is required\n"),
494  service_name);
495  GNUNET_free_non_null(hostname);
496  return GNUNET_SYSERR;
497  }
498  if (0 == port)
499  {
500  saddrs = GNUNET_new_array(2, struct sockaddr *);
501  saddrlens = GNUNET_new_array(2, socklen_t);
502  add_unixpath(saddrs, saddrlens, unixpath, abstract);
503  GNUNET_free_non_null(unixpath);
504  GNUNET_free_non_null(hostname);
505  *addrs = saddrs;
506  *addr_lens = saddrlens;
507  return 1;
508  }
509 
510  if (NULL != hostname)
511  {
513  "Resolving `%s' since that is where `%s' will bind to.\n",
514  hostname,
515  service_name);
516  memset(&hints, 0, sizeof(struct addrinfo));
517  if (disablev6)
518  hints.ai_family = AF_INET;
519  hints.ai_protocol = IPPROTO_TCP;
520  if ((0 != (ret = getaddrinfo(hostname, NULL, &hints, &res))) ||
521  (NULL == res))
522  {
524  _("Failed to resolve `%s': %s\n"),
525  hostname,
526  gai_strerror(ret));
527  GNUNET_free(hostname);
528  GNUNET_free_non_null(unixpath);
529  return GNUNET_SYSERR;
530  }
531  next = res;
532  i = 0;
533  while (NULL != (pos = next))
534  {
535  next = pos->ai_next;
536  if ((disablev6) && (pos->ai_family == AF_INET6))
537  continue;
538  i++;
539  }
540  if (0 == i)
541  {
543  _("Failed to find %saddress for `%s'.\n"),
544  disablev6 ? "IPv4 " : "",
545  hostname);
546  freeaddrinfo(res);
547  GNUNET_free(hostname);
548  GNUNET_free_non_null(unixpath);
549  return GNUNET_SYSERR;
550  }
551  resi = i;
552  if (NULL != unixpath)
553  resi++;
554  saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
555  saddrlens = GNUNET_new_array(resi + 1, socklen_t);
556  i = 0;
557  if (NULL != unixpath)
558  {
559  add_unixpath(saddrs, saddrlens, unixpath, abstract);
560  i++;
561  }
562  next = res;
563  while (NULL != (pos = next))
564  {
565  next = pos->ai_next;
566  if ((disablev6) && (AF_INET6 == pos->ai_family))
567  continue;
568  if ((IPPROTO_TCP != pos->ai_protocol) && (0 != pos->ai_protocol))
569  continue; /* not TCP */
570  if ((SOCK_STREAM != pos->ai_socktype) && (0 != pos->ai_socktype))
571  continue; /* huh? */
573  "Service `%s' will bind to `%s'\n",
574  service_name,
575  GNUNET_a2s(pos->ai_addr, pos->ai_addrlen));
576  if (AF_INET == pos->ai_family)
577  {
578  GNUNET_assert(sizeof(struct sockaddr_in) == pos->ai_addrlen);
579  saddrlens[i] = pos->ai_addrlen;
580  saddrs[i] = GNUNET_malloc(saddrlens[i]);
581  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
582  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
583  }
584  else
585  {
586  GNUNET_assert(AF_INET6 == pos->ai_family);
587  GNUNET_assert(sizeof(struct sockaddr_in6) == pos->ai_addrlen);
588  saddrlens[i] = pos->ai_addrlen;
589  saddrs[i] = GNUNET_malloc(saddrlens[i]);
590  GNUNET_memcpy(saddrs[i], pos->ai_addr, saddrlens[i]);
591  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
592  }
593  i++;
594  }
595  GNUNET_free(hostname);
596  freeaddrinfo(res);
597  resi = i;
598  }
599  else
600  {
601  /* will bind against everything, just set port */
602  if (disablev6)
603  {
604  /* V4-only */
605  resi = 1;
606  if (NULL != unixpath)
607  resi++;
608  i = 0;
609  saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
610  saddrlens = GNUNET_new_array(resi + 1, socklen_t);
611  if (NULL != unixpath)
612  {
613  add_unixpath(saddrs, saddrlens, unixpath, abstract);
614  i++;
615  }
616  saddrlens[i] = sizeof(struct sockaddr_in);
617  saddrs[i] = GNUNET_malloc(saddrlens[i]);
618 #if HAVE_SOCKADDR_IN_SIN_LEN
619  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[i];
620 #endif
621  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
622  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
623  }
624  else
625  {
626  /* dual stack */
627  resi = 2;
628  if (NULL != unixpath)
629  resi++;
630  saddrs = GNUNET_new_array(resi + 1, struct sockaddr *);
631  saddrlens = GNUNET_new_array(resi + 1, socklen_t);
632  i = 0;
633  if (NULL != unixpath)
634  {
635  add_unixpath(saddrs, saddrlens, unixpath, abstract);
636  i++;
637  }
638  saddrlens[i] = sizeof(struct sockaddr_in6);
639  saddrs[i] = GNUNET_malloc(saddrlens[i]);
640 #if HAVE_SOCKADDR_IN_SIN_LEN
641  ((struct sockaddr_in6 *)saddrs[i])->sin6_len = saddrlens[0];
642 #endif
643  ((struct sockaddr_in6 *)saddrs[i])->sin6_family = AF_INET6;
644  ((struct sockaddr_in6 *)saddrs[i])->sin6_port = htons(port);
645  i++;
646  saddrlens[i] = sizeof(struct sockaddr_in);
647  saddrs[i] = GNUNET_malloc(saddrlens[i]);
648 #if HAVE_SOCKADDR_IN_SIN_LEN
649  ((struct sockaddr_in *)saddrs[i])->sin_len = saddrlens[1];
650 #endif
651  ((struct sockaddr_in *)saddrs[i])->sin_family = AF_INET;
652  ((struct sockaddr_in *)saddrs[i])->sin_port = htons(port);
653  }
654  }
655  GNUNET_free_non_null(unixpath);
656  *addrs = saddrs;
657  *addr_lens = saddrlens;
658  return resi;
659 }
int GNUNET_CONFIGURATION_get_value_number(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, unsigned long long *number)
Get a configuration value that should be a number.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
#define LOG(kind,...)
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:181
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
int GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
#define GNUNET_new_array(n, type)
Allocate a size n array with structs or unions of the given type.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
static int res
int GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static char * hostname
Our hostname; we give this to all the peers we start.
static uint16_t port
Port number.
Definition: gnunet-bcd.c:81
#define LOG_STRERROR(kind, syscall)
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
handle to a socket
Definition: network.c: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:151
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static void add_unixpath(struct sockaddr **saddrs, socklen_t *saddrlens, const char *unixpath, int abstract)
Add the given UNIX domain path as an address to the list (as the first entry).
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
#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:900
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 673 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().

677 {
678  struct GNUNET_MQ_Envelope *env;
680 
681  (void)name;
683  msg->result = htonl(result);
684  msg->arm_msg.request_id = GNUNET_htonll(request_id);
686 }
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:75
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2424
#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:88
uint32_t result
Result from the enum GNUNET_ARM_Result
Definition: arm.h:93
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:84
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
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 698 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().

701 {
702  struct GNUNET_MQ_Envelope *env;
704  size_t namelen;
705 
707  "Sending status %u of service `%s' to client\n",
708  (unsigned int)status,
709  name);
710  namelen = strlen(name) + 1;
712  msg->status = htonl((uint32_t)(status));
713  GNUNET_memcpy((char *)&msg[1], name, namelen);
714  if (NULL == unicast)
715  {
716  if (NULL != notifier)
718  &msg->header,
719  GNUNET_YES);
720  GNUNET_MQ_discard(env);
721  }
722  else
723  {
725  }
726 }
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:2424
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
struct GNUNET_MessageHeader header
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_STATUS.
Definition: arm.h:45
#define GNUNET_MQ_msg_extra(mvar, esize, type)
Allocate an envelope, with extra space allocated after the space needed by the message struct...
Definition: gnunet_mq_lib.h:52
uint16_t status
See PRISM_STATUS_*-constants.
void GNUNET_MQ_discard(struct GNUNET_MQ_Envelope *mqm)
Discard the message queue message, free all allocated resources.
Definition: mq.c:319
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:50
void GNUNET_notification_context_broadcast(struct GNUNET_NotificationContext *nc, const struct GNUNET_MessageHeader *msg, int can_drop)
Send a message to all subscribers of this context.
Definition: nc.c:187
#define GNUNET_log(kind,...)
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_MQ_send(struct GNUNET_MQ_Handle *mq, struct GNUNET_MQ_Envelope *ev)
Send a message with the given message queue.
Definition: mq.c:351
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 738 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, 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().

741 {
742  char *loprefix;
743  char *options;
744  int use_debug;
745  int is_simple_service;
746  struct ServiceListeningInfo *sli;
747  SOCKTYPE *lsocks;
748  unsigned int ls;
749  char *binary;
750  char *quotedbinary;
751 
752  /* calculate listen socket list */
753  lsocks = NULL;
754  ls = 0;
755  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
756  {
757  GNUNET_array_append(lsocks,
758  ls,
760  if (NULL != sli->accept_task)
761  {
763  sli->accept_task = NULL;
764  }
765  }
766 
767  GNUNET_array_append(lsocks, ls, -1);
768 
769  /* obtain configuration */
771  sl->name,
772  "PREFIX",
773  &loprefix))
774  loprefix = GNUNET_strdup(prefix_command);
775  else
776  loprefix = GNUNET_CONFIGURATION_expand_dollar(cfg, loprefix);
778  sl->name,
779  "OPTIONS",
780  &options))
781  options = NULL;
782  else
783  options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
784  {
785  char *new_options;
786  char *optpos;
787  char *fin_options;
788 
789  fin_options = GNUNET_strdup(final_option);
790  /* replace '{}' with service name */
791  while (NULL != (optpos = strstr(fin_options, "{}")))
792  {
793  /* terminate string at opening parenthesis */
794  *optpos = 0;
795  GNUNET_asprintf(&new_options,
796  "%s%s%s",
797  fin_options,
798  sl->name,
799  optpos + 2);
800  GNUNET_free(fin_options);
801  fin_options = new_options;
802  }
803  if (NULL != options)
804  {
805  /* combine "fin_options" with "options" */
806  optpos = options;
807  GNUNET_asprintf(&options, "%s %s", fin_options, optpos);
808  GNUNET_free(fin_options);
809  GNUNET_free(optpos);
810  }
811  else
812  {
813  /* only have "fin_options", use that */
814  options = fin_options;
815  }
816  }
817  options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
818  use_debug = GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "DEBUG");
819  {
820  const char *service_type = NULL;
821  const char *choices[] = { "GNUNET", "SIMPLE", NULL };
822 
823  is_simple_service = GNUNET_NO;
825  sl->name,
826  "TYPE",
827  choices,
828  &service_type)) &&
829  (0 == strcasecmp(service_type, "SIMPLE")))
830  is_simple_service = GNUNET_YES;
831  }
832 
833  GNUNET_assert(NULL == sl->proc);
834  if (GNUNET_YES == is_simple_service)
835  {
836  /* A simple service will receive no GNUnet specific
837  command line options. */
838  binary = GNUNET_strdup(sl->binary);
839  binary = GNUNET_CONFIGURATION_expand_dollar(cfg, binary);
840  GNUNET_asprintf(&quotedbinary, "\"%s\"", sl->binary);
842  "Starting simple service `%s' using binary `%s'\n",
843  sl->name,
844  sl->binary);
845  /* FIXME: dollar expansion should only be done outside
846  * of ''-quoted strings, escaping should be considered. */
847  if (NULL != options)
848  options = GNUNET_CONFIGURATION_expand_dollar(cfg, options);
851  lsocks,
852  loprefix,
853  quotedbinary,
854  options,
855  NULL);
856  }
857  else
858  {
859  /* actually start process */
861  "Starting service `%s' using binary `%s' and configuration `%s'\n",
862  sl->name,
863  sl->binary,
864  sl->config);
866  GNUNET_asprintf(&quotedbinary, "\"%s\"", binary);
867 
868  if (GNUNET_YES == use_debug)
869  {
870  if (NULL == sl->config)
873  lsocks,
874  loprefix,
875  quotedbinary,
876  "-L",
877  "DEBUG",
878  options,
879  NULL);
880  else
883  lsocks,
884  loprefix,
885  quotedbinary,
886  "-c",
887  sl->config,
888  "-L",
889  "DEBUG",
890  options,
891  NULL);
892  }
893  else
894  {
895  if (NULL == sl->config)
898  lsocks,
899  loprefix,
900  quotedbinary,
901  options,
902  NULL);
903  else
906  lsocks,
907  loprefix,
908  quotedbinary,
909  "-c",
910  sl->config,
911  options,
912  NULL);
913  }
914  }
915  GNUNET_free(binary);
916  GNUNET_free(quotedbinary);
917  if (NULL == sl->proc)
918  {
920  _("Failed to start service `%s'\n"),
921  sl->name);
922  if (client)
923  signal_result(client,
924  sl->name,
925  request_id,
927  }
928  else
929  {
931  _("Starting service `%s'\n"),
932  sl->name);
934  if (client)
935  signal_result(client, sl->name, request_id, GNUNET_ARM_RESULT_STARTING);
936  }
937  /* clean up */
938  GNUNET_free(loprefix);
939  GNUNET_free(options);
940  GNUNET_array_grow(lsocks, ls, 0);
941 }
int GNUNET_NETWORK_get_fd(const struct GNUNET_NETWORK_Handle *desc)
Return file descriptor for this network handle.
Definition: network.c:1068
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:237
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:762
#define GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
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:181
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
#define GNUNET_array_grow(arr, size, tsize)
Grow a well-typed (!) array.
Tried to start a service, but that failed for some reason.
Service starting was initiated.
Record with information about a listen socket we have open.
When these flags are set, the child process will inherit stdout and stderr of the parent...
Definition: gnunet_os_lib.h:96
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:77
char * name
Name of the service.
struct ServiceListeningInfo * next
This is a linked list.
int GNUNET_CONFIGURATION_get_value_choice(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, const char *const *choices, const char **value)
Get a configuration value that should be in a set of predefined strings.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_free(ptr)
Wrapper around free.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
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 952 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().

953 {
954  struct ServiceList *sl;
955 
956  sl = running_head;
957  while (sl != NULL)
958  {
959  if (0 == strcasecmp(sl->name, name))
960  return sl;
961  sl = sl->next;
962  }
963  return NULL;
964 }
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 974 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().

975 {
976  struct ServiceListeningInfo *sli = cls;
977  struct ServiceList *sl = sli->sl;
978 
979  sli->accept_task = NULL;
981  start_process(sl, NULL, 0);
982 }
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
List of our services.
Record with information about a listen socket we have open.
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
static int in_shutdown
Are we in shutdown mode?
Here is the call graph for this function:
Here is the caller graph for this function:

◆ create_listen_socket()

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

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

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

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

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

Referenced by setup_service().

997 {
998  static int on = 1;
999  struct GNUNET_NETWORK_Handle *sock;
1000  struct ServiceListeningInfo *sli;
1001 
1002  int match_uid;
1003  int match_gid;
1004 
1005  switch (sa->sa_family)
1006  {
1007  case AF_INET:
1008  sock = GNUNET_NETWORK_socket_create(PF_INET, SOCK_STREAM, 0);
1009  break;
1010 
1011  case AF_INET6:
1012  sock = GNUNET_NETWORK_socket_create(PF_INET6, SOCK_STREAM, 0);
1013  break;
1014 
1015  case AF_UNIX:
1016  if (0 == strcmp(GNUNET_a2s(sa, addr_len),
1017  "@")) /* Do not bind to blank UNIX path! */
1018  return;
1019  sock = GNUNET_NETWORK_socket_create(PF_UNIX, SOCK_STREAM, 0);
1020  break;
1021 
1022  default:
1023  GNUNET_break(0);
1024  sock = NULL;
1025  errno = EAFNOSUPPORT;
1026  break;
1027  }
1028  if (NULL == sock)
1029  {
1031  _("Unable to create socket for service `%s': %s\n"),
1032  sl->name,
1033  strerror(errno));
1034  GNUNET_free(sa);
1035  return;
1036  }
1038  SOL_SOCKET,
1039  SO_REUSEADDR,
1040  &on,
1041  sizeof(on)))
1043  "setsockopt");
1044 #ifdef IPV6_V6ONLY
1045  if ((sa->sa_family == AF_INET6) &&
1047  IPPROTO_IPV6,
1048  IPV6_V6ONLY,
1049  &on,
1050  sizeof(on))))
1052  "setsockopt");
1053 #endif
1054  if (AF_UNIX == sa->sa_family)
1055  GNUNET_NETWORK_unix_precheck((struct sockaddr_un *)sa);
1056  if (GNUNET_OK !=
1057  GNUNET_NETWORK_socket_bind(sock, (const struct sockaddr *)sa, addr_len))
1058  {
1059  GNUNET_log(
1061  _(
1062  "Unable to bind listening socket for service `%s' to address `%s': %s\n"),
1063  sl->name,
1064  GNUNET_a2s(sa, addr_len),
1065  strerror(errno));
1067  GNUNET_free(sa);
1068  return;
1069  }
1070  if ((AF_UNIX == sa->sa_family)
1071 #ifdef LINUX
1072  /* Permission settings are not required when abstract sockets are used */
1073  && ('\0' != ((const struct sockaddr_un *)sa)->sun_path[0])
1074 #endif
1075  )
1076  {
1077  match_uid =
1078  GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "UNIX_MATCH_UID");
1079  match_gid =
1080  GNUNET_CONFIGURATION_get_value_yesno(cfg, sl->name, "UNIX_MATCH_GID");
1081  GNUNET_DISK_fix_permissions(((const struct sockaddr_un *)sa)->sun_path,
1082  match_uid,
1083  match_gid);
1084  }
1085  if (GNUNET_OK != GNUNET_NETWORK_socket_listen(sock, 5))
1086  {
1089  GNUNET_free(sa);
1090  return;
1091  }
1093  _("ARM now monitors connections to service `%s' at `%s'\n"),
1094  sl->name,
1095  GNUNET_a2s(sa, addr_len));
1096  sli = GNUNET_new(struct ServiceListeningInfo);
1097  sli->service_addr = sa;
1098  sli->service_addr_len = addr_len;
1099  sli->listen_socket = sock;
1100  sli->sl = sl;
1101  sli->accept_task =
1103  sock,
1105  sli);
1107 }
int GNUNET_NETWORK_socket_listen(const struct GNUNET_NETWORK_Handle *desc, int backlog)
Listen on a socket.
Definition: network.c:696
int GNUNET_NETWORK_socket_setsockopt(struct GNUNET_NETWORK_Handle *fd, int level, int option_name, const void *option_value, socklen_t option_len)
Set socket option.
Definition: network.c:871
#define GNUNET_CONTAINER_DLL_insert(head, tail, element)
Insert an element at the head of a DLL.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
int GNUNET_NETWORK_socket_bind(struct GNUNET_NETWORK_Handle *desc, const struct sockaddr *address, socklen_t address_len)
Bind a socket to a particular address.
Definition: network.c:474
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
socklen_t service_addr_len
Number of bytes in service_addr.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Record with information about a listen socket we have open.
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages)...
static const struct GNUNET_CONFIGURATION_Handle * cfg
Our configuration.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
void GNUNET_DISK_fix_permissions(const char *fn, int require_uid_match, int require_gid_match)
Update POSIX permissions mask of a file on disk.
Definition: disk.c:376
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:1467
void GNUNET_NETWORK_unix_precheck(const struct sockaddr_un *un)
If services crash, they can leave a unix domain socket file on the disk.
Definition: network.c:194
char * name
Name of the service.
struct ServiceListeningInfo * 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:548
#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:900
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 1117 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().

1118 {
1121  GNUNET_assert(NULL == sl->listen_head);
1124  GNUNET_free(sl->name);
1125  GNUNET_free(sl);
1126 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct ServiceList * running_head
List of running services.
char * config
Name of the configuration file used.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
static struct ServiceList * running_tail
List of running services.
char * binary
Name of the binary used.
static int in_shutdown
Are we in shutdown mode?
#define GNUNET_YES
Definition: gnunet_common.h:77
char * name
Name of the service.
#define GNUNET_free(ptr)
Wrapper around free.
Here is the caller graph for this function:

◆ check_start()

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

Check START-message.

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

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

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

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

◆ handle_start()

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

Handle START-message.

Parameters
clsidentification of the client
amsgthe actual message

Definition at line 1153 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().

1154 {
1155  struct GNUNET_SERVICE_Client *client = cls;
1156  const char *servicename;
1157  struct ServiceList *sl;
1158  uint64_t request_id;
1159 
1160  request_id = GNUNET_ntohll(amsg->request_id);
1161  servicename = (const char *)&amsg[1];
1163  if (GNUNET_YES == in_shutdown)
1164  {
1165  signal_result(client,
1166  servicename,
1167  request_id,
1169  return;
1170  }
1171  sl = find_service(servicename);
1172  if (NULL == sl)
1173  {
1174  signal_result(client,
1175  servicename,
1176  request_id,
1178  return;
1179  }
1180  sl->force_start = GNUNET_YES;
1181  if (NULL != sl->proc)
1182  {
1183  signal_result(client,
1184  servicename,
1185  request_id,
1187  return;
1188  }
1189  start_process(sl, client, request_id);
1190 }
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:75
Asked to start it, but it&#39;s already started.
Handle to a client that is connected to a service.
Definition: service.c:246
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
List of our services.
Asked to start something, but ARM is shutting down and can&#39;t comply.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
Asked to start or stop a service, but it&#39;s not known.
static int in_shutdown
Are we in shutdown mode?
#define GNUNET_YES
Definition: gnunet_common.h:77
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
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 1199 of file gnunet-service-arm.c.

References GNUNET_ERROR_TYPE_DEBUG, GNUNET_log, and GNUNET_SCHEDULER_shutdown().

Referenced by handle_stop().

1200 {
1201  (void)cls;
1202  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Triggering shutdown\n");
1204 }
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
#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 1216 of file gnunet-service-arm.c.

References GNUNET_MQ_check_zero_termination, and GNUNET_OK.

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

◆ handle_stop()

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

Handle STOP-message.

Parameters
clsidentification of the client
amsgthe actual message

Definition at line 1231 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().

1232 {
1233  struct GNUNET_SERVICE_Client *client = cls;
1234  struct ServiceList *sl;
1235  const char *servicename;
1236  uint64_t request_id;
1237 
1238  request_id = GNUNET_ntohll(amsg->request_id);
1239  servicename = (const char *)&amsg[1];
1241  _("Preparing to stop `%s'\n"),
1242  servicename);
1244  if (0 == strcasecmp(servicename, "arm"))
1245  {
1246  broadcast_status(servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1247  signal_result(client, servicename, request_id, GNUNET_ARM_RESULT_STOPPING);
1250  return;
1251  }
1252  sl = find_service(servicename);
1253  if (NULL == sl)
1254  {
1255  signal_result(client,
1256  servicename,
1257  request_id,
1259  return;
1260  }
1261  sl->force_start = GNUNET_NO;
1262  if (GNUNET_YES == in_shutdown)
1263  {
1264  /* shutdown in progress */
1265  signal_result(client,
1266  servicename,
1267  request_id,
1269  return;
1270  }
1271  if (NULL != sl->killing_client)
1272  {
1273  /* killing already in progress */
1274  signal_result(client,
1275  servicename,
1276  request_id,
1278  return;
1279  }
1280  if (NULL == sl->proc)
1281  {
1282  /* process is down */
1283  signal_result(client,
1284  servicename,
1285  request_id,
1287  return;
1288  }
1290  "Sending kill signal to service `%s', waiting for process to die.\n",
1291  servicename);
1292  broadcast_status(servicename, GNUNET_ARM_SERVICE_STOPPING, NULL);
1293  /* no signal_start - only when it's STOPPED */
1297  sl->killing_client = client;
1298  sl->killing_client_request_id = request_id;
1299 }
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:75
#define GNUNET_NO
Definition: gnunet_common.h:78
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
Handle to a client that is connected to a service.
Definition: service.c:246
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
static struct ServiceList * find_service(const char *name)
Find the process with the given service name in the given list and return it.
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).
#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:1264
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:77
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate)...
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:242
struct GNUNET_SERVICE_Client * killing_client
Client to notify upon kill completion (waitpid), NULL if we should simply restart the process...
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
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:2411
int GNUNET_OS_process_kill(struct GNUNET_OS_Process *proc, int sig)
Sends a signal to the process.
Definition: os_priority.c:224
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 1309 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.

1310 {
1311  struct GNUNET_SERVICE_Client *client = cls;
1312  struct GNUNET_MQ_Envelope *env;
1314  size_t string_list_size;
1315  struct ServiceList *sl;
1316  uint16_t count;
1317  char *pos;
1318 
1319  GNUNET_break(0 == ntohl(request->reserved));
1320  count = 0;
1321  string_list_size = 0;
1322 
1323  /* first count the running processes get their name's size */
1324  for (sl = running_head; NULL != sl; sl = sl->next)
1325  {
1326  if (NULL != sl->proc)
1327  {
1328  string_list_size += strlen(sl->name);
1329  string_list_size += strlen(sl->binary);
1330  string_list_size += 4;
1331  count++;
1332  }
1333  }
1334 
1335  env = GNUNET_MQ_msg_extra(msg,
1336  string_list_size,
1338  msg->arm_msg.request_id = request->request_id;
1339  msg->count = htons(count);
1340 
1341  pos = (char *)&msg[1];
1342  for (sl = running_head; NULL != sl; sl = sl->next)
1343  {
1344  if (NULL != sl->proc)
1345  {
1346  size_t s = strlen(sl->name) + strlen(sl->binary) + 4;
1347  GNUNET_snprintf(pos, s, "%s (%s)", sl->name, sl->binary);
1348  pos += s;
1349  }
1350  }
1353 }
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:75
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:2424
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, with an ID.
Definition: arm.h:107
uint32_t reserved
For alignment.
Definition: arm.h:68
uint16_t count
Number of &#39;\0&#39; terminated strings that follow this message.
Definition: arm.h:113
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct ServiceList * next
This is a doubly-linked list.
Handle to a client that is connected to a service.
Definition: service.c:246
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:102
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:351
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:2234
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 1363 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.

1364 {
1365  struct GNUNET_SERVICE_Client *client = cls;
1366  struct GNUNET_MQ_Envelope *env;
1367  struct GNUNET_MessageHeader *msg;
1368 
1369  (void)message;
1373 }
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:2424
#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:246
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:351
void GNUNET_SERVICE_client_continue(struct GNUNET_SERVICE_Client *c)
Continue receiving further messages from the given client.
Definition: service.c:2234
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 1381 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().

1382 {
1383  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Last shutdown phase\n");
1384  if (NULL != notifier)
1385  {
1387  notifier = NULL;
1388  }
1389  if (NULL != service)
1390  {
1392  service = NULL;
1393  }
1394  if (NULL != child_death_task)
1395  {
1397  child_death_task = NULL;
1398  }
1399 }
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:135
void GNUNET_SERVICE_shutdown(struct GNUNET_SERVICE_Handle *sh)
Explicitly stops the service.
Definition: service.c:2370
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:956
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 1409 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().

1410 {
1411  struct ServiceList *i;
1412  unsigned int res;
1413 
1414  for (res = 0, i = running_head; NULL != i; i = i->next, res++)
1416  return res;
1417 }
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 1426 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().

1427 {
1428  struct ServiceList *pos;
1429  struct ServiceList *nxt;
1430  struct ServiceListeningInfo *sli;
1431 
1432  (void)cls;
1433  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "First shutdown phase\n");
1434  if (NULL != child_restart_task)
1435  {
1437  child_restart_task = NULL;
1438  }
1440  /* first, stop listening */
1441  for (pos = running_head; NULL != pos; pos = pos->next)
1442  {
1443  while (NULL != (sli = pos->listen_head))
1444  {
1446  if (NULL != sli->accept_task)
1447  {
1449  sli->accept_task = NULL;
1450  }
1453  GNUNET_free(sli->service_addr);
1454  GNUNET_free(sli);
1455  }
1456  }
1457  /* then, shutdown all existing service processes */
1458  nxt = running_head;
1459  while (NULL != (pos = nxt))
1460  {
1461  nxt = pos->next;
1462  if (NULL != pos->proc)
1463  {
1464  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Stopping service `%s'\n", pos->name);
1468  }
1469  else
1470  {
1471  free_service(pos);
1472  }
1473  }
1474  /* finally, should all service processes be already gone, terminate for real */
1475  if (NULL == running_head)
1476  do_shutdown();
1477  else
1479  "Delaying shutdown, have %u childs still running\n",
1481 }
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
static struct ServiceList * running_head
List of running services.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
static unsigned int list_count(struct ServiceList *running_head)
Count how many services are still active.
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
struct ServiceList * next
This is a doubly-linked list.
#define GNUNET_log_strerror(level, cmd)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
List of our services.
Record with information about a listen socket we have open.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
static void free_service(struct ServiceList *sl)
Remove and free an entry in the service list.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
static int in_shutdown
Are we in shutdown mode?
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
#define GNUNET_YES
Definition: gnunet_common.h:77
char * name
Name of the service.
struct GNUNET_TIME_Absolute killed_at
Time we asked the service to shut down (used to calculate time it took the service to terminate)...
#define GNUNET_TERM_SIG
The termination signal.
Definition: platform.h:242
struct ServiceListeningInfo * listen_tail
Linked list of listen sockets associated with this service.
int GNUNET_NETWORK_socket_close(struct GNUNET_NETWORK_Handle *desc)
Close a socket.
Definition: network.c:548
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:224
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:956
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 1490 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().

1492 {
1493  struct ServiceList *sl;
1494  struct GNUNET_TIME_Relative lowestRestartDelay;
1495  struct ServiceListeningInfo *sli;
1496 
1497  (void)cls;
1498  child_restart_task = NULL;
1500  lowestRestartDelay = GNUNET_TIME_UNIT_FOREVER_REL;
1501 
1502  /* check for services that need to be restarted due to
1503  * configuration changes or because the last restart failed */
1504  for (sl = running_head; NULL != sl; sl = sl->next)
1505  {
1506  if (NULL != sl->proc)
1507  continue;
1508  /* service is currently not running */
1510  {
1511  /* restart is now allowed */
1512  if (sl->force_start)
1513  {
1514  /* process should run by default, start immediately */
1516  _("Restarting service `%s'.\n"),
1517  sl->name);
1518  start_process(sl, NULL, 0);
1519  }
1520  else
1521  {
1522  /* process is run on-demand, ensure it is re-started if there is demand */
1523  for (sli = sl->listen_head; NULL != sli; sli = sli->next)
1524  if (NULL == sli->accept_task)
1525  {
1526  /* accept was actually paused, so start it again */
1527  sli->accept_task =
1529  sli->listen_socket,
1531  sli);
1532  }
1533  }
1534  }
1535  else
1536  {
1537  /* update calculation for earliest time to reactivate a service */
1538  lowestRestartDelay =
1539  GNUNET_TIME_relative_min(lowestRestartDelay,
1541  sl->restart_at));
1542  }
1543  }
1544  if (lowestRestartDelay.rel_value_us !=
1545  GNUNET_TIME_UNIT_FOREVER_REL.rel_value_us)
1546  {
1548  "Will restart process in %s\n",
1549  GNUNET_STRINGS_relative_time_to_string(lowestRestartDelay,
1550  GNUNET_YES));
1552  GNUNET_SCHEDULER_add_delayed_with_priority(lowestRestartDelay,
1555  NULL);
1556  }
1557 }
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:1169
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
struct ServiceList * sl
Service this listen socket is for.
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct ServiceList * next
This is a doubly-linked list.
List of our services.
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:686
#define GNUNET_TIME_UNIT_FOREVER_REL
Constant used to specify "forever".
Record with information about a listen socket we have open.
static void delayed_restart_task(void *cls)
Task run whenever it is time to restart a child that died.
Run when otherwise idle.
int force_start
Is this service to be started by default (or did a client tell us explicitly to start it)...
struct GNUNET_TIME_Relative GNUNET_TIME_relative_min(struct GNUNET_TIME_Relative t1, struct GNUNET_TIME_Relative t2)
Return the minimum of two relative time values.
Definition: time.c:272
static void start_process(struct ServiceList *sl, struct GNUNET_SERVICE_Client *client, uint64_t request_id)
Actually start the process for the given service.
struct GNUNET_OS_Process * proc
Process structure pointer of the child.
struct GNUNET_NETWORK_Handle * listen_socket
Our listening socket.
#define GNUNET_log(kind,...)
static int in_shutdown
Are we in shutdown mode?
static struct GNUNET_SCHEDULER_Task * child_restart_task
ID of task called whenever the timeout for restarting a child expires.
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_remaining(struct GNUNET_TIME_Absolute future)
Given a timestamp in the future, how much time remains until then?
Definition: time.c:331
#define GNUNET_YES
Definition: gnunet_common.h:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1467
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 1567 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().

1568 {
1569  struct ServiceList *pos;
1570  struct ServiceList *next;
1571  struct ServiceListeningInfo *sli;
1572  const char *statstr;
1573  int statcode;
1574  int ret;
1575  char c[16];
1576  enum GNUNET_OS_ProcessStatusType statusType;
1577  unsigned long statusCode;
1578  const struct GNUNET_DISK_FileHandle *pr;
1579 
1580  (void)cls;
1582  child_death_task = NULL;
1583  /* consume the signal */
1584  GNUNET_break(0 < GNUNET_DISK_file_read(pr, &c, sizeof(c)));
1585 
1586  /* check for services that died (WAITPID) */
1587  next = running_head;
1588  while (NULL != (pos = next))
1589  {
1590  next = pos->next;
1591 
1592  if (NULL == pos->proc)
1593  {
1594  if (GNUNET_YES == in_shutdown)
1595  free_service(pos);
1596  continue;
1597  }
1598 #if HAVE_WAIT4
1599  if (NULL != wait_file)
1600  {
1601  /* need to use 'wait4()' to obtain and log performance data */
1602  struct rusage ru;
1603  int status;
1604  pid_t pid;
1605 
1606  pid = GNUNET_OS_process_get_pid(pos->proc);
1607  ret = wait4(pid, &status, WNOHANG, &ru);
1608  if (ret <= 0)
1609  continue; /* no process done */
1610  if (WIFEXITED(status))
1611  {
1612  statusType = GNUNET_OS_PROCESS_EXITED;
1613  statusCode = WEXITSTATUS(status);
1614  }
1615  else if (WIFSIGNALED(status))
1616  {
1617  statusType = GNUNET_OS_PROCESS_SIGNALED;
1618  statusCode = WTERMSIG(status);
1619  }
1620  else if (WIFSTOPPED(status))
1621  {
1622  statusType = GNUNET_OS_PROCESS_SIGNALED;
1623  statusCode = WSTOPSIG(status);
1624  }
1625 #ifdef WIFCONTINUED
1626  else if (WIFCONTINUED(status))
1627  {
1628  statusType = GNUNET_OS_PROCESS_RUNNING;
1629  statusCode = 0;
1630  }
1631 #endif
1632  else
1633  {
1634  statusType = GNUNET_OS_PROCESS_UNKNOWN;
1635  statusCode = 0;
1636  }
1637  if ((GNUNET_OS_PROCESS_EXITED == statusType) ||
1638  (GNUNET_OS_PROCESS_SIGNALED == statusType))
1639  {
1640  double utime = ru.ru_utime.tv_sec + (ru.ru_utime.tv_usec / 10e6);
1641  double stime = ru.ru_stime.tv_sec + (ru.ru_stime.tv_usec / 10e6);
1642  fprintf(wait_file,
1643  "%s(%u) %.3f %.3f %llu %llu %llu %llu %llu\n",
1644  pos->binary,
1645  (unsigned int)pid,
1646  utime,
1647  stime,
1648  (unsigned long long)ru.ru_maxrss,
1649  (unsigned long long)ru.ru_inblock,
1650  (unsigned long long)ru.ru_oublock,
1651  (unsigned long long)ru.ru_nvcsw,
1652  (unsigned long long)ru.ru_nivcsw);
1653  }
1654  }
1655  else /* continue with JUST this "if" as "else" (intentionally no brackets!) */
1656 #endif
1657  if ((GNUNET_SYSERR == (ret = GNUNET_OS_process_status(pos->proc,
1658  &statusType,
1659  &statusCode))) ||
1660  (ret == GNUNET_NO) || (statusType == GNUNET_OS_PROCESS_STOPPED) ||
1661  (statusType == GNUNET_OS_PROCESS_UNKNOWN) ||
1662  (statusType == GNUNET_OS_PROCESS_RUNNING))
1663  continue;
1664 
1665  if (statusType == GNUNET_OS_PROCESS_EXITED)
1666  {
1667  statstr = _(/* process termination method */ "exit");
1668  statcode = statusCode;
1669  }
1670  else if (statusType == GNUNET_OS_PROCESS_SIGNALED)
1671  {
1672  statstr = _(/* process termination method */ "signal");
1673  statcode = statusCode;
1674  }
1675  else
1676  {
1677  statstr = _(/* process termination method */ "unknown");
1678  statcode = 0;
1679  }
1680  if (0 != pos->killed_at.abs_value_us)
1681  {
1683  _("Service `%s' took %s to terminate\n"),
1684  pos->name,
1687  GNUNET_YES));
1688  }
1690  pos->proc = NULL;
1692  if (NULL != pos->killing_client)
1693  {
1695  pos->name,
1698  pos->killing_client = NULL;
1699  pos->killing_client_request_id = 0;
1700  }
1701  if (GNUNET_YES != in_shutdown)
1702  {
1703  if ((statusType == GNUNET_OS_PROCESS_EXITED) && (statcode == 0))
1704  {
1705  /* process terminated normally, allow restart at any time */
1706  pos->restart_at.abs_value_us = 0;
1707  GNUNET_log(
1709  _("Service `%s' terminated normally, will restart at any time\n"),
1710  pos->name);
1711  /* process can still be re-started on-demand, ensure it is re-started if there is demand */
1712  for (sli = pos->listen_head; NULL != sli; sli = sli->next)
1713  {
1714  GNUNET_break(NULL == sli->accept_task);
1715  sli->accept_task =
1717  sli->listen_socket,
1719  sli);
1720  }
1721  }
1722  else
1723  {
1724  GNUNET_log(
1726  _("Service `%s' terminated with status %s/%d, will restart in %s\n"),
1727  pos->name,
1728  statstr,
1729  statcode,
1731  {
1732  /* Reduce backoff based on runtime of the process,
1733  so that there is a cool-down if a process actually
1734  runs for a while. */
1735  struct GNUNET_TIME_Relative runtime;
1736  unsigned int minutes;
1737 
1739  minutes =
1740  runtime.rel_value_us / GNUNET_TIME_UNIT_MINUTES.rel_value_us;
1741  if (minutes > 31)
1743  else
1744  pos->backoff.rel_value_us <<= minutes;
1745  }
1746  /* schedule restart */
1749  if (NULL != child_restart_task)
1754  NULL);
1755  }
1756  }
1757  else
1758  {
1759  free_service(pos);
1760  }
1761  }
1764  pr,
1766  NULL);
1767  if ((NULL == running_head) && (GNUNET_YES == in_shutdown))
1768  do_shutdown();
1769  else if (GNUNET_YES == in_shutdown)
1771  "Delaying shutdown after child's death, still have %u children\n",
1773 }
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:273
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:286
ssize_t GNUNET_DISK_file_read(const struct GNUNET_DISK_FileHandle *h, void *result, size_t len)
Read the contents of a binary file into a buffer.
Definition: disk.c:729
int GNUNET_OS_process_status(struct GNUNET_OS_Process *proc, enum GNUNET_OS_ProcessStatusType *type, unsigned long *code)
Retrieve the status of a process, waiting on it if dead.
Definition: os_priority.c:963
#define GNUNET_TIME_UNIT_MINUTES
One minute.
struct GNUNET_TIME_Absolute GNUNET_TIME_relative_to_absolute(struct GNUNET_TIME_Relative rel)
Convert relative time to an absolute time in the future.
Definition: time.c:246
struct GNUNET_TIME_Relative backoff
Process exponential backoff time.
struct ServiceListeningInfo * listen_head
Linked list of listen sockets associated with this service.
static unsigned int list_count(struct ServiceList *running_head)
Count how many services are still active.
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1615
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:1744
struct GNUNET_SCHEDULER_Task * accept_task
Task doing the accepting.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
struct ServiceList * next
This is a doubly-linked list.
static void signal_result(struct GNUNET_SERVICE_Client *client, const char *name, uint64_t request_id, enum GNUNET_ARM_Result result)
Signal our client that we will start or stop the service.
uint64_t killing_client_request_id
ID of the request that killed the service (for reporting back).
List of our services.
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_with_priority(enum GNUNET_SCHEDULER_Priority prio, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified priority.
Definition: scheduler.c:1191
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:686
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:76
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:77
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_net(struct GNUNET_TIME_Relative delay, struct GNUNET_NETWORK_Handle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1467
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:956
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 1781 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().

1782 {
1783  static char c;
1784  int old_errno = errno; /* back-up errno */
1785 
1786  GNUNET_break(
1787  1 ==
1790  &c,
1791  sizeof(c)));
1792  errno = old_errno; /* restore errno */
1793 }
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
const struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_handle(const struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd n)
Get the handle to a particular pipe end.
Definition: disk.c:1744
ssize_t GNUNET_DISK_file_write(const struct GNUNET_DISK_FileHandle *h, const void *buffer, size_t n)
Write a buffer to a file.
Definition: disk.c:817
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 1805 of file gnunet-service-arm.c.

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

Referenced by run().

1806 {
1807  struct ServiceList *sl;
1808  char *binary;
1809  char *config;
1810  struct stat sbuf;
1811  struct sockaddr **addrs;
1812  socklen_t *addr_lens;
1813  int ret;
1814 
1815  (void)cls;
1816  if (0 == strcasecmp(section, "arm"))
1817  return;
1818  if (GNUNET_OK !=
1819  GNUNET_CONFIGURATION_get_value_string(cfg, section, "BINARY", &binary))
1820  {
1821  /* not a service section */
1822  return;
1823  }
1824  if ((GNUNET_YES ==
1825  GNUNET_CONFIGURATION_have_value(cfg, section, "RUN_PER_USER")) &&
1826  (GNUNET_YES ==
1828  {
1829  if (GNUNET_NO == start_user)
1830  {
1831  GNUNET_free(binary);
1832  return; /* user service, and we don't deal with those */
1833  }
1834  }
1835  else
1836  {
1837  if (GNUNET_NO == start_system)
1838  {
1839  GNUNET_free(binary);
1840  return; /* system service, and we don't deal with those */
1841  }
1842  }
1843  sl = find_service(section);
1844  if (NULL != sl)
1845  {
1846  /* got the same section twice!? */
1847  GNUNET_break(0);
1848  GNUNET_free(binary);
1849  return;
1850  }
1851  config = NULL;
1853  section,
1854  "CONFIG",
1855  &config)) &&
1857  "PATHS",
1858  "DEFAULTCONFIG",
1859  &config))) ||
1860  (0 != stat(config, &sbuf)))
1861  {
1862  if (NULL != config)
1863  {
1865  section,
1866  "CONFIG",
1867  strerror(errno));
1868  GNUNET_free(config);
1869  config = NULL;
1870  }
1871  }
1872  sl = GNUNET_new(struct ServiceList);
1873  sl->name = GNUNET_strdup(section);
1874  sl->binary = binary;
1875  sl->config = config;
1878  if (GNUNET_CONFIGURATION_have_value(cfg, section, "PIPECONTROL"))
1879  sl->pipe_control =
1882  if (GNUNET_YES ==
1883  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "IMMEDIATE_START"))
1884  {
1885  sl->force_start = GNUNET_YES;
1886  if (GNUNET_YES ==
1888  return;
1889  }
1890  else
1891  {
1892  if (GNUNET_YES !=
1893  GNUNET_CONFIGURATION_get_value_yesno(cfg, section, "START_ON_DEMAND"))
1894  return;
1895  }
1896  if (0 >= (ret = get_server_addresses(section, cfg, &addrs, &addr_lens)))
1897  return;
1898  /* this will free (or capture) addrs[i] */
1899  for (unsigned int i = 0; i < (unsigned int)ret; i++)
1900  create_listen_socket(addrs[i], addr_lens[i], sl);
1901  GNUNET_free(addrs);
1902  GNUNET_free(addr_lens);
1903 }
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 GNUNET_NO
Definition: gnunet_common.h:78
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
struct GNUNET_TIME_Absolute restart_at
Absolute time at which the process is scheduled to restart in case of death.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int pipe_control
Should we use pipes to signal this process? (YES for Java binaries and if we are on Windoze)...
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
static void create_listen_socket(struct sockaddr *sa, socklen_t addr_len, struct ServiceList *sl)
Creating a listening socket for each of the service&#39;s addresses and wait for the first incoming conne...
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:77
char * name
Name of the service.
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
#define GNUNET_free(ptr)
Wrapper around free.
static int start_system
Are we starting system services?
Here is the call graph for this function:
Here is the caller graph for this function:

◆ client_connect_cb()

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

A client connected, mark as a monitoring client.

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

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

References GNUNET_SERVICE_client_mark_monitor().

Referenced by main().

1918 {
1919  /* All clients are considered to be of the "monitor" kind
1920  * (that is, they don't affect ARM shutdown).
1921  */
1922  (void)cls;
1923  (void)mq;
1925  return client;
1926 }
void GNUNET_SERVICE_client_mark_monitor(struct GNUNET_SERVICE_Client *c)
Set the &#39;monitor&#39; flag on this client.
Definition: service.c:2394
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 1937 of file gnunet-service-arm.c.

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

Referenced by main().

1940 {
1941  (void)cls;
1942  GNUNET_assert(client == app_ctx);
1943  for (struct ServiceList *sl = running_head; NULL != sl; sl = sl->next)
1944  if (sl->killing_client == client)
1945  sl->killing_client = NULL;
1946 }
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 1958 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().

1959 {
1960  struct GNUNET_SERVICE_Client *client = cls;
1961 
1962  (void)message;
1963  /* FIXME: might want to start by letting monitor know about
1964  services that are already running */
1965  /* Removal is handled by the server implementation, internally. */
1970 }
struct GNUNET_MQ_Handle * GNUNET_SERVICE_client_get_mq(struct GNUNET_SERVICE_Client *c)
Obtain the message queue of c.
Definition: service.c:2424
void GNUNET_notification_context_add(struct GNUNET_NotificationContext *nc, struct GNUNET_MQ_Handle *mq)
Add a subscriber to the notification context.
Definition: nc.c:158
Handle to a client that is connected to a service.
Definition: service.c:246
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:2234
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 1981 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().

1984 {
1985  struct ServiceList *sl;
1986 
1987  (void)cls;
1988  cfg = c;
1989  service = serv;
1995  NULL);
1996 #if HAVE_WAIT4
1997  if (GNUNET_OK ==
1999  "ARM",
2000  "RESOURCE_DIAGNOSTICS",
2001  &wait_filename))
2002  {
2003  wait_file = fopen(wait_filename, "w");
2004  if (NULL == wait_file)
2005  {
2007  "fopen",
2008  wait_filename);
2009  }
2010  }
2011 #endif
2013  "ARM",
2014  "GLOBAL_PREFIX",
2015  &prefix_command))
2017  else
2020  "ARM",
2021  "GLOBAL_POSTFIX",
2022  &final_option))
2024  else
2026  start_user =
2027  GNUNET_CONFIGURATION_get_value_yesno(cfg, "ARM", "START_USER_SERVICES");
2028  start_system =
2029  GNUNET_CONFIGURATION_get_value_yesno(cfg, "ARM", "START_SYSTEM_SERVICES");
2030  if ((GNUNET_NO == start_user) && (GNUNET_NO == start_system))
2031  {
2032  GNUNET_log(
2034  "Please configure either START_USER_SERVICES or START_SYSTEM_SERVICES or both.\n");
2036  global_ret = 1;
2037  return;
2038  }
2040 
2041  /* start default services... */
2042  for (sl = running_head; NULL != sl; sl = sl->next)
2043  if (GNUNET_YES == sl->force_start)
2044  start_process(sl, NULL, 0);
2046 }
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:1284
char * GNUNET_CONFIGURATION_expand_dollar(const struct GNUNET_CONFIGURATION_Handle *cfg, char *orig)
Expand an expression of the form "$FOO/BAR" to "DIRECTORY/BAR" where either in the "PATHS" section or...
static void maint_child_death(void *cls)
Task triggered whenever we receive a SIGCHLD (child process died).
#define GNUNET_NO
Definition: gnunet_common.h:78
struct GNUNET_SCHEDULER_Task * GNUNET_SCHEDULER_add_read_file(struct GNUNET_TIME_Relative delay, const struct GNUNET_DISK_FileHandle *rfd, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay or when the specified file descriptor is ready f...
Definition: scheduler.c:1615
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
void GNUNET_SCHEDULER_shutdown(void)
Request the shutdown of a scheduler.
Definition: scheduler.c:517
#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:1744
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:119
void GNUNET_CONFIGURATION_iterate_sections(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_CONFIGURATION_Section_Iterator iter, void *iter_cls)
Iterate over all sections in the configuration.
#define GNUNET_log(kind,...)
int GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
static struct GNUNET_NotificationContext * notifier
Context for notifications we need to send to our clients.
#define GNUNET_YES
Definition: gnunet_common.h:77
int GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static int global_ret
Return value from main.
static void setup_service(void *cls, const char *section)
Setup our service record for the given section in the configuration file (assuming the section is for...
static int start_system
Are we starting system services?
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

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

The main function for the arm service.

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

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

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

2058 {
2059  struct GNUNET_SIGNAL_Context *shc_chld;
2063  struct GNUNET_ARM_Message,
2064  NULL),
2065  GNUNET_MQ_hd_var_size(stop,
2067  struct GNUNET_ARM_Message,
2068  NULL),
2071  struct GNUNET_MessageHeader,
2072  NULL),
2075  struct GNUNET_ARM_Message,
2076  NULL),
2079  struct GNUNET_MessageHeader,
2080  NULL),
2082 
2084  GNUNET_assert(NULL != sigpipe);
2085  shc_chld =
2087  if (0 != GNUNET_SERVICE_run_(argc,
2088  argv,
2089  "arm",
2091  &run,
2094  NULL,
2095  handlers))
2096  global_ret = 2;
2097 #if HAVE_WAIT4
2098  if (NULL != wait_file)
2099  {
2100  fclose(wait_file);
2101  wait_file = NULL;
2102  }
2103  if (NULL != wait_filename)
2104  {
2105  GNUNET_free(wait_filename);
2106  wait_filename = NULL;
2107  }
2108 #endif
2110  shc_chld = NULL;
2112  sigpipe = NULL;
2113  return global_ret;
2114 }
#define GNUNET_SIGCHLD
Definition: platform.h:42
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
Do not trigger server shutdown on signal at all; instead, allow for the user to terminate the server ...
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static void client_disconnect_cb(void *cls, struct GNUNET_SERVICE_Client *client, void *app_ctx)
A client disconnected, clean up associated state.
#define GNUNET_MESSAGE_TYPE_ARM_START
Request to ARM to start a service.
#define GNUNET_MESSAGE_TYPE_ARM_STOP
Request to ARM to stop a service.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
#define GNUNET_NO
Definition: gnunet_common.h:78
void GNUNET_SIGNAL_handler_uninstall(struct GNUNET_SIGNAL_Context *ctx)
Uninstall a previously installed signal hander.
Definition: signal.c:75
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:1518
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:50
#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:1706
#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:1962
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 194 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 199 of file gnunet-service-arm.c.

◆ cfg

const struct GNUNET_CONFIGURATION_Handle* cfg
static

Our configuration.

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

◆ prefix_command

char* prefix_command
static

Command to prepend to each actual command.

Definition at line 209 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 214 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 219 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 225 of file gnunet-service-arm.c.

◆ sigpipe

struct GNUNET_DISK_PipeHandle* sigpipe
static

Pipe used to communicate shutdown via signal.

Definition at line 230 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 240 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 245 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 250 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 262 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 267 of file gnunet-service-arm.c.