gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r37329 - in gnunet/src: arm include testbed testing


From: gnunet
Subject: [GNUnet-SVN] r37329 - in gnunet/src: arm include testbed testing
Date: Thu, 23 Jun 2016 16:22:35 +0200

Author: grothoff
Date: 2016-06-23 16:22:34 +0200 (Thu, 23 Jun 2016)
New Revision: 37329

Modified:
   gnunet/src/arm/arm_api.c
   gnunet/src/arm/arm_monitor_api.c
   gnunet/src/arm/gnunet-arm.c
   gnunet/src/arm/test_arm_api.c
   gnunet/src/arm/test_exponential_backoff.c
   gnunet/src/arm/test_gnunet_service_arm.c
   gnunet/src/include/gnunet_arm_service.h
   gnunet/src/include/gnunet_testbed_logger_service.h
   gnunet/src/include/gnunet_testing_lib.h
   gnunet/src/testbed/gnunet-service-testbed_peers.c
   gnunet/src/testbed/test_testbed_api.c
   gnunet/src/testbed/test_testbed_logger_api.c
   gnunet/src/testing/testing.c
Log:
refactoring ARM api to use new MQ

Modified: gnunet/src/arm/arm_api.c
===================================================================
--- gnunet/src/arm/arm_api.c    2016-06-22 17:24:29 UTC (rev 37328)
+++ gnunet/src/arm/arm_api.c    2016-06-23 14:22:34 UTC (rev 37329)
@@ -32,151 +32,131 @@
 
 #define LOG(kind,...) GNUNET_log_from (kind, "arm-api",__VA_ARGS__)
 
+
 /**
- * Handle for interacting with ARM.
+ * Entry in a doubly-linked list of operations awaiting for replies
+ * (in-order) from the ARM service.
  */
-struct GNUNET_ARM_Handle
+struct GNUNET_ARM_Operation
 {
   /**
-   * Our control connection to the ARM service.
+   * This is a doubly-linked list.
    */
-  struct GNUNET_CLIENT_Connection *client;
+  struct GNUNET_ARM_Operation *next;
 
   /**
-   * The configuration that we are using.
+   * This is a doubly-linked list.
    */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
+  struct GNUNET_ARM_Operation *prev;
 
   /**
-   * Handle for our current transmission request.
+   * ARM handle.
    */
-  struct GNUNET_CLIENT_TransmitHandle *cth;
+  struct GNUNET_ARM_Handle *h;
 
   /**
-   * Head of doubly-linked list of pending requests.
+   * Callback for service state change requests.
    */
-  struct ARMControlMessage *control_pending_head;
+  GNUNET_ARM_ResultCallback result_cont;
 
   /**
-   * Tail of doubly-linked list of pending requests.
+   * Callback for service list requests.
    */
-  struct ARMControlMessage *control_pending_tail;
+  GNUNET_ARM_ServiceListCallback list_cont;
 
   /**
-   * Head of doubly-linked list of sent requests.
+   * Closure for @e result_cont or @e list_cont.
    */
-  struct ARMControlMessage *control_sent_head;
+  void *cont_cls;
 
   /**
-   * Tail of doubly-linked list of sent requests.
+   * Task for async completion.
    */
-  struct ARMControlMessage *control_sent_tail;
+  struct GNUNET_SCHEDULER_Task *async;
 
   /**
-   * Callback to invoke on connection/disconnection.
+   * Unique ID for the request.
    */
-  GNUNET_ARM_ConnectionStatusCallback conn_status;
+  uint64_t id;
 
   /**
-   * Closure for conn_status.
+   * Result of this operation for #notify_starting().
    */
-  void *conn_status_cls;
+  enum GNUNET_ARM_Result starting_ret;
 
   /**
-   * ARM control message for the 'arm_termination_handler'
-   * with the continuation to call once the ARM shutdown is done.
+   * Is this an operation to stop the ARM service?
    */
-  struct ARMControlMessage *thm;
-
-  /**
-   * ID of the reconnect task (if any).
-   */
-  struct GNUNET_SCHEDULER_Task *reconnect_task;
-
-  /**
-   * Current delay we use for re-trying to connect to core.
-   */
-  struct GNUNET_TIME_Relative retry_backoff;
-
-  /**
-   * Counter for request identifiers
-   */
-  uint64_t request_id_counter;
-
-  /**
-   * Are we currently disconnected and hence unable to send?
-   */
-  unsigned char currently_down;
-
-  /**
-   * #GNUNET_YES if we're running a service test.
-   */
-  unsigned char service_test_is_active;
+  int is_arm_stop;
 };
 
 
 /**
- * Entry in a doubly-linked list of control messages to be transmitted
- * to the arm service.
- *
- * The actual message is allocated at the end of this struct.
+ * Handle for interacting with ARM.
  */
-struct ARMControlMessage
+struct GNUNET_ARM_Handle
 {
   /**
-   * This is a doubly-linked list.
+   * Our connection to the ARM service.
    */
-  struct ARMControlMessage *next;
+  struct GNUNET_MQ_Handle *mq;
 
   /**
-   * This is a doubly-linked list.
+   * The configuration that we are using.
    */
-  struct ARMControlMessage *prev;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
 
   /**
-   * ARM handle.
+   * Head of doubly-linked list of pending operations.
    */
-  struct GNUNET_ARM_Handle *h;
+  struct GNUNET_ARM_Operation *operation_pending_head;
 
   /**
-   * Message to send.
+   * Tail of doubly-linked list of pending operations.
    */
-  struct GNUNET_ARM_Message *msg;
+  struct GNUNET_ARM_Operation *operation_pending_tail;
 
   /**
-   * Callback for service state change requests.
+   * Callback to invoke on connection/disconnection.
    */
-  GNUNET_ARM_ResultCallback result_cont;
+  GNUNET_ARM_ConnectionStatusCallback conn_status;
 
   /**
-   * Callback for service list requests.
+   * Closure for @e conn_status.
    */
-  GNUNET_ARM_ServiceListCallback list_cont;
+  void *conn_status_cls;
 
   /**
-   * Closure for @e result_cont or @e list_cont.
+   * ARM operation where the goal is to wait for ARM shutdown to
+   * complete.  This operation is special in that it waits for an
+   * error on the @e mq.  So we complete it by calling the
+   * continuation in the #mq_error_handler().  Note that the operation
+   * is no longer in the @e operation_pending_head DLL once it is
+   * referenced from this field.
    */
-  void *cont_cls;
+  struct GNUNET_ARM_Operation *thm;
 
   /**
-   * Timeout for the operation.
+   * ID of the reconnect task (if any).
    */
-  struct GNUNET_TIME_Absolute timeout;
+  struct GNUNET_SCHEDULER_Task *reconnect_task;
 
   /**
-   * Task to run when request times out.
+   * Current delay we use for re-trying to connect to core.
    */
-  struct GNUNET_SCHEDULER_Task *timeout_task_id;
+  struct GNUNET_TIME_Relative retry_backoff;
 
   /**
-   * Flags for passing std descriptors to ARM (when starting ARM).
+   * Counter for request identifiers.  They are used to match replies
+   * from ARM to operations in the @e operation_pending_head DLL.
    */
-  enum GNUNET_OS_InheritStdioFlags std_inheritance;
+  uint64_t request_id_counter;
 
   /**
-   * Type of the request expressed as a message type (start, stop or list).
+   * Have we detected that ARM is up?
    */
-  uint16_t type;
+  int currently_up;
+
 };
 
 
@@ -191,18 +171,6 @@
 
 
 /**
- * Check the list of pending requests, send the next
- * one to the arm.
- *
- * @param h arm handle
- * @param ignore_currently_down transmit message even if not initialized?
- */
-static void
-trigger_next_request (struct GNUNET_ARM_Handle *h,
-                      int ignore_currently_down);
-
-
-/**
  * Task scheduled to try to re-connect to arm.
  *
  * @param cls the `struct GNUNET_ARM_Handle`
@@ -213,8 +181,6 @@
   struct GNUNET_ARM_Handle *h = cls;
 
   h->reconnect_task = NULL;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Connecting to ARM service after delay\n");
   reconnect_arm (h);
 }
 
@@ -228,28 +194,33 @@
 static void
 reconnect_arm_later (struct GNUNET_ARM_Handle *h)
 {
-  if (GNUNET_NO != h->currently_down)
-    return;
-  if (NULL != h->cth)
+  struct GNUNET_ARM_Operation *op;
+
+  if (NULL != h->mq)
   {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth);
-    h->cth = NULL;
+    GNUNET_MQ_destroy (h->mq);
+    h->mq = NULL;
   }
-  if (NULL != h->client)
-  {
-    GNUNET_CLIENT_disconnect (h->client);
-    h->client = NULL;
-  }
-  h->currently_down = GNUNET_YES;
+  h->currently_up = GNUNET_NO;
   GNUNET_assert (NULL == h->reconnect_task);
   h->reconnect_task =
       GNUNET_SCHEDULER_add_delayed (h->retry_backoff,
                                    &reconnect_arm_task,
                                    h);
-  /* Don't clear pending messages on disconnection, deliver them later
-  clear_pending_messages (h, GNUNET_ARM_REQUEST_DISCONNECTED);
-  GNUNET_assert (NULL == h->control_pending_head);
-  */
+  while (NULL != (op = h->operation_pending_head))
+  {
+    if (NULL != op->result_cont)
+      op->result_cont (op->cont_cls,
+                       GNUNET_ARM_REQUEST_DISCONNECTED,
+                       0);
+    if (NULL != op->list_cont)
+      op->list_cont (op->cont_cls,
+                     GNUNET_ARM_REQUEST_DISCONNECTED,
+                     0,
+                     NULL);
+    GNUNET_ARM_operation_cancel (op);
+  }
+  GNUNET_assert (NULL == h->operation_pending_head);
   h->retry_backoff = GNUNET_TIME_STD_BACKOFF (h->retry_backoff);
   if (NULL != h->conn_status)
     h->conn_status (h->conn_status_cls,
@@ -264,14 +235,14 @@
  * @param id unique message ID to use for the lookup
  * @return NULL if not found
  */
-static struct ARMControlMessage *
-find_cm_by_id (struct GNUNET_ARM_Handle *h,
+static struct GNUNET_ARM_Operation *
+find_op_by_id (struct GNUNET_ARM_Handle *h,
                uint64_t id)
 {
-  struct ARMControlMessage *result;
+  struct GNUNET_ARM_Operation *result;
 
-  for (result = h->control_sent_head; NULL != result; result = result->next)
-    if (id == result->msg->request_id)
+  for (result = h->operation_pending_head; NULL != result; result = 
result->next)
+    if (id == result->id)
       return result;
   return NULL;
 }
@@ -278,163 +249,37 @@
 
 
 /**
- * Handler for ARM 'termination' reply (failure to receive).
- *
- * @param cls our `struct GNUNET_ARM_Handle`
- * @param msg expected to be NULL
- */
-static void
-arm_termination_handler (void *cls,
-                         const struct GNUNET_MessageHeader *msg)
-{
-  struct GNUNET_ARM_Handle *h = cls;
-  struct ARMControlMessage *cm;
-
-  if (NULL != msg)
-  {
-    GNUNET_break (0);
-    GNUNET_CLIENT_receive (h->client,
-                           &arm_termination_handler,
-                           h,
-                          GNUNET_TIME_UNIT_FOREVER_REL);
-    return;
-  }
-  cm = h->thm;
-  h->thm = NULL;
-  h->currently_down = GNUNET_YES;
-  GNUNET_CLIENT_disconnect (h->client);
-  h->client = NULL;
-  if (NULL != cm->result_cont)
-    cm->result_cont (cm->cont_cls,
-                    GNUNET_ARM_REQUEST_SENT_OK,
-                    (const char *) &cm->msg[1],
-                    GNUNET_ARM_RESULT_STOPPED);
-  GNUNET_free (cm->msg);
-  GNUNET_free (cm);
-}
-
-
-/**
  * Handler for ARM replies.
  *
  * @param cls our `struct GNUNET_ARM_Handle`
- * @param msg the message received from the arm service
+ * @param res the message received from the arm service
  */
 static void
-client_notify_handler (void *cls,
-                       const struct GNUNET_MessageHeader *msg)
+handle_arm_result (void *cls,
+                   const struct GNUNET_ARM_ResultMessage *res)
 {
   struct GNUNET_ARM_Handle *h = cls;
-  const struct GNUNET_ARM_Message *arm_msg;
-  const struct GNUNET_ARM_ResultMessage *res;
-  const struct GNUNET_ARM_ListResultMessage *lres;
-  struct ARMControlMessage *cm;
-  const char **list;
-  const char *pos;
+  struct GNUNET_ARM_Operation *op;
   uint64_t id;
   enum GNUNET_ARM_Result result;
-  uint16_t size_check;
-  uint16_t rcount;
-  uint16_t msize;
-  unsigned char fail;
+  GNUNET_ARM_ResultCallback result_cont;
+  void *result_cont_cls;
 
-  list = NULL;
-  rcount = 0;
-  if (NULL == msg)
+  id = GNUNET_ntohll (res->arm_msg.request_id);
+  op = find_op_by_id (h,
+                      id);
+  if (NULL == op)
   {
-    LOG (GNUNET_ERROR_TYPE_INFO,
-         _("Client was disconnected from arm service, trying to 
reconnect.\n"));
-    reconnect_arm_later (h);
-    return;
-  }
-  msize = ntohs (msg->size);
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Processing message of type %u and size %u from arm service\n",
-       ntohs (msg->type), msize);
-  if (msize < sizeof (struct GNUNET_ARM_Message))
-  {
-    GNUNET_break (0);
-    reconnect_arm_later (h);
-    return;
-  }
-  arm_msg = (const struct GNUNET_ARM_Message *) msg;
-  GNUNET_break (0 == ntohl (arm_msg->reserved));
-  id = GNUNET_ntohll (arm_msg->request_id);
-  cm = find_cm_by_id (h, id);
-  if (NULL == cm)
-  {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Message with unknown id %llu\n",
-         id);
+         (unsigned long long) id);
     return;
   }
-  fail = GNUNET_NO;
-  switch (ntohs (msg->type))
-  {
-  case GNUNET_MESSAGE_TYPE_ARM_RESULT:
-    if (msize < sizeof (struct GNUNET_ARM_ResultMessage))
-    {
-      GNUNET_assert (0);
-      fail = GNUNET_YES;
-    }
-    break;
-  case GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT:
-    if (msize < sizeof (struct GNUNET_ARM_ListResultMessage))
-    {
-      GNUNET_break (0);
-      fail = GNUNET_YES;
-      break;
-    }
-    size_check = 0;
-    lres = (const struct GNUNET_ARM_ListResultMessage *) msg;
-    rcount = ntohs (lres->count);
-    {
-      unsigned int i;
 
-      list = GNUNET_malloc (sizeof (const char *) * rcount);
-      pos = (const char *)&lres[1];
-      for (i = 0; i < rcount; i++)
-      {
-        const char *end = memchr (pos, 0, msize - size_check);
-        if (NULL == end)
-        {
-          GNUNET_break (0);
-          fail = GNUNET_YES;
-          break;
-        }
-        list[i] = pos;
-        size_check += (end - pos) + 1;
-        pos = end + 1;
-      }
-      if (GNUNET_YES == fail)
-      {
-        GNUNET_free (list);
-        list = NULL;
-      }
-    }
-    break;
-  default:
-    fail = GNUNET_YES;
-    break;
-  }
-  GNUNET_assert (NULL != cm->timeout_task_id);
-  GNUNET_SCHEDULER_cancel (cm->timeout_task_id);
-  GNUNET_CONTAINER_DLL_remove (h->control_sent_head,
-                               h->control_sent_tail,
-                               cm);
-  if (GNUNET_YES == fail)
+  result = (enum GNUNET_ARM_Result) ntohl (res->result);
+  if ( (GNUNET_YES == op->is_arm_stop) &&
+       (GNUNET_ARM_RESULT_STOPPING == result) )
   {
-    reconnect_arm_later (h);
-    GNUNET_free (cm->msg);
-    GNUNET_free (cm);
-    return;
-  }
-  if ( (GNUNET_MESSAGE_TYPE_ARM_RESULT == ntohs (msg->type)) &&
-       (0 == strcasecmp ((const char *) &cm->msg[1],
-                        "arm")) &&
-       (NULL != (res = (const struct GNUNET_ARM_ResultMessage *) msg)) &&
-       (GNUNET_ARM_RESULT_STOPPING == ntohl (res->result)) )
-  {
     /* special case: if we are stopping 'gnunet-service-arm', we do not just
        wait for the result message, but also wait for the service to close
        the connection (and then we have to close our client handle as well);
@@ -443,184 +288,159 @@
     if (NULL != h->thm)
     {
       GNUNET_break (0);
-      cm->result_cont (h->thm->cont_cls,
+      op->result_cont (h->thm->cont_cls,
                       GNUNET_ARM_REQUEST_SENT_OK,
-                       (const char *) &h->thm->msg[1],
                       GNUNET_ARM_RESULT_IS_NOT_KNOWN);
-      GNUNET_free (h->thm->msg);
       GNUNET_free (h->thm);
     }
-    h->thm = cm;
-    GNUNET_CLIENT_receive (h->client,
-                           &arm_termination_handler,
-                           h,
-                          GNUNET_TIME_UNIT_FOREVER_REL);
+    GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
+                                 h->operation_pending_tail,
+                                 op);
+    h->thm = op;
     return;
   }
-  GNUNET_CLIENT_receive (h->client,
-                         &client_notify_handler,
-                         h,
-                         GNUNET_TIME_UNIT_FOREVER_REL);
-  switch (ntohs (msg->type))
+  result_cont = op->result_cont;
+  result_cont_cls = op->cont_cls;
+  GNUNET_ARM_operation_cancel (op);
+  if (NULL != result_cont)
+    result_cont (result_cont_cls,
+                 GNUNET_ARM_REQUEST_SENT_OK,
+                 result);
+}
+
+
+/**
+ * Checked that list result message is well-formed.
+ *
+ * @param cls our `struct GNUNET_ARM_Handle`
+ * @param lres the message received from the arm service
+ * @return #GNUNET_OK if message is well-formed
+ */
+static int
+check_arm_list_result (void *cls,
+                       const struct GNUNET_ARM_ListResultMessage *lres)
+{
+  const char *pos = (const char *) &lres[1];
+  uint16_t rcount = ntohs (lres->count);
+  uint16_t msize = ntohs (lres->arm_msg.header.size);
+  uint16_t size_check;
+
+  size_check = 0;
+  for (unsigned int i = 0; i < rcount; i++)
   {
-  case GNUNET_MESSAGE_TYPE_ARM_RESULT:
-    res = (const struct GNUNET_ARM_ResultMessage *) msg;
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Received response from ARM for service `%s': %u\n",
-         (const char *) &cm->msg[1], ntohs (msg->type));
-    result = (enum GNUNET_ARM_Result) ntohl (res->result);
-    if (NULL != cm->result_cont)
-      cm->result_cont (cm->cont_cls,
-                       GNUNET_ARM_REQUEST_SENT_OK,
-                       (const char *) &cm->msg[1],
-                       result);
-    break;
-  case GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT:
-    if (NULL != cm->list_cont)
-        cm->list_cont (cm->cont_cls,
-                       GNUNET_ARM_REQUEST_SENT_OK,
-                       rcount,
-                       list);
-    GNUNET_free_non_null (list);
-    break;
+    const char *end = memchr (pos, 0, msize - size_check);
+    if (NULL == end)
+    {
+      GNUNET_break (0);
+      return GNUNET_SYSERR;
+    }
+    size_check += (end - pos) + 1;
+    pos = end + 1;
   }
-  GNUNET_free (cm->msg);
-  GNUNET_free (cm);
+  return GNUNET_OK;
 }
 
 
 /**
- * Transmit the next message to the arm service.
+ * Handler for ARM list replies.
  *
- * @param cls closure with the `struct GNUNET_ARM_Handle`
- * @param size number of bytes available in @a buf
- * @param buf where the callee should write the message
- * @return number of bytes written to @a buf
+ * @param cls our `struct GNUNET_ARM_Handle`
+ * @param lres the message received from the arm service
  */
-static size_t
-transmit_arm_message (void *cls,
-                      size_t size,
-                      void *buf)
+static void
+handle_arm_list_result (void *cls,
+                        const struct GNUNET_ARM_ListResultMessage *lres)
 {
   struct GNUNET_ARM_Handle *h = cls;
-  struct ARMControlMessage *cm;
-  struct GNUNET_ARM_Message *arm_msg;
-  uint64_t request_id;
-  int notify_connection;
-  uint16_t msize;
+  uint16_t rcount = ntohs (lres->count);
+  const char *list[rcount];
+  const char *pos = (const char *) &lres[1];
+  uint16_t msize = ntohs (lres->arm_msg.header.size);
+  struct GNUNET_ARM_Operation *op;
+  uint16_t size_check;
+  uint64_t id;
 
-  notify_connection = GNUNET_NO;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "transmit_arm_message is running with %p buffer of size %lu. ARM is 
known to be %s\n",
-       buf, size, h->currently_down ? "unconnected" : "connected");
-  GNUNET_assert (NULL == h->reconnect_task);
-  h->cth = NULL;
-  if ((GNUNET_YES == h->currently_down) && (NULL != buf))
+  id = GNUNET_ntohll (lres->arm_msg.request_id);
+  op = find_op_by_id (h,
+                      id);
+  if (NULL == op)
   {
-    h->currently_down = GNUNET_NO;
-    notify_connection = GNUNET_YES;
-    h->retry_backoff = GNUNET_TIME_UNIT_MILLISECONDS;
-    GNUNET_CLIENT_receive (h->client, &client_notify_handler, h,
-                           GNUNET_TIME_UNIT_FOREVER_REL);
-  }
-  if (NULL == buf)
-  {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Transmission failed, initiating reconnect\n");
-    reconnect_arm_later (h);
-    return 0;
+         "Message with unknown id %llu\n",
+         (unsigned long long) id);
+    return;
   }
-  if (NULL == (cm = h->control_pending_head))
+  size_check = 0;
+  for (unsigned int i = 0; i < rcount; i++)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Queue is empty, not sending anything\n");
-    msize = 0;
-    goto end;
+    const char *end = memchr (pos,
+                              0,
+                              msize - size_check);
+
+    /* Assert, as this was already checked in #check_arm_list_result() */
+    GNUNET_assert (NULL != end);
+    list[i] = pos;
+    size_check += (end - pos) + 1;
+    pos = end + 1;
   }
-  GNUNET_assert (NULL != cm->msg);
-  msize = ntohs (cm->msg->header.size);
-  if (size < msize)
+  if (NULL != op->list_cont)
+    op->list_cont (op->cont_cls,
+                   GNUNET_ARM_REQUEST_SENT_OK,
+                   rcount,
+                   list);
+  GNUNET_ARM_operation_cancel (op);
+}
+
+
+/**
+ * Receive confirmation from test, ARM service is up.
+ *
+ * @param cls closure with the `struct GNUNET_ARM_Handle`
+ * @param msg message received
+ */
+static void
+handle_confirm (void *cls,
+                const struct GNUNET_MessageHeader *msg)
+{
+  struct GNUNET_ARM_Handle *h = cls;
+
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Got confirmation from ARM that we are up!\n");
+  if (GNUNET_NO == h->currently_up)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "Request is too big (%u < %u), not sending it\n", size, msize);
-    trigger_next_request (h, GNUNET_NO);
-    msize = 0;
-    goto end;
+    h->currently_up = GNUNET_YES;
+    if (NULL != h->conn_status)
+      h->conn_status (h->conn_status_cls,
+                      GNUNET_YES);
   }
-  arm_msg = cm->msg;
-  if (0 == h->request_id_counter)
-    h->request_id_counter++;
-  request_id = h->request_id_counter++;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Transmitting control message with %u bytes of type %u to arm with id 
%llu\n",
-       (unsigned int) msize,
-       (unsigned int) ntohs (cm->msg->header.type),
-       request_id);
-  arm_msg->reserved = htonl (0);
-  arm_msg->request_id = GNUNET_htonll (request_id);
-  memcpy (buf, cm->msg, msize);
-  /* Otherwise we won't be able to find it later! */
-  arm_msg->request_id = request_id;
-  GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
-                               h->control_pending_tail,
-                               cm);
-  GNUNET_CONTAINER_DLL_insert_tail (h->control_sent_head,
-                                    h->control_sent_tail,
-                                    cm);
-  /* Don't free msg, keep it around (kind of wasteful, but then we don't
-   * really have many messages to handle, and it'll be freed when it times
-   * out anyway.
-   */
-  trigger_next_request (h, GNUNET_NO);
-
- end:
-  if ((GNUNET_YES == notify_connection) && (NULL != h->conn_status))
-    h->conn_status (h->conn_status_cls, GNUNET_YES);
-  return msize;
 }
 
 
 /**
- * Check the list of pending requests, send the next
- * one to the arm.
+ * Generic error handler, called with the appropriate error code and
+ * the same closure specified at the creation of the message queue.
+ * Not every message queue implementation supports an error handler.
  *
- * @param h arm handle
- * @param ignore_currently_down transmit message even if not initialized?
+ * @param cls closure with the `struct GNUNET_ARM_Handle *`
+ * @param error error code
  */
 static void
-trigger_next_request (struct GNUNET_ARM_Handle *h,
-                      int ignore_currently_down)
+mq_error_handler (void *cls,
+                  enum GNUNET_MQ_Error error)
 {
-  uint16_t msize;
+  struct GNUNET_ARM_Handle *h = cls;
+  struct GNUNET_ARM_Operation *op;
 
-  msize = sizeof (struct GNUNET_MessageHeader);
-  if ((GNUNET_YES == h->currently_down) && (ignore_currently_down == 
GNUNET_NO))
+  h->currently_up = GNUNET_NO;
+  if (NULL != (op = h->thm))
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "ARM connection down, not processing queue\n");
-    return;
+    h->thm = NULL;
+    op->result_cont (op->cont_cls,
+                    GNUNET_ARM_REQUEST_SENT_OK,
+                    GNUNET_ARM_RESULT_STOPPED);
+    GNUNET_free (op);
   }
-  if (NULL != h->cth)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Request pending, not processing queue\n");
-    return;
-  }
-  if (NULL != h->control_pending_head)
-    msize =
-        ntohs (h->control_pending_head->msg->header.size);
-  else if (GNUNET_NO == ignore_currently_down)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Request queue empty, not processing queue\n");
-    return;                     /* no pending message */
-  }
-  h->cth =
-      GNUNET_CLIENT_notify_transmit_ready (h->client,
-                                           msize,
-                                           GNUNET_TIME_UNIT_FOREVER_REL,
-                                           GNUNET_NO,
-                                           &transmit_arm_message, h);
+  reconnect_arm_later (h);
 }
 
 
@@ -633,13 +453,36 @@
 static int
 reconnect_arm (struct GNUNET_ARM_Handle *h)
 {
-  GNUNET_assert (NULL == h->client);
-  GNUNET_assert (GNUNET_YES == h->currently_down);
-  h->client = GNUNET_CLIENT_connect ("arm", h->cfg);
-  if (NULL == h->client)
+  GNUNET_MQ_hd_fixed_size (arm_result,
+                           GNUNET_MESSAGE_TYPE_ARM_RESULT,
+                           struct GNUNET_ARM_ResultMessage);
+  GNUNET_MQ_hd_var_size (arm_list_result,
+                         GNUNET_MESSAGE_TYPE_ARM_LIST_RESULT,
+                         struct GNUNET_ARM_ListResultMessage);
+  GNUNET_MQ_hd_fixed_size (confirm,
+                           GNUNET_MESSAGE_TYPE_TEST,
+                           struct GNUNET_MessageHeader);
+  struct GNUNET_MQ_MessageHandler handlers[] = {
+    make_arm_result_handler (h),
+    make_arm_list_result_handler (h),
+    make_confirm_handler (h),
+    GNUNET_MQ_handler_end ()
+  };
+  struct GNUNET_MessageHeader *test;
+  struct GNUNET_MQ_Envelope *env;
+
+  if (NULL != h->mq)
+    return GNUNET_OK;
+  GNUNET_assert (GNUNET_NO == h->currently_up);
+  h->mq = GNUNET_CLIENT_connecT (h->cfg,
+                                 "arm",
+                                 handlers,
+                                 &mq_error_handler,
+                                 h);
+  if (NULL == h->mq)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-          "arm_api, GNUNET_CLIENT_connect returned NULL\n");
+         "GNUNET_CLIENT_connect returned NULL\n");
     if (NULL != h->conn_status)
       h->conn_status (h->conn_status_cls,
                       GNUNET_SYSERR);
@@ -646,9 +489,11 @@
     return GNUNET_SYSERR;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "arm_api, GNUNET_CLIENT_connect returned non-NULL\n");
-  trigger_next_request (h,
-                        GNUNET_YES);
+       "Sending TEST message to ARM\n");
+  env = GNUNET_MQ_msg (test,
+                       GNUNET_MESSAGE_TYPE_TEST);
+  GNUNET_MQ_send (h->mq,
+                  env);
   return GNUNET_OK;
 }
 
@@ -661,22 +506,20 @@
  *        the ARM service may internally use a different
  *        configuration to determine how to start the service).
  * @param conn_status will be called when connecting/disconnecting
- * @param cls closure for conn_status
+ * @param conn_status_cls closure for @a conn_status
  * @return context to use for further ARM operations, NULL on error.
  */
 struct GNUNET_ARM_Handle *
 GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                     GNUNET_ARM_ConnectionStatusCallback conn_status,
-                   void *cls)
+                   void *conn_status_cls)
 {
   struct GNUNET_ARM_Handle *h;
 
   h = GNUNET_new (struct GNUNET_ARM_Handle);
-  h->cfg = GNUNET_CONFIGURATION_dup (cfg);
-  h->currently_down = GNUNET_YES;
-  h->reconnect_task = NULL;
+  h->cfg = cfg;
   h->conn_status = conn_status;
-  h->conn_status_cls = cls;
+  h->conn_status_cls = conn_status_cls;
   if (GNUNET_OK != reconnect_arm (h))
   {
     GNUNET_free (h);
@@ -692,43 +535,37 @@
  * @param h the handle that was being used
  */
 void
-GNUNET_ARM_disconnect_and_free (struct GNUNET_ARM_Handle *h)
+GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h)
 {
-  struct ARMControlMessage *cm;
+  struct GNUNET_ARM_Operation *op;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Disconnecting from ARM service\n");
-  if (NULL != h->cth)
+  while (NULL != (op = h->operation_pending_head))
   {
-    GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth);
-    h->cth = NULL;
-  }
-  while ((NULL != (cm = h->control_pending_head))
-         || (NULL != (cm = h->control_sent_head)) )
-  {
-    if (NULL != h->control_pending_head)
-      GNUNET_CONTAINER_DLL_remove (h->control_pending_head,
-                                   h->control_pending_tail,
-                                   cm);
-    else
-      GNUNET_CONTAINER_DLL_remove (h->control_sent_head,
-                                   h->control_sent_tail,
-                                   cm);
-    GNUNET_assert (NULL != cm->timeout_task_id);
-    GNUNET_SCHEDULER_cancel (cm->timeout_task_id);
-    if (NULL != cm->result_cont)
-      cm->result_cont (cm->cont_cls,
+    GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
+                                 h->operation_pending_tail,
+                                 op);
+    if (NULL != op->result_cont)
+      op->result_cont (op->cont_cls,
                        GNUNET_ARM_REQUEST_DISCONNECTED,
-                       NULL,
                        0);
-    /* FIXME: What about list callback? */
-    GNUNET_free_non_null (cm->msg);
-    GNUNET_free (cm);
+    if (NULL != op->list_cont)
+      op->list_cont (op->cont_cls,
+                     GNUNET_ARM_REQUEST_DISCONNECTED,
+                     0,
+                     NULL);
+    if (NULL != op->async)
+    {
+      GNUNET_SCHEDULER_cancel (op->async);
+      op->async = NULL;
+    }
+    GNUNET_free (op);
   }
-  if (NULL != h->client)
+  if (NULL != h->mq)
   {
-    GNUNET_CLIENT_disconnect (h->client);
-    h->client = NULL;
+    GNUNET_MQ_destroy (h->mq);
+    h->mq = NULL;
   }
   if (NULL != h->reconnect_task)
   {
@@ -735,70 +572,23 @@
     GNUNET_SCHEDULER_cancel (h->reconnect_task);
     h->reconnect_task = NULL;
   }
-  if (GNUNET_NO == h->service_test_is_active)
-  {
-    GNUNET_CONFIGURATION_destroy (h->cfg);
-    GNUNET_free (h);
-  }
+  GNUNET_free (h);
 }
 
 
 /**
- * Message timed out. Remove it from the queue.
- *
- * @param cls the message (struct ARMControlMessage *)
- */
-static void
-control_message_timeout (void *cls)
-{
-  struct ARMControlMessage *cm = cls;
-  struct GNUNET_ARM_Message *arm_msg;
-
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Control message timed out\n");
-  arm_msg = cm->msg;
-  if ((NULL == arm_msg) || (0 == arm_msg->request_id))
-  {
-    GNUNET_CONTAINER_DLL_remove (cm->h->control_pending_head,
-                                 cm->h->control_pending_tail,
-                                 cm);
-  }
-  else
-  {
-    GNUNET_CONTAINER_DLL_remove (cm->h->control_sent_head,
-                                 cm->h->control_sent_tail,
-                                 cm);
-  }
-  if (NULL != cm->result_cont)
-    cm->result_cont (cm->cont_cls,
-                     GNUNET_ARM_REQUEST_TIMEOUT,
-                     NULL, 0);
-  else if (NULL != cm->list_cont)
-    cm->list_cont (cm->cont_cls,
-                   GNUNET_ARM_REQUEST_TIMEOUT,
-                   0, NULL);
-  GNUNET_free_non_null (cm->msg);
-  GNUNET_free (cm);
-}
-
-
-/**
  * A client specifically requested starting of ARM itself.
- * This function is called with information about whether
- * or not ARM is running; if it is, report success.  If
- * it is not, start the ARM process.
+ * Starts the ARM service.
  *
- * @param cls the context for the request that we will report on (struct 
ARMControlMessage *)
- * @param result #GNUNET_YES if ARM is running
+ * @param h the handle with configuration details
+ * @param std_inheritance inheritance of std streams
+ * @return operation status code
  */
-static void
-arm_service_report (void *cls,
-                   int result)
+static enum GNUNET_ARM_Result
+start_arm_service (struct GNUNET_ARM_Handle *h,
+                   enum GNUNET_OS_InheritStdioFlags std_inheritance)
 {
-  struct ARMControlMessage *cm = cls;
-  struct GNUNET_ARM_Handle *h;
   struct GNUNET_OS_Process *proc;
-  unsigned char test_is_active;
   char *cbinary;
   char *binary;
   char *quotedbinary;
@@ -806,51 +596,20 @@
   char *loprefix;
   char *lopostfix;
 
-  test_is_active = cm->h->service_test_is_active;
-  if ((GNUNET_YES == test_is_active) &&
-      (GNUNET_YES == result))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "Looks like `%s' is already running.\n",
-        "gnunet-service-arm");
-    /* arm is running! */
-    if (cm->result_cont)
-      cm->result_cont (cm->cont_cls,
-                      GNUNET_ARM_REQUEST_SENT_OK, "arm",
-                      GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
-  }
-  if (GNUNET_NO == test_is_active)
-  {
-    /* User disconnected & destroyed ARM handle in the middle of
-     * the service test, so we kept the handle around until now.
-     */
-    GNUNET_CONFIGURATION_destroy (cm->h->cfg);
-    GNUNET_free (cm->h);
-  }
-  if ((GNUNET_YES == result) ||
-      (GNUNET_NO == test_is_active))
-  {
-    GNUNET_free (cm);
-    return;
-  }
-  cm->h->service_test_is_active = GNUNET_NO;
-  LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Looks like `%s' is not running, will start it.\n",
-       "gnunet-service-arm");
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cm->h->cfg,
+      GNUNET_CONFIGURATION_get_value_string (h->cfg,
                                              "arm",
                                              "PREFIX",
                                              &loprefix))
     loprefix = GNUNET_strdup ("");
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cm->h->cfg,
+      GNUNET_CONFIGURATION_get_value_string (h->cfg,
                                              "arm",
                                              "OPTIONS",
                                              &lopostfix))
     lopostfix = GNUNET_strdup ("");
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cm->h->cfg,
+      GNUNET_CONFIGURATION_get_value_string (h->cfg,
                                              "arm",
                                              "BINARY",
                                              &cbinary))
@@ -858,18 +617,14 @@
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_WARNING,
                                "arm",
                                "BINARY");
-    if (cm->result_cont)
-      cm->result_cont (cm->cont_cls,
-                      GNUNET_ARM_REQUEST_SENT_OK, "arm",
-                      GNUNET_ARM_RESULT_IS_NOT_KNOWN);
-    GNUNET_free (cm);
     GNUNET_free (loprefix);
     GNUNET_free (lopostfix);
-    return;
+    return GNUNET_ARM_RESULT_IS_NOT_KNOWN;
   }
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (cm->h->cfg,
-                                               "arm", "CONFIG",
+      GNUNET_CONFIGURATION_get_value_filename (h->cfg,
+                                               "arm",
+                                               "CONFIG",
                                                &config))
     config = NULL;
   binary = GNUNET_OS_get_libexec_binary_path (cbinary);
@@ -878,15 +633,15 @@
                   binary);
   GNUNET_free (cbinary);
   if ( (GNUNET_YES ==
-        GNUNET_CONFIGURATION_have_value (cm->h->cfg,
+        GNUNET_CONFIGURATION_have_value (h->cfg,
                                          "TESTING",
                                          "WEAKRANDOM")) &&
        (GNUNET_YES ==
-        GNUNET_CONFIGURATION_get_value_yesno (cm->h->cfg,
+        GNUNET_CONFIGURATION_get_value_yesno (h->cfg,
                                               "TESTING",
                                               "WEAKRANDOM")) &&
        (GNUNET_NO ==
-        GNUNET_CONFIGURATION_have_value (cm->h->cfg,
+        GNUNET_CONFIGURATION_have_value (h->cfg,
                                          "TESTING",
                                          "HOSTFILE")))
   {
@@ -894,39 +649,43 @@
     /* we're clearly running a test, don't daemonize */
     if (NULL == config)
       proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        cm->std_inheritance,
+                                        std_inheritance,
                                         NULL,
                                         loprefix,
                                         quotedbinary,
                                         /* no daemonization! */
-                                        lopostfix, NULL);
+                                        lopostfix,
+                                        NULL);
     else
       proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        cm->std_inheritance,
+                                        std_inheritance,
                                         NULL,
                                         loprefix,
                                         quotedbinary,
                                         "-c", config,
                                         /* no daemonization! */
-                                        lopostfix, NULL);
+                                        lopostfix,
+                                        NULL);
   }
   else
   {
     if (NULL == config)
       proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        cm->std_inheritance,
+                                        std_inheritance,
                                         NULL,
                                         loprefix,
                                         quotedbinary,
-                                        "-d", lopostfix, NULL);
+                                        "-d", /* do daemonize */
+                                        lopostfix, NULL);
     else
       proc = GNUNET_OS_start_process_s (GNUNET_NO,
-                                        cm->std_inheritance,
+                                        std_inheritance,
                                         NULL,
                                         loprefix,
                                         quotedbinary,
                                         "-c", config,
-                                        "-d", lopostfix,
+                                        "-d", /* do daemonize */
+                                        lopostfix,
                                         NULL);
   }
   GNUNET_free (binary);
@@ -935,22 +694,32 @@
   GNUNET_free (loprefix);
   GNUNET_free (lopostfix);
   if (NULL == proc)
+    return GNUNET_ARM_RESULT_START_FAILED;
+  GNUNET_OS_process_destroy (proc);
+  return GNUNET_ARM_RESULT_STARTING;
+}
+
+
+/**
+ * Abort an operation.  Only prevents the callback from being
+ * called, the operation may still complete.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_ARM_operation_cancel (struct GNUNET_ARM_Operation *op)
+{
+  struct GNUNET_ARM_Handle *h = op->h;
+
+  if (h->thm == op)
   {
-    if (cm->result_cont)
-      cm->result_cont (cm->cont_cls,
-                       GNUNET_ARM_REQUEST_SENT_OK, "arm",
-                       GNUNET_ARM_RESULT_START_FAILED);
-    GNUNET_free (cm);
+    op->result_cont = NULL;
     return;
   }
-  if (cm->result_cont)
-    cm->result_cont (cm->cont_cls,
-                     GNUNET_ARM_REQUEST_SENT_OK, "arm",
-                     GNUNET_ARM_RESULT_STARTING);
-  GNUNET_OS_process_destroy (proc);
-  h = cm->h;
-  GNUNET_free (cm);
-  reconnect_arm (h);
+  GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
+                               h->operation_pending_tail,
+                               op);
+  GNUNET_free (op);
 }
 
 
@@ -959,21 +728,21 @@
  *
  * @param h handle to ARM
  * @param service_name name of the service
- * @param timeout how long to wait before failing for good
  * @param cb callback to invoke when service is ready
  * @param cb_cls closure for @a cb
  * @param type type of the request
+ * @return handle to queue, NULL on error
  */
-static void
+static struct GNUNET_ARM_Operation *
 change_service (struct GNUNET_ARM_Handle *h,
                 const char *service_name,
-               struct GNUNET_TIME_Relative timeout,
                 GNUNET_ARM_ResultCallback cb,
                void *cb_cls,
                 uint16_t type)
 {
-  struct ARMControlMessage *cm;
+  struct GNUNET_ARM_Operation *op;
   size_t slen;
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_ARM_Message *msg;
 
   slen = strlen (service_name) + 1;
@@ -981,38 +750,81 @@
       GNUNET_SERVER_MAX_MESSAGE_SIZE)
   {
     GNUNET_break (0);
-    if (cb != NULL)
-      cb (cb_cls, GNUNET_ARM_REQUEST_TOO_LONG, NULL, 0);
-    return;
+    return NULL;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Requesting %s of service `%s'.\n",
-       (GNUNET_MESSAGE_TYPE_ARM_START == type) ? "start" : "termination",
-       service_name);
-  cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen);
-  cm->h = h;
-  cm->result_cont = cb;
-  cm->cont_cls = cb_cls;
-  cm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  memcpy (&cm[1], service_name, slen);
-  msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message) + slen);
-  msg->header.size = htons (sizeof (struct GNUNET_ARM_Message) + slen);
-  msg->header.type = htons (type);
+  if (0 == h->request_id_counter)
+    h->request_id_counter++;
+  op = GNUNET_new (struct GNUNET_ARM_Operation);
+  op->h = h;
+  op->result_cont = cb;
+  op->cont_cls = cb_cls;
+  op->id = h->request_id_counter++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
+                                    h->operation_pending_tail,
+                                    op);
+  env = GNUNET_MQ_msg_extra (msg,
+                             slen,
+                             type);
   msg->reserved = htonl (0);
-  memcpy (&msg[1], service_name, slen);
-  cm->msg = msg;
+  msg->request_id = GNUNET_htonll (op->id);
+  memcpy (&msg[1],
+          service_name,
+          slen);
+  GNUNET_MQ_send (h->mq,
+                  env);
+  return op;
+}
+
+
+/**
+ * Task run to notify application that ARM is already up.
+ *
+ * @param cls the operation that asked ARM to be started
+ */
+static void
+notify_running (void *cls)
+{
+  struct GNUNET_ARM_Operation *op = cls;
+  struct GNUNET_ARM_Handle *h = op->h;
+
+  op->async = NULL;
+  GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
+                               h->operation_pending_tail,
+                               op);
+  if (NULL != op->result_cont)
+    op->result_cont (op->cont_cls,
+                     GNUNET_ARM_REQUEST_SENT_OK,
+                     GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
+  if ( (GNUNET_YES == h->currently_up) &&
+       (NULL != h->conn_status) )
+    h->conn_status (h->conn_status_cls,
+                    GNUNET_YES);
+  GNUNET_free (op);
+}
+
+
+/**
+ * Task run to notify application that ARM is being started.
+ *
+ * @param cls the operation that asked ARM to be started
+ */
+static void
+notify_starting (void *cls)
+{
+  struct GNUNET_ARM_Operation *op = cls;
+  struct GNUNET_ARM_Handle *h = op->h;
+
+  op->async = NULL;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-      "Inserting a control message into the queue. Timeout is %s\n",
-       GNUNET_STRINGS_relative_time_to_string 
(GNUNET_TIME_absolute_get_remaining (cm->timeout),
-                                              GNUNET_NO));
-  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
-                                    h->control_pending_tail,
-                                    cm);
-  cm->timeout_task_id =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                    (cm->timeout),
-                                   &control_message_timeout,
-                                    cm);
-  trigger_next_request (h, GNUNET_NO);
+       "Notifying client that we started the ARM service\n");
+  GNUNET_CONTAINER_DLL_remove (h->operation_pending_head,
+                               h->operation_pending_tail,
+                               op);
+  if (NULL != op->result_cont)
+    op->result_cont (op->cont_cls,
+                     GNUNET_ARM_REQUEST_SENT_OK,
+                     op->starting_ret);
+  GNUNET_free (op);
 }
 
 
@@ -1022,132 +834,116 @@
  * @param h handle to ARM
  * @param service_name name of the service
  * @param std_inheritance inheritance of std streams
- * @param timeout how long to wait before failing for good
  * @param cont callback to invoke after request is sent or not sent
  * @param cont_cls closure for @a cont
+ * @return handle for the operation, NULL on error
  */
-void
+struct GNUNET_ARM_Operation *
 GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
                                  const char *service_name,
                                  enum GNUNET_OS_InheritStdioFlags 
std_inheritance,
-                                 struct GNUNET_TIME_Relative timeout,
                                  GNUNET_ARM_ResultCallback cont,
                                  void *cont_cls)
 {
-  struct ARMControlMessage *cm;
-  size_t slen;
+  struct GNUNET_ARM_Operation *op;
+  enum GNUNET_ARM_Result ret;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Asked to start service `%s' within %s\n", service_name,
-       GNUNET_STRINGS_relative_time_to_string (timeout, GNUNET_NO));
-  if (0 == strcasecmp ("arm", service_name))
+       "Starting service `%s'\n",
+       service_name);
+  if (0 != strcasecmp ("arm",
+                       service_name))
+    return change_service (h,
+                           service_name,
+                           cont,
+                           cont_cls,
+                           GNUNET_MESSAGE_TYPE_ARM_START);
+
+  /* Possible cases:
+   * 1) We're connected to ARM already. Invoke the callback immediately.
+   * 2) We're not connected to ARM.
+   *    Cancel any reconnection attempts temporarily, then perform
+   *    a service test.
+   */
+  if (GNUNET_YES == h->currently_up)
   {
-    /* Possible cases:
-     * 1) We're connected to ARM already. Invoke the callback immediately.
-     * 2) We're not connected to ARM.
-     *    Cancel any reconnection attempts temporarily, then perform
-     *    a service test.
-     */
-    if (GNUNET_NO == h->currently_down)
-    {
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "ARM is already running\n");
-      if (NULL != cont)
-        cont (cont_cls,
-              GNUNET_ARM_REQUEST_SENT_OK,
-              "arm",
-              GNUNET_ARM_RESULT_IS_STARTED_ALREADY);
-    }
-    else if (GNUNET_NO == h->service_test_is_active)
-    {
-      if (NULL != h->cth)
-      {
-        GNUNET_CLIENT_notify_transmit_ready_cancel (h->cth);
-        h->cth = NULL;
-      }
-      if (NULL != h->client)
-      {
-        GNUNET_CLIENT_disconnect (h->client);
-        h->client = NULL;
-      }
-      if (NULL != h->reconnect_task)
-      {
-        GNUNET_SCHEDULER_cancel (h->reconnect_task);
-        h->reconnect_task = NULL;
-      }
-
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-          "Not connected to ARM, will do a service test\n");
-
-      slen = strlen ("arm") + 1;
-      cm = GNUNET_malloc (sizeof (struct ARMControlMessage) + slen);
-      cm->h = h;
-      cm->result_cont = cont;
-      cm->cont_cls = cont_cls;
-      cm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-      cm->std_inheritance = std_inheritance;
-      memcpy (&cm[1], service_name, slen);
-      h->service_test_is_active = GNUNET_YES;
-      GNUNET_CLIENT_service_test ("arm",
-                                  h->cfg,
-                                  timeout,
-                                  &arm_service_report,
-                                 cm);
-    }
-    else
-    {
-      /* Service test is already running - tell user to chill out and try
-       * again later.
-       */
-      LOG (GNUNET_ERROR_TYPE_DEBUG,
-           "Service test is already in progress, we're busy\n");
-      if (NULL != cont)
-        cont (cont_cls,
-              GNUNET_ARM_REQUEST_BUSY,
-              NULL, 0);
-    }
-    return;
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "ARM is already running\n");
+    op = GNUNET_new (struct GNUNET_ARM_Operation);
+    op->h = h;
+    op->result_cont = cont;
+    op->cont_cls = cont_cls;
+    GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
+                                      h->operation_pending_tail,
+                                      op);
+    op->async = GNUNET_SCHEDULER_add_now (&notify_running,
+                                          op);
+    return op;
   }
-  change_service (h,
-                  service_name,
-                  timeout,
-                  cont, cont_cls,
-                 GNUNET_MESSAGE_TYPE_ARM_START);
+  /* This is an inherently uncertain choice, as it is of course
+     theoretically possible that ARM is up and we just did not
+     yet complete the MQ handshake.  However, given that users
+     are unlikely to hammer 'gnunet-arm -s' on a busy system,
+     the above check should catch 99.99% of the cases where ARM
+     is already running. */
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Starting ARM service\n");
+  ret = start_arm_service (h,
+                           std_inheritance);
+  if (GNUNET_ARM_RESULT_STARTING == ret)
+    reconnect_arm (h);
+  op = GNUNET_new (struct GNUNET_ARM_Operation);
+  op->h = h;
+  op->result_cont = cont;
+  op->cont_cls = cont_cls;
+  GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
+                                    h->operation_pending_tail,
+                                    op);
+  op->starting_ret = ret;
+  op->async = GNUNET_SCHEDULER_add_now (&notify_starting,
+                                        op);
+  return op;
 }
 
 
 /**
- * Request a service to be stopped.
- * Stopping arm itself will not invalidate its handle, and
- * ARM API will try to restore connection to the ARM service,
- * even if ARM connection was lost because you asked for ARM to be stopped.
- * Call #GNUNET_ARM_disconnect_and_free() to free the handle and prevent
+ * Request a service to be stopped.  Stopping arm itself will not
+ * invalidate its handle, and ARM API will try to restore connection
+ * to the ARM service, even if ARM connection was lost because you
+ * asked for ARM to be stopped.  Call
+ * #GNUNET_ARM_disconnect() to free the handle and prevent
  * further connection attempts.
  *
  * @param h handle to ARM
  * @param service_name name of the service
- * @param timeout how long to wait before failing for good
  * @param cont callback to invoke after request is sent or is not sent
  * @param cont_cls closure for @a cont
+ * @return handle for the operation, NULL on error
  */
-void
+struct GNUNET_ARM_Operation *
 GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h,
                                 const char *service_name,
-                                struct GNUNET_TIME_Relative timeout,
                                 GNUNET_ARM_ResultCallback cont,
                                 void *cont_cls)
 {
+  struct GNUNET_ARM_Operation *op;
+
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Stopping service `%s' within %s\n",
-       service_name,
-       GNUNET_STRINGS_relative_time_to_string (timeout,
-                                               GNUNET_NO));
-  change_service (h,
-                  service_name,
-                  timeout,
-                  cont,
-                  cont_cls,
-                 GNUNET_MESSAGE_TYPE_ARM_STOP);
+       "Stopping service `%s'\n",
+       service_name);
+  op = change_service (h,
+                       service_name,
+                       cont,
+                       cont_cls,
+                       GNUNET_MESSAGE_TYPE_ARM_STOP);
+  if (NULL == op)
+    return NULL;
+  /* If the service is ARM, set a flag as we will use MQ errors
+     to detect that the process is really gone. */
+  if (0 == strcasecmp (service_name,
+                       "arm"))
+    op->is_arm_stop = GNUNET_YES;
+  return op;
 }
 
 
@@ -1155,43 +951,38 @@
  * Request a list of running services.
  *
  * @param h handle to ARM
- * @param timeout how long to wait before failing for good
  * @param cont callback to invoke after request is sent or is not sent
  * @param cont_cls closure for @a cont
+ * @return handle for the operation, NULL on error
  */
-void
+struct GNUNET_ARM_Operation *
 GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h,
-                                 struct GNUNET_TIME_Relative timeout,
                                  GNUNET_ARM_ServiceListCallback cont,
                                  void *cont_cls)
 {
-  struct ARMControlMessage *cm;
+  struct GNUNET_ARM_Operation *op;
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_ARM_Message *msg;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Requesting LIST from ARM service with timeout: %s\n",
-       GNUNET_STRINGS_relative_time_to_string (timeout,
-                                               GNUNET_YES));
-  cm = GNUNET_new (struct ARMControlMessage);
-  cm->h = h;
-  cm->list_cont = cont;
-  cm->cont_cls = cont_cls;
-  cm->timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  msg = GNUNET_malloc (sizeof (struct GNUNET_ARM_Message));
-  msg->header.size = htons (sizeof (struct GNUNET_ARM_Message));
-  msg->header.type = htons (GNUNET_MESSAGE_TYPE_ARM_LIST);
+       "Requesting LIST from ARM service\n");
+  if (0 == h->request_id_counter)
+    h->request_id_counter++;
+  op = GNUNET_new (struct GNUNET_ARM_Operation);
+  op->h = h;
+  op->list_cont = cont;
+  op->cont_cls = cont_cls;
+  op->id = h->request_id_counter++;
+  GNUNET_CONTAINER_DLL_insert_tail (h->operation_pending_head,
+                                    h->operation_pending_tail,
+                                    op);
+  env = GNUNET_MQ_msg (msg,
+                       GNUNET_MESSAGE_TYPE_ARM_LIST);
   msg->reserved = htonl (0);
-  cm->msg = msg;
-  GNUNET_CONTAINER_DLL_insert_tail (h->control_pending_head,
-                                    h->control_pending_tail,
-                                    cm);
-  cm->timeout_task_id =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                    (cm->timeout),
-                                   &control_message_timeout,
-                                    cm);
-  trigger_next_request (h,
-                        GNUNET_NO);
+  msg->request_id = GNUNET_htonll (op->id);
+  GNUNET_MQ_send (h->mq,
+                  env);
+  return op;
 }
 
 

Modified: gnunet/src/arm/arm_monitor_api.c
===================================================================
--- gnunet/src/arm/arm_monitor_api.c    2016-06-22 17:24:29 UTC (rev 37328)
+++ gnunet/src/arm/arm_monitor_api.c    2016-06-23 14:22:34 UTC (rev 37329)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2009, 2010, 2012, 2013 GNUnet e.V.
+     Copyright (C) 2009, 2010, 2012, 2013, 2016 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -21,7 +21,8 @@
 /**
  * @file arm/arm_monitor_api.c
  * @brief API for monitoring the ARM service
- * @author Christian Grothoff, LRN
+ * @author Christian Grothoff
+ * @author LRN
  */
 #include "platform.h"
 #include "gnunet_arm_service.h"
@@ -241,9 +242,9 @@
  * @return context to use for further ARM monitor operations, NULL on error.
  */
 struct GNUNET_ARM_MonitorHandle *
-GNUNET_ARM_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                    GNUNET_ARM_ServiceStatusCallback cont,
-                    void *cont_cls)
+GNUNET_ARM_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                          GNUNET_ARM_ServiceStatusCallback cont,
+                          void *cont_cls)
 {
   struct GNUNET_ARM_MonitorHandle *h;
 
@@ -266,7 +267,7 @@
  * @param h the handle that was being used
  */
 void
-GNUNET_ARM_monitor_disconnect_and_free (struct GNUNET_ARM_MonitorHandle *h)
+GNUNET_ARM_monitor_stop (struct GNUNET_ARM_MonitorHandle *h)
 {
   if (NULL != h->mq)
   {

Modified: gnunet/src/arm/gnunet-arm.c
===================================================================
--- gnunet/src/arm/gnunet-arm.c 2016-06-22 17:24:29 UTC (rev 37328)
+++ gnunet/src/arm/gnunet-arm.c 2016-06-23 14:22:34 UTC (rev 37329)
@@ -29,28 +29,6 @@
 #include "gnunet_util_lib.h"
 
 /**
- * Timeout for stopping services.  Long to give some services a real chance.
- */
-#define STOP_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 
1)
-
-/**
- * Timeout for stopping ARM.  Extra-long since ARM needs to stop everyone else.
- */
-#define STOP_TIMEOUT_ARM GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MINUTES, 2)
-
-/**
- * Timeout for starting services, very short because of the strange way start 
works
- * (by checking if running before starting, so really this time is always 
waited on
- * startup (annoying)).
- */
-#define START_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
1)
-
-/**
- * Timeout for listing all running services.
- */
-#define LIST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 
2)
-
-/**
  * Set if we are to shutdown all services (including ARM).
  */
 static int end;
@@ -132,6 +110,7 @@
 
 /**
  * User defined timestamp for completing operations.
+ * FIXME: to be implemented!
  */
 static struct GNUNET_TIME_Relative timeout;
 
@@ -150,6 +129,10 @@
  */
 static struct GNUNET_SCHEDULER_Task *al_task;
 
+/**
+ * Current operation.
+ */
+static struct GNUNET_ARM_Operation *op;
 
 /**
  * Attempts to delete configuration file and GNUNET_HOME
@@ -193,14 +176,19 @@
     GNUNET_SCHEDULER_cancel (al_task);
     al_task = NULL;
   }
+  if (NULL != op)
+  {
+    GNUNET_ARM_operation_cancel (op);
+    op = NULL;
+  }
   if (NULL != h)
   {
-    GNUNET_ARM_disconnect_and_free (h);
+    GNUNET_ARM_disconnect (h);
     h = NULL;
   }
   if (NULL != m)
   {
-    GNUNET_ARM_monitor_disconnect_and_free (m);
+    GNUNET_ARM_monitor_stop (m);
     m = NULL;
   }
   if ((GNUNET_YES == end) && (GNUNET_YES == delete))
@@ -229,8 +217,6 @@
     return _("We disconnected from ARM before we could send a request");
   case GNUNET_ARM_REQUEST_BUSY:
     return _("ARM API is busy");
-  case GNUNET_ARM_REQUEST_TOO_LONG:
-    return _("Request does not fit into a message");
   case GNUNET_ARM_REQUEST_TIMEOUT:
     return _("Request timed out");
   }
@@ -289,8 +275,8 @@
  * our first attempt.
  *
  * @param cls closure
- * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
- *                  GNUNET_SYSERR on error.
+ * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
+ *                  #GNUNET_SYSERR on error.
  */
 static void
 conn_status (void *cls,
@@ -318,7 +304,6 @@
  *
  * @param cls closure unused
  * @param rs what happened to our request
- * @param service name of the service we tried to start ("arm")
  * @param result if the request was processed, this is the result
  *               according to ARM
  */
@@ -325,11 +310,11 @@
 static void
 start_callback (void *cls,
                enum GNUNET_ARM_RequestStatus rs,
-               const char *service,
                enum GNUNET_ARM_Result result)
 {
   char *msg;
 
+  op = NULL;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
     GNUNET_asprintf (&msg, "%s", _("Failed to start the ARM service: %s\n"));
@@ -362,7 +347,6 @@
  *
  * @param cls closure unused
  * @param rs what happened to our request
- * @param service name of the service we tried to start ("arm")
  * @param result if the request was processed, this is the result
  *               according to ARM
  */
@@ -369,11 +353,11 @@
 static void
 stop_callback (void *cls,
               enum GNUNET_ARM_RequestStatus rs,
-              const char *service,
               enum GNUNET_ARM_Result result)
 {
   char *msg;
 
+  op = NULL;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
     GNUNET_asprintf (&msg, "%s",
@@ -416,7 +400,6 @@
  *
  * @param cls closure unused
  * @param rs what happened to our request
- * @param service name of the service we tried to start
  * @param result if the request was processed, this is the result
  *               according to ARM
  */
@@ -423,11 +406,11 @@
 static void
 init_callback (void *cls,
               enum GNUNET_ARM_RequestStatus rs,
-              const char *service,
               enum GNUNET_ARM_Result result)
 {
   char *msg;
 
+  op = NULL;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
     GNUNET_asprintf (&msg,
@@ -441,9 +424,11 @@
   if ((GNUNET_ARM_RESULT_STARTING != result) &&
       (GNUNET_ARM_RESULT_IS_STARTED_ALREADY != result))
   {
-    GNUNET_asprintf (&msg, _("Failed to start the `%s' service: %s\n"),
-                     init, ret_string (result));
-    FPRINTF (stdout, msg, service);
+    GNUNET_asprintf (&msg,
+                     _("Failed to start the `%s' service: %s\n"),
+                     init,
+                     ret_string (result));
+    FPRINTF (stdout, "%s", msg);
     GNUNET_free (msg);
     GNUNET_SCHEDULER_shutdown ();
     return;
@@ -465,7 +450,6 @@
  *
  * @param cls closure unused
  * @param rs what happened to our request
- * @param service name of the service we tried to start
  * @param result if the request was processed, this is the result
  *               according to ARM
  */
@@ -472,10 +456,11 @@
 static void
 term_callback (void *cls,
               enum GNUNET_ARM_RequestStatus rs,
-              const char *service,
               enum GNUNET_ARM_Result result)
 {
   char *msg;
+
+  op = NULL;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
     GNUNET_asprintf (&msg,
@@ -492,7 +477,7 @@
     GNUNET_asprintf (&msg,
                     _("Failed to kill the `%s' service: %s\n"),
                      term, ret_string (result));
-    FPRINTF (stdout, msg, service);
+    FPRINTF (stdout, "%s", msg);
     GNUNET_free (msg);
     GNUNET_SCHEDULER_shutdown ();
     return;
@@ -525,6 +510,7 @@
 {
   unsigned int i;
 
+  op = NULL;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
     char *msg;
@@ -573,9 +559,10 @@
       {
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "Termination action\n");
-        GNUNET_ARM_request_service_stop (h, term,
-                                        (0 == timeout.rel_value_us) ? 
STOP_TIMEOUT : timeout,
-                                        &term_callback, NULL);
+        op = GNUNET_ARM_request_service_stop (h,
+                                              term,
+                                              &term_callback,
+                                              NULL);
        return;
       }
       break;
@@ -584,9 +571,10 @@
       {
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "End action\n");
-        GNUNET_ARM_request_service_stop (h, "arm",
-                                        (0 == timeout.rel_value_us) ? 
STOP_TIMEOUT_ARM : timeout,
-                                        &stop_callback, NULL);
+        op = GNUNET_ARM_request_service_stop (h,
+                                              "arm",
+                                              &stop_callback,
+                                              NULL);
         return;
       }
       break;
@@ -595,11 +583,11 @@
       {
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "Start action\n");
-        GNUNET_ARM_request_service_start (h, "arm",
-            (no_stdout ? 0 : GNUNET_OS_INHERIT_STD_OUT) |
-            (no_stderr ? 0 : GNUNET_OS_INHERIT_STD_ERR),
-            (0 == timeout.rel_value_us) ? START_TIMEOUT: timeout,
-            start_callback, NULL);
+        op = GNUNET_ARM_request_service_start (h, "arm",
+                                               (no_stdout ? 0 : 
GNUNET_OS_INHERIT_STD_OUT) |
+                                               (no_stderr ? 0 : 
GNUNET_OS_INHERIT_STD_ERR),
+                                               &start_callback,
+                                               NULL);
         return;
       }
       break;
@@ -608,10 +596,10 @@
       {
         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "Initialization action\n");
-        GNUNET_ARM_request_service_start (h, init,
-                                         GNUNET_OS_INHERIT_STD_NONE,
-                                         (0 == timeout.rel_value_us) ? 
STOP_TIMEOUT : timeout,
-                                         &init_callback, NULL);
+        op = GNUNET_ARM_request_service_start (h, init,
+                                               GNUNET_OS_INHERIT_STD_NONE,
+                                               &init_callback,
+                                               NULL);
         return;
       }
       break;
@@ -620,9 +608,9 @@
       {
        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                    "Going to list all running services controlled by ARM.\n");
-        GNUNET_ARM_request_service_list (h,
-                                        (0 == timeout.rel_value_us) ? 
LIST_TIMEOUT : timeout,
-                                        &list_callback, &list);
+        op = GNUNET_ARM_request_service_list (h,
+                                              &list_callback,
+                                              &list);
        return;
       }
       break;
@@ -676,13 +664,21 @@
     break;
   }
   if (! quiet)
-    {
-      if (NULL != msg)
-       FPRINTF (stderr, msg, service);
-      else
-       FPRINTF (stderr, _("Unknown status %u for service %s.\n"), status, 
service);
-    }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got service %s status %d\n", service, 
(int) status);
+  {
+    if (NULL != msg)
+      FPRINTF (stderr,
+               msg,
+               service);
+    else
+      FPRINTF (stderr,
+               _("Unknown status %u for service %s.\n"),
+               status,
+               service);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got service %s status %d\n",
+              service, (int)
+              status);
 }
 
 
@@ -705,30 +701,44 @@
   cfg = GNUNET_CONFIGURATION_dup (c);
   config_file = cfgfile;
   if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "GNUNET_HOME", 
&dir))
+      GNUNET_CONFIGURATION_get_value_string (cfg,
+                                             "PATHS",
+                                             "GNUNET_HOME",
+                                             &dir))
   {
     GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
-                              "PATHS", "GNUNET_HOME");
+                              "PATHS",
+                               "GNUNET_HOME");
     return;
   }
   if (NULL != cfgfile)
   {
     if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_filename (cfg, "arm", "CONFIG",
+        GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                 "arm",
+                                                 "CONFIG",
                                                 &armconfig))
     {
-      GNUNET_CONFIGURATION_set_value_string (cfg, "arm", "CONFIG",
+      GNUNET_CONFIGURATION_set_value_string (cfg,
+                                             "arm",
+                                             "CONFIG",
                                              cfgfile);
     }
     else
       GNUNET_free (armconfig);
   }
-  if (NULL == (h = GNUNET_ARM_connect (cfg, &conn_status, NULL)))
+  if (NULL == (h = GNUNET_ARM_connect (cfg,
+                                       &conn_status,
+                                       NULL)))
     return;
   if (monitor)
-    m = GNUNET_ARM_monitor (cfg, &srv_status, NULL);
-  al_task = GNUNET_SCHEDULER_add_now (&action_loop, NULL);
-  GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL);
+    m = GNUNET_ARM_monitor_start (cfg,
+                            &srv_status,
+                            NULL);
+  al_task = GNUNET_SCHEDULER_add_now (&action_loop,
+                                      NULL);
+  GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+                                 NULL);
 }
 
 
@@ -774,7 +784,8 @@
     GNUNET_GETOPT_OPTION_END
   };
 
-  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
+  if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv,
+                                                 &argc, &argv))
     return 2;
 
   if (GNUNET_OK ==

Modified: gnunet/src/arm/test_arm_api.c
===================================================================
--- gnunet/src/arm/test_arm_api.c       2016-06-22 17:24:29 UTC (rev 37328)
+++ gnunet/src/arm/test_arm_api.c       2016-06-23 14:22:34 UTC (rev 37329)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2009, 2011 GNUnet e.V.
+     Copyright (C) 2009, 2011, 2016 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -28,10 +28,6 @@
 
 #define LOG(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
 
-#define START_ARM GNUNET_YES
-
-#define START_TIMEOUT GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_MILLISECONDS, 1500)
-
 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
 
 static const struct GNUNET_CONFIGURATION_Handle *cfg;
@@ -38,16 +34,19 @@
 
 static struct GNUNET_ARM_Handle *arm;
 
+static struct GNUNET_ARM_Operation *op;
+
 static int ok = 1;
 
 static int phase = 0;
 
+
 static void
 arm_stop_cb (void *cls,
             enum GNUNET_ARM_RequestStatus status,
-            const char *servicename,
             enum GNUNET_ARM_Result result)
 {
+  op = NULL;
   /* (6), a stop request should be sent to ARM successfully */
   /* ARM should report that it is stopping */
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -54,7 +53,9 @@
   GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED);
   GNUNET_break (phase == 6);
   phase++;
-  LOG ("Sent 'STOP' request for arm to ARM %s\n", (status == 
GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
+  LOG ("Sent 'STOP' request for arm to ARM %s\n",
+       (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : 
"unsuccessfully");
+  GNUNET_SCHEDULER_shutdown ();
 }
 
 
@@ -61,8 +62,9 @@
 static void
 resolver_stop_cb (void *cls,
                  enum GNUNET_ARM_RequestStatus status,
-                 const char *servicename, enum GNUNET_ARM_Result result)
+                  enum GNUNET_ARM_Result result)
 {
+  op = NULL;
   /* (5), a stop request should be sent to ARM successfully.
    * ARM should report that resolver is stopped.
    */
@@ -69,19 +71,21 @@
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
   GNUNET_break (result == GNUNET_ARM_RESULT_STOPPED);
   GNUNET_break (phase == 5);
-  LOG ("Sent 'STOP' request for resolver to ARM %s\n", (status == 
GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
+  LOG ("Sent 'STOP' request for resolver to ARM %s\n",
+       (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : 
"unsuccessfully");
   phase++;
-#if START_ARM
-  GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL);
-#else
-  arm_stop_cb (NULL, GNUNET_ARM_STATUS_SENT_OK, "arm", 
GNUNET_ARM_SERVICE_STOPPING);
-  arm_conn (NULL, GNUNET_NO);
-#endif
+  GNUNET_assert (NULL == op);
+  op = GNUNET_ARM_request_service_stop (arm,
+                                        "arm",
+                                        &arm_stop_cb,
+                                        NULL);
 }
 
 
 static void
-dns_notify (void *cls, const struct sockaddr *addr, socklen_t addrlen)
+dns_notify (void *cls,
+            const struct sockaddr *addr,
+            socklen_t addrlen)
 {
   if (addr == NULL)
     {
@@ -91,7 +95,11 @@
       LOG ("Finished resolving localhost\n");
       if (ok != 0)
         ok = 2;
-      GNUNET_ARM_request_service_stop (arm, "resolver", TIMEOUT, 
resolver_stop_cb, NULL);
+      GNUNET_assert (NULL == op);
+      op = GNUNET_ARM_request_service_stop (arm,
+                                            "resolver",
+                                            &resolver_stop_cb,
+                                            NULL);
       return;
     }
   /* (3), resolver should resolve localhost */
@@ -106,9 +114,9 @@
 static void
 resolver_start_cb (void *cls,
                   enum GNUNET_ARM_RequestStatus status,
-                  const char *servicename,
                   enum GNUNET_ARM_Result result)
 {
+  op = NULL;
   /* (2), the start request for resolver should be sent successfully
    * ARM should report that resolver service is starting.
    */
@@ -115,20 +123,17 @@
   GNUNET_assert (status == GNUNET_ARM_REQUEST_SENT_OK);
   GNUNET_break (phase == 2);
   GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
-  LOG ("Sent 'START' request for resolver to ARM %s\n", (status == 
GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
+  LOG ("Sent 'START' request for resolver to ARM %s\n",
+       (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : 
"unsuccessfully");
   phase++;
-  GNUNET_RESOLVER_ip_get ("localhost", AF_INET, TIMEOUT, &dns_notify, NULL);
+  GNUNET_RESOLVER_ip_get ("localhost",
+                          AF_INET,
+                          TIMEOUT,
+                          &dns_notify, NULL);
 }
 
 
 static void
-trigger_disconnect (void *cls)
-{
-  GNUNET_ARM_disconnect_and_free ((struct GNUNET_ARM_Handle *) cls);
-}
-
-
-static void
 arm_conn (void *cls,
          int connected)
 {
@@ -146,7 +151,12 @@
     LOG ("Connected to ARM\n");
     GNUNET_break (phase == 1);
     phase++;
-    GNUNET_ARM_request_service_start (arm, "resolver", 
GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, resolver_start_cb, NULL);
+    GNUNET_assert (NULL == op);
+    op = GNUNET_ARM_request_service_start (arm,
+                                           "resolver",
+                                           GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                           &resolver_start_cb,
+                                           NULL);
   }
   else
   {
@@ -157,7 +167,6 @@
       ok = 3;
     else if (ok == 1)
       ok = 0;
-    GNUNET_SCHEDULER_add_now (&trigger_disconnect, arm);
   }
 }
 
@@ -165,9 +174,9 @@
 static void
 arm_start_cb (void *cls,
              enum GNUNET_ARM_RequestStatus status,
-             const char *servicename,
              enum GNUNET_ARM_Result result)
 {
+  op = NULL;
   /* (0) The request should be "sent" successfully
    * ("sent", because it isn't going anywhere, ARM API starts ARM service
    * by itself).
@@ -175,7 +184,8 @@
    */
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
   GNUNET_break (phase == 0);
-  LOG ("Sent 'START' request for arm to ARM %s\n", (status == 
GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : "unsuccessfully");
+  LOG ("Sent 'START' request for arm to ARM %s\n",
+       (status == GNUNET_ARM_REQUEST_SENT_OK) ? "successfully" : 
"unsuccessfully");
   GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
   phase++;
 }
@@ -182,19 +192,40 @@
 
 
 static void
-task (void *cls, char *const *args, const char *cfgfile,
+do_shutdown (void *cls)
+{
+  if (NULL != op)
+  {
+    GNUNET_ARM_operation_cancel (op);
+    op = NULL;
+  }
+  if (NULL != arm)
+  {
+    GNUNET_ARM_disconnect (arm);
+    arm = NULL;
+  }
+}
+
+
+static void
+task (void *cls,
+      char *const *args,
+      const char *cfgfile,
       const struct GNUNET_CONFIGURATION_Handle *c)
 {
   cfg = c;
-  arm = GNUNET_ARM_connect (cfg, &arm_conn, NULL);
+  arm = GNUNET_ARM_connect (cfg,
+                            &arm_conn,
+                            NULL);
   if (NULL == arm)
     return;
-#if START_ARM
-  GNUNET_ARM_request_service_start (arm, "arm", 
GNUNET_OS_INHERIT_STD_OUT_AND_ERR, START_TIMEOUT, arm_start_cb, NULL);
-#else
-  arm_start_cb (NULL, arm, GNUNET_ARM_REQUEST_SENT_OK, "arm", 
GNUNET_ARM_RESULT_STARTING);
-  arm_conn (NULL, arm, GNUNET_YES);
-#endif
+  GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
+                                 NULL);
+  op = GNUNET_ARM_request_service_start (arm,
+                                         "arm",
+                                         GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                         &arm_start_cb,
+                                         NULL);
 }
 
 

Modified: gnunet/src/arm/test_exponential_backoff.c
===================================================================
--- gnunet/src/arm/test_exponential_backoff.c   2016-06-22 17:24:29 UTC (rev 
37328)
+++ gnunet/src/arm/test_exponential_backoff.c   2016-06-23 14:22:34 UTC (rev 
37329)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2009 GNUnet e.V.
+     Copyright (C) 2009, 2016 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
@@ -70,8 +70,10 @@
 #endif
 
 
-typedef void (*GNUNET_CLIENT_ShutdownTask) (void *cls, int reason);
+typedef void
+(*GNUNET_CLIENT_ShutdownTask) (void *cls, int reason);
 
+
 /**
  * Context for handling the shutdown of a service.
  */
@@ -118,7 +120,8 @@
  * @param msg NULL, indicating socket closure.
  */
 static void
-service_shutdown_handler (void *cls, const struct GNUNET_MessageHeader *msg)
+service_shutdown_handler (void *cls,
+                          const struct GNUNET_MessageHeader *msg)
 {
   struct ShutdownContext *shutdown_ctx = cls;
 
@@ -147,7 +150,8 @@
 {
   struct ShutdownContext *shutdown_ctx = cls;
 
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "service_shutdown_cancel called!\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "service_shutdown_cancel called!\n");
   shutdown_ctx->cont (shutdown_ctx->cont_cls, GNUNET_SYSERR);
   GNUNET_CLIENT_disconnect (shutdown_ctx->sock);
   GNUNET_free (shutdown_ctx);
@@ -207,8 +211,9 @@
  */
 static void
 do_nothing_service_shutdown (struct GNUNET_CLIENT_Connection *sock,
-                     struct GNUNET_TIME_Relative timeout,
-                     GNUNET_CLIENT_ShutdownTask cont, void *cont_cls)
+                             struct GNUNET_TIME_Relative timeout,
+                             GNUNET_CLIENT_ShutdownTask cont,
+                             void *cont_cls)
 {
   struct ShutdownContext *shutdown_ctx;
 
@@ -266,7 +271,10 @@
   else if (trialCount == 13)
   {
     GNUNET_CLIENT_disconnect (doNothingConnection);
-    GNUNET_ARM_request_service_stop (arm, SERVICE, TIMEOUT, NULL, NULL);
+    GNUNET_ARM_request_service_stop (arm,
+                                     SERVICE,
+                                     NULL,
+                                     NULL);
     if (waitedFor_prev.rel_value_us >= waitedFor.rel_value_us)
       ok = 9;
     else
@@ -284,8 +292,8 @@
 static void
 trigger_disconnect (void *cls)
 {
-  GNUNET_ARM_disconnect_and_free (arm);
-  GNUNET_ARM_monitor_disconnect_and_free (mon);
+  GNUNET_ARM_disconnect (arm);
+  GNUNET_ARM_monitor_stop (mon);
 }
 
 
@@ -292,7 +300,6 @@
 static void
 arm_stop_cb (void *cls,
             enum GNUNET_ARM_RequestStatus status,
-            const char *servicename,
             enum GNUNET_ARM_Result result)
 {
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -303,14 +310,19 @@
 
 
 static void
-srv_status (void *cls, const char *service, enum GNUNET_ARM_ServiceStatus 
status)
+srv_status (void *cls,
+            const char *service,
+            enum GNUNET_ARM_ServiceStatus status)
 {
   LOG ("Service %s is %u, phase %u\n", service, status, phase);
   if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED)
   {
     phase++;
-    GNUNET_ARM_request_service_start (arm, SERVICE,
-        GNUNET_OS_INHERIT_STD_OUT_AND_ERR, TIMEOUT, NULL, NULL);
+    GNUNET_ARM_request_service_start (arm,
+                                      SERVICE,
+                                      GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                      NULL,
+                                      NULL);
     return;
   }
   if (phase == 1)
@@ -322,7 +334,8 @@
     phase++;
     ok = 1;
     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
-                                 &kill_task, NULL);
+                                 &kill_task,
+                                  NULL);
   }
   else if ((phase == 2) && (strcasecmp (SERVICE, service) == 0))
   {
@@ -337,7 +350,10 @@
     else if ((status == GNUNET_ARM_SERVICE_STOPPED) && (trialCount == 14))
     {
       phase++;
-      GNUNET_ARM_request_service_stop (arm, "arm", TIMEOUT, arm_stop_cb, NULL);
+      GNUNET_ARM_request_service_stop (arm,
+                                       "arm",
+                                       &arm_stop_cb,
+                                       NULL);
     }
   }
 }
@@ -344,7 +360,9 @@
 
 
 static void
-arm_start_cb (void *cls, enum GNUNET_ARM_RequestStatus status, const char 
*servicename, enum GNUNET_ARM_Result result)
+arm_start_cb (void *cls,
+              enum GNUNET_ARM_RequestStatus status,
+              enum GNUNET_ARM_Result result)
 {
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
   GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
@@ -355,7 +373,9 @@
 
 
 static void
-task (void *cls, char *const *args, const char *cfgfile,
+task (void *cls,
+      char *const *args,
+      const char *cfgfile,
       const struct GNUNET_CONFIGURATION_Handle *c)
 {
   cfg = c;
@@ -362,19 +382,25 @@
   arm = GNUNET_ARM_connect (cfg, NULL, NULL);
   if (NULL != arm)
   {
-    mon = GNUNET_ARM_monitor (cfg, &srv_status, NULL);
+    mon = GNUNET_ARM_monitor_start (cfg, &srv_status, NULL);
     if (NULL != mon)
     {
 #if START_ARM
-      GNUNET_ARM_request_service_start (arm, "arm",
-          GNUNET_OS_INHERIT_STD_OUT_AND_ERR, GNUNET_TIME_UNIT_ZERO, 
arm_start_cb, NULL);
+      GNUNET_ARM_request_service_start (arm,
+                                        "arm",
+                                        GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
+                                        &arm_start_cb,
+                                        NULL);
 #else
-      arm_start_cb (NULL, arm, GNUNET_ARM_REQUEST_SENT_OK, "arm", 
GNUNET_ARM_SERVICE_STARTING);
+      arm_start_cb (NULL,
+                    arm,
+                    GNUNET_ARM_REQUEST_SENT_OK,
+                    GNUNET_ARM_SERVICE_STARTING);
 #endif
     }
     else
     {
-      GNUNET_ARM_disconnect_and_free (arm);
+      GNUNET_ARM_disconnect (arm);
       arm = NULL;
     }
   }

Modified: gnunet/src/arm/test_gnunet_service_arm.c
===================================================================
--- gnunet/src/arm/test_gnunet_service_arm.c    2016-06-22 17:24:29 UTC (rev 
37328)
+++ gnunet/src/arm/test_gnunet_service_arm.c    2016-06-23 14:22:34 UTC (rev 
37329)
@@ -51,7 +51,7 @@
 static void
 trigger_disconnect (void *cls)
 {
-  GNUNET_ARM_disconnect_and_free (arm);
+  GNUNET_ARM_disconnect (arm);
   arm = NULL;
 }
 
@@ -59,7 +59,6 @@
 static void
 arm_stop_cb (void *cls,
             enum GNUNET_ARM_RequestStatus status,
-            const char *servicename,
             enum GNUNET_ARM_Result result)
 {
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -100,15 +99,15 @@
  stop_arm:
   GNUNET_ARM_request_service_stop (arm,
                                    "arm",
-                                   TIMEOUT,
-                                   &arm_stop_cb, NULL);
+                                   &arm_stop_cb,
+                                   NULL);
 }
 
 
 static void
 hostname_resolve_cb (void *cls,
-                   const struct sockaddr *addr,
-                   socklen_t addrlen)
+                     const struct sockaddr *addr,
+                     socklen_t addrlen)
 {
   if ((0 == ret) || (4 == ret) || (1 == resolved_ok))
     return;
@@ -120,8 +119,8 @@
     ret = 3;
     GNUNET_ARM_request_service_stop (arm,
                                      "arm",
-                                     TIMEOUT,
-                                     &arm_stop_cb, NULL);
+                                     &arm_stop_cb,
+                                     NULL);
     return;
   }
   if (0 == asked_for_a_list)
@@ -129,7 +128,6 @@
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                 "Resolved hostname, now checking the service list\n");
     GNUNET_ARM_request_service_list (arm,
-                                     TIMEOUT,
                                      &service_list,
                                      NULL);
     asked_for_a_list = 1;
@@ -141,7 +139,6 @@
 static void
 arm_start_cb (void *cls,
              enum GNUNET_ARM_RequestStatus status,
-             const char *servicename,
              enum GNUNET_ARM_Result result)
 {
   GNUNET_break (status == GNUNET_ARM_REQUEST_SENT_OK);
@@ -150,7 +147,8 @@
               "Trying to resolve our own hostname!\n");
   /* connect to the resolver service */
   if (NULL ==
-      GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, TIMEOUT,
+      GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC,
+                                        TIMEOUT,
                                         &hostname_resolve_cb,
                                         NULL))
   {
@@ -159,8 +157,9 @@
     GNUNET_break (0);
     ret = 2;
     GNUNET_ARM_request_service_stop (arm,
-                                     "arm", TIMEOUT,
-                                     &arm_stop_cb, NULL);
+                                     "arm",
+                                     &arm_stop_cb,
+                                     NULL);
   }
 }
 
@@ -171,11 +170,14 @@
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  arm = GNUNET_ARM_connect (c, NULL, NULL);
-  GNUNET_ARM_request_service_start (arm, "arm",
+  arm = GNUNET_ARM_connect (c,
+                            NULL,
+                            NULL);
+  GNUNET_ARM_request_service_start (arm,
+                                    "arm",
                                     GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
-                                    START_TIMEOUT,
-                                    &arm_start_cb, NULL);
+                                    &arm_start_cb,
+                                    NULL);
 }
 
 

Modified: gnunet/src/include/gnunet_arm_service.h
===================================================================
--- gnunet/src/include/gnunet_arm_service.h     2016-06-22 17:24:29 UTC (rev 
37328)
+++ gnunet/src/include/gnunet_arm_service.h     2016-06-23 14:22:34 UTC (rev 
37329)
@@ -1,6 +1,6 @@
 /*
       This file is part of GNUnet
-      Copyright (C) 2009 GNUnet e.V.
+      Copyright (C) 2009, 2016 GNUnet e.V.
 
       GNUnet is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published
@@ -48,7 +48,7 @@
 /**
  * Version of the arm API.
  */
-#define GNUNET_ARM_VERSION 0x00000002
+#define GNUNET_ARM_VERSION 0x00000003
 
 
 /**
@@ -78,12 +78,6 @@
   GNUNET_ARM_REQUEST_BUSY = 3,
 
   /**
-   * It was discovered that the request would be too long to fit in a message,
-   * and thus it was not sent.
-   */
-  GNUNET_ARM_REQUEST_TOO_LONG = 4,
-
-  /**
    * Request time ran out before we had a chance to send it.
    */
   GNUNET_ARM_REQUEST_TIMEOUT = 5
@@ -180,16 +174,22 @@
  */
 struct GNUNET_ARM_Handle;
 
+/**
+ * Handle for an ARM operation.
+ */
+struct GNUNET_ARM_Operation;
 
+
 /**
  * Function called whenever we connect to or disconnect from ARM.
  *
  * @param cls closure
- * @param connected GNUNET_YES if connected, GNUNET_NO if disconnected,
- *                  GNUNET_SYSERR if there was an error.
+ * @param connected #GNUNET_YES if connected, #GNUNET_NO if disconnected,
+ *                  #GNUNET_SYSERR if there was an error.
  */
-typedef void (*GNUNET_ARM_ConnectionStatusCallback) (void *cls,
-                                                    int connected);
+typedef void
+(*GNUNET_ARM_ConnectionStatusCallback) (void *cls,
+                                        int connected);
 
 
 /**
@@ -196,17 +196,16 @@
  * Function called in response to a start/stop request.
  * Will be called when request was not sent successfully,
  * or when a reply comes. If the request was not sent successfully,
- * 'rs' will indicate that, and 'service' and 'result' will be undefined.
+ * @a rs will indicate that, and @a result will be undefined.
  *
  * @param cls closure
  * @param rs status of the request
- * @param service service name
  * @param result result of the operation
  */
-typedef void (*GNUNET_ARM_ResultCallback) (void *cls,
-                                          enum GNUNET_ARM_RequestStatus rs,
-                                          const char *service,
-                                          enum GNUNET_ARM_Result result);
+typedef void
+(*GNUNET_ARM_ResultCallback) (void *cls,
+                              enum GNUNET_ARM_RequestStatus rs,
+                              enum GNUNET_ARM_Result result);
 
 
 /**
@@ -213,7 +212,7 @@
  * Callback function invoked when list operation is complete.
  * Will be called when request was not sent successfully,
  * or when a reply comes. If the request was not sent successfully,
- * 'rs' will indicate that, and 'count' and 'list' will be undefined.
+ * @a rs will indicate that, and @a count and @a list will be undefined.
  *
  * @param cls closure
  * @param rs status of the request
@@ -220,10 +219,11 @@
  * @param count number of strings in the list
  * @param list list of running services
  */
-typedef void (*GNUNET_ARM_ServiceListCallback) (void *cls,
-                                               enum GNUNET_ARM_RequestStatus 
rs,
-                                               unsigned int count,
-                                               const char *const*list);
+typedef void
+(*GNUNET_ARM_ServiceListCallback) (void *cls,
+                                   enum GNUNET_ARM_RequestStatus rs,
+                                   unsigned int count,
+                                   const char *const*list);
 
 
 /**
@@ -234,13 +234,13 @@
  *        the ARM service may internally use a different
  *        configuration to determine how to start the service).
  * @param conn_status will be called when connecting/disconnecting
- * @param cls closure for conn_status
+ * @param conn_status_cls closure for @a conn_status
  * @return context to use for further ARM operations, NULL on error.
  */
 struct GNUNET_ARM_Handle *
 GNUNET_ARM_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                    GNUNET_ARM_ConnectionStatusCallback conn_status,
-                   void *cls);
+                   void *conn_status_cls);
 
 
 /**
@@ -249,21 +249,31 @@
  * @param h the handle that was being used
  */
 void
-GNUNET_ARM_disconnect_and_free (struct GNUNET_ARM_Handle *h);
+GNUNET_ARM_disconnect (struct GNUNET_ARM_Handle *h);
 
 
 /**
+ * Abort an operation.  Only prevents the callback from being
+ * called, the operation may still complete.
+ *
+ * @param op operation to cancel
+ */
+void
+GNUNET_ARM_operation_cancel (struct GNUNET_ARM_Operation *op);
+
+
+/**
  * Request a list of running services.
  *
  * @param h handle to ARM
- * @param timeout how long to wait before failing for good
  * @param cont callback to invoke after request is sent or is not sent
- * @param cont_cls closure for callback
+ * @param cont_cls closure for @a cont
+ * @return handle for the operation, NULL on error
  */
-void
+struct GNUNET_ARM_Operation *
 GNUNET_ARM_request_service_list (struct GNUNET_ARM_Handle *h,
-                                struct GNUNET_TIME_Relative timeout,
-                                GNUNET_ARM_ServiceListCallback cont, void 
*cont_cls);
+                                GNUNET_ARM_ServiceListCallback cont,
+                                 void *cont_cls);
 
 
 /**
@@ -271,20 +281,20 @@
  * Stopping arm itself will not invalidate its handle, and
  * ARM API will try to restore connection to the ARM service,
  * even if ARM connection was lost because you asked for ARM to be stopped.
- * Call GNUNET_ARM_disconnect_and_free () to free the handle and prevent
+ * Call #GNUNET_ARM_disconnect() to free the handle and prevent
  * further connection attempts.
  *
  * @param h handle to ARM
  * @param service_name name of the service
- * @param timeout how long to wait before failing for good
  * @param cont callback to invoke after request is sent or is not sent
- * @param cont_cls closure for callback
+ * @param cont_cls closure for @a cont
+ * @return handle for the operation, NULL on error
  */
-void
+struct GNUNET_ARM_Operation *
 GNUNET_ARM_request_service_stop (struct GNUNET_ARM_Handle *h,
                                 const char *service_name,
-                                struct GNUNET_TIME_Relative timeout,
-                                GNUNET_ARM_ResultCallback cont, void 
*cont_cls);
+                                GNUNET_ARM_ResultCallback cont,
+                                 void *cont_cls);
 
 
 /**
@@ -293,15 +303,14 @@
  * @param h handle to ARM
  * @param service_name name of the service
  * @param std_inheritance inheritance of std streams
- * @param timeout how long to wait before failing for good
  * @param cont callback to invoke after request is sent or not sent
- * @param cont_cls closure for callback
+ * @param cont_cls closure for @a cont
+ * @return handle for the operation, NULL on error
  */
-void
+struct GNUNET_ARM_Operation *
 GNUNET_ARM_request_service_start (struct GNUNET_ARM_Handle *h,
                                  const char *service_name,
                                  enum GNUNET_OS_InheritStdioFlags 
std_inheritance,
-                                 struct GNUNET_TIME_Relative timeout,
                                  GNUNET_ARM_ResultCallback cont,
                                  void *cont_cls);
 
@@ -316,13 +325,13 @@
  * Function called in when a status update arrives.
  *
  * @param cls closure
- * @param arm handle to the arm connection
  * @param service service name
  * @param status status of the service
  */
-typedef void (*GNUNET_ARM_ServiceStatusCallback) (void *cls,
-                                                 const char *service,
-                                                 enum GNUNET_ARM_ServiceStatus 
status);
+typedef void
+(*GNUNET_ARM_ServiceStatusCallback) (void *cls,
+                                     const char *service,
+                                     enum GNUNET_ARM_ServiceStatus status);
 
 
 /**
@@ -333,13 +342,13 @@
  *        the ARM service may internally use a different
  *        configuration to determine how to start the service).
  * @param cont callback to invoke on status updates
- * @param cont_cls closure
+ * @param cont_cls closure for @a cont
  * @return context to use for further ARM monitor operations, NULL on error.
  */
 struct GNUNET_ARM_MonitorHandle *
-GNUNET_ARM_monitor (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                   GNUNET_ARM_ServiceStatusCallback cont,
-                   void *cont_cls);
+GNUNET_ARM_monitor_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                          GNUNET_ARM_ServiceStatusCallback cont,
+                          void *cont_cls);
 
 
 /**
@@ -348,7 +357,7 @@
  * @param h the handle that was being used
  */
 void
-GNUNET_ARM_monitor_disconnect_and_free (struct GNUNET_ARM_MonitorHandle *h);
+GNUNET_ARM_monitor_stop (struct GNUNET_ARM_MonitorHandle *h);
 
 #if 0                           /* keep Emacsens' auto-indent happy */
 {

Modified: gnunet/src/include/gnunet_testbed_logger_service.h
===================================================================
--- gnunet/src/include/gnunet_testbed_logger_service.h  2016-06-22 17:24:29 UTC 
(rev 37328)
+++ gnunet/src/include/gnunet_testbed_logger_service.h  2016-06-23 14:22:34 UTC 
(rev 37329)
@@ -75,7 +75,9 @@
  * @param cls the closure given to GNUNET_TESTBED_LOGGER_send()
  * @param size the amount of data sent
  */
-typedef void (*GNUNET_TESTBED_LOGGER_FlushCompletion) (void *cls, size_t size);
+typedef void
+(*GNUNET_TESTBED_LOGGER_FlushCompletion) (void *cls,
+                                          size_t size);
 
 
 /**
@@ -89,7 +91,8 @@
  */
 void
 GNUNET_TESTBED_LOGGER_write (struct GNUNET_TESTBED_LOGGER_Handle *h,
-                             const void *data, size_t size);
+                             const void *data,
+                             size_t size);
 
 
 /**

Modified: gnunet/src/include/gnunet_testing_lib.h
===================================================================
--- gnunet/src/include/gnunet_testing_lib.h     2016-06-22 17:24:29 UTC (rev 
37328)
+++ gnunet/src/include/gnunet_testing_lib.h     2016-06-23 14:22:34 UTC (rev 
37329)
@@ -157,9 +157,7 @@
 GNUNET_TESTING_system_create_with_portrange (const char *testdir,
                                             const char *trusted_ip,
                                             const char *hostname,
-                                             const struct
-                                             GNUNET_TESTING_SharedService *
-                                             shared_services,
+                                             const struct 
GNUNET_TESTING_SharedService *shared_services,
                                             uint16_t lowport,
                                             uint16_t highport);
 
@@ -185,12 +183,12 @@
  * GNUnet source code.
  *
  * This is primarily a helper function used internally
- * by 'GNUNET_TESTING_peer_configure'.
+ * by #GNUNET_TESTING_peer_configure().
  *
  * @param system the testing system handle
  * @param key_number desired pre-created hostkey to obtain
  * @param id set to the peer's identity (hash of the public
- *        key; if NULL, GNUNET_SYSERR is returned immediately
+ *        key; if NULL, #GNUNET_SYSERR is returned immediately
  * @return NULL on error (not enough keys)
  */
 struct GNUNET_CRYPTO_EddsaPrivateKey *
@@ -227,10 +225,10 @@
  * system. The default configuration will be available in PATHS section under
  * the option DEFAULTCONFIG after the call. SERVICE_HOME is also set in PATHS
  * section to the temporary directory specific to this configuration. If we run
- * out of "*port" numbers, return SYSERR.
+ * out of "*port" numbers, return #GNUNET_SYSERR.
  *
  * This is primarily a helper function used internally
- * by 'GNUNET_TESTING_peer_configure'.
+ * by #GNUNET_TESTING_peer_configure().
  *
  * @param system system to use to coordinate resource usage
  * @param cfg template configuration to update
@@ -353,9 +351,9 @@
  *
  * @param peer the peer to stop
  * @param cb the callback to signal peer shutdown
- * @param cb_cls closure for the above callback
- * @return GNUNET_OK upon successfully giving the request to the ARM API (this
- *           does not mean that the peer is successfully stopped); 
GNUNET_SYSERR
+ * @param cb_cls closure for the @a cb
+ * @return #GNUNET_OK upon successfully giving the request to the ARM API (this
+ *           does not mean that the peer is successfully stopped); 
#GNUNET_SYSERR
  *           upon any error.
  */
 int

Modified: gnunet/src/testbed/gnunet-service-testbed_peers.c
===================================================================
--- gnunet/src/testbed/gnunet-service-testbed_peers.c   2016-06-22 17:24:29 UTC 
(rev 37328)
+++ gnunet/src/testbed/gnunet-service-testbed_peers.c   2016-06-23 14:22:34 UTC 
(rev 37329)
@@ -1,6 +1,6 @@
 /*
   This file is part of GNUnet.
-  Copyright (C) 2008--2013 GNUnet e.V.
+  Copyright (C) 2008--2013, 2016 GNUnet e.V.
 
   GNUnet is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
@@ -72,6 +72,11 @@
   struct GNUNET_SERVER_Client *client;
 
   /**
+   * Name of the service.
+   */
+  char *service;
+
+  /**
    * The operation id of the associated request
    */
   uint64_t op_id;
@@ -421,7 +426,8 @@
                                              &msg->header,
                                              peer_create_success_cb, fo_ctxt);
   fo_ctxt->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (GST_timeout, &peer_create_forward_timeout,
+      GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                    &peer_create_forward_timeout,
                                     fo_ctxt);
   GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -475,7 +481,8 @@
                                                fopc->operation_id, 
&msg->header,
                                                &peer_destroy_success_cb, fopc);
     fopc->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, 
&GST_forwarded_operation_timeout,
+        GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                      &GST_forwarded_operation_timeout,
                                       fopc);
     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -568,7 +575,8 @@
                                                
&GST_forwarded_operation_reply_relay,
                                                fopc);
     fopc->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, 
&GST_forwarded_operation_timeout,
+        GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                      &GST_forwarded_operation_timeout,
                                       fopc);
     GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -594,7 +602,7 @@
 
 
 /**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
+ * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
  *
  * @param cls NULL
  * @param client identification of the client
@@ -601,7 +609,8 @@
  * @param message the actual message
  */
 void
-GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
+GST_handle_peer_stop (void *cls,
+                      struct GNUNET_SERVER_Client *client,
                       const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_TESTBED_PeerStopMessage *msg;
@@ -612,10 +621,13 @@
 
   msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
   peer_id = ntohl (msg->peer_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Received PEER_STOP for peer %u\n",
+       (unsigned int) peer_id);
   if (!VALID_PEER_ID (peer_id))
   {
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
+    GST_send_operation_fail_msg (client,
+                                 GNUNET_ntohll (msg->operation_id),
                                  "Peer not found");
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
@@ -623,8 +635,9 @@
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarding PEER_STOP for peer %u\n",
-         peer_id);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Forwarding PEER_STOP for peer %u\n",
+         (unsigned int) peer_id);
     fopc = GNUNET_new (struct ForwardedOperationContext);
     GNUNET_SERVER_client_keep (client);
     fopc->client = client;
@@ -633,25 +646,35 @@
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
-                                               fopc->operation_id, 
&msg->header,
+                                               fopc->operation_id,
+                                               &msg->header,
                                                
&GST_forwarded_operation_reply_relay,
                                                fopc);
     fopc->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, 
&GST_forwarded_operation_timeout,
+        GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                      &GST_forwarded_operation_timeout,
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fopc);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
   if (GNUNET_OK != stop_peer (peer))
   {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id);
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
+    LOG (GNUNET_ERROR_TYPE_WARNING,
+         "Stopping peer %u failed\n",
+         (unsigned int) peer_id);
+    GST_send_operation_fail_msg (client,
+                                 GNUNET_ntohll (msg->operation_id),
                                  "Peer not running");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peer %u successfully stopped\n",
+       (unsigned int) peer_id);
   reply = GNUNET_new (struct GNUNET_TESTBED_PeerEventMessage);
   reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
   reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
@@ -689,10 +712,12 @@
 
   msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
   peer_id = ntohl (msg->peer_id);
-  LOG_DEBUG ("Received GET_CONFIG for peer %u\n", peer_id);
+  LOG_DEBUG ("Received GET_CONFIG for peer %u\n",
+             (unsigned int) peer_id);
   if (!VALID_PEER_ID (peer_id))
   {
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
+    GST_send_operation_fail_msg (client,
+                                 GNUNET_ntohll (msg->operation_id),
                                  "Peer not found");
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
@@ -700,7 +725,8 @@
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
-    LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id);
+    LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n",
+               (unsigned int) peer_id);
     fopc = GNUNET_new (struct ForwardedOperationContext);
     GNUNET_SERVER_client_keep (client);
     fopc->client = client;
@@ -709,21 +735,28 @@
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
-                                               fopc->operation_id, 
&msg->header,
+                                               fopc->operation_id,
+                                               &msg->header,
                                                
&GST_forwarded_operation_reply_relay,
                                                fopc);
     fopc->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, 
&GST_forwarded_operation_timeout,
+        GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                      &GST_forwarded_operation_timeout,
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fopc);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
-  LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", peer_id);
+  LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n",
+             peer_id);
   config =
       GNUNET_CONFIGURATION_serialize 
(GST_peer_list[peer_id]->details.local.cfg,
                                       &c_size);
-  xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig);
+  xc_size = GNUNET_TESTBED_compress_config_ (config,
+                                             c_size,
+                                             &xconfig);
   GNUNET_free (config);
   msize =
       xc_size +
@@ -799,7 +832,8 @@
   emsg = NULL;
   peer->details.local.peer
       = GNUNET_TESTING_peer_configure (GST_context->system,
-                                       peer->details.local.cfg, peer->id,
+                                       peer->details.local.cfg,
+                                       peer->id,
                                        NULL /* Peer id */ ,
                                        &emsg);
   return emsg;
@@ -811,11 +845,13 @@
  *
  * @param cls the closure given to GNUNET_TESTING_peer_stop_async()
  * @param p the respective peer whose status is being reported
- * @param success GNUNET_YES if the peer is stopped; GNUNET_SYSERR upon any
+ * @param success #GNUNET_YES if the peer is stopped; #GNUNET_SYSERR upon any
  *          error
  */
 static void
-prc_stop_cb (void *cls, struct GNUNET_TESTING_Peer *p, int success)
+prc_stop_cb (void *cls,
+             struct GNUNET_TESTING_Peer *p,
+             int success)
 {
   struct PeerReconfigureContext *prc = cls;
   struct Peer *peer;
@@ -829,16 +865,20 @@
   prc->stopped = 1;
   if (NULL != emsg)
   {
-    GST_send_operation_fail_msg (prc->client, prc->op_id, emsg);
+    GST_send_operation_fail_msg (prc->client,
+                                 prc->op_id,
+                                 emsg);
     goto cleanup;
   }
   if (GNUNET_OK != start_peer (peer))
   {
-    GST_send_operation_fail_msg (prc->client, prc->op_id,
+    GST_send_operation_fail_msg (prc->client,
+                                 prc->op_id,
                                  "Failed to start reconfigured peer");
     goto cleanup;
   }
-  GST_send_operation_success_msg (prc->client, prc->op_id);
+  GST_send_operation_success_msg (prc->client,
+                                  prc->op_id);
 
  cleanup:
   cleanup_prc (prc);
@@ -847,7 +887,7 @@
 
 
 /**
- * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages.
+ * Handler for #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages.
  * Should stop the peer asyncronously, destroy it and create it again with the
  * new configuration.
  *
@@ -856,7 +896,8 @@
  * @param message the actual message
  */
 void
-GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client,
+GST_handle_peer_reconfigure (void *cls,
+                             struct GNUNET_SERVER_Client *client,
                              const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
@@ -873,7 +914,8 @@
   if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage))
   {
     GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_SYSERR);
     return;
   }
   msg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) message;
@@ -882,8 +924,11 @@
   if (!VALID_PEER_ID (peer_id))
   {
     GNUNET_break (0);
-    GST_send_operation_fail_msg (client, op_id, "Peer not found");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GST_send_operation_fail_msg (client,
+                                 op_id,
+                                 "Peer not found");
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   peer = GST_peer_list[peer_id];
@@ -898,29 +943,40 @@
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
-                                               fopc->operation_id, 
&msg->header,
+                                               fopc->operation_id,
+                                               &msg->header,
                                                
&GST_forwarded_operation_reply_relay,
                                                fopc);
     fopc->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, 
&GST_forwarded_operation_timeout,
+        GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                      &GST_forwarded_operation_timeout,
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fopc);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
-  LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n", peer_id);
+  LOG_DEBUG ("Received PEER_RECONFIGURE for peer %u\n",
+             (unsigned int) peer_id);
   if (0 < peer->reference_cnt)
   {
     GNUNET_break (0);
-    GST_send_operation_fail_msg (client, op_id, "Peer in use");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GST_send_operation_fail_msg (client,
+                                 op_id,
+                                 "Peer in use");
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   if (GNUNET_YES == peer->destroy_flag)
   {
     GNUNET_break (0);
-    GST_send_operation_fail_msg (client, op_id, "Peer is being destroyed");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GST_send_operation_fail_msg (client,
+                                 op_id,
+                                 "Peer is being destroyed");
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   cfg = GNUNET_TESTBED_extract_config_ (message);
@@ -927,31 +983,45 @@
   if (NULL == cfg)
   {
     GNUNET_break (0);
-    GST_send_operation_fail_msg (client, op_id, "Compression error");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GST_send_operation_fail_msg (client,
+                                 op_id,
+                                 "Compression error");
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     return;
   }
   if (GNUNET_NO == peer->details.local.is_running)
   {
-    emsg = update_peer_config (peer, cfg);
+    emsg = update_peer_config (peer,
+                               cfg);
     if (NULL != emsg)
-      GST_send_operation_fail_msg (client, op_id, emsg);
-    GST_send_operation_success_msg (client, op_id);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+      GST_send_operation_fail_msg (client,
+                                   op_id,
+                                   emsg);
+    GST_send_operation_success_msg (client,
+                                    op_id);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     GNUNET_free_non_null (emsg);
     return;
   }
   prc = GNUNET_new (struct PeerReconfigureContext);
   if (GNUNET_OK !=
-      GNUNET_TESTING_peer_stop_async (peer->details.local.peer, &prc_stop_cb,
+      GNUNET_TESTING_peer_stop_async (peer->details.local.peer,
+                                      &prc_stop_cb,
                                       prc))
   {
     GNUNET_assert (0 < GNUNET_asprintf (&emsg,
                                         "Error trying to stop peer %u 
asynchronously\n",
                                         peer_id));
-    LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
-    GST_send_operation_fail_msg (client, op_id, emsg);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    LOG (GNUNET_ERROR_TYPE_ERROR,
+         "%s\n",
+         emsg);
+    GST_send_operation_fail_msg (client,
+                                 op_id,
+                                 emsg);
+    GNUNET_SERVER_receive_done (client,
+                                GNUNET_OK);
     GNUNET_free (prc);
     GNUNET_free (emsg);
     return;
@@ -961,8 +1031,11 @@
   prc->op_id = op_id;
   prc->client = client;
   GNUNET_SERVER_client_keep (client);
-  GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_CONTAINER_DLL_insert_tail (prc_head,
+                                    prc_tail,
+                                    prc);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }
 
 
@@ -975,14 +1048,17 @@
 cleanup_mctx (struct ManageServiceContext *mctx)
 {
   mctx->expired = GNUNET_YES;
-  GNUNET_CONTAINER_DLL_remove (mctx_head, mctx_tail, mctx);
+  GNUNET_CONTAINER_DLL_remove (mctx_head,
+                               mctx_tail,
+                               mctx);
   GNUNET_SERVER_client_drop (mctx->client);
-  GNUNET_ARM_disconnect_and_free (mctx->ah);
+  GNUNET_ARM_disconnect (mctx->ah);
   GNUNET_assert (0 < mctx->peer->reference_cnt);
   mctx->peer->reference_cnt--;
   if ( (GNUNET_YES == mctx->peer->destroy_flag)
        && (0 == mctx->peer->reference_cnt) )
     GST_destroy_peer (mctx->peer);
+  GNUNET_free (mctx->service);
   GNUNET_free (mctx);
 }
 
@@ -999,7 +1075,7 @@
 
 
 /**
- * Returns a string interpretation of 'rs'
+ * Returns a string interpretation of @a rs.
  *
  * @param rs the request status from ARM
  * @return a string interpretation of the request status
@@ -1017,8 +1093,6 @@
     return _("We disconnected from ARM before we could send a request");
   case GNUNET_ARM_REQUEST_BUSY:
     return _("ARM API is busy");
-  case GNUNET_ARM_REQUEST_TOO_LONG:
-    return _("Request doesn't fit into a message");
   case GNUNET_ARM_REQUEST_TIMEOUT:
     return _("Request timed out");
   }
@@ -1027,7 +1101,7 @@
 
 
 /**
- * Returns a string interpretation of the 'result'
+ * Returns a string interpretation of the @a result.
  *
  * @param result the arm result
  * @return a string interpretation
@@ -1066,17 +1140,16 @@
  * Function called in response to a start/stop request.
  * Will be called when request was not sent successfully,
  * or when a reply comes. If the request was not sent successfully,
- * 'rs' will indicate that, and 'service' and 'result' will be undefined.
+ * @a rs will indicate that, and @a result will be undefined.
  *
  * @param cls ManageServiceContext
  * @param rs status of the request
- * @param service service name
  * @param result result of the operation
  */
 static void
 service_manage_result_cb (void *cls,
                           enum GNUNET_ARM_RequestStatus rs,
-                          const char *service, enum GNUNET_ARM_Result result)
+                          enum GNUNET_ARM_Result result)
 {
   struct ManageServiceContext *mctx = cls;
   char *emsg;
@@ -1086,8 +1159,10 @@
     return;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
-    GNUNET_asprintf (&emsg, "Error communicating with Peer %u's ARM: %s",
-                     mctx->peer->id, arm_req_string (rs));
+    GNUNET_asprintf (&emsg,
+                     "Error communicating with Peer %u's ARM: %s",
+                     mctx->peer->id,
+                     arm_req_string (rs));
     goto ret;
   }
   if (1 == mctx->start)
@@ -1098,7 +1173,9 @@
             || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) )
   {
     /* stopping a service failed */
-    GNUNET_asprintf (&emsg, arm_ret_string (result), service);
+    GNUNET_asprintf (&emsg,
+                     arm_ret_string (result),
+                     mctx->service);
     goto ret;
   }
   /* service stopped successfully */
@@ -1110,7 +1187,9 @@
             || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) )
   {
     /* starting a service failed */
-    GNUNET_asprintf (&emsg, arm_ret_string (result), service);
+    GNUNET_asprintf (&emsg,
+                     arm_ret_string (result),
+                     mctx->service);
     goto ret;
   }
   /* service started successfully */
@@ -1119,10 +1198,13 @@
   if (NULL != emsg)
   {
     LOG_DEBUG ("%s\n", emsg);
-    GST_send_operation_fail_msg (mctx->client, mctx->op_id, emsg);
+    GST_send_operation_fail_msg (mctx->client,
+                                 mctx->op_id,
+                                 emsg);
   }
   else
-    GST_send_operation_success_msg (mctx->client, mctx->op_id);
+    GST_send_operation_success_msg (mctx->client,
+                                    mctx->op_id);
   GNUNET_free_non_null (emsg);
   cleanup_mctx (mctx);
 }
@@ -1136,7 +1218,8 @@
  * @param message the actual message
  */
 void
-GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
+GST_handle_manage_peer_service (void *cls,
+                                struct GNUNET_SERVER_Client *client,
                                 const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg;
@@ -1202,13 +1285,17 @@
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
-                                               fopc->operation_id, 
&msg->header,
+                                               fopc->operation_id,
+                                               &msg->header,
                                                
&GST_forwarded_operation_reply_relay,
                                                fopc);
     fopc->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, 
&GST_forwarded_operation_timeout,
+        GNUNET_SCHEDULER_add_delayed (GST_timeout,
+                                      &GST_forwarded_operation_timeout,
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fopc);
     GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
@@ -1242,17 +1329,19 @@
   GNUNET_SERVER_client_keep (client);
   mctx->client = client;
   mctx->start = msg->start;
-  GNUNET_CONTAINER_DLL_insert_tail (mctx_head, mctx_tail, mctx);
+  mctx->service = GNUNET_strdup (service);
+  GNUNET_CONTAINER_DLL_insert_tail (mctx_head,
+                                    mctx_tail,
+                                    mctx);
   if (1 == mctx->start)
-    GNUNET_ARM_request_service_start (mctx->ah, service,
+    GNUNET_ARM_request_service_start (mctx->ah,
+                                      service,
                                       GNUNET_OS_INHERIT_STD_ERR,
-                                      GST_timeout,
-                                      service_manage_result_cb,
+                                      &service_manage_result_cb,
                                       mctx);
   else
     GNUNET_ARM_request_service_stop (mctx->ah, service,
-                                     GST_timeout,
-                                     service_manage_result_cb,
+                                     &service_manage_result_cb,
                                      mctx);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   return;
@@ -1334,21 +1423,25 @@
   if (0 == hc->nslaves)
   {
     if (GNUNET_YES == hc->timeout)
-      GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id,
+      GST_send_operation_fail_msg (fo_ctxt->client,
+                                   fo_ctxt->operation_id,
                                    "Timeout at a slave controller");
     else
-      GST_send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id);
+      GST_send_operation_success_msg (fo_ctxt->client,
+                                      fo_ctxt->operation_id);
     GNUNET_free (hc);
     hc = NULL;
   }
   GNUNET_SERVER_client_drop (fo_ctxt->client);
-  GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt);
+  GNUNET_CONTAINER_DLL_remove (fopcq_head,
+                               fopcq_tail,
+                               fo_ctxt);
   GNUNET_free (fo_ctxt);
 }
 
 
 /**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages
+ * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages
  *
  * @param cls NULL
  * @param client identification of the client
@@ -1355,7 +1448,8 @@
  * @param message the actual message
  */
 void
-GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
+GST_handle_shutdown_peers (void *cls,
+                           struct GNUNET_SERVER_Client *client,
                            const struct GNUNET_MessageHeader *message)
 {
   const struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
@@ -1398,14 +1492,18 @@
                                                &msg->header,
                                                shutdown_peers_reply_cb,
                                                fo_ctxt);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fo_ctxt);
   }
   LOG_DEBUG ("Shutting down peers\n");
   GST_destroy_peers ();
   if (0 == hc->nslaves)
   {
-    GST_send_operation_success_msg (client, op_id);
+    GST_send_operation_success_msg (client,
+                                    op_id);
     GNUNET_free (hc);
   }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVER_receive_done (client,
+                              GNUNET_OK);
 }

Modified: gnunet/src/testbed/test_testbed_api.c
===================================================================
--- gnunet/src/testbed/test_testbed_api.c       2016-06-22 17:24:29 UTC (rev 
37328)
+++ gnunet/src/testbed/test_testbed_api.c       2016-06-23 14:22:34 UTC (rev 
37329)
@@ -219,7 +219,7 @@
 {
   FAIL_TEST (NULL != op_result, return);
   FAIL_TEST (op_result == arm_handle, return);
-  GNUNET_ARM_disconnect_and_free (arm_handle);
+  GNUNET_ARM_disconnect (arm_handle);
   arm_handle = NULL;
   FAIL_TEST (PEER_SERVICE_CONNECT == sub_test, return);
   FAIL_TEST (NULL != operation, return);
@@ -451,11 +451,13 @@
   cfg = GNUNET_CONFIGURATION_dup (config);
   host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
   FAIL_TEST (NULL != host, return);
-  cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, status_cb,
+  cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host,
+                                        &status_cb,
                                         NULL);
   abort_task =
       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort,
+                                    (GNUNET_TIME_UNIT_MINUTES, 5),
+                                    &do_abort,
                                     NULL);
 }
 

Modified: gnunet/src/testbed/test_testbed_logger_api.c
===================================================================
--- gnunet/src/testbed/test_testbed_logger_api.c        2016-06-22 17:24:29 UTC 
(rev 37328)
+++ gnunet/src/testbed/test_testbed_logger_api.c        2016-06-23 14:22:34 UTC 
(rev 37329)
@@ -17,13 +17,11 @@
       Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
       Boston, MA 02110-1301, USA.
  */
-
 /**
  * @file testbed/test_testbed_logger_api.c
  * @brief testcases for the testbed logger api
  * @author Sree Harsha Totakura
  */
-
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_testing_lib.h"
@@ -53,8 +51,8 @@
 /**
  * Abort task identifier
  */
-static struct GNUNET_SCHEDULER_Task * abort_task;
-static struct GNUNET_SCHEDULER_Task * write_task;
+static struct GNUNET_SCHEDULER_Task *abort_task;
+static struct GNUNET_SCHEDULER_Task *write_task;
 
 static int result;
 
@@ -78,6 +76,7 @@
     }                                                           \
   } while (0)
 
+
 /**
  * Shutdown nicely
  *
@@ -99,7 +98,8 @@
 static void
 do_abort (void *cls)
 {
-  LOG (GNUNET_ERROR_TYPE_WARNING, "Aborting\n");
+  LOG (GNUNET_ERROR_TYPE_WARNING,
+       "Aborting\n");
   abort_task = NULL;
   shutdown_now ();
 }
@@ -125,20 +125,34 @@
   size_t len;
   uint64_t fs;
 
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Iterator sees file %s\n",
+       filename);
   len = strlen (filename);
-  if (len < 5)                  /* log file: `pid'.dat */
-    return GNUNET_OK;
-
   fn = filename + len;
   if (0 != strcasecmp (".dat", fn - 4))
     return GNUNET_OK;
   if (GNUNET_OK !=
-      GNUNET_DISK_file_size (filename, &fs,
-                            GNUNET_NO, GNUNET_YES))
+      GNUNET_DISK_file_size (filename,
+                             &fs,
+                            GNUNET_NO,
+                             GNUNET_YES))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Failed to obtain file size for file %s\n",
+         filename);
     return GNUNET_SYSERR;
-  if ((BSIZE * 2) != fs)        /* The file size should be equal to what we
-                                   have written */
+  }
+  if ((BSIZE * 2) != fs)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Unexpected file size for file %s\n",
+         filename);
+    /* The file size should be equal to what we
+       have written */
     return GNUNET_SYSERR;
+  }
+  result = GNUNET_OK;
   return GNUNET_OK;
 }
 
@@ -151,11 +165,21 @@
  * @param size the amount of data sent
  */
 static void
-flush_comp (void *cls, size_t size)
+flush_comp (void *cls,
+            size_t size)
 {
-  FAIL_TEST (&write_task == cls, return);
-  FAIL_TEST ((BSIZE * 2) == size, return);
-  FAIL_TEST (GNUNET_OK == GNUNET_TESTING_peer_stop (peer), return);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Flush running\n");
+  FAIL_TEST (&write_task == cls,
+             return);
+  FAIL_TEST ((BSIZE * 2) == size,
+             return);
+  FAIL_TEST (GNUNET_OK ==
+             GNUNET_TESTING_peer_stop (peer),
+             return);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peer stopped, scanning %s\n",
+       search_dir);
   FAIL_TEST (GNUNET_SYSERR !=
             GNUNET_DISK_directory_scan (search_dir,
                                         &iterator_cb,
@@ -172,17 +196,22 @@
   char buf[BSIZE];
 
   write_task = NULL;
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Write task running\n");
   if (0 == i)
     write_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS(1),
                                               &do_write,
                                               NULL);
   (void) memset (buf, i, BSIZE);
-  GNUNET_TESTBED_LOGGER_write (h, buf, BSIZE);
+  GNUNET_TESTBED_LOGGER_write (h,
+                               buf,
+                               BSIZE);
   if (0 == i++)
     return;
   GNUNET_TESTBED_LOGGER_flush (h,
                               GNUNET_TIME_UNIT_FOREVER_REL,
-                               &flush_comp, &write_task);
+                               &flush_comp,
+                               &write_task);
 }
 
 
@@ -199,13 +228,22 @@
           const struct GNUNET_CONFIGURATION_Handle *cfg,
            struct GNUNET_TESTING_Peer *p)
 {
-  FAIL_TEST (NULL != (h = GNUNET_TESTBED_LOGGER_connect (cfg)), return);
-  FAIL_TEST (GNUNET_OK == GNUNET_CONFIGURATION_get_value_filename
-             (cfg, "testbed-logger", "dir", &search_dir), return);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Connecting to logger\n");
+  FAIL_TEST (NULL != (h = GNUNET_TESTBED_LOGGER_connect (cfg)),
+             return);
+  FAIL_TEST (GNUNET_OK ==
+             GNUNET_CONFIGURATION_get_value_filename (cfg,
+                                                      "testbed-logger",
+                                                      "dir",
+                                                      &search_dir),
+             return);
   peer = p;
-  write_task = GNUNET_SCHEDULER_add_now (&do_write, NULL);
+  write_task = GNUNET_SCHEDULER_add_now (&do_write,
+                                         NULL);
   abort_task = GNUNET_SCHEDULER_add_delayed (TIME_REL_SECS (10),
-                                             &do_abort, NULL);
+                                             &do_abort,
+                                             NULL);
 }
 
 
@@ -218,6 +256,9 @@
   int ret;
 
   result = GNUNET_SYSERR;
+  GNUNET_log_setup ("test-testbed-logger-api",
+                    "WARNING",
+                    NULL);
   ret = GNUNET_TESTING_service_run ("test-testbed-logger",
                                     "testbed-logger",
                                     "test_testbed_logger_api.conf",

Modified: gnunet/src/testing/testing.c
===================================================================
--- gnunet/src/testing/testing.c        2016-06-22 17:24:29 UTC (rev 37328)
+++ gnunet/src/testing/testing.c        2016-06-23 14:22:34 UTC (rev 37329)
@@ -1355,65 +1355,6 @@
 
 
 /**
- * Start a service at a peer using its ARM service
- *
- * @param peer the peer whose service has to be started
- * @param service_name name of the service to start
- * @param timeout how long should the ARM API try to send the request to start
- *          the service
- * @param cont the callback to call with result and status from ARM API
- * @param cont_cls the closure for the above callback
- * @return #GNUNET_OK upon successfully queuing the service start request;
- *           #GNUNET_SYSERR upon error
- */
-int
-GNUNET_TESTING_peer_service_start (struct GNUNET_TESTING_Peer *peer,
-                                   const char *service_name,
-                                   struct GNUNET_TIME_Relative timeout,
-                                   GNUNET_ARM_ResultCallback cont,
-                                   void *cont_cls)
-{
-  if (NULL == peer->ah)
-    return GNUNET_SYSERR;
-  GNUNET_ARM_request_service_start (peer->ah,
-                                    service_name,
-                                    GNUNET_OS_INHERIT_STD_ALL,
-                                    timeout,
-                                    cont, cont_cls);
-  return GNUNET_OK;
-}
-
-
-/**
- * Stop a service at a peer using its ARM service
- *
- * @param peer the peer whose service has to be stopped
- * @param service_name name of the service to stop
- * @param timeout how long should the ARM API try to send the request to stop
- *          the service
- * @param cont the callback to call with result and status from ARM API
- * @param cont_cls the closure for the above callback
- * @return #GNUNET_OK upon successfully queuing the service stop request;
- *           #GNUNET_SYSERR upon error
- */
-int
-GNUNET_TESTING_peer_service_stop (struct GNUNET_TESTING_Peer *peer,
-                                  const char *service_name,
-                                  struct GNUNET_TIME_Relative timeout,
-                                  GNUNET_ARM_ResultCallback cont,
-                                  void *cont_cls)
-{
-  if (NULL == peer->ah)
-    return GNUNET_SYSERR;
-  GNUNET_ARM_request_service_stop (peer->ah,
-                                   service_name,
-                                   timeout,
-                                   cont, cont_cls);
-  return GNUNET_OK;
-}
-
-
-/**
  * Sends SIGTERM to the peer's main process
  *
  * @param peer the handle to the peer
@@ -1510,7 +1451,7 @@
     return;
   }
   GNUNET_break (GNUNET_OK == GNUNET_TESTING_peer_wait (peer));
-  GNUNET_ARM_disconnect_and_free (peer->ah);
+  GNUNET_ARM_disconnect (peer->ah);
   peer->ah = NULL;
   peer->cb (peer->cb_cls, peer, GNUNET_YES);
 }
@@ -1556,7 +1497,7 @@
 GNUNET_TESTING_peer_stop_async_cancel (struct GNUNET_TESTING_Peer *peer)
 {
   GNUNET_assert (NULL != peer->ah);
-  GNUNET_ARM_disconnect_and_free (peer->ah);
+  GNUNET_ARM_disconnect (peer->ah);
   peer->ah = NULL;
 }
 
@@ -1576,9 +1517,9 @@
   if (NULL != peer->main_process)
     GNUNET_TESTING_peer_stop (peer);
   if (NULL != peer->ah)
-    GNUNET_ARM_disconnect_and_free (peer->ah);
+    GNUNET_ARM_disconnect (peer->ah);
   if (NULL != peer->mh)
-    GNUNET_ARM_monitor_disconnect_and_free (peer->mh);
+    GNUNET_ARM_monitor_stop (peer->mh);
   GNUNET_free (peer->cfgfile);
   if (NULL != peer->cfg)
     GNUNET_CONFIGURATION_destroy (peer->cfg);




reply via email to

[Prev in Thread] Current Thread [Next in Thread]