eliminate KX short cut
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed_peers.c
index c07fa87c5419d2616e0b00cc1a4583f04e4b76f7..aacd6258324b6583f4bf5d541f5b8f11206ec8b8 100644 (file)
@@ -1,10 +1,10 @@
 /*
   This file is part of GNUnet.
 /*
   This file is part of GNUnet.
-  (C) 2008--2013 Christian Grothoff (and other contributing authors)
+  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
 
   GNUnet is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 2, or (at your
+  by the Free Software Foundation; either version 3, or (at your
   option) any later version.
 
   GNUnet is distributed in the hope that it will be useful, but
   option) any later version.
 
   GNUnet is distributed in the hope that it will be useful, but
 
   You should have received a copy of the GNU General Public License
   along with GNUnet; see the file COPYING.  If not, write to the
 
   You should have received a copy of the GNU General Public License
   along with GNUnet; see the file COPYING.  If not, write to the
-  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-  Boston, MA 02111-1307, USA.
+  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+  Boston, MA 02110-1301, USA.
 */
 
 
 /**
  * @file testbed/gnunet-service-testbed_peers.c
  * @brief implementation of TESTBED service that deals with peer management
 */
 
 
 /**
  * @file testbed/gnunet-service-testbed_peers.c
  * @brief implementation of TESTBED service that deals with peer management
- * @author Sree Harsha Totakura <sreeharsha@totakura.in> 
+ * @author Sree Harsha Totakura <sreeharsha@totakura.in>
  */
 
 #include "gnunet-service-testbed.h"
  */
 
 #include "gnunet-service-testbed.h"
  */
 struct Peer **GST_peer_list;
 
  */
 struct Peer **GST_peer_list;
 
+/**
+ * The current number of peers running locally under this controller
+ */
+unsigned int GST_num_local_peers;
+
 
 /**
  * Context information to manage peers' services
 
 /**
  * Context information to manage peers' services
@@ -64,13 +69,18 @@ struct ManageServiceContext
   /**
    * The client which requested to manage the peer's service
    */
   /**
    * The client which requested to manage the peer's service
    */
-  struct GNUNET_SERVER_Client *client;
-  
+  struct GNUNET_SERVICE_Client *client;
+
+  /**
+   * Name of the service.
+   */
+  char *service;
+
   /**
    * The operation id of the associated request
    */
   uint64_t op_id;
   /**
    * The operation id of the associated request
    */
   uint64_t op_id;
-  
+
   /**
    * 1 if the service at the peer has to be started; 0 if it has to be stopped
    */
   /**
    * 1 if the service at the peer has to be started; 0 if it has to be stopped
    */
@@ -80,7 +90,7 @@ struct ManageServiceContext
    * Is this context expired?  Do not work on this context if it is set to
    * GNUNET_YES
    */
    * Is this context expired?  Do not work on this context if it is set to
    * GNUNET_YES
    */
-  uint8_t expired;  
+  uint8_t expired;
 };
 
 
 };
 
 
@@ -102,7 +112,7 @@ struct PeerReconfigureContext
   /**
    * The client which gave this operation to us
    */
   /**
    * The client which gave this operation to us
    */
-  struct GNUNET_SERVER_Client *client;
+  struct GNUNET_SERVICE_Client *client;
 
   /**
    * The configuration handle to use as the new template
 
   /**
    * The configuration handle to use as the new template
@@ -162,6 +172,8 @@ peer_list_add (struct Peer *peer)
     GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id);
   GNUNET_assert (NULL == GST_peer_list[peer->id]);
   GST_peer_list[peer->id] = peer;
     GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id);
   GNUNET_assert (NULL == GST_peer_list[peer->id]);
   GST_peer_list[peer->id] = peer;
+  if (GNUNET_NO == peer->is_remote)
+    GST_num_local_peers++;
 }
 
 
 }
 
 
@@ -176,6 +188,8 @@ peer_list_remove (struct Peer *peer)
   unsigned int orig_size;
   uint32_t id;
 
   unsigned int orig_size;
   uint32_t id;
 
+  if (GNUNET_NO == peer->is_remote)
+    GST_num_local_peers--;
   GST_peer_list[peer->id] = NULL;
   orig_size = GST_peer_list_size;
   while (GST_peer_list_size >= LIST_GROW_STEP)
   GST_peer_list[peer->id] = NULL;
   orig_size = GST_peer_list_size;
   while (GST_peer_list_size >= LIST_GROW_STEP)
@@ -202,16 +216,14 @@ peer_list_remove (struct Peer *peer)
  * timed out
  *
  * @param cls the FowardedOperationContext
  * timed out
  *
  * @param cls the FowardedOperationContext
- * @param tc the TaskContext from the scheduler
  */
 static void
  */
 static void
-peer_create_forward_timeout (void *cls,
-                             const struct GNUNET_SCHEDULER_TaskContext *tc)
+peer_create_forward_timeout (void *cls)
 {
   struct ForwardedOperationContext *fopc = cls;
 
   GNUNET_free (fopc->cls);
 {
   struct ForwardedOperationContext *fopc = cls;
 
   GNUNET_free (fopc->cls);
-  GST_forwarded_operation_timeout (fopc, tc);
+  GST_forwarded_operation_timeout (fopc);
 }
 
 
 }
 
 
@@ -234,7 +246,8 @@ peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
     remote_peer = fopc->cls;
     peer_list_add (remote_peer);
   }
     remote_peer = fopc->cls;
     peer_list_add (remote_peer);
   }
-  GST_forwarded_operation_reply_relay (fopc, msg);
+  GST_forwarded_operation_reply_relay (fopc,
+                                       msg);
 }
 
 
 }
 
 
@@ -265,6 +278,115 @@ GST_destroy_peer (struct Peer *peer)
 }
 
 
 }
 
 
+/**
+ * Cleanup the context information created for managing a peer's service
+ *
+ * @param mctx the ManageServiceContext
+ */
+static void
+cleanup_mctx (struct ManageServiceContext *mctx)
+{
+  mctx->expired = GNUNET_YES;
+  GNUNET_CONTAINER_DLL_remove (mctx_head,
+                               mctx_tail,
+                               mctx);
+  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);
+}
+
+
+/**
+ * Stops a peer
+ *
+ * @param peer the peer to stop
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
+ */
+static int
+stop_peer (struct Peer *peer)
+{
+  GNUNET_assert (GNUNET_NO == peer->is_remote);
+  if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer))
+    return GNUNET_SYSERR;
+  peer->details.local.is_running = GNUNET_NO;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Cleans up the given PeerReconfigureContext
+ *
+ * @param prc the PeerReconfigureContext
+ */
+static void
+cleanup_prc (struct PeerReconfigureContext *prc)
+{
+  struct Peer *peer;
+
+  if (VALID_PEER_ID (prc->peer_id))
+  {
+    peer = GST_peer_list [prc->peer_id];
+    if (1 != prc->stopped)
+    {
+      GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer);
+      stop_peer (peer);         /* Stop the peer synchronously */
+    }
+  }
+  if (NULL != prc->cfg)
+    GNUNET_CONFIGURATION_destroy (prc->cfg);
+  GNUNET_CONTAINER_DLL_remove (prc_head,
+                               prc_tail,
+                               prc);
+  GNUNET_free (prc);
+}
+
+
+/**
+ * Notify peers subsystem that @a client disconnected.
+ *
+ * @param client the client that disconnected
+ */
+void
+GST_notify_client_disconnect_peers (struct GNUNET_SERVICE_Client *client)
+{
+  struct ForwardedOperationContext *fopc;
+  struct ForwardedOperationContext *fopcn;
+  struct ManageServiceContext *mctx;
+  struct ManageServiceContext *mctxn;
+  struct PeerReconfigureContext *prc;
+  struct PeerReconfigureContext *prcn;
+
+  for (fopc = fopcq_head; NULL != fopc; fopc = fopcn)
+  {
+    fopcn = fopc->next;
+    if (client == fopc->client)
+    {
+      if (OP_PEER_CREATE == fopc->type)
+        GNUNET_free (fopc->cls);
+      GNUNET_SCHEDULER_cancel (fopc->timeout_task);
+      GST_forwarded_operation_timeout (fopc);
+    }
+  }
+  for (mctx = mctx_head; NULL != mctx; mctx = mctxn)
+  {
+    mctxn = mctx->next;
+    if (client == mctx->client)
+      cleanup_mctx (mctx);
+  }
+  for (prc = prc_head; NULL != prc; prc = prcn)
+  {
+    prcn = prc->next;
+    if (client == prc->client)
+      cleanup_prc (prc);
+  }
+}
+
+
 /**
  * Callback to be called when forwarded peer destroy operation is successfull. We
  * have to relay the reply msg back to the client
 /**
  * Callback to be called when forwarded peer destroy operation is successfull. We
  * have to relay the reply msg back to the client
@@ -287,22 +409,38 @@ peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
     if (0 == remote_peer->reference_cnt)
       GST_destroy_peer (remote_peer);
   }
     if (0 == remote_peer->reference_cnt)
       GST_destroy_peer (remote_peer);
   }
-  GST_forwarded_operation_reply_relay (fopc, msg);
+  GST_forwarded_operation_reply_relay (fopc,
+                                       msg);
 }
 
 
 /**
 }
 
 
 /**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
+ * Check #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
  *
  *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
+ * @return #GNUNET_OK if @a msg is well-formed
+ */
+int
+check_peer_create (void *cls,
+                   const struct GNUNET_TESTBED_PeerCreateMessage *msg)
+{
+  return GNUNET_OK; /* checked later */
+}
+
+
+/**
+ * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
+ *
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
+handle_peer_create (void *cls,
+                    const struct GNUNET_TESTBED_PeerCreateMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_PeerCreateMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
   struct GNUNET_CONFIGURATION_Handle *cfg;
   struct ForwardedOperationContext *fo_ctxt;
   struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
   struct GNUNET_CONFIGURATION_Handle *cfg;
   struct ForwardedOperationContext *fo_ctxt;
@@ -311,52 +449,54 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
   char *emsg;
   uint32_t host_id;
   uint32_t peer_id;
   char *emsg;
   uint32_t host_id;
   uint32_t peer_id;
-  uint16_t msize;
 
 
-
-  msize = ntohs (message->size);
-  if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage))
-  {
-    GNUNET_break (0);           /* We need configuration */
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message;
   host_id = ntohl (msg->host_id);
   peer_id = ntohl (msg->peer_id);
   if (VALID_PEER_ID (peer_id))
   {
   host_id = ntohl (msg->host_id);
   peer_id = ntohl (msg->peer_id);
   if (VALID_PEER_ID (peer_id))
   {
-    (void) GNUNET_asprintf (&emsg, "Peer with ID %u already exists", peer_id);
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
+    (void) GNUNET_asprintf (&emsg,
+                            "Peer with ID %u already exists",
+                            peer_id);
+    GST_send_operation_fail_msg (client,
+                                 GNUNET_ntohll (msg->operation_id),
                                  emsg);
     GNUNET_free (emsg);
                                  emsg);
     GNUNET_free (emsg);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   if (UINT32_MAX == peer_id)
     return;
   }
   if (UINT32_MAX == peer_id)
-  {    
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
+  {
+    GST_send_operation_fail_msg (client,
+                                 GNUNET_ntohll (msg->operation_id),
                                  "Cannot create peer with given ID");
                                  "Cannot create peer with given ID");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   if (host_id == GST_context->host_id)
   {
     /* We are responsible for this peer */
     return;
   }
   if (host_id == GST_context->host_id)
   {
     /* We are responsible for this peer */
-    cfg = GNUNET_TESTBED_extract_config_ (message);
+    cfg = GNUNET_TESTBED_extract_config_ (&msg->header);
     if (NULL == cfg)
     {
       GNUNET_break (0);
     if (NULL == cfg)
     {
       GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      GNUNET_SERVICE_client_drop (client);
       return;
     }
       return;
     }
-    GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID",
+    GNUNET_CONFIGURATION_set_value_number (cfg,
+                                           "TESTBED",
+                                           "PEERID",
                                            (unsigned long long) peer_id);
                                            (unsigned long long) peer_id);
-    peer = GNUNET_malloc (sizeof (struct Peer));
+
+    GNUNET_CONFIGURATION_set_value_number (cfg,
+                                           "PATHS",
+                                           "PEERID",
+                                           (unsigned long long) peer_id);
+    peer = GNUNET_new (struct Peer);
     peer->is_remote = GNUNET_NO;
     peer->details.local.cfg = cfg;
     peer->id = peer_id;
     peer->is_remote = GNUNET_NO;
     peer->details.local.cfg = cfg;
     peer->id = peer_id;
-    LOG_DEBUG ("Creating peer with id: %u\n", (unsigned int) peer->id);
+    LOG_DEBUG ("Creating peer with id: %u\n",
+               (unsigned int) peer->id);
     peer->details.local.peer =
         GNUNET_TESTING_peer_configure (GST_context->system,
                                        peer->details.local.cfg, peer->id,
     peer->details.local.peer =
         GNUNET_TESTING_peer_configure (GST_context->system,
                                        peer->details.local.cfg, peer->id,
@@ -364,26 +504,24 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
                                        &emsg);
     if (NULL == peer->details.local.peer)
     {
                                        &emsg);
     if (NULL == peer->details.local.peer)
     {
-      LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
+      LOG (GNUNET_ERROR_TYPE_WARNING,
+           "Configuring peer failed: %s\n",
+           emsg);
       GNUNET_free (emsg);
       GNUNET_free (peer);
       GNUNET_break (0);
       GNUNET_free (emsg);
       GNUNET_free (peer);
       GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
+      GNUNET_SERVICE_client_drop (client);
       return;
     }
     peer->details.local.is_running = GNUNET_NO;
     peer_list_add (peer);
       return;
     }
     peer->details.local.is_running = GNUNET_NO;
     peer_list_add (peer);
-    reply =
-        GNUNET_malloc (sizeof
-                       (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
-    reply->header.size =
-        htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage));
-    reply->header.type =
-        htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS);
+    env = GNUNET_MQ_msg (reply,
+                         GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS);
     reply->peer_id = msg->peer_id;
     reply->operation_id = msg->operation_id;
     reply->peer_id = msg->peer_id;
     reply->operation_id = msg->operation_id;
-    GST_queue_message (client, &reply->header);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
+                    env);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
 
     return;
   }
 
@@ -392,16 +530,15 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
   if (NULL == route)
   {
     GNUNET_break (0);
   if (NULL == route)
   {
     GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client); // ?
     return;
   }
     return;
   }
-  peer = GNUNET_malloc (sizeof (struct Peer));
+  peer = GNUNET_new (struct Peer);
   peer->is_remote = GNUNET_YES;
   peer->id = peer_id;
   peer->details.remote.slave = GST_slave_list[route->dest];
   peer->details.remote.remote_host_id = host_id;
   peer->is_remote = GNUNET_YES;
   peer->id = peer_id;
   peer->details.remote.slave = GST_slave_list[route->dest];
   peer->details.remote.remote_host_id = host_id;
-  fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-  GNUNET_SERVER_client_keep (client);
+  fo_ctxt = GNUNET_new (struct ForwardedOperationContext);
   fo_ctxt->client = client;
   fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
   fo_ctxt->cls = peer;
   fo_ctxt->client = client;
   fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
   fo_ctxt->cls = peer;
@@ -411,50 +548,53 @@ GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
                                              [route->dest]->controller,
                                              fo_ctxt->operation_id,
                                              &msg->header,
                                              [route->dest]->controller,
                                              fo_ctxt->operation_id,
                                              &msg->header,
-                                             peer_create_success_cb, fo_ctxt);
+                                             &peer_create_success_cb,
+                                             fo_ctxt);
   fo_ctxt->timeout_task =
   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);
                                     fo_ctxt);
-  GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
 /**
 }
 
 
 /**
- * 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
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
-                         const struct GNUNET_MessageHeader *message)
+handle_peer_destroy (void *cls,
+                     const struct GNUNET_TESTBED_PeerDestroyMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   uint32_t peer_id;
 
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   uint32_t peer_id;
 
-  msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
   peer_id = ntohl (msg->peer_id);
   peer_id = ntohl (msg->peer_id);
-  LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n",
-             peer_id, GNUNET_ntohll (msg->operation_id));
+  LOG_DEBUG ("Received peer destory on peer: %u and operation id: %llu\n",
+             (unsigned int) peer_id,
+             (unsigned long long) GNUNET_ntohll (msg->operation_id));
   if (!VALID_PEER_ID (peer_id))
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Asked to destroy a non existent peer with id: %u\n", peer_id);
   if (!VALID_PEER_ID (peer_id))
   {
     LOG (GNUNET_ERROR_TYPE_ERROR,
          "Asked to destroy a non existent peer with id: %u\n", 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 doesn't exist");
                                  "Peer doesn't exist");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     /* Forward the destory message to sub controller */
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     /* Forward the destory message to sub controller */
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    fopc = GNUNET_new (struct ForwardedOperationContext);
     fopc->client = client;
     fopc->cls = peer;
     fopc->type = OP_PEER_DESTROY;
     fopc->client = client;
     fopc->cls = peer;
     fopc->type = OP_PEER_DESTROY;
@@ -462,13 +602,18 @@ GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
-                                               fopc->operation_id, &msg->header,
-                                               &peer_destroy_success_cb, fopc);
+                                               fopc->operation_id,
+                                               &msg->header,
+                                               &peer_destroy_success_cb,
+                                               fopc);
     fopc->timeout_task =
     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);
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   peer->destroy_flag = GNUNET_YES;
     return;
   }
   peer->destroy_flag = GNUNET_YES;
@@ -477,8 +622,9 @@ GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
   else
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Delaying peer destroy as peer is currently in use\n");
   else
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Delaying peer destroy as peer is currently in use\n");
-  GST_send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GST_send_operation_success_msg (client,
+                                  GNUNET_ntohll (msg->operation_id));
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
 }
 
 
@@ -486,7 +632,7 @@ GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
  * Stats a peer
  *
  * @param peer the peer to start
  * Stats a peer
  *
  * @param peer the peer to start
- * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
+ * @return #GNUNET_OK upon success; #GNUNET_SYSERR upon failure
  */
 static int
 start_peer (struct Peer *peer)
  */
 static int
 start_peer (struct Peer *peer)
@@ -500,54 +646,36 @@ start_peer (struct Peer *peer)
 
 
 /**
 
 
 /**
- * Stops a peer
- *
- * @param peer the peer to stop
- * @return GNUNET_OK upon success; GNUNET_SYSERR upon failure
- */
-static int
-stop_peer (struct Peer *peer)
-{
-  GNUNET_assert (GNUNET_NO == peer->is_remote);
-  if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer))
-    return GNUNET_SYSERR;
-  peer->details.local.is_running = GNUNET_NO;
-  return GNUNET_OK;
-}
-
-
-/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
+ * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_START_PEER messages
  *
  *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
+handle_peer_start (void *cls,
+                   const struct GNUNET_TESTBED_PeerStartMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_PeerStartMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_TESTBED_PeerEventMessage *reply;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   uint32_t peer_id;
 
   struct GNUNET_TESTBED_PeerEventMessage *reply;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   uint32_t peer_id;
 
-  msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message;
   peer_id = ntohl (msg->peer_id);
   peer_id = ntohl (msg->peer_id);
-  if (!VALID_PEER_ID (peer_id))
+  if (! VALID_PEER_ID (peer_id))
   {
     GNUNET_break (0);
     LOG (GNUNET_ERROR_TYPE_ERROR,
   {
     GNUNET_break (0);
     LOG (GNUNET_ERROR_TYPE_ERROR,
-         "Asked to start a non existent peer with id: %u\n", peer_id);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+         "Asked to start a non existent peer with id: %u\n",
+         peer_id);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    fopc = GNUNET_new (struct ForwardedOperationContext);
     fopc->client = client;
     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
     fopc->type = OP_PEER_START;
     fopc->client = client;
     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
     fopc->type = OP_PEER_START;
@@ -558,115 +686,129 @@ GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
                                                &GST_forwarded_operation_reply_relay,
                                                fopc);
     fopc->timeout_task =
                                                &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);
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   if (GNUNET_OK != start_peer (peer))
   {
     GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
                                  "Failed to start");
     return;
   }
   if (GNUNET_OK != start_peer (peer))
   {
     GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
                                  "Failed to start");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
     return;
   }
-  reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
-  reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
-  reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
+  env = GNUNET_MQ_msg (reply,
+                       GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
   reply->host_id = htonl (GST_context->host_id);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START);
   reply->host_id = htonl (GST_context->host_id);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
-  GST_queue_message (client, &reply->header);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
+                  env);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
 /**
 }
 
 
 /**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
+ * Message handler for #GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER messages
  *
  *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
-                      const struct GNUNET_MessageHeader *message)
+handle_peer_stop (void *cls,
+                  const struct GNUNET_TESTBED_PeerStopMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_PeerStopMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_TESTBED_PeerEventMessage *reply;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   uint32_t peer_id;
 
   struct GNUNET_TESTBED_PeerEventMessage *reply;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   uint32_t peer_id;
 
-  msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message;
   peer_id = ntohl (msg->peer_id);
   peer_id = ntohl (msg->peer_id);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id);
-  if (!VALID_PEER_ID (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");
                                  "Peer not found");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     return;
   }
   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);
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Forwarding PEER_STOP for peer %u\n",
+         (unsigned int) peer_id);
+    fopc = GNUNET_new (struct ForwardedOperationContext);
     fopc->client = client;
     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
     fopc->type = OP_PEER_STOP;
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
     fopc->client = client;
     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
     fopc->type = OP_PEER_STOP;
     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 =
                                                &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);
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fopc);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   if (GNUNET_OK != stop_peer (peer))
   {
     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");
                                  "Peer not running");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
     return;
   }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id);
-  reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
-  reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
-  reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage));
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Peer %u successfully stopped\n",
+       (unsigned int) peer_id);
+  env = GNUNET_MQ_msg (reply,
+                       GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT);
   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
   reply->host_id = htonl (GST_context->host_id);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
   reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP);
   reply->host_id = htonl (GST_context->host_id);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
-  GST_queue_message (client, &reply->header);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
+                  env);
+  GNUNET_SERVICE_client_continue (client);
   GNUNET_TESTING_peer_wait (peer->details.local.peer);
 }
 
 
 /**
   GNUNET_TESTING_peer_wait (peer->details.local.peer);
 }
 
 
 /**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
+ * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION messages
  *
  *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
+handle_peer_get_config (void *cls,
+                        const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
+  struct GNUNET_MQ_Envelope *env;
   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
   struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
   struct ForwardedOperationContext *fopc;
   struct Peer *peer;
@@ -675,98 +817,106 @@ GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
   size_t c_size;
   size_t xc_size;
   uint32_t peer_id;
   size_t c_size;
   size_t xc_size;
   uint32_t peer_id;
-  uint16_t msize;
 
 
-  msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message;
   peer_id = ntohl (msg->peer_id);
   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))
   {
   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");
                                  "Peer not found");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
-    LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id);
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n",
+               (unsigned int) peer_id);
+    fopc = GNUNET_new (struct ForwardedOperationContext);
     fopc->client = client;
     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
     fopc->type = OP_PEER_INFO;
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
     fopc->client = client;
     fopc->operation_id = GNUNET_ntohll (msg->operation_id);
     fopc->type = OP_PEER_INFO;
     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 =
                                                &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);
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
     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);
   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);
   GNUNET_free (config);
-  msize =
-      xc_size +
-      sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
-  reply = GNUNET_realloc (xconfig, msize);
-  (void) memmove (&reply[1], reply, xc_size);
-  reply->header.size = htons (msize);
-  reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION);
+  env = GNUNET_MQ_msg_extra (reply,
+                             xc_size,
+                             GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
   GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer,
                                     &reply->peer_identity);
   reply->config_size = htons ((uint16_t) c_size);
   reply->peer_id = msg->peer_id;
   reply->operation_id = msg->operation_id;
   GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer,
                                     &reply->peer_identity);
   reply->config_size = htons ((uint16_t) c_size);
-  GST_queue_message (client, &reply->header);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_memcpy (&reply[1],
+                 xconfig,
+                 xc_size);
+  GNUNET_free (xconfig);
+  GNUNET_MQ_send (GNUNET_SERVICE_client_get_mq (client),
+                  env);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
 /**
 }
 
 
 /**
- * Cleans up the given PeerReconfigureContext
- *
- * @param prc the PeerReconfigureContext
+ * Cleans up the Peer reconfigure context list
  */
  */
-static void
-cleanup_prc (struct PeerReconfigureContext *prc)
+void
+GST_free_prcq ()
 {
 {
-  struct Peer *peer;
-
-  if (VALID_PEER_ID (prc->peer_id))
-  {
-    peer = GST_peer_list [prc->peer_id];
-    if (1 != prc->stopped)
-    {
-      GNUNET_TESTING_peer_stop_async_cancel (peer->details.local.peer);
-      stop_peer (peer);         /* Stop the peer synchronously */
-    }
-  }
-  if (NULL != prc->cfg)
-    GNUNET_CONFIGURATION_destroy (prc->cfg);
-  GNUNET_SERVER_client_drop (prc->client);
-  GNUNET_CONTAINER_DLL_remove (prc_head, prc_tail, prc);
-  GNUNET_free (prc);
+  while (NULL != prc_head)
+    cleanup_prc (prc_head);
 }
 
 
 /**
 }
 
 
 /**
- * Cleans up the Peer reconfigure context list
+ * Update peer configuration
+ *
+ * @param peer the peer to update
+ * @param cfg the new configuration
+ * @return error message (freshly allocated); NULL upon success
  */
  */
-void
-GST_free_prcq ()
+static char *
+update_peer_config (struct Peer *peer,
+                    struct GNUNET_CONFIGURATION_Handle *cfg)
 {
 {
-  while (NULL != prc_head)
-    cleanup_prc (prc_head);
+  char *emsg;
+
+  GNUNET_TESTING_peer_destroy (peer->details.local.peer);
+  GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
+  peer->details.local.cfg = cfg;
+  emsg = NULL;
+  peer->details.local.peer
+      = GNUNET_TESTING_peer_configure (GST_context->system,
+                                       peer->details.local.cfg,
+                                       peer->id,
+                                       NULL /* Peer id */ ,
+                                       &emsg);
+  return emsg;
 }
 
 
 }
 
 
@@ -775,44 +925,41 @@ GST_free_prcq ()
  *
  * @param cls the closure given to GNUNET_TESTING_peer_stop_async()
  * @param p the respective peer whose status is being reported
  *
  * @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
  *          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;
   char *emsg;
 {
   struct PeerReconfigureContext *prc = cls;
   struct Peer *peer;
   char *emsg;
-  
+
   GNUNET_assert (VALID_PEER_ID (prc->peer_id));
   peer = GST_peer_list [prc->peer_id];
   GNUNET_assert (GNUNET_NO == peer->is_remote);
   GNUNET_assert (VALID_PEER_ID (prc->peer_id));
   peer = GST_peer_list [prc->peer_id];
   GNUNET_assert (GNUNET_NO == peer->is_remote);
-  GNUNET_TESTING_peer_destroy (peer->details.local.peer);
-  GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
-  peer->details.local.cfg = prc->cfg;
+  emsg = update_peer_config (peer, prc->cfg);
   prc->cfg = NULL;
   prc->stopped = 1;
   prc->cfg = NULL;
   prc->stopped = 1;
-  emsg = NULL;
-  peer->details.local.peer
-      = GNUNET_TESTING_peer_configure (GST_context->system,
-                                       peer->details.local.cfg, peer->id,
-                                       NULL /* Peer id */ ,
-                                       &emsg);
-  if (NULL == peer->details.local.peer)
+  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))
   {
     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;
   }
                                  "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);
   return;
  cleanup:
   cleanup_prc (prc);
   return;
@@ -820,119 +967,149 @@ prc_stop_cb (void *cls, struct GNUNET_TESTING_Peer *p, int success)
 
 
 /**
 
 
 /**
- * Handler for GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages.
+ * Check #GNUNET_MESSAGE_TYPDE_TESTBED_RECONFIGURE_PEER type messages.
+ *
+ * @param cls identification of the client
+ * @param msg the actual message
+ * @return #GNUNET_OK if @a msg is well-formed
+ */
+int
+check_peer_reconfigure (void *cls,
+                        const struct GNUNET_TESTBED_PeerReconfigureMessage *msg)
+{
+  return GNUNET_OK; /* checked later */
+}
+
+
+/**
+ * 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.
  *
  * Should stop the peer asyncronously, destroy it and create it again with the
  * new configuration.
  *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_peer_reconfigure (void *cls, struct GNUNET_SERVER_Client *client,
-                             const struct GNUNET_MessageHeader *message)
+handle_peer_reconfigure (void *cls,
+                         const struct GNUNET_TESTBED_PeerReconfigureMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_PeerReconfigureMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
   struct Peer *peer;
   struct GNUNET_CONFIGURATION_Handle *cfg;
   struct ForwardedOperationContext *fopc;
   struct PeerReconfigureContext *prc;
   struct Peer *peer;
   struct GNUNET_CONFIGURATION_Handle *cfg;
   struct ForwardedOperationContext *fopc;
   struct PeerReconfigureContext *prc;
+  char *emsg;
   uint64_t op_id;
   uint32_t peer_id;
   uint64_t op_id;
   uint32_t peer_id;
-  uint16_t msize;
-  
-  msize = ntohs (message->size);
-  if (msize <= sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage))
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  msg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) message;
+
   peer_id = ntohl (msg->peer_id);
   op_id = GNUNET_ntohll (msg->operation_id);
   peer_id = ntohl (msg->peer_id);
   op_id = GNUNET_ntohll (msg->operation_id);
-  if (!VALID_PEER_ID (peer_id))
+  if (! VALID_PEER_ID (peer_id))
   {
     GNUNET_break (0);
   {
     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_SERVICE_client_continue (client);
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id);
     return;
   }
   peer = GST_peer_list[peer_id];
   if (GNUNET_YES == peer->is_remote)
   {
     LOG_DEBUG ("Forwarding PEER_RECONFIGURE for peer: %u\n", peer_id);
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    fopc = GNUNET_new (struct ForwardedOperationContext);
     fopc->client = client;
     fopc->operation_id = op_id;
     fopc->type = OP_PEER_RECONFIGURE;
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
     fopc->client = client;
     fopc->operation_id = op_id;
     fopc->type = OP_PEER_RECONFIGURE;
     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 =
                                                &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);
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
+                                      fopc);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
     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);
   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_SERVICE_client_continue (client);
     return;
   }
   if (GNUNET_YES == peer->destroy_flag)
   {
     GNUNET_break (0);
     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_SERVICE_client_continue (client);
     return;
   }
     return;
   }
-  cfg = GNUNET_TESTBED_extract_config_ (message);
+  cfg = GNUNET_TESTBED_extract_config_ (&msg->header);
   if (NULL == cfg)
   {
   if (NULL == cfg)
   {
-    GNUNET_break (0);    
-    GST_send_operation_fail_msg (client, op_id, "Compression error");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_break (0);
+    GST_send_operation_fail_msg (client,
+                                 op_id,
+                                 "Compression error");
+    GNUNET_SERVICE_client_continue (client);
+    return;
+  }
+  if (GNUNET_NO == peer->details.local.is_running)
+  {
+    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_SERVICE_client_continue (client);
+    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,
+                                      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_SERVICE_client_continue (client);
+    GNUNET_free (prc);
+    GNUNET_free (emsg);
     return;
   }
     return;
   }
-  prc = GNUNET_malloc (sizeof (struct PeerReconfigureContext));
   prc->cfg = cfg;
   prc->peer_id = peer_id;
   prc->op_id = op_id;
   prc->cfg = cfg;
   prc->peer_id = peer_id;
   prc->op_id = op_id;
-  prc->client = client;  
-  GNUNET_SERVER_client_keep (client);
-  GNUNET_CONTAINER_DLL_insert_tail (prc_head, prc_tail, prc);
-  GNUNET_TESTING_peer_stop_async (peer->details.local.peer, prc_stop_cb, prc);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Cleanup the context information created for managing a peer's service
- *
- * @param mctx the ManageServiceContext
- */
-static void
-cleanup_mctx (struct ManageServiceContext *mctx)
-{
-  mctx->expired = GNUNET_YES;
-  GNUNET_CONTAINER_DLL_remove (mctx_head, mctx_tail, mctx);
-  GNUNET_SERVER_client_drop (mctx->client);
-  GNUNET_ARM_disconnect_and_free (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);
+  prc->client = client;
+  GNUNET_CONTAINER_DLL_insert_tail (prc_head,
+                                    prc_tail,
+                                    prc);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
 }
 
 
@@ -948,7 +1125,7 @@ GST_free_mctxq ()
 
 
 /**
 
 
 /**
- * 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
  *
  * @param rs the request status from ARM
  * @return a string interpretation of the request status
@@ -960,23 +1137,15 @@ arm_req_string (enum GNUNET_ARM_RequestStatus rs)
   {
   case GNUNET_ARM_REQUEST_SENT_OK:
     return _("Message was sent successfully");
   {
   case GNUNET_ARM_REQUEST_SENT_OK:
     return _("Message was sent successfully");
-  case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR:
-    return _("Misconfiguration (can't connect to the ARM service)");
   case GNUNET_ARM_REQUEST_DISCONNECTED:
     return _("We disconnected from ARM before we could send a request");
   case GNUNET_ARM_REQUEST_DISCONNECTED:
     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");
   }
   return _("Unknown request status");
 }
 
 
 /**
   }
   return _("Unknown request status");
 }
 
 
 /**
- * Returns a string interpretation of the 'result'
+ * Returns a string interpretation of the @a result.
  *
  * @param result the arm result
  * @return a string interpretation
  *
  * @param result the arm result
  * @return a string interpretation
@@ -1015,17 +1184,16 @@ arm_ret_string (enum GNUNET_ARM_Result result)
  * 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,
  * 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 cls ManageServiceContext
  * @param rs status of the request
- * @param service service name
  * @param result result of the operation
  */
 static void
  * @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)
+service_manage_result_cb (void *cls,
+                          enum GNUNET_ARM_RequestStatus rs,
+                          enum GNUNET_ARM_Result result)
 {
   struct ManageServiceContext *mctx = cls;
   char *emsg;
 {
   struct ManageServiceContext *mctx = cls;
   char *emsg;
@@ -1035,8 +1203,10 @@ service_manage_result_cb (void *cls,
     return;
   if (GNUNET_ARM_REQUEST_SENT_OK != rs)
   {
     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)
     goto ret;
   }
   if (1 == mctx->start)
@@ -1047,7 +1217,9 @@ service_manage_result_cb (void *cls,
             || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) )
   {
     /* stopping a service failed */
             || (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 */
     goto ret;
   }
   /* service stopped successfully */
@@ -1059,69 +1231,81 @@ service_manage_result_cb (void *cls,
             || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) )
   {
     /* starting a service failed */
             || (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 */
     goto ret;
   }
   /* service started successfully */
-  
+
  ret:
   if (NULL != emsg)
   {
     LOG_DEBUG ("%s\n", emsg);
  ret:
   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
   }
   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);
 }
 
 
 /**
   GNUNET_free_non_null (emsg);
   cleanup_mctx (mctx);
 }
 
 
 /**
- * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message
+ * Check #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE message
  *
  *
- * @param cls NULL
- * @param client identification of client
- * @param message the actual message
+ * @param cls identification of client
+ * @param msg the actual message
+ * @return #GNUNET_OK if @a msg is well-formed
  */
  */
-void
-GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
-                                const struct GNUNET_MessageHeader *message)
+int
+check_manage_peer_service (void *cls,
+                           const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg;
-  const char* service;
-  struct Peer *peer;
-  char *emsg;
-  struct GNUNET_ARM_Handle *ah;
-  struct ManageServiceContext *mctx;
-  struct ForwardedOperationContext *fopc;
-  uint64_t op_id;
-  uint32_t peer_id;
   uint16_t msize;
   uint16_t msize;
-  
+  const char* service;
 
 
-  msize = ntohs (message->size);
-  if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage))
-  {
-    GNUNET_break_op (0);  
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message;
-  service = (const char *) &msg[1];  
+  msize = ntohs (msg->header.size);
+  service = (const char *) &msg[1];
   if ('\0' != service[msize - sizeof
                       (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1])
   {
     GNUNET_break_op (0);
   if ('\0' != service[msize - sizeof
                       (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1])
   {
     GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
+    return GNUNET_SYSERR;
   }
   if (1 < msg->start)
   {
     GNUNET_break_op (0);
   }
   if (1 < msg->start)
   {
     GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;    
+    return GNUNET_SYSERR;
   }
   }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE messages
+ *
+ * @param cls identification of client
+ * @param msg the actual message
+ */
+void
+handle_manage_peer_service (void *cls,
+                            const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg)
+{
+  struct GNUNET_SERVICE_Client *client = cls;
+  const char* service;
+  struct Peer *peer;
+  char *emsg;
+  struct GNUNET_ARM_Handle *ah;
+  struct ManageServiceContext *mctx;
+  struct ForwardedOperationContext *fopc;
+  uint64_t op_id;
+  uint32_t peer_id;
+
+  service = (const char *) &msg[1];
   peer_id = ntohl (msg->peer_id);
   op_id = GNUNET_ntohll (msg->operation_id);
   LOG_DEBUG ("Received request to manage service %s on peer %u\n",
   peer_id = ntohl (msg->peer_id);
   op_id = GNUNET_ntohll (msg->operation_id);
   LOG_DEBUG ("Received request to manage service %s on peer %u\n",
@@ -1142,8 +1326,7 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
   if (GNUNET_YES == peer->is_remote)
   {
     /* Forward the destory message to sub controller */
   if (GNUNET_YES == peer->is_remote)
   {
     /* Forward the destory message to sub controller */
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    fopc = GNUNET_new (struct ForwardedOperationContext);
     fopc->client = client;
     fopc->cls = peer;
     fopc->type = OP_MANAGE_SERVICE;
     fopc->client = client;
     fopc->cls = peer;
     fopc->type = OP_MANAGE_SERVICE;
@@ -1151,16 +1334,25 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
     fopc->opc =
         GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
                                                slave->controller,
     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 =
                                                &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);
                                       fopc);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    GNUNET_SERVICE_client_continue (client);
     return;
   }
     return;
   }
+  if (GNUNET_NO == peer->details.local.is_running)
+  {
+    emsg = GNUNET_strdup ("Peer not running\n");
+    goto err_ret;
+  }
   if ((0 != peer->reference_cnt)
       && ( (0 == strcasecmp ("core", service))
            || (0 == strcasecmp ("transport", service)) )  )
   if ((0 != peer->reference_cnt)
       && ( (0 == strcasecmp ("core", service))
            || (0 == strcasecmp ("transport", service)) )  )
@@ -1178,34 +1370,35 @@ GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
                      peer_id);
     goto err_ret;
   }
                      peer_id);
     goto err_ret;
   }
-  mctx = GNUNET_malloc (sizeof (struct ManageServiceContext));
+  mctx = GNUNET_new (struct ManageServiceContext);
   mctx->peer = peer;
   peer->reference_cnt++;
   mctx->op_id = op_id;
   mctx->ah = ah;
   mctx->peer = peer;
   peer->reference_cnt++;
   mctx->op_id = op_id;
   mctx->ah = ah;
-  GNUNET_SERVER_client_keep (client);
   mctx->client = client;
   mctx->start = msg->start;
   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)
   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,
                                       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,
                                       mctx);
   else
     GNUNET_ARM_request_service_stop (mctx->ah, service,
-                                     GST_timeout,
-                                     service_manage_result_cb,
+                                     &service_manage_result_cb,
                                      mctx);
                                      mctx);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVICE_client_continue (client);
   return;
 
  err_ret:
   LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
   GST_send_operation_fail_msg (client, op_id, emsg);
   GNUNET_free (emsg);
   return;
 
  err_ret:
   LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg);
   GST_send_operation_fail_msg (client, op_id, emsg);
   GNUNET_free (emsg);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVICE_client_continue (client);
 }
 
 
 }
 
 
@@ -1238,7 +1431,7 @@ GST_destroy_peers ()
   {
     peer = GST_peer_list[id];
     if (NULL == peer)
   {
     peer = GST_peer_list[id];
     if (NULL == peer)
-      continue;    
+      continue;
     if (GNUNET_NO == peer->is_remote)
     {
       if (GNUNET_YES == peer->details.local.is_running)
     if (GNUNET_NO == peer->is_remote)
     {
       if (GNUNET_YES == peer->details.local.is_running)
@@ -1254,38 +1447,6 @@ GST_destroy_peers ()
 }
 
 
 }
 
 
-/**
- * Task run upon timeout of forwarded SHUTDOWN_PEERS operation
- *
- * @param cls the ForwardedOperationContext
- * @param tc the scheduler task context
- */
-static void
-shutdown_peers_timeout_cb (void *cls,
-                           const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ForwardedOperationContext *fo_ctxt = cls;
-  struct HandlerContext_ShutdownPeers *hc;
-
-  fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  hc = fo_ctxt->cls;
-  hc->timeout = GNUNET_YES;
-  GNUNET_assert (0 < hc->nslaves);
-  hc->nslaves--;
-  if (0 == hc->nslaves)
-  {
-    GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id,
-                                 "Timeout at a slave controller");
-    GNUNET_free (hc);
-    hc = NULL;
-  }
-  GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc);  
-  GNUNET_SERVER_client_drop (fo_ctxt->client);
-  GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt);
-  GNUNET_free (fo_ctxt);
-}
-
-
 /**
  * The reply msg handler forwarded SHUTDOWN_PEERS operation.  Checks if a
  * success reply is received from all clients and then sends the success message
 /**
  * The reply msg handler forwarded SHUTDOWN_PEERS operation.  Checks if a
  * success reply is received from all clients and then sends the success message
@@ -1300,51 +1461,49 @@ shutdown_peers_reply_cb (void *cls,
 {
   struct ForwardedOperationContext *fo_ctxt = cls;
   struct HandlerContext_ShutdownPeers *hc;
 {
   struct ForwardedOperationContext *fo_ctxt = cls;
   struct HandlerContext_ShutdownPeers *hc;
-  
+
   hc = fo_ctxt->cls;
   hc = fo_ctxt->cls;
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != fo_ctxt->timeout_task);
-  GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task);
-  fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK;
   GNUNET_assert (0 < hc->nslaves);
   hc->nslaves--;
   GNUNET_assert (0 < hc->nslaves);
   hc->nslaves--;
-  if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != 
+  if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS !=
       ntohs (msg->type))
     hc->timeout = GNUNET_YES;
   if (0 == hc->nslaves)
   {
     if (GNUNET_YES == hc->timeout)
       ntohs (msg->type))
     hc->timeout = GNUNET_YES;
   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
                                    "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_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);
 }
 
 
 /**
   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
- * @param message the actual message
+ * @param cls identification of the client
+ * @param msg the actual message
  */
 void
  */
 void
-GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
-                           const struct GNUNET_MessageHeader *message)
+handle_shutdown_peers (void *cls,
+                       const struct GNUNET_TESTBED_ShutdownPeersMessage *msg)
 {
 {
-  const struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
+  struct GNUNET_SERVICE_Client *client = cls;
   struct HandlerContext_ShutdownPeers *hc;
   struct Slave *slave;
   struct ForwardedOperationContext *fo_ctxt;
   uint64_t op_id;
   unsigned int cnt;
 
   struct HandlerContext_ShutdownPeers *hc;
   struct Slave *slave;
   struct ForwardedOperationContext *fo_ctxt;
   uint64_t op_id;
   unsigned int cnt;
 
-  msg = (const struct GNUNET_TESTBED_ShutdownPeersMessage *) message;
   LOG_DEBUG ("Received SHUTDOWN_PEERS\n");
     /* Stop and destroy all peers */
   GST_free_mctxq ();
   LOG_DEBUG ("Received SHUTDOWN_PEERS\n");
     /* Stop and destroy all peers */
   GST_free_mctxq ();
@@ -1353,7 +1512,7 @@ GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
   GST_clear_fopcq ();
   /* Forward to all slaves which we have started */
   op_id = GNUNET_ntohll (msg->operation_id);
   GST_clear_fopcq ();
   /* Forward to all slaves which we have started */
   op_id = GNUNET_ntohll (msg->operation_id);
-  hc = GNUNET_malloc (sizeof (struct HandlerContext_ShutdownPeers));
+  hc = GNUNET_new (struct HandlerContext_ShutdownPeers);
   /* FIXME: have a better implementation where we track which slaves are
      started by this controller */
   for (cnt = 0; cnt < GST_slave_list_size; cnt++)
   /* FIXME: have a better implementation where we track which slaves are
      started by this controller */
   for (cnt = 0; cnt < GST_slave_list_size; cnt++)
@@ -1365,8 +1524,7 @@ GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
       continue;
     LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n");
     hc->nslaves++;
       continue;
     LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n");
     hc->nslaves++;
-    fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
+    fo_ctxt = GNUNET_new (struct ForwardedOperationContext);
     fo_ctxt->client = client;
     fo_ctxt->operation_id = op_id;
     fo_ctxt->cls = hc;
     fo_ctxt->client = client;
     fo_ctxt->operation_id = op_id;
     fo_ctxt->cls = hc;
@@ -1377,17 +1535,17 @@ GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
                                                &msg->header,
                                                shutdown_peers_reply_cb,
                                                fo_ctxt);
                                                &msg->header,
                                                shutdown_peers_reply_cb,
                                                fo_ctxt);
-    fo_ctxt->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, &shutdown_peers_timeout_cb,
+    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head,
+                                      fopcq_tail,
                                       fo_ctxt);
                                       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)
   {
   }
   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_free (hc);
   }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);  
+  GNUNET_SERVICE_client_continue (client);
 }
 }