static void
service_list (void *cls,
	      enum GNUNET_ARM_RequestStatus rs,
	      unsigned int count,
              const char *const*list)
{
  unsigned int i;

  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
	      "%u services are are currently running\n",
	      count);
  if (GNUNET_ARM_REQUEST_SENT_OK != rs)
    goto stop_arm;
  for (i=0;i<count;i++)
  {
    if (0 == strcasecmp (list[i],
                         "resolver (gnunet-service-resolver)"))
    {
      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                  "Got service list, now stopping arm\n");
      ret = 0;
    }
  }

 stop_arm:
  GNUNET_ARM_request_service_stop (arm,
                                   "arm",
                                   TIMEOUT,
                                   &arm_stop_cb, NULL);
}
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);
  GNUNET_break (result == GNUNET_ARM_RESULT_STARTING);
  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
              "Trying to resolve our own hostname!\n");
  /* connect to the resolver service */
  if (NULL ==
      GNUNET_RESOLVER_hostname_resolve (AF_UNSPEC, TIMEOUT,
                                        &hostname_resolve_cb,
                                        NULL))
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Unable initiate connection to resolver service\n");
    GNUNET_break (0);
    ret = 2;
    GNUNET_ARM_request_service_stop (arm,
                                     "arm", TIMEOUT,
                                     &arm_stop_cb, NULL);
  }
}
static void
hostname_resolve_cb (void *cls,
                   const struct sockaddr *addr,
                   socklen_t addrlen)
{
  if ((0 == ret) || (4 == ret) || (1 == resolved_ok))
    return;
  if (NULL == addr)
  {
    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                "Name not resolved!\n");
    GNUNET_break (0);
    ret = 3;
    GNUNET_ARM_request_service_stop (arm,
                                     "arm",
                                     TIMEOUT,
                                     &arm_stop_cb, NULL);
    return;
  }
  if (0 == asked_for_a_list)
  {
    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;
    resolved_ok = 1;
  }
}
static void
srv_status (void *cls,
            const char *service,
            enum GNUNET_ARM_ServiceStatus status)
{
  if (status == GNUNET_ARM_SERVICE_MONITORING_STARTED)
  {
    LOG ("ARM monitor started, starting mock service\n");
    phase++;
    GNUNET_ARM_request_service_start (arm,
                                      SERVICE,
                                      GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
                                      NULL,
                                      NULL);
    return;
  }
  if (0 != strcasecmp (service, SERVICE))
    return; /* not what we care about */
  if (phase == 1)
  {
    GNUNET_break (status == GNUNET_ARM_SERVICE_STARTING);
    GNUNET_break (phase == 1);
    LOG ("do-nothing is starting\n");
    phase++;
    ok = 1;
    GNUNET_assert (NULL == kt);
    startedWaitingAt = GNUNET_TIME_absolute_get ();
    kt = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
                                       &kill_task,
                                       NULL);
  }
  else if (phase == 2)
  {
    /* We passively monitor ARM for status updates. ARM should tell us
     * when do-nothing dies (no need to run a service upness test ourselves).
     */
    if (status == GNUNET_ARM_SERVICE_STARTING)
    {
      waitedFor = GNUNET_TIME_absolute_get_duration (startedWaitingAt);
      LOG ("Waited for: %s\n",
           GNUNET_STRINGS_relative_time_to_string (waitedFor,
                                                   GNUNET_YES));

      LOG ("do-nothing is starting, killing it...\n");
      GNUNET_assert (NULL == kt);
      kt = GNUNET_SCHEDULER_add_now (&kill_task, &ok);
    }
    else if ((status == GNUNET_ARM_SERVICE_STOPPED) && (trialCount == 14))
    {
      phase++;
      LOG ("do-nothing stopped working %u times, we are done here\n",
           (unsigned int) trialCount);
      GNUNET_ARM_request_service_stop (arm,
                                       "arm",
                                       &arm_stop_cb,
                                       NULL);
    }
  }
}
static void
kill_task (void *cbData)
{
  struct ShutdownContext *shutdown_ctx
    = GNUNET_new (struct ShutdownContext);
  struct GNUNET_MQ_Envelope *env;
  struct GNUNET_MessageHeader *msg;
  struct GNUNET_MQ_MessageHandler handlers[] = {
    GNUNET_MQ_handler_end ()
  };

  kt = NULL;
  if (trialCount == 13)
  {
    LOG ("Saw enough kills, asking ARM to stop mock service for good\n");
    GNUNET_ARM_request_service_stop (arm,
                                     SERVICE,
                                     NULL,
                                     NULL);
    ok = 0;
    trialCount++;
    GNUNET_free (shutdown_ctx);
    return;
  }
  shutdown_ctx->mq = GNUNET_CLIENT_connect (cfg,
                                            SERVICE,
                                            handlers,
                                            &mq_error_handler,
                                            shutdown_ctx);
  GNUNET_assert (NULL != shutdown_ctx->mq);
  trialCount++;
  LOG ("Sending a shutdown request to the mock service\n");
  env = GNUNET_MQ_msg (msg,
                       GNUNET_MESSAGE_TYPE_ARM_STOP); /* FIXME: abuse of message type */
  GNUNET_MQ_send (shutdown_ctx->mq,
                  env);
  shutdown_ctx->cancel_task
    = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
                                    &service_shutdown_timeout,
                                    shutdown_ctx);
}