GNUnet  0.11.x
arm_api.c
Go to the documentation of this file.
1 /*
2  This file is part of GNUnet.
3  Copyright (C) 2009, 2010, 2012, 2013, 2016, 2019 GNUnet e.V.
4 
5  GNUnet is free software: you can redistribute it and/or modify it
6  under the terms of the GNU Affero General Public License as published
7  by the Free Software Foundation, either version 3 of the License,
8  or (at your option) any later version.
9 
10  GNUnet is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  Affero General Public License for more details.
14 
15  You should have received a copy of the GNU Affero General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18  SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_arm_service.h"
30 #include "gnunet_protocols.h"
31 #include "arm.h"
32 
33 #define LOG(kind, ...) GNUNET_log_from (kind, "arm-api", __VA_ARGS__)
34 
35 
41 {
46 
51 
56 
61 
66 
70  void *cont_cls;
71 
76 
80  uint64_t id;
81 
86 
91 
96 };
97 
98 
103 {
108 
113 
118 
123 
128 
133 
143 
148 
152  struct GNUNET_TIME_Relative retry_backoff;
153 
159 
164 };
165 
166 
173 static int
175 
176 
182 static void
184 {
185  struct GNUNET_ARM_Handle *h = cls;
186 
187  h->reconnect_task = NULL;
188  reconnect_arm (h);
189 }
190 
191 
198 static void
200 {
201  struct GNUNET_ARM_Operation *op;
202 
203  if (NULL != h->mq)
204  {
205  GNUNET_MQ_destroy (h->mq);
206  h->mq = NULL;
207  }
208  h->currently_up = GNUNET_NO;
209  GNUNET_assert (NULL == h->reconnect_task);
210  h->reconnect_task =
213  h);
214  while (NULL != (op = h->operation_pending_head))
215  {
216  if (NULL != op->result_cont)
217  op->result_cont (op->cont_cls,
219  0);
220  if (NULL != op->list_cont)
221  op->list_cont (op->cont_cls,
223  0,
224  NULL);
226  }
229  if (NULL != h->conn_status)
231  GNUNET_NO);
232 }
233 
234 
242 static struct GNUNET_ARM_Operation *
244  uint64_t id)
245 {
247  NULL != result;
248  result = result->next)
249  if (id == result->id)
250  return result;
251  return NULL;
252 }
253 
254 
261 static void
262 handle_arm_result (void *cls,
263  const struct GNUNET_ARM_ResultMessage *res)
264 {
265  struct GNUNET_ARM_Handle *h = cls;
266  struct GNUNET_ARM_Operation *op;
267  uint64_t id;
270  void *result_cont_cls;
271 
272  id = GNUNET_ntohll (res->arm_msg.request_id);
273  op = find_op_by_id (h,
274  id);
275  if (NULL == op)
276  {
278  "Message with unknown id %llu\n",
279  (unsigned long long) id);
280  return;
281  }
282 
283  result = (enum GNUNET_ARM_Result) ntohl (res->result);
284  if ( (GNUNET_YES == op->is_arm_stop) &&
286  {
287  /* special case: if we are stopping 'gnunet-service-arm', we do not just
288  wait for the result message, but also wait for the service to close
289  the connection (and then we have to close our client handle as well);
290  this is done by installing a different receive handler, waiting for
291  the connection to go down */if (NULL != h->thm)
292  {
293  GNUNET_break (0);
294  op->result_cont (h->thm->cont_cls,
297  GNUNET_free (h->thm);
298  }
301  op);
302  h->thm = op;
303  return;
304  }
305  result_cont = op->result_cont;
306  result_cont_cls = op->cont_cls;
308  if (NULL != result_cont)
309  result_cont (result_cont_cls,
311  result);
312 }
313 
314 
324 static const char *
325 pool_get (const char *pool_start,
326  size_t pool_size,
327  size_t str_index)
328 {
329  const char *str_start;
330  const char *end;
331 
332  if (str_index >= pool_size)
333  return NULL;
334  str_start = pool_start + str_index;
335  end = memchr (str_start, 0, pool_size - str_index);
336  if (NULL == end)
337  return NULL;
338  return str_start;
339 }
340 
341 
349 static int
351  const struct GNUNET_ARM_ListResultMessage *lres)
352 {
353  uint16_t rcount = ntohs (lres->count);
354  uint16_t msize = ntohs (lres->arm_msg.header.size) - sizeof(*lres);
355  struct GNUNET_ARM_ServiceInfoMessage *ssm;
356  size_t pool_size;
357  char *pool_start;
358 
359  (void) cls;
360  if ((rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage) > msize))
361  {
362  GNUNET_break_op (0);
363  return GNUNET_NO;
364  }
365  ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &lres[1];
366  pool_start = (char *) (ssm + rcount);
367  pool_size = msize - (rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage));
368  for (unsigned int i = 0; i < rcount; i++)
369  {
370  uint16_t name_index = ntohs (ssm->name_index);
371  uint16_t binary_index = ntohs (ssm->binary_index);
372  if (NULL == pool_get (pool_start,
373  pool_size,
374  name_index))
375  {
376  GNUNET_break_op (0);
377  return GNUNET_NO;
378  }
379  if (NULL == pool_get (pool_start,
380  pool_size,
381  binary_index))
382  {
383  GNUNET_break_op (0);
384  return GNUNET_NO;
385  }
386  ssm++;
387  }
388  return GNUNET_OK;
389 }
390 
391 
398 static void
400  const struct GNUNET_ARM_ListResultMessage *lres)
401 {
402  struct GNUNET_ARM_Handle *h = cls;
403  uint16_t rcount = ntohs (lres->count);
404  uint16_t msize = ntohs (lres->arm_msg.header.size) - sizeof(*lres);
405  struct GNUNET_ARM_ServiceInfo list[rcount];
406  struct GNUNET_ARM_ServiceInfoMessage *ssm;
407  struct GNUNET_ARM_Operation *op;
408  uint64_t id;
409  size_t pool_size;
410  char *pool_start;
411 
412  id = GNUNET_ntohll (lres->arm_msg.request_id);
413  op = find_op_by_id (h, id);
414  if (NULL == op)
415  {
417  "Message with unknown id %llu\n",
418  (unsigned long long) id);
419  return;
420  }
421 
422  GNUNET_assert ((rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage) <=
423  msize));
424 
425  ssm = (struct GNUNET_ARM_ServiceInfoMessage *) &lres[1];
426  pool_start = (char *) (ssm + rcount);
427  pool_size = msize - (rcount * sizeof (struct GNUNET_ARM_ServiceInfoMessage));
428 
429  for (unsigned int i = 0; i < rcount; i++)
430  {
431  uint16_t name_index = ntohs (ssm->name_index);
432  uint16_t binary_index = ntohs (ssm->binary_index);
433  const char *name;
434  const char *binary;
435 
436  name = pool_get (pool_start, pool_size, name_index);
437  binary = pool_get (pool_start, pool_size, binary_index);
438  GNUNET_assert (NULL != name);
439  GNUNET_assert (NULL != binary);
440  list[i] = (struct GNUNET_ARM_ServiceInfo) {
441  .name = name,
442  .binary = binary,
443  .status = ntohl (ssm->status),
444  .last_started_at = GNUNET_TIME_absolute_ntoh (ssm->last_started_at),
445  .restart_at = GNUNET_TIME_absolute_ntoh (ssm->restart_at),
446  .last_exit_status = ntohs (ssm->last_exit_status),
447  };
448  ssm++;
449  }
450  if (NULL != op->list_cont)
451  op->list_cont (op->cont_cls,
453  rcount,
454  list);
456 }
457 
458 
465 static void
466 handle_confirm (void *cls,
467  const struct GNUNET_MessageHeader *msg)
468 {
469  struct GNUNET_ARM_Handle *h = cls;
470 
471  (void) msg;
473  "Got confirmation from ARM that we are up!\n");
474  if (GNUNET_NO == h->currently_up)
475  {
477  if (NULL != h->conn_status)
479  }
480 }
481 
482 
491 static void
492 mq_error_handler (void *cls,
493  enum GNUNET_MQ_Error error)
494 {
495  struct GNUNET_ARM_Handle *h = cls;
496  struct GNUNET_ARM_Operation *op;
497 
498  (void) error;
499  h->currently_up = GNUNET_NO;
500  if (NULL != (op = h->thm))
501  {
502  h->thm = NULL;
503  op->result_cont (op->cont_cls,
506  GNUNET_free (op);
507  }
509 }
510 
511 
518 static int
520 {
521  struct GNUNET_MQ_MessageHandler handlers[] = {
522  GNUNET_MQ_hd_fixed_size (arm_result,
525  h),
526  GNUNET_MQ_hd_var_size (arm_list_result,
529  h),
530  GNUNET_MQ_hd_fixed_size (confirm,
532  struct GNUNET_MessageHeader,
533  h),
535  };
536  struct GNUNET_MessageHeader *test;
537  struct GNUNET_MQ_Envelope *env;
538 
539  if (NULL != h->mq)
540  return GNUNET_OK;
542  h->mq = GNUNET_CLIENT_connect (h->cfg,
543  "arm",
544  handlers,
546  h);
547  if (NULL == h->mq)
548  {
550  "GNUNET_CLIENT_connect returned NULL\n");
551  if (NULL != h->conn_status)
553  GNUNET_SYSERR);
554  return GNUNET_SYSERR;
555  }
557  "Sending TEST message to ARM\n");
558  env = GNUNET_MQ_msg (test,
560  GNUNET_MQ_send (h->mq, env);
561  return GNUNET_OK;
562 }
563 
564 
576 struct GNUNET_ARM_Handle *
579  void *conn_status_cls)
580 {
581  struct GNUNET_ARM_Handle *h;
582 
583  h = GNUNET_new (struct GNUNET_ARM_Handle);
584  h->cfg = cfg;
587  if (GNUNET_OK != reconnect_arm (h))
588  {
589  GNUNET_free (h);
590  return NULL;
591  }
592  return h;
593 }
594 
595 
601 void
603 {
604  struct GNUNET_ARM_Operation *op;
605 
606  LOG (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from ARM service\n");
607  while (NULL != (op = h->operation_pending_head))
608  {
611  op);
612  if (NULL != op->result_cont)
613  op->result_cont (op->cont_cls,
615  0);
616  if (NULL != op->list_cont)
617  op->list_cont (op->cont_cls,
619  0,
620  NULL);
621  if (NULL != op->async)
622  {
624  op->async = NULL;
625  }
626  GNUNET_free (op);
627  }
628  if (NULL != h->mq)
629  {
630  GNUNET_MQ_destroy (h->mq);
631  h->mq = NULL;
632  }
633  if (NULL != h->reconnect_task)
634  {
636  h->reconnect_task = NULL;
637  }
638  GNUNET_free (h);
639 }
640 
641 
651 static enum GNUNET_ARM_Result
653  enum GNUNET_OS_InheritStdioFlags std_inheritance,
654  struct GNUNET_DISK_FileHandle *sigfd)
655 {
656  struct GNUNET_OS_Process *proc;
657  char *cbinary;
658  char *binary;
659  char *quotedbinary;
660  char *config;
661  char *loprefix;
662  char *lopostfix;
663  int ld[2];
664  int *lsocks;
665 
666  if (NULL == sigfd)
667  {
668  lsocks = NULL;
669  }
670  else
671  {
672  ld[0] = sigfd->fd;
673  ld[1] = -1;
674  lsocks = ld;
675  }
677  "arm",
678  "PREFIX",
679  &loprefix))
680  loprefix = GNUNET_strdup ("");
681  else
682  loprefix = GNUNET_CONFIGURATION_expand_dollar (h->cfg, loprefix);
684  "arm",
685  "OPTIONS",
686  &lopostfix))
687  lopostfix = GNUNET_strdup ("");
688  else
689  lopostfix = GNUNET_CONFIGURATION_expand_dollar (h->cfg,
690  lopostfix);
691  if (GNUNET_OK !=
693  "arm",
694  "BINARY",
695  &cbinary))
696  {
698  "arm",
699  "BINARY");
700  GNUNET_free (loprefix);
701  GNUNET_free (lopostfix);
703  }
705  "arm",
706  "CONFIG",
707  &config))
708  config = NULL;
709  binary = GNUNET_OS_get_libexec_binary_path (cbinary);
710  GNUNET_asprintf (&quotedbinary,
711  "\"%s\"",
712  binary);
713  GNUNET_free (cbinary);
714  if ( (GNUNET_YES ==
716  "TESTING",
717  "WEAKRANDOM")) &&
718  (GNUNET_YES ==
720  "TESTING",
721  "WEAKRANDOM")) &&
722  (GNUNET_NO ==
724  "TESTING",
725  "HOSTFILE")) )
726  {
727  /* Means we are ONLY running locally */
728  /* we're clearly running a test, don't daemonize */
729  if (NULL == config)
730  proc = GNUNET_OS_start_process_s (std_inheritance,
731  lsocks,
732  loprefix,
733  quotedbinary,
734  /* no daemonization! */
735  lopostfix,
736  NULL);
737  else
738  proc = GNUNET_OS_start_process_s (std_inheritance,
739  lsocks,
740  loprefix,
741  quotedbinary,
742  "-c",
743  config,
744  /* no daemonization! */
745  lopostfix,
746  NULL);
747  }
748  else
749  {
750  if (NULL == config)
751  proc = GNUNET_OS_start_process_s (std_inheritance,
752  lsocks,
753  loprefix,
754  quotedbinary,
755  "-d", /* do daemonize */
756  lopostfix,
757  NULL);
758  else
759  proc = GNUNET_OS_start_process_s (std_inheritance,
760  lsocks,
761  loprefix,
762  quotedbinary,
763  "-c",
764  config,
765  "-d", /* do daemonize */
766  lopostfix,
767  NULL);
768  }
769  GNUNET_free (binary);
770  GNUNET_free (quotedbinary);
771  if (NULL != config)
772  GNUNET_free (config);
773  GNUNET_free (loprefix);
774  GNUNET_free (lopostfix);
775  if (NULL == proc)
779 }
780 
781 
788 void
790 {
791  struct GNUNET_ARM_Handle *h = op->h;
792 
793  if (NULL != op->async)
794  {
796  op->async = NULL;
797  }
798  if (NULL != op->rfd)
799  {
801  op->rfd = NULL;
802  }
803  if (h->thm == op)
804  {
805  op->result_cont = NULL;
806  return;
807  }
810  op);
811  GNUNET_free (op);
812 }
813 
814 
825 static struct GNUNET_ARM_Operation *
827  const char *service_name,
829  void *cb_cls,
830  uint16_t type)
831 {
832  struct GNUNET_ARM_Operation *op;
833  size_t slen;
834  struct GNUNET_MQ_Envelope *env;
835  struct GNUNET_ARM_Message *msg;
836 
837  slen = strlen (service_name) + 1;
838  if (slen + sizeof(struct GNUNET_ARM_Message) >= GNUNET_MAX_MESSAGE_SIZE)
839  {
840  GNUNET_break (0);
841  return NULL;
842  }
843  if (0 == h->request_id_counter)
844  h->request_id_counter++;
845  op = GNUNET_new (struct GNUNET_ARM_Operation);
846  op->h = h;
847  op->result_cont = cb;
848  op->cont_cls = cb_cls;
849  op->id = h->request_id_counter++;
852  op);
853  env = GNUNET_MQ_msg_extra (msg, slen, type);
854  msg->reserved = htonl (0);
855  msg->request_id = GNUNET_htonll (op->id);
856  GNUNET_memcpy (&msg[1], service_name, slen);
857  GNUNET_MQ_send (h->mq, env);
858  return op;
859 }
860 
861 
867 static void
868 notify_running (void *cls)
869 {
870  struct GNUNET_ARM_Operation *op = cls;
871  struct GNUNET_ARM_Handle *h = op->h;
872 
873  op->async = NULL;
876  op);
877  if (NULL != op->result_cont)
878  op->result_cont (op->cont_cls,
881  if ( (GNUNET_YES == h->currently_up) &&
882  (NULL != h->conn_status) )
884  GNUNET_YES);
885  GNUNET_free (op);
886 }
887 
888 
894 static void
895 notify_starting (void *cls)
896 {
897  struct GNUNET_ARM_Operation *op = cls;
898  struct GNUNET_ARM_Handle *h = op->h;
899 
900  op->async = NULL;
902  "Notifying client that we started the ARM service\n");
905  op);
906  if (NULL != op->result_cont)
907  op->result_cont (op->cont_cls,
909  op->starting_ret);
910  GNUNET_free (op);
911 }
912 
913 
924 struct GNUNET_ARM_Operation *
926  const char *service_name,
928  std_inheritance,
930  void *cont_cls)
931 {
932  struct GNUNET_ARM_Operation *op;
933  enum GNUNET_ARM_Result ret;
934  struct GNUNET_DISK_PipeHandle *sig;
935  struct GNUNET_DISK_FileHandle *wsig;
936 
938  "Starting service `%s'\n",
939  service_name);
940  if (0 != strcasecmp ("arm",
941  service_name))
942  return change_service (h,
943  service_name,
944  cont,
945  cont_cls,
947 
948  /* Possible cases:
949  * 1) We're connected to ARM already. Invoke the callback immediately.
950  * 2) We're not connected to ARM.
951  * Cancel any reconnection attempts temporarily, then perform
952  * a service test.
953  */
954  if (GNUNET_YES == h->currently_up)
955  {
957  "ARM is already running\n");
958  op = GNUNET_new (struct GNUNET_ARM_Operation);
959  op->h = h;
960  op->result_cont = cont;
961  op->cont_cls = cont_cls;
964  op);
966  return op;
967  }
968  /* This is an inherently uncertain choice, as it is of course
969  theoretically possible that ARM is up and we just did not
970  yet complete the MQ handshake. However, given that users
971  are unlikely to hammer 'gnunet-arm -s' on a busy system,
972  the above check should catch 99.99% of the cases where ARM
973  is already running. */
975  "Starting ARM service\n");
976  if (NULL == (sig = GNUNET_DISK_pipe (GNUNET_DISK_PF_NONE)))
977  {
979  "pipe");
980  } else {
981  wsig = GNUNET_DISK_pipe_detach_end (sig,
983  ret = start_arm_service (h,
984  std_inheritance,
985  wsig);
986  GNUNET_DISK_file_close (wsig);
987  if (GNUNET_ARM_RESULT_STARTING == ret)
988  reconnect_arm (h);
989  }
990  op = GNUNET_new (struct GNUNET_ARM_Operation);
991  op->h = h;
992  op->result_cont = cont;
993  op->cont_cls = cont_cls;
996  op);
997  op->starting_ret = ret;
998  if (NULL != sig)
999  {
1000  op->rfd = GNUNET_DISK_pipe_detach_end (sig,
1002  /* Wait at most a minute for gnunet-service-arm to be up, as beyond
1003  that something clearly just went wrong */
1005  op->rfd,
1006  &notify_starting,
1007  op);
1008  GNUNET_DISK_pipe_close (sig);
1009  }
1010  else
1011  {
1013  op);
1014  }
1015  return op;
1016 }
1017 
1018 
1033 struct GNUNET_ARM_Operation *
1035  const char *service_name,
1037  void *cont_cls)
1038 {
1039  struct GNUNET_ARM_Operation *op;
1040 
1042  "Stopping service `%s'\n",
1043  service_name);
1044  op = change_service (h,
1045  service_name,
1046  cont,
1047  cont_cls,
1049  if (NULL == op)
1050  return NULL;
1051  /* If the service is ARM, set a flag as we will use MQ errors
1052  to detect that the process is really gone. */
1053  if (0 == strcasecmp (service_name,
1054  "arm"))
1055  op->is_arm_stop = GNUNET_YES;
1056  return op;
1057 }
1058 
1059 
1068 struct GNUNET_ARM_Operation *
1071  void *cont_cls)
1072 {
1073  struct GNUNET_ARM_Operation *op;
1074  struct GNUNET_MQ_Envelope *env;
1075  struct GNUNET_ARM_Message *msg;
1076 
1078  "Requesting LIST from ARM service\n");
1079  if (0 == h->request_id_counter)
1080  h->request_id_counter++;
1081  op = GNUNET_new (struct GNUNET_ARM_Operation);
1082  op->h = h;
1083  op->list_cont = cont;
1084  op->cont_cls = cont_cls;
1085  op->id = h->request_id_counter++;
1088  op);
1089  env = GNUNET_MQ_msg (msg,
1091  msg->reserved = htonl (0);
1092  msg->request_id = GNUNET_htonll (op->id);
1093  GNUNET_MQ_send (h->mq, env);
1094  return op;
1095 }
1096 
1097 
1098 /* end of arm_api.c */
#define GNUNET_CONTAINER_DLL_remove(head, tail, element)
Remove an element from a DLL.
void(* GNUNET_ARM_ServiceListCallback)(void *cls, enum GNUNET_ARM_RequestStatus rs, unsigned int count, const struct GNUNET_ARM_ServiceInfo *list)
Callback function invoked when list operation is complete.
static void notify_starting(void *cls)
Task run to notify application that ARM is being started.
Definition: arm_api.c:895
struct GNUNET_ARM_Operation * next
This is a doubly-linked list.
Definition: arm_api.c:45
GNUNET_OS_InheritStdioFlags
Flags that determine which of the standard streams should be inherited by the child process...
Definition: gnunet_os_lib.h:68
ARM stopping was initiated (there&#39;s no "stopped" for ARM itself).
struct GNUNET_OS_Process * GNUNET_OS_start_process_s(enum GNUNET_OS_InheritStdioFlags std_inheritance, const int *lsocks, const char *filename,...)
Start a process.
Definition: os_priority.c:747
No special options, use non-blocking read/write operations.
const struct GNUNET_CONFIGURATION_Handle * cfg
The configuration that we are using.
Definition: arm_api.c:112
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_ntoh(struct GNUNET_TIME_AbsoluteNBO a)
Convert absolute time from network byte order.
Definition: time.c:542
#define GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT
Response from ARM for listing currently running services.
static const struct GNUNET_CONFIGURATION_Handle * cfg
Configuration we are using.
Definition: gnunet-abd.c:36
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
uint64_t request_id
ID of a request that is being replied to.
Definition: arm.h:77
struct GNUNET_MQ_Handle * GNUNET_CLIENT_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *service_name, const struct GNUNET_MQ_MessageHandler *handlers, GNUNET_MQ_ErrorHandler error_handler, void *error_handler_cls)
Create a message queue to connect to a GNUnet service.
Definition: client.c:1063
void GNUNET_OS_process_destroy(struct GNUNET_OS_Process *proc)
Cleans up process structure contents (OS-dependent) and deallocates it.
Definition: os_priority.c:287
struct GNUNET_SCHEDULER_Task * reconnect_task
ID of the reconnect task (if any).
Definition: arm_api.c:147
GNUNET_MQ_Error
Error codes for the queue.
#define GNUNET_TIME_UNIT_MINUTES
One minute.
#define LOG(kind,...)
Definition: arm_api.c:33
static const char * pool_get(const char *pool_start, size_t pool_size, size_t str_index)
Read from a string pool.
Definition: arm_api.c:325
#define GNUNET_MESSAGE_TYPE_ARM_RESULT
Response from ARM.
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.
enum GNUNET_GenericReturnValue GNUNET_DISK_file_close(struct GNUNET_DISK_FileHandle *h)
Close an open file.
Definition: disk.c:1283
static int check_arm_list_result(void *cls, const struct GNUNET_ARM_ListResultMessage *lres)
Check that list result message is well-formed.
Definition: arm_api.c:350
Entry in a doubly-linked list of operations awaiting for replies (in-order) from the ARM service...
Definition: arm_api.c:40
#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.
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT, with an ID.
Definition: arm.h:150
We disconnected from ARM, and request was not sent.
static void handle_confirm(void *cls, const struct GNUNET_MessageHeader *msg)
Receive confirmation from test, ARM service is up.
Definition: arm_api.c:466
#define GNUNET_memcpy(dst, src, n)
Call memcpy() but check for n being 0 first.
#define GNUNET_MQ_hd_fixed_size(name, code, str, ctx)
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
#define GNUNET_MQ_msg(mvar, type)
Allocate a GNUNET_MQ_Envelope.
Definition: gnunet_mq_lib.h:67
Handle for interacting with ARM.
Definition: arm_api.c:102
static void reconnect_arm_task(void *cls)
Task scheduled to try to re-connect to arm.
Definition: arm_api.c:183
struct GNUNET_MQ_Handle * mq
Our connection to the ARM service.
Definition: arm_api.c:107
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:1667
void GNUNET_ARM_operation_cancel(struct GNUNET_ARM_Operation *op)
Abort an operation.
Definition: arm_api.c:789
#define GNUNET_new(type)
Allocate a struct or union of the given type.
GNUNET_ARM_Result
Replies to ARM requests.
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_filename(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be the name of a file or directory.
void * cont_cls
Closure for result_cont or list_cont.
Definition: arm_api.c:70
Asked to start it, but it&#39;s already started.
uint16_t size
The length of the struct (in bytes, including the length field itself), in big-endian format...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_string(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option, char **value)
Get a configuration value that should be a string.
uint32_t reserved
For alignment.
Definition: arm.h:70
void GNUNET_ARM_disconnect(struct GNUNET_ARM_Handle *h)
Disconnect from the ARM service (if connected) and destroy the context.
Definition: arm_api.c:602
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
struct GNUNET_DISK_FileHandle * rfd
File descriptor to close on operation stop, if not NULL.
Definition: arm_api.c:90
uint16_t count
Number of &#39;struct GNUNET_ARM_ServiceInfoMessage&#39; that are at the end of this message.
Definition: arm.h:156
#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 * async
Task for async completion.
Definition: arm_api.c:75
static void notify_running(void *cls)
Task run to notify application that ARM is already up.
Definition: arm_api.c:868
GNUNET_ARM_ConnectionStatusCallback conn_status
Callback to invoke on connection/disconnection.
Definition: arm_api.c:127
#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...
static enum GNUNET_ARM_Result start_arm_service(struct GNUNET_ARM_Handle *h, enum GNUNET_OS_InheritStdioFlags std_inheritance, struct GNUNET_DISK_FileHandle *sigfd)
A client specifically requested starting of ARM itself.
Definition: arm_api.c:652
#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_SCHEDULER_Task * GNUNET_SCHEDULER_add_delayed(struct GNUNET_TIME_Relative delay, GNUNET_SCHEDULER_TaskCallback task, void *task_cls)
Schedule a new task to be run with a specified delay.
Definition: scheduler.c:1269
struct GNUNET_ARM_Message arm_msg
Reply to client, of type is GNUNET_MESSAGE_TYPE_ARM_RESULT, with an ID.
Definition: arm.h:91
Tried to start a service, but that failed for some reason.
struct GNUNET_ARM_Operation * GNUNET_ARM_request_service_stop(struct GNUNET_ARM_Handle *h, const char *service_name, GNUNET_ARM_ResultCallback cont, void *cont_cls)
Request a service to be stopped.
Definition: arm_api.c:1034
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
Service starting was initiated.
uint32_t result
Result from the enum GNUNET_ARM_Result
Definition: arm.h:96
struct GNUNET_DISK_FileHandle * GNUNET_DISK_pipe_detach_end(struct GNUNET_DISK_PipeHandle *p, enum GNUNET_DISK_PipeEnd end)
Detaches one of the ends from the pipe.
Definition: disk.c:1535
#define GNUNET_MQ_hd_var_size(name, code, str, ctx)
#define GNUNET_break_op(cond)
Use this for assertion violations caused by other peers (i.e.
static struct GNUNET_ARM_Operation * change_service(struct GNUNET_ARM_Handle *h, const char *service_name, GNUNET_ARM_ResultCallback cb, void *cb_cls, uint16_t type)
Start or stop a service.
Definition: arm_api.c:826
enum GNUNET_GenericReturnValue GNUNET_DISK_pipe_close(struct GNUNET_DISK_PipeHandle *p)
Closes an interprocess channel.
Definition: disk.c:1562
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:1296
static void conn_status(void *cls, int connected)
Function called whenever we connect to or disconnect from ARM.
Definition: gnunet-arm.c:302
GNUNET_ARM_ServiceListCallback list_cont
Callback for service list requests.
Definition: arm_api.c:65
static char * service_name
Option -s: service name (hash to get service descriptor)
Definition: gnunet-vpn.c:51
static const struct GNUNET_CONFIGURATION_Handle * config
struct GNUNET_ARM_Operation * GNUNET_ARM_request_service_list(struct GNUNET_ARM_Handle *h, GNUNET_ARM_ServiceListCallback cont, void *cont_cls)
Request a list of running services.
Definition: arm_api.c:1069
struct GNUNET_MessageHeader header
Reply to client, type is GNUNET_MESSAGE_TYPE_ARM_RESULT or GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT.
Definition: arm.h:65
static int result
Global testing status.
The writing-end of a pipe.
static void reconnect_arm_later(struct GNUNET_ARM_Handle *h)
Close down any existing connection to the ARM service and try re-establishing it later.
Definition: arm_api.c:199
The reading-end of a pipe.
void(* GNUNET_ARM_ConnectionStatusCallback)(void *cls, int connected)
Function called whenever we connect to or disconnect from ARM.
struct GNUNET_ARM_Handle * GNUNET_ARM_connect(const struct GNUNET_CONFIGURATION_Handle *cfg, GNUNET_ARM_ConnectionStatusCallback conn_status, void *conn_status_cls)
Set up a context for communicating with ARM, then start connecting to the ARM service using that cont...
Definition: arm_api.c:577
const char * name
The name of the service.
struct GNUNET_ARM_Operation * operation_pending_head
Head of doubly-linked list of pending operations.
Definition: arm_api.c:117
static void handle_arm_result(void *cls, const struct GNUNET_ARM_ResultMessage *res)
Handler for ARM replies.
Definition: arm_api.c:262
Message handler for a specific message type.
static int res
struct GNUNET_ARM_Operation * thm
ARM operation where the goal is to wait for ARM shutdown to complete.
Definition: arm_api.c:142
struct GNUNET_DISK_PipeHandle * GNUNET_DISK_pipe(enum GNUNET_DISK_PipeFlags pf)
Creates an interprocess channel.
Definition: disk.c:1419
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
void(* GNUNET_ARM_ResultCallback)(void *cls, enum GNUNET_ARM_RequestStatus rs, enum GNUNET_ARM_Result result)
Function called in response to a start/stop request.
uint64_t GNUNET_htonll(uint64_t n)
Convert unsigned 64-bit integer to network byte order.
Definition: common_endian.c:36
struct GNUNET_ARM_Operation * GNUNET_ARM_request_service_start(struct GNUNET_ARM_Handle *h, const char *service_name, enum GNUNET_OS_InheritStdioFlags std_inheritance, GNUNET_ARM_ResultCallback cont, void *cont_cls)
Request for a service to be started.
Definition: arm_api.c:925
uint16_t name_index
String pool index for the service&#39;s name.
Definition: arm.h:104
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_have_value(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Test if we have a value for a particular option.
#define GNUNET_MESSAGE_TYPE_ARM_LIST
Request to ARM to list all currently running services.
int16_t last_exit_status
Last process exit status.
Definition: arm.h:114
uint64_t id
Unique ID for the request.
Definition: arm_api.c:80
struct GNUNET_MQ_Envelope * env
Definition: 005.c:1
Reply from ARM to client for the GNUNET_MESSAGE_TYPE_ARM_LIST request followed by count &#39;\0&#39; terminat...
Definition: arm.h:144
struct GNUNET_ARM_Operation * prev
This is a doubly-linked list.
Definition: arm_api.c:50
#define GNUNET_CONTAINER_DLL_insert_tail(head, tail, element)
Insert an element at the tail of a DLL.
#define GNUNET_TIME_STD_BACKOFF(r)
Perform our standard exponential back-off calculation, starting at 1 ms and then going by a factor of...
#define GNUNET_MAX_MESSAGE_SIZE
Largest supported message (to be precise, one byte more than the largest possible message...
void * conn_status_cls
Closure for conn_status.
Definition: arm_api.c:132
Message was sent successfully.
Handle to a message queue.
Definition: mq.c:85
struct GNUNET_ARM_Handle * h
ARM handle.
Definition: arm_api.c:55
uint64_t request_id_counter
Counter for request identifiers.
Definition: arm_api.c:158
#define GNUNET_MESSAGE_TYPE_ARM_TEST
Test if ARM service is online.
struct GNUNET_TIME_Relative retry_backoff
Current delay we use for re-trying to connect to core.
Definition: arm_api.c:152
Reply from ARM to client.
Definition: arm.h:86
struct GNUNET_TIME_AbsoluteNBO last_started_at
Time when the service was first started, if applicable.
Definition: arm.h:135
int currently_up
Have we detected that ARM is up?
Definition: arm_api.c:163
configuration data
const char * name
enum GNUNET_ARM_Result starting_ret
Result of this operation for notify_starting().
Definition: arm_api.c:85
int is_arm_stop
Is this an operation to stop the ARM service?
Definition: arm_api.c:95
Entry in list of pending tasks.
Definition: scheduler.c:134
uint32_t status
Status from the &#39;enum GNUNET_ARM_ServiceStatus&#39;.
Definition: arm.h:124
Information about a service managed by ARM.
Asked to start or stop a service, but it&#39;s not known.
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 ...
enum GNUNET_GenericReturnValue GNUNET_CONFIGURATION_get_value_yesno(const struct GNUNET_CONFIGURATION_Handle *cfg, const char *section, const char *option)
Get a configuration value that should be in a set of "YES" or "NO".
static struct GNUNET_ARM_Operation * find_op_by_id(struct GNUNET_ARM_Handle *h, uint64_t id)
Find a control message by its unique ID.
Definition: arm_api.c:243
enum GNUNET_TESTBED_UnderlayLinkModelType type
the type of this model
Header for all communications.
void GNUNET_MQ_destroy(struct GNUNET_MQ_Handle *mq)
Destroy the message queue.
Definition: mq.c:837
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:355
int fd
File handle on Unix-like systems.
struct GNUNET_ARM_Operation * operation_pending_tail
Tail of doubly-linked list of pending operations.
Definition: arm_api.c:122
static struct GNUNET_ARM_Operation * op
Current operation.
Definition: gnunet-arm.c:144
static int reconnect_arm(struct GNUNET_ARM_Handle *h)
Connect to arm.
Definition: arm_api.c:519
Service was stopped (never sent for ARM itself).
static void handle_arm_list_result(void *cls, const struct GNUNET_ARM_ListResultMessage *lres)
Handler for ARM list replies.
Definition: arm_api.c:399
GNUNET_ARM_ResultCallback result_cont
Callback for service state change requests.
Definition: arm_api.c:60
Handle used to access files (and pipes).
Handle used to manage a pipe.
Definition: disk.c:68
struct GNUNET_TIME_AbsoluteNBO restart_at
Time when the service will be restarted, if applicable to the current status.
Definition: arm.h:130
#define GNUNET_MQ_handler_end()
End-marker for the handlers array.
uint16_t binary_index
String pool index for the service&#39;s binary.
Definition: arm.h:109
uint64_t GNUNET_ntohll(uint64_t n)
Convert unsigned 64-bit integer to host byte order.
Definition: common_endian.c:53
#define GNUNET_free(ptr)
Wrapper around free.
Time for relative time used by GNUnet, in microseconds.
void * GNUNET_SCHEDULER_cancel(struct GNUNET_SCHEDULER_Task *task)
Cancel the task with the specified identifier.
Definition: scheduler.c:972
static void mq_error_handler(void *cls, enum GNUNET_MQ_Error error)
Generic error handler, called with the appropriate error code and the same closure specified at the c...
Definition: arm_api.c:492