Fix regression caused by SVN 34522
[oweals/gnunet.git] / src / testbed / gnunet-service-testbed.c
index 4195ee3663be1caaba98f1ccf40a1cfa40e77b6d..a1d6aed0951bb5bae4ccea565e876a18799a438a 100644 (file)
@@ -4,7 +4,7 @@
 
   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
  */
 
 #include "gnunet-service-testbed.h"
  */
 
 #include "gnunet-service-testbed.h"
-#include "gnunet_arm_service.h"
-
-#include <zlib.h>
-
-
-/**
- * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler
- */
-struct HandlerContext_ShutdownPeers
-{
-  /**
-   * The number of slave we expect to hear from since we forwarded the
-   * GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them
-   */
-  unsigned int nslaves;
-
-  /**
-   * Did we observe a timeout with respect to this operation at any of the
-   * slaves
-   */
-  int timeout;
-};
-
+#include "gnunet-service-testbed_barriers.h"
+#include "gnunet-service-testbed_connectionpool.h"
 
 /***********/
 /* Globals */
 
 /***********/
 /* Globals */
@@ -56,23 +35,13 @@ struct HandlerContext_ShutdownPeers
 /**
  * Our configuration
  */
 /**
  * Our configuration
  */
-struct GNUNET_CONFIGURATION_Handle *our_config;
+struct GNUNET_CONFIGURATION_Handle *GST_config;
 
 /**
  * The master context; generated with the first INIT message
  */
 struct Context *GST_context;
 
 
 /**
  * The master context; generated with the first INIT message
  */
 struct Context *GST_context;
 
-/**
- * A list of directly linked neighbours
- */
-struct Slave **GST_slave_list;
-
-/**
- * A list of peers we know about
- */
-struct Peer **GST_peer_list;
-
 /**
  * Array of hosts
  */
 /**
  * Array of hosts
  */
@@ -103,11 +72,6 @@ const struct GNUNET_TIME_Relative GST_timeout;
  */
 unsigned int GST_host_list_size;
 
  */
 unsigned int GST_host_list_size;
 
-/**
- * The size of directly linked neighbours list
- */
-unsigned int GST_slave_list_size;
-
 /**
  * The size of the peer list
  */
 /**
  * The size of the peer list
  */
@@ -154,16 +118,6 @@ static char *hostname;
  */
 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
 
  */
 static struct GNUNET_SERVER_TransmitHandle *transmit_handle;
 
-/**
- * The head for the LCF queue
- */
-static struct LCFContextQueue *lcfq_head;
-
-/**
- * The tail for the LCF queue
- */
-static struct LCFContextQueue *lcfq_tail;
-
 /**
  * The message queue head
  */
 /**
  * The message queue head
  */
@@ -174,30 +128,6 @@ static struct MessageQueue *mq_head;
  */
 static struct MessageQueue *mq_tail;
 
  */
 static struct MessageQueue *mq_tail;
 
-/**
- * The hashmap of shared services
- */
-static struct GNUNET_CONTAINER_MultiHashMap *ss_map;
-
-/**
- * A list of routes
- */
-static struct Route **route_list;
-
-/**
- * The event mask for the events we listen from sub-controllers
- */
-static uint64_t event_mask;
-
-/**
- * The size of the route list
- */
-static unsigned int route_list_size;
-
-/**
- * The lcf_task handle
- */
-static GNUNET_SCHEDULER_TaskIdentifier lcf_proc_task_id;
 
 /**
  * The shutdown task handle
 
 /**
  * The shutdown task handle
@@ -261,7 +191,7 @@ GST_queue_message (struct GNUNET_SERVER_Client *client,
   size = ntohs (msg->size);
   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
   size = ntohs (msg->size);
   GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
                  (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
-  mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
+  mq_entry = GNUNET_new (struct MessageQueue);
   mq_entry->msg = msg;
   mq_entry->client = client;
   GNUNET_SERVER_client_keep (client);
   mq_entry->msg = msg;
   mq_entry->client = client;
   GNUNET_SERVER_client_keep (client);
@@ -276,30 +206,6 @@ GST_queue_message (struct GNUNET_SERVER_Client *client,
 }
 
 
 }
 
 
-/**
- * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow()
- * several times we call it only once. The array is also made to grow in steps
- * of LIST_GROW_STEP.
- *
- * @param ptr the array pointer to grow
- * @param size the size of array
- * @param accommodate_size the size which the array has to accommdate; after
- *          this call the array will be big enough to accommdate sizes upto
- *          accommodate_size
- */
-#define array_grow_large_enough(ptr, size, accommodate_size) \
-  do                                                                    \
-  {                                                                     \
-    unsigned int growth_size;                                           \
-    GNUNET_assert (size <= accommodate_size);                            \
-    growth_size = size;                                                 \
-    while (growth_size <= accommodate_size)                             \
-      growth_size += LIST_GROW_STEP;                                    \
-    GNUNET_array_grow (ptr, size, growth_size);                         \
-    GNUNET_assert (size > accommodate_size);                            \
-  } while (0)
-
-
 /**
  * Function to add a host to the current list of known hosts
  *
 /**
  * Function to add a host to the current list of known hosts
  *
@@ -314,7 +220,7 @@ host_list_add (struct GNUNET_TESTBED_Host *host)
 
   host_id = GNUNET_TESTBED_host_get_id_ (host);
   if (GST_host_list_size <= host_id)
 
   host_id = GNUNET_TESTBED_host_get_id_ (host);
   if (GST_host_list_size <= host_id)
-    array_grow_large_enough (GST_host_list, GST_host_list_size, host_id);
+    GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id);
   if (NULL != GST_host_list[host_id])
   {
     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
   if (NULL != GST_host_list[host_id])
   {
     LOG_DEBUG ("A host with id: %u already exists\n", host_id);
@@ -325,122 +231,6 @@ host_list_add (struct GNUNET_TESTBED_Host *host)
 }
 
 
 }
 
 
-/**
- * Adds a route to the route list
- *
- * @param route the route to add
- */
-static void
-route_list_add (struct Route *route)
-{
-  if (route->dest >= route_list_size)
-    array_grow_large_enough (route_list, route_list_size, route->dest);
-  GNUNET_assert (NULL == route_list[route->dest]);
-  route_list[route->dest] = route;
-}
-
-
-/**
- * Adds a slave to the slave array
- *
- * @param slave the slave controller to add
- */
-static void
-slave_list_add (struct Slave *slave)
-{
-  if (slave->host_id >= GST_slave_list_size)
-    array_grow_large_enough (GST_slave_list, GST_slave_list_size,
-                             slave->host_id);
-  GNUNET_assert (NULL == GST_slave_list[slave->host_id]);
-  GST_slave_list[slave->host_id] = slave;
-}
-
-
-/**
- * Adds a peer to the peer array
- *
- * @param peer the peer to add
- */
-static void
-peer_list_add (struct Peer *peer)
-{
-  if (peer->id >= GST_peer_list_size)
-    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;
-}
-
-
-/**
- * Removes a the give peer from the peer array
- *
- * @param peer the peer to be removed
- */
-static void
-peer_list_remove (struct Peer *peer)
-{
-  unsigned int orig_size;
-  uint32_t id;
-
-  GST_peer_list[peer->id] = NULL;
-  orig_size = GST_peer_list_size;
-  while (GST_peer_list_size >= LIST_GROW_STEP)
-  {
-    for (id = GST_peer_list_size - 1;
-         (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX);
-         id--)
-      if (NULL != GST_peer_list[id])
-        break;
-    if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1))
-      break;
-    GST_peer_list_size -= LIST_GROW_STEP;
-  }
-  if (orig_size == GST_peer_list_size)
-    return;
-  GST_peer_list =
-      GNUNET_realloc (GST_peer_list,
-                      sizeof (struct Peer *) * GST_peer_list_size);
-}
-
-
-/**
- * Finds the route with directly connected host as destination through which
- * the destination host can be reached
- *
- * @param host_id the id of the destination host
- * @return the route with directly connected destination host; NULL if no route
- *           is found
- */
-struct Route *
-GST_find_dest_route (uint32_t host_id)
-{
-  struct Route *route;
-
-  if (route_list_size <= host_id)
-    return NULL;
-  while (NULL != (route = route_list[host_id]))
-  {
-    if (route->thru == GST_context->host_id)
-      break;
-    host_id = route->thru;
-  }
-  return route;
-}
-
-
-/**
- * Routes message to a host given its host_id
- *
- * @param host_id the id of the destination host
- * @param msg the message to be routed
- */
-static void
-route_message (uint32_t host_id, const struct GNUNET_MessageHeader *msg)
-{
-  GNUNET_break (0);
-}
-
-
 /**
  * Send operation failure message to client
  *
 /**
  * Send operation failure message to client
  *
@@ -476,9 +266,9 @@ GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client,
  * @param client the client to send the message to
  * @param operation_id the id of the operation which was successful
  */
  * @param client the client to send the message to
  * @param operation_id the id of the operation which was successful
  */
-static void
-send_operation_success_msg (struct GNUNET_SERVER_Client *client,
-                            uint64_t operation_id)
+void
+GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client,
+                                uint64_t operation_id)
 {
   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
   uint16_t msize;
 {
   struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg;
   uint16_t msize;
@@ -493,61 +283,6 @@ send_operation_success_msg (struct GNUNET_SERVER_Client *client,
   GST_queue_message (client, &msg->header);
 }
 
   GST_queue_message (client, &msg->header);
 }
 
-
-/**
- * Function to send a failure reponse for controller link operation
- *
- * @param client the client to send the message to
- * @param operation_id the operation ID of the controller link request
- * @param cfg the configuration with which the delegated controller is started.
- *          Can be NULL if the delegated controller is not started but just
- *          linked to.
- * @param emsg set to an error message explaining why the controller link
- *          failed.  Setting this to NULL signifies success.  !This should be
- *          NULL if cfg is set!
- */
-static void
-send_controller_link_response (struct GNUNET_SERVER_Client *client,
-                               uint64_t operation_id,
-                               const struct GNUNET_CONFIGURATION_Handle
-                               *cfg,
-                               const char *emsg)
-{
-  struct GNUNET_TESTBED_ControllerLinkResponse *msg;
-  char *xconfig;
-  size_t config_size;
-  size_t xconfig_size;  
-  uint16_t msize;
-
-  GNUNET_assert ((NULL == cfg) || (NULL == emsg));
-  xconfig = NULL;
-  xconfig_size = 0;
-  config_size = 0;
-  msize = sizeof (struct GNUNET_TESTBED_ControllerLinkResponse);
-  if (NULL != cfg)
-  {
-    xconfig = GNUNET_TESTBED_compress_cfg_ (cfg,
-                                            &config_size,
-                                            &xconfig_size);
-    msize += xconfig_size;
-  }
-  if (NULL != emsg)
-    msize += strlen (emsg);
-  msg = GNUNET_malloc (msize);
-  msg->header.type = htons
-      (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT);
-  msg->header.size = htons (msize);
-  if (NULL == emsg)
-    msg->success = htons (GNUNET_YES);
-  msg->operation_id = GNUNET_htonll (operation_id);
-  msg->config_size = htons ((uint16_t) config_size);
-  if (NULL != xconfig)
-    memcpy (&msg[1], xconfig, xconfig_size);
-  if (NULL != emsg)
-    memcpy (&msg[1], emsg, strlen (emsg));
-  GST_queue_message (client, &msg->header);
-}
-
 /**
  * Callback which will be called after a host registration succeeded or failed
  *
 /**
  * Callback which will be called after a host registration succeeded or failed
  *
@@ -629,7 +364,7 @@ GST_queue_host_registration (struct Slave *slave,
        "Queueing host registration for host %u at %u\n",
        GNUNET_TESTBED_host_get_id_ (host),
        GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
        "Queueing host registration for host %u at %u\n",
        GNUNET_TESTBED_host_get_id_ (host),
        GNUNET_TESTBED_host_get_id_ (GST_host_list[slave->host_id]));
-  hr = GNUNET_malloc (sizeof (struct HostRegistration));
+  hr = GNUNET_new (struct HostRegistration);
   hr->cb = cb;
   hr->cb_cls = cb_cls;
   hr->host = host;
   hr->cb = cb;
   hr->cb_cls = cb_cls;
   hr->host = host;
@@ -640,55 +375,6 @@ GST_queue_host_registration (struct Slave *slave,
 }
 
 
 }
 
 
-/**
- * The  Link Controller forwarding task
- *
- * @param cls the LCFContext
- * @param tc the Task context from scheduler
- */
-static void
-lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Completion callback for host registrations while forwarding Link Controller messages
- *
- * @param cls the LCFContext
- * @param emsg the error message; NULL if host registration is successful
- */
-static void
-lcf_proc_cc (void *cls, const char *emsg)
-{
-  struct LCFContext *lcf = cls;
-
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
-  switch (lcf->state)
-  {
-  case INIT:
-    if (NULL != emsg)
-      goto registration_error;
-    lcf->state = DELEGATED_HOST_REGISTERED;
-    lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-    break;
-  case DELEGATED_HOST_REGISTERED:
-    if (NULL != emsg)
-      goto registration_error;
-    lcf->state = SLAVE_HOST_REGISTERED;
-    lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-    break;
-  default:
-    GNUNET_assert (0);          /* Shouldn't reach here */
-  }
-  return;
-
-registration_error:
-  LOG (GNUNET_ERROR_TYPE_WARNING, "Host registration failed with message: %s\n",
-       emsg);
-  lcf->state = FINISHED;
-  lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-}
-
-
 /**
  * Callback to relay the reply msg of a forwarded operation back to the client
  *
 /**
  * Callback to relay the reply msg of a forwarded operation back to the client
  *
@@ -738,240 +424,53 @@ GST_forwarded_operation_timeout (void *cls,
 
 
 /**
 
 
 /**
- * The  Link Controller forwarding task
- *
- * @param cls the LCFContext
- * @param tc the Task context from scheduler
- */
-static void
-lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Task to free resources when forwarded link controllers has been timedout
- *
- * @param cls the LCFContext
- * @param tc the task context from scheduler
- */
-static void
-lcf_forwarded_operation_timeout (void *cls,
-                                 const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct LCFContext *lcf = cls;
-
-  lcf->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  //  GST_forwarded_operation_timeout (lcf->fopc, tc);
-  LOG (GNUNET_ERROR_TYPE_WARNING,
-       "A forwarded controller link operation has timed out\n");
-  send_controller_link_response (lcf->client, lcf->operation_id, NULL,
-                                 "A forwarded controller link operation has "
-                                 "timed out\n");
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
-  lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-}
-
-
-/**
- * The  Link Controller forwarding task
+ * Parse service sharing specification line.
+ * Format is "[<service:share>] [<service:share>] ..."
  *
  *
- * @param cls the LCFContext
- * @param tc the Task context from scheduler
+ * @param ss_str the spec string to be parsed
+ * @param cfg the configuration to use for shared services
+ * @return an array suitable to pass to GNUNET_TESTING_system_create().  NULL
+ *           upon empty service sharing specification.
  */
  */
-static void
-lcf_proc_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+static struct GNUNET_TESTING_SharedService *
+parse_shared_services (char *ss_str, struct GNUNET_CONFIGURATION_Handle *cfg)
 {
 {
-  struct LCFContext *lcf = cls;
-  struct LCFContextQueue *lcfq;
-
-  lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
-  switch (lcf->state)
-  {
-  case INIT:
-    if (GNUNET_NO ==
-        GNUNET_TESTBED_is_host_registered_ (GST_host_list
-                                            [lcf->delegated_host_id],
-                                            lcf->gateway->controller))
-    {
-      GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
-                                   GST_host_list[lcf->delegated_host_id]);
-    }
-    else
-    {
-      lcf->state = DELEGATED_HOST_REGISTERED;
-      lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-    }
-    break;
-  case DELEGATED_HOST_REGISTERED:
-    if (GNUNET_NO ==
-        GNUNET_TESTBED_is_host_registered_ (GST_host_list[lcf->slave_host_id],
-                                            lcf->gateway->controller))
-    {
-      GST_queue_host_registration (lcf->gateway, lcf_proc_cc, lcf,
-                                   GST_host_list[lcf->slave_host_id]);
-    }
-    else
-    {
-      lcf->state = SLAVE_HOST_REGISTERED;
-      lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-    }
-    break;
-  case SLAVE_HOST_REGISTERED:
-    lcf->op = GNUNET_TESTBED_controller_link (lcf,
-                                              lcf->gateway->controller,
-                                              GST_host_list[lcf->delegated_host_id],
-                                              GST_host_list[lcf->slave_host_id],
-                                              NULL,
-                                              lcf->is_subordinate);
-    lcf->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, &lcf_forwarded_operation_timeout,
-                                      lcf);
-    lcf->state = FINISHED;
-    break;
-  case FINISHED:
-    lcfq = lcfq_head;
-    GNUNET_assert (lcfq->lcf == lcf);
-    GNUNET_assert (NULL != lcf->cfg);
-    GNUNET_CONFIGURATION_destroy (lcf->cfg);
-    GNUNET_SERVER_client_drop (lcf->client);
-    GNUNET_TESTBED_operation_done (lcf->op);
-    GNUNET_free (lcf);
-    GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
-    GNUNET_free (lcfq);
-    if (NULL != lcfq_head)
-      lcf_proc_task_id =
-          GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq_head->lcf);
-  }
-}
-
+  struct GNUNET_TESTING_SharedService ss;
+  struct GNUNET_TESTING_SharedService *slist;
+  char service[256];
+  char *arg;
+  unsigned int n;
+#define GROW_SS                                 \
+  do {                                          \
+    GNUNET_array_grow (slist, n, n+1);                                  \
+    (void) memcpy (&slist[n - 1], &ss,                                  \
+                   sizeof (struct GNUNET_TESTING_SharedService));       \
+  } while (0)
 
 
-/**
- * Callback for event from slave controllers
- *
- * @param cls struct Slave *
- * @param event information about the event
- */
-static void
-slave_event_callback (void *cls,
-                      const struct GNUNET_TESTBED_EventInformation *event)
-{
-  struct RegisteredHostContext *rhc;
-  struct LCFContext *lcf;
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  struct GNUNET_TESTBED_Operation *old_op;
-
-  /* We currently only get here when working on RegisteredHostContexts and
-     LCFContexts */
-  GNUNET_assert (GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type);
-  rhc = event->op_cls;
-  if (CLOSURE_TYPE_RHC == rhc->type)
+  slist = NULL;
+  n = 0;
+  ss.cfg = cfg;
+  for (; NULL != (arg = strtok (ss_str, " ")); ss_str = NULL)
   {
   {
-    GNUNET_assert (rhc->sub_op == event->op);
-    switch (rhc->state)
+    ss.service = NULL;
+    ss.share = 0;
+    if (2 != sscanf (arg, "%255[^:]:%u", service, &ss.share))
     {
     {
-    case RHC_GET_CFG:
-      cfg = event->details.operation_finished.generic;
-      old_op = rhc->sub_op;
-      rhc->state = RHC_LINK;
-      rhc->sub_op =
-          GNUNET_TESTBED_controller_link (rhc, rhc->gateway->controller,
-                                          rhc->reg_host, rhc->host, cfg,
-                                          GNUNET_NO);
-      GNUNET_TESTBED_operation_done (old_op);
-      break;
-    case RHC_LINK:
-      LOG_DEBUG ("OL: Linking controllers successfull\n");
-      GNUNET_TESTBED_operation_done (rhc->sub_op);
-      rhc->sub_op = NULL;
-      rhc->state = RHC_OL_CONNECT;
-      GST_process_next_focc (rhc);
-      break;
-    default:
-      GNUNET_assert (0);
+      LOG (GNUNET_ERROR_TYPE_WARNING, "Ignoring shared service spec: %s", arg);
+      continue;
     }
     }
-    return;
-  }
-  lcf = event->op_cls;
-  if (CLOSURE_TYPE_LCF == lcf->type)
-  {    
-    GNUNET_assert (lcf->op == event->op);
-    GNUNET_assert (FINISHED == lcf->state);
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != lcf->timeout_task);
-    GNUNET_SCHEDULER_cancel (lcf->timeout_task);
-    if (NULL == event->details.operation_finished.emsg)
-      send_controller_link_response (lcf->client, lcf->operation_id,
-                                     GNUNET_TESTBED_host_get_cfg_ 
-                                     (GST_host_list[lcf->delegated_host_id]),
-                                     NULL);
-    else
-      send_controller_link_response (lcf->client, lcf->operation_id,
-                                     NULL,
-                                     event->details.operation_finished.emsg);
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
-    lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcf);
-    return;
-  }
-  GNUNET_assert (0);
-}
-
-
-/**
- * Callback to signal successfull startup of the controller process
- *
- * @param cls the handle to the slave whose status is to be found here
- * @param cfg the configuration with which the controller has been started;
- *          NULL if status is not GNUNET_OK
- * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
- *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
- */
-static void
-slave_status_callback (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
-                       int status)
-{
-  struct Slave *slave = cls;
-  struct LinkControllersContext *lcc;
-
-  lcc = slave->lcc;
-  if (GNUNET_SYSERR == status)
-  {
-    slave->controller_proc = NULL;
-    GST_slave_list[slave->host_id] = NULL;
-    GNUNET_free (slave);
-    slave = NULL;
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Unexpected slave shutdown\n");
-    GNUNET_SCHEDULER_shutdown ();       /* We too shutdown */
-    goto clean_lcc;
+    LOG_DEBUG ("Will be sharing %s service among %u peers\n", service, ss.share);
+    ss.service = GNUNET_strdup (service);
+    GROW_SS;
   }
   }
-  slave->controller =
-      GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id],
-                                         event_mask, &slave_event_callback,
-                                         slave);
-  if (NULL != slave->controller)
+  if (NULL != slist)
   {
   {
-    send_controller_link_response (lcc->client, lcc->operation_id, cfg, NULL);
-  }
-  else
-  {
-    send_controller_link_response (lcc->client, lcc->operation_id, NULL,
-                                   "Could not connect to delegated controller");
-    GNUNET_TESTBED_controller_stop (slave->controller_proc);
-    GST_slave_list[slave->host_id] = NULL;
-    GNUNET_free (slave);
-    slave = NULL;
-  }
-
-clean_lcc:
-  if (NULL != lcc)
-  {
-    if (NULL != lcc->client)
-    {
-      GNUNET_SERVER_receive_done (lcc->client, GNUNET_OK);
-      GNUNET_SERVER_client_drop (lcc->client);
-      lcc->client = NULL;
-    }
-    GNUNET_free (lcc);
+    /* Add trailing NULL block */
+    (void) memset (&ss, 0, sizeof (struct GNUNET_TESTING_SharedService));
+    GROW_SS;
   }
   }
-  if (NULL != slave)
-    slave->lcc = NULL;
+  return slist;
+#undef GROW_SS
 }
 
 
 }
 
 
@@ -989,6 +488,9 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
   const struct GNUNET_TESTBED_InitMessage *msg;
   struct GNUNET_TESTBED_Host *host;
   const char *controller_hostname;
   const struct GNUNET_TESTBED_InitMessage *msg;
   struct GNUNET_TESTBED_Host *host;
   const char *controller_hostname;
+  char *ss_str;
+  struct GNUNET_TESTING_SharedService *ss;
+  unsigned int cnt;
   uint16_t msize;
 
   if (NULL != GST_context)
   uint16_t msize;
 
   if (NULL != GST_context)
@@ -1013,7 +515,17 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
     return;
   }
-  GST_context = GNUNET_malloc (sizeof (struct Context));
+  ss_str = NULL;
+  ss = NULL;
+  if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (GST_config, "TESTBED",
+                                                          "SHARED_SERVICES",
+                                                          &ss_str))
+  {
+    ss = parse_shared_services (ss_str, GST_config);
+    GNUNET_free (ss_str);
+    ss_str = NULL;
+  }
+  GST_context = GNUNET_new (struct Context);
   GNUNET_SERVER_client_keep (client);
   GST_context->client = client;
   GST_context->host_id = ntohl (msg->host_id);
   GNUNET_SERVER_client_keep (client);
   GST_context->client = client;
   GST_context->host_id = ntohl (msg->host_id);
@@ -1021,11 +533,21 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
   LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip);
   GST_context->system =
       GNUNET_TESTING_system_create ("testbed", GST_context->master_ip,
   LOG_DEBUG ("Our IP: %s\n", GST_context->master_ip);
   GST_context->system =
       GNUNET_TESTING_system_create ("testbed", GST_context->master_ip,
-                                    hostname);
+                                    hostname, ss);
+  if (NULL != ss)
+  {
+    for (cnt = 0; NULL != ss[cnt].service; cnt++)
+    {
+      ss_str = (char *) ss[cnt].service;
+      GNUNET_free (ss_str);
+    }
+    GNUNET_free (ss);
+    ss = NULL;
+  }
   host =
       GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
                                           GST_context->master_ip, NULL,
   host =
       GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
                                           GST_context->master_ip, NULL,
-                                          our_config, 0);
+                                          GST_config, 0);
   host_list_add (host);
   LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
   host_list_add (host);
   LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id);
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -1068,7 +590,7 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
   username_length = ntohs (msg->username_length);
   hostname_length = ntohs (msg->hostname_length);
   /* msg must contain hostname */
   username_length = ntohs (msg->username_length);
   hostname_length = ntohs (msg->hostname_length);
   /* msg must contain hostname */
-  if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) + 
+  if ((msize <= (sizeof (struct GNUNET_TESTBED_AddHostMessage) +
                  username_length))
       || (0 == hostname_length))
   {
                  username_length))
       || (0 == hostname_length))
   {
@@ -1095,7 +617,6 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
   }
   hostname = GNUNET_malloc (hostname_length + 1);
   strncpy (hostname, ptr, hostname_length);
   }
   hostname = GNUNET_malloc (hostname_length + 1);
   strncpy (hostname, ptr, hostname_length);
-  ptr += hostname_length;
   if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message)))
   {
     GNUNET_free_non_null (username);
   if (NULL == (host_cfg = GNUNET_TESTBED_extract_config_ (message)))
   {
     GNUNET_free_non_null (username);
@@ -1150,825 +671,36 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
 
 
 /**
 
 
 /**
- * Iterator over hash map entries.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-int
-ss_exists_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
-{
-  struct SharedService *queried_ss = cls;
-  struct SharedService *ss = value;
-
-  if (0 == strcmp (ss->name, queried_ss->name))
-    return GNUNET_NO;
-  else
-    return GNUNET_YES;
-}
-
-
-/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST messages
+ * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
  *
  * @param cls NULL
  * @param client identification of the client
  * @param message the actual message
  */
 static void
  *
  * @param cls NULL
  * @param client identification of the client
  * @param message the actual message
  */
 static void
-handle_configure_shared_service (void *cls, struct GNUNET_SERVER_Client *client,
-                                 const struct GNUNET_MessageHeader *message)
+handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
+                         const struct GNUNET_MessageHeader *message)
 {
 {
-  const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
-  struct SharedService *ss;
-  char *service_name;
-  struct GNUNET_HashCode hash;
-  uint16_t msg_size;
-  uint16_t service_name_size;
-
-  msg = (const struct GNUNET_TESTBED_ConfigureSharedServiceMessage *) message;
-  msg_size = ntohs (message->size);
-  if (msg_size <= sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage))
+  struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
+  struct Slave *slave;
+  struct GNUNET_TESTBED_SlaveConfiguration *reply;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+  char *config;
+  char *xconfig;
+  size_t config_size;
+  size_t xconfig_size;
+  size_t reply_size;
+  uint64_t op_id;
+  uint32_t slave_id;
+
+  msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
+  slave_id = ntohl (msg->slave_id);
+  op_id = GNUNET_ntohll (msg->operation_id);
+  if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id]))
   {
   {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  service_name_size =
-      msg_size - sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage);
-  service_name = (char *) &msg[1];
-  if ('\0' != service_name[service_name_size - 1])
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  LOG_DEBUG ("Received service sharing request for %s, with %d peers\n",
-             service_name, ntohl (msg->num_peers));
-  if (ntohl (msg->host_id) != GST_context->host_id)
-  {
-    route_message (ntohl (msg->host_id), message);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  ss = GNUNET_malloc (sizeof (struct SharedService));
-  ss->name = strdup (service_name);
-  ss->num_shared = ntohl (msg->num_peers);
-  GNUNET_CRYPTO_hash (ss->name, service_name_size, &hash);
-  if (GNUNET_SYSERR ==
-      GNUNET_CONTAINER_multihashmap_get_multiple (ss_map, &hash,
-                                                  &ss_exists_iterator, ss))
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Service %s already configured as a shared service. "
-         "Ignoring service sharing request \n", ss->name);
-    GNUNET_free (ss->name);
-    GNUNET_free (ss);
-    return;
-  }
-  GNUNET_CONTAINER_multihashmap_put (ss_map, &hash, ss,
-                                     GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
-}
-
-
-/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS message
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client,
-                         const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_ControllerLinkRequest *msg;
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  struct LCFContextQueue *lcfq;
-  struct Route *route;
-  struct Route *new_route;
-  uint32_t delegated_host_id;
-  uint32_t slave_host_id;
-  uint16_t msize;
-
-  if (NULL == GST_context)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  msize = ntohs (message->size);
-  if (sizeof (struct GNUNET_TESTBED_ControllerLinkRequest) >= msize)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  msg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) message;
-  delegated_host_id = ntohl (msg->delegated_host_id);
-  if (delegated_host_id == GST_context->host_id)
-  {
-    GNUNET_break (0);
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Trying to link ourselves\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if ((delegated_host_id >= GST_host_list_size) ||
-      (NULL == GST_host_list[delegated_host_id]))
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING,
-         "Delegated host %u not registered with us\n", delegated_host_id);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  slave_host_id = ntohl (msg->slave_host_id);
-  if ((slave_host_id >= GST_host_list_size) ||
-      (NULL == GST_host_list[slave_host_id]))
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Slave host %u not registered with us\n",
-         slave_host_id);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if (slave_host_id == delegated_host_id)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Slave and delegated host are same\n");
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  cfg = GNUNET_TESTBED_extract_config_ (message); /* destroy cfg here or in lcfcontext */
-  if (NULL == cfg)
-  {
-    GNUNET_break (0);         /* Configuration parsing error */
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if (slave_host_id == GST_context->host_id)    /* Link from us */
-  {
-    struct Slave *slave;
-    struct LinkControllersContext *lcc;
-
-    if ((delegated_host_id < GST_slave_list_size) &&
-        (NULL != GST_slave_list[delegated_host_id]))
-    {
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    slave = GNUNET_malloc (sizeof (struct Slave));
-    slave->host_id = delegated_host_id;
-    slave->reghost_map = GNUNET_CONTAINER_multihashmap_create (100, GNUNET_NO);
-    slave_list_add (slave);
-    if (1 != msg->is_subordinate)
-    {
-      slave->controller =
-          GNUNET_TESTBED_controller_connect (cfg, GST_host_list[slave->host_id],
-                                             event_mask, &slave_event_callback,
-                                             slave);
-      if (NULL != slave->controller)
-        send_controller_link_response (client,
-                                       GNUNET_ntohll (msg->operation_id),
-                                       NULL,
-                                       NULL);
-      else
-        send_controller_link_response (client,
-                                       GNUNET_ntohll (msg->operation_id),
-                                       NULL,
-                                       "Could not connect to delegated controller");
-      GNUNET_SERVER_receive_done (client, GNUNET_OK);
-      return;
-    }
-    lcc = GNUNET_malloc (sizeof (struct LinkControllersContext));
-    lcc->operation_id = GNUNET_ntohll (msg->operation_id);
-    GNUNET_SERVER_client_keep (client);
-    lcc->client = client;
-    slave->lcc = lcc;
-    slave->controller_proc =
-        GNUNET_TESTBED_controller_start (GST_context->master_ip,
-                                         GST_host_list[slave->host_id], cfg,
-                                         &slave_status_callback, slave);
-    GNUNET_CONFIGURATION_destroy (cfg);
-    new_route = GNUNET_malloc (sizeof (struct Route));
-    new_route->dest = delegated_host_id;
-    new_route->thru = GST_context->host_id;
-    route_list_add (new_route);
-    return;
-  }
-
-  /* Route the request */
-  if (slave_host_id >= route_list_size)
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "No route towards slave host");
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  lcfq = GNUNET_malloc (sizeof (struct LCFContextQueue));
-  lcfq->lcf = GNUNET_malloc (sizeof (struct LCFContext));
-  lcfq->lcf->type = CLOSURE_TYPE_LCF;
-  lcfq->lcf->delegated_host_id = delegated_host_id;
-  lcfq->lcf->slave_host_id = slave_host_id;
-  route = GST_find_dest_route (slave_host_id);
-  GNUNET_assert (NULL != route);        /* because we add routes carefully */
-  GNUNET_assert (route->dest < GST_slave_list_size);
-  GNUNET_assert (NULL != GST_slave_list[route->dest]);
-  lcfq->lcf->cfg = cfg;
-  lcfq->lcf->is_subordinate = msg->is_subordinate;
-  lcfq->lcf->state = INIT;
-  lcfq->lcf->operation_id = GNUNET_ntohll (msg->operation_id);
-  lcfq->lcf->gateway = GST_slave_list[route->dest];
-  GNUNET_SERVER_client_keep (client);
-  lcfq->lcf->client = client;
-  if (NULL == lcfq_head)
-  {
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
-    GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
-    lcf_proc_task_id = GNUNET_SCHEDULER_add_now (&lcf_proc_task, lcfq->lcf);
-  }
-  else
-    GNUNET_CONTAINER_DLL_insert_tail (lcfq_head, lcfq_tail, lcfq);
-  /* FIXME: Adding a new route should happen after the controllers are linked
-   * successfully */
-  if (1 != msg->is_subordinate)
-  {
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  if ((delegated_host_id < route_list_size) &&
-      (NULL != route_list[delegated_host_id]))
-  {
-    GNUNET_break_op (0);        /* Are you trying to link delegated host twice
-                                 * with is subordinate flag set to GNUNET_YES? */
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  new_route = GNUNET_malloc (sizeof (struct Route));
-  new_route->dest = delegated_host_id;
-  new_route->thru = route->dest;
-  route_list_add (new_route);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * The task to be executed if the forwarded peer create operation has been
- * timed out
- *
- * @param cls the FowardedOperationContext
- * @param tc the TaskContext from the scheduler
- */
-static void
-peer_create_forward_timeout (void *cls,
-                             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct ForwardedOperationContext *fopc = cls;
-
-  GNUNET_free (fopc->cls);
-  GST_forwarded_operation_timeout (fopc, tc);
-}
-
-
-/**
- * Callback to be called when forwarded peer create operation is successfull. We
- * have to relay the reply msg back to the client
- *
- * @param cls ForwardedOperationContext
- * @param msg the peer create success message
- */
-static void
-peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
-{
-  struct ForwardedOperationContext *fopc = cls;
-  struct Peer *remote_peer;
-
-  if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS)
-  {
-    GNUNET_assert (NULL != fopc->cls);
-    remote_peer = fopc->cls;
-    peer_list_add (remote_peer);
-  }
-  GST_forwarded_operation_reply_relay (fopc, msg);
-}
-
-
-/**
- * Function to destroy a peer
- *
- * @param peer the peer structure to destroy
- */
-void
-GST_destroy_peer (struct Peer *peer)
-{
-  GNUNET_break (0 == peer->reference_cnt);
-  if (GNUNET_YES == peer->is_remote)
-  {
-    peer_list_remove (peer);
-    GNUNET_free (peer);
-    return;
-  }
-  if (GNUNET_YES == peer->details.local.is_running)
-  {
-    GNUNET_TESTING_peer_stop (peer->details.local.peer);
-    peer->details.local.is_running = GNUNET_NO;
-  }
-  GNUNET_TESTING_peer_destroy (peer->details.local.peer);
-  GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
-  peer_list_remove (peer);
-  GNUNET_free (peer);
-}
-
-
-/**
- * Callback to be called when forwarded peer destroy operation is successfull. We
- * have to relay the reply msg back to the client
- *
- * @param cls ForwardedOperationContext
- * @param msg the peer create success message
- */
-static void
-peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg)
-{
-  struct ForwardedOperationContext *fopc = cls;
-  struct Peer *remote_peer;
-
-  if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS ==
-      ntohs (msg->type))
-  {
-    remote_peer = fopc->cls;
-    GNUNET_assert (NULL != remote_peer);
-    remote_peer->destroy_flag = GNUNET_YES;
-    if (0 == remote_peer->reference_cnt)
-      GST_destroy_peer (remote_peer);
-  }
-  GST_forwarded_operation_reply_relay (fopc, msg);
-}
-
-
-
-/**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client,
-                    const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_PeerCreateMessage *msg;
-  struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply;
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-  struct ForwardedOperationContext *fo_ctxt;
-  struct Route *route;
-  struct Peer *peer;
-  char *config;
-  size_t dest_size;
-  int ret;
-  uint32_t config_size;
-  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 (UINT32_MAX == peer_id)
-  {
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
-                                 "Cannot create peer with given ID");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  if (host_id == GST_context->host_id)
-  {
-    char *emsg;
-
-    /* We are responsible for this peer */
-    msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
-    config_size = ntohl (msg->config_size);
-    config = GNUNET_malloc (config_size);
-    dest_size = config_size;
-    if (Z_OK !=
-        (ret =
-         uncompress ((Bytef *) config, (uLongf *) & dest_size,
-                     (const Bytef *) &msg[1], (uLong) msize)))
-    {
-      GNUNET_break (0);         /* uncompression error */
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    if (config_size != dest_size)
-    {
-      GNUNET_break (0);         /* Uncompressed config size mismatch */
-      GNUNET_free (config);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    cfg = GNUNET_CONFIGURATION_create ();
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO))
-    {
-      GNUNET_break (0);         /* Configuration parsing error */
-      GNUNET_free (config);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      return;
-    }
-    GNUNET_free (config);
-    GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID",
-                                           (unsigned long long) peer_id);
-    peer = GNUNET_malloc (sizeof (struct Peer));
-    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);
-    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)
-    {
-      LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg);
-      GNUNET_free (emsg);
-      GNUNET_free (peer);
-      GNUNET_break (0);
-      GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-      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);
-    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);
-    return;
-  }
-
-  /* Forward peer create request */
-  route = GST_find_dest_route (host_id);
-  if (NULL == route)
-  {
-    GNUNET_break (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-
-  peer = GNUNET_malloc (sizeof (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;
-  fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-  GNUNET_SERVER_client_keep (client);
-  fo_ctxt->client = client;
-  fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id);
-  fo_ctxt->cls = peer;          //GST_slave_list[route->dest]->controller;
-  fo_ctxt->type = OP_PEER_CREATE;
-  fo_ctxt->opc =
-      GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list
-                                             [route->dest]->controller,
-                                             fo_ctxt->operation_id,
-                                             &msg->header,
-                                             peer_create_success_cb, fo_ctxt);
-  fo_ctxt->timeout_task =
-      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);
-}
-
-
-/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client,
-                     const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_PeerDestroyMessage *msg;
-  struct ForwardedOperationContext *fopc;
-  struct Peer *peer;
-  uint32_t peer_id;
-
-  msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message;
-  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));
-  if ((GST_peer_list_size <= peer_id) || (NULL == GST_peer_list[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),
-                                 "Peer doesn't exist");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    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->client = client;
-    fopc->cls = peer;
-    fopc->type = OP_PEER_DESTROY;
-    fopc->operation_id = GNUNET_ntohll (msg->operation_id);
-    fopc->opc =
-        GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
-                                               slave->controller,
-                                               fopc->operation_id, &msg->header,
-                                               &peer_destroy_success_cb, fopc);
-    fopc->timeout_task =
-        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);
-    return;
-  }
-  peer->destroy_flag = GNUNET_YES;
-  if (0 == peer->reference_cnt)
-    GST_destroy_peer (peer);
-  else
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Delaying peer destroy as peer is currently in use\n");
-  send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id));
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-}
-
-
-/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client,
-                   const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_PeerStartMessage *msg;
-  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);
-  if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id]))
-  {
-    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);
-    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->client = client;
-    fopc->operation_id = GNUNET_ntohll (msg->operation_id);
-    fopc->type = OP_PEER_START;
-    fopc->opc =
-        GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
-                                               slave->controller,
-                                               fopc->operation_id, &msg->header,
-                                               &GST_forwarded_operation_reply_relay,
-                                               fopc);
-    fopc->timeout_task =
-        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);
-    return;
-  }
-  if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer))
-  {
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
-                                 "Failed to start");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  peer->details.local.is_running = GNUNET_YES;
-  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));
-  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);
-}
-
-
-/**
- * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client,
-                  const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_PeerStopMessage *msg;
-  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);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id);
-  if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id]))
-  {
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
-                                 "Peer not found");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    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);
-    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,
-                                               &GST_forwarded_operation_reply_relay,
-                                               fopc);
-    fopc->timeout_task =
-        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);
-    return;
-  }
-  if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer))
-  {
-    LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id);
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
-                                 "Peer not running");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id);
-  peer->details.local.is_running = GNUNET_NO;
-  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));
-  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_TESTING_peer_wait (peer->details.local.peer);
-}
-
-
-/**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client,
-                        const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg;
-  struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply;
-  struct Peer *peer;
-  char *config;
-  char *xconfig;
-  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);
-  if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id]))
-  {
-    GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id),
-                                 "Peer not found");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
-    return;
-  }
-  peer = GST_peer_list[peer_id];
-  if (GNUNET_YES == peer->is_remote)
-  {
-    struct ForwardedOperationContext *fopc;
-
-    LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id);
-    fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
-    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,
-                                               &GST_forwarded_operation_reply_relay,
-                                               fopc);
-    fopc->timeout_task =
-        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);
-    return;
-  }
-  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);
-  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);
-  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);
-}
-
-
-/**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
-                         const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
-  struct Slave *slave;
-  struct GNUNET_TESTBED_SlaveConfiguration *reply;
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-  char *config;
-  char *xconfig;
-  size_t config_size;
-  size_t xconfig_size;
-  size_t reply_size;
-  uint64_t op_id;
-  uint32_t slave_id;
-
-  msg = (struct GNUNET_TESTBED_SlaveGetConfigurationMessage *) message;
-  slave_id = ntohl (msg->slave_id);
-  op_id = GNUNET_ntohll (msg->operation_id);
-  if ((GST_slave_list_size <= slave_id) || (NULL == GST_slave_list[slave_id]))
-  {
-    /* FIXME: Add forwardings for this type of message here.. */
-    GST_send_operation_fail_msg (client, op_id, "Slave not found");
-    GNUNET_SERVER_receive_done (client, GNUNET_OK);
+    /* FIXME: Add forwardings for this type of message here.. */
+    GST_send_operation_fail_msg (client, op_id, "Slave not found");
+    GNUNET_SERVER_receive_done (client, GNUNET_OK);
     return;
   }
   slave = GST_slave_list[slave_id];
     return;
   }
   slave = GST_slave_list[slave_id];
@@ -1991,289 +723,15 @@ handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client,
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
   GNUNET_SERVER_receive_done (client, GNUNET_OK);
 }
 
-struct ManageServiceContext
-{
-
-  struct ManageServiceContext *next;
-
-  struct ManageServiceContext *prev;
-
-  struct GNUNET_ARM_Handle *ah;
-
-  struct Peer *peer;
-
-  struct GNUNET_SERVER_Client *client;
-  
-  uint64_t op_id;
-  
-  uint8_t start;
-
-  uint8_t expired;
-  
-};
-
-static struct ManageServiceContext *mctx_head;
-
-static struct ManageServiceContext *mctx_tail;
-
-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);
-}
-
-static void
-free_mctxq ()
-{
-  while (NULL != mctx_head)
-    cleanup_mctx (mctx_head);
-}
-
-static const char *
-arm_req_string (enum GNUNET_ARM_RequestStatus rs)
-{
-  switch (rs)
-  {
-  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_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");
-}
-
-static const char *
-arm_ret_string (enum GNUNET_ARM_Result result)
-{
-  switch (result)
-  {
-  case GNUNET_ARM_RESULT_STOPPED:
-    return _("%s is stopped");
-  case GNUNET_ARM_RESULT_STARTING:
-    return _("%s is starting");
-  case GNUNET_ARM_RESULT_STOPPING:
-    return _("%s is stopping");
-  case GNUNET_ARM_RESULT_IS_STARTING_ALREADY:
-    return _("%s is starting already");
-  case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY:
-    return _("%s is stopping already");
-  case GNUNET_ARM_RESULT_IS_STARTED_ALREADY:
-    return _("%s is started already");
-  case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY:
-    return _("%s is stopped already");
-  case GNUNET_ARM_RESULT_IS_NOT_KNOWN:
-    return _("%s service is not known to ARM");
-  case GNUNET_ARM_RESULT_START_FAILED:
-    return _("%s service failed to start");
-  case GNUNET_ARM_RESULT_IN_SHUTDOWN:
-    return _("%s service can't be started because ARM is shutting down");
-  }
-  return _("%.s Unknown result code.");
-}
-
-static void
-service_manage_result_cb (void *cls, struct GNUNET_ARM_Handle *arm,
-                          enum GNUNET_ARM_RequestStatus rs, 
-                          const char *service, enum GNUNET_ARM_Result result)
-{
-  struct ManageServiceContext *mctx = cls;
-  char *emsg;
-
-  emsg = NULL;
-  if (GNUNET_YES == mctx->expired)
-    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));
-    goto ret;
-  }
-  if (1 == mctx->start)
-    goto service_start_check;
-  if (! ((GNUNET_ARM_RESULT_STOPPED == result)
-            || (GNUNET_ARM_RESULT_STOPPING == result)
-            || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result)
-            || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) )
-  {
-    /* stopping a service failed */
-    GNUNET_asprintf (&emsg, arm_ret_string (result), service);
-    goto ret;
-  }
-  /* service stopped successfully */
-  goto ret;
-
- service_start_check:
-  if (! ((GNUNET_ARM_RESULT_STARTING == result)
-            || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result)
-            || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) )
-  {
-    /* starting a service failed */
-    GNUNET_asprintf (&emsg, arm_ret_string (result), service);
-    goto ret;
-  }
-  /* service started successfully */
-  
- ret:
-  if (NULL != emsg)
-  {
-    LOG_DEBUG ("%s\n", emsg);
-    GST_send_operation_fail_msg (mctx->client, mctx->op_id, emsg);
-  }
-  else
-    send_operation_success_msg (mctx->client, mctx->op_id);
-  GNUNET_free_non_null (emsg);
-  cleanup_mctx (mctx);
-}
-
-static void
-handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client,
-                            const struct GNUNET_MessageHeader *message)
-{
-  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;
-  
-
-  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];  
-  if ('\0' != service[msize - sizeof
-                      (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1])
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;
-  }
-  if (1 < msg->start)
-  {
-    GNUNET_break_op (0);
-    GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
-    return;    
-  }
-  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",
-             service, (unsigned int) peer_id);
-  if ((GST_peer_list_size <= peer_id)
-      || (NULL == (peer = GST_peer_list[peer_id])))
-  {
-    GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer "
-                     "with id: %u", peer_id);
-    goto err_ret;
-  }
-  if (0 == strcasecmp ("arm", service))
-  {
-    emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service.  "
-                          "Use peer start/stop for that");
-    goto err_ret;
-  }
-  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->client = client;
-    fopc->cls = peer;
-    fopc->type = OP_MANAGE_SERVICE;
-    fopc->operation_id = op_id;
-    fopc->opc =
-        GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote.
-                                               slave->controller,
-                                               fopc->operation_id, &msg->header,
-                                               &GST_forwarded_operation_reply_relay,
-                                               fopc);
-    fopc->timeout_task =
-        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);
-    return;
-  }
-  if ((0 != peer->reference_cnt)
-      && ( (0 == strcasecmp ("core", service))
-           || (0 == strcasecmp ("transport", service)) )  )
-  {
-    GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u "
-                     "since it is required by existing operations",
-                     service, peer_id);
-    goto err_ret;
-  }
-  ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL);
-  if (NULL == ah)
-  {
-    GNUNET_asprintf (&emsg,
-                     "Cannot connect to ARM service of peer with id: %u",
-                     peer_id);
-    goto err_ret;
-  }
-  mctx = GNUNET_malloc (sizeof (struct ManageServiceContext));
-  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;
-  GNUNET_CONTAINER_DLL_insert_tail (mctx_head, mctx_tail, mctx);
-  if (1 == mctx->start)
-    GNUNET_ARM_request_service_start (mctx->ah, service,
-                                      GNUNET_OS_INHERIT_STD_ERR,
-                                      GST_timeout,
-                                      service_manage_result_cb,
-                                      mctx);
-  else
-    GNUNET_ARM_request_service_stop (mctx->ah, service,
-                                     GST_timeout,
-                                     service_manage_result_cb,
-                                     mctx);
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
-  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);
-}
 
 /**
  * Clears the forwarded operations queue
  */
 
 /**
  * Clears the forwarded operations queue
  */
-static void
-clear_fopcq ()
+void
+GST_clear_fopcq ()
 {
   struct ForwardedOperationContext *fopc;
 {
   struct ForwardedOperationContext *fopc;
-  
+
   while (NULL != (fopc = fopcq_head))
   {
     GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
   while (NULL != (fopc = fopcq_head))
   {
     GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fopc);
@@ -2289,7 +747,7 @@ clear_fopcq ()
     case OP_SHUTDOWN_PEERS:
       {
         struct HandlerContext_ShutdownPeers *hc = fopc->cls;
     case OP_SHUTDOWN_PEERS:
       {
         struct HandlerContext_ShutdownPeers *hc = fopc->cls;
-        
+
         GNUNET_assert (0 < hc->nslaves);
         hc->nslaves--;
         if (0 == hc->nslaves)
         GNUNET_assert (0 < hc->nslaves);
         hc->nslaves--;
         if (0 == hc->nslaves)
@@ -2304,6 +762,7 @@ clear_fopcq ()
     case OP_LINK_CONTROLLERS:
     case OP_GET_SLAVE_CONFIG:
     case OP_MANAGE_SERVICE:
     case OP_LINK_CONTROLLERS:
     case OP_GET_SLAVE_CONFIG:
     case OP_MANAGE_SERVICE:
+    case OP_PEER_RECONFIGURE:
       break;
     case OP_FORWARDED:
       GNUNET_assert (0);
       break;
     case OP_FORWARDED:
       GNUNET_assert (0);
@@ -2313,242 +772,6 @@ clear_fopcq ()
 }
 
 
 }
 
 
-/**
- * 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_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
- * to the client
- *
- * @param cls ForwardedOperationContext
- * @param msg the message to relay
- */
-static void
-shutdown_peers_reply_cb (void *cls,
-                         const struct GNUNET_MessageHeader *msg)
-{
-  struct ForwardedOperationContext *fo_ctxt = cls;
-  struct HandlerContext_ShutdownPeers *hc;
-  
-  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--;
-  if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != 
-      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,
-                                   "Timeout at a slave controller");
-    else
-      send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id);
-  }
-  GNUNET_SERVER_client_drop (fo_ctxt->client);
-  GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt);
-  GNUNET_free (fo_ctxt);
-}
-
-
-/**
- * Stops and destroys all peers
- */
-static void
-destroy_peers ()
-{
-  struct Peer *peer;
-  unsigned int id;
-
-  if (NULL == GST_peer_list)
-    return;
-  for (id = 0; id < GST_peer_list_size; id++)
-  {
-    peer = GST_peer_list[id];
-    if (NULL == peer)
-      continue;
-    /* If destroy flag is set it means that this peer should have been
-     * destroyed by a context which we destroy before */
-    GNUNET_break (GNUNET_NO == peer->destroy_flag);
-    /* counter should be zero as we free all contexts before */
-    GNUNET_break (0 == peer->reference_cnt);
-    if ((GNUNET_NO == peer->is_remote) &&
-        (GNUNET_YES == peer->details.local.is_running))
-      GNUNET_TESTING_peer_kill (peer->details.local.peer);
-  }
-  for (id = 0; id < GST_peer_list_size; id++)
-  {
-    peer = GST_peer_list[id];
-    if (NULL == peer)
-      continue;    
-    if (GNUNET_NO == peer->is_remote)
-    {
-      if (GNUNET_YES == peer->details.local.is_running)
-        GNUNET_TESTING_peer_wait (peer->details.local.peer);
-      GNUNET_TESTING_peer_destroy (peer->details.local.peer);
-      GNUNET_CONFIGURATION_destroy (peer->details.local.cfg);
-    }
-    GNUNET_free (peer);
-  }
-  GNUNET_free_non_null (GST_peer_list);
-  GST_peer_list = NULL;
-  GST_peer_list_size = 0;
-}
-
-
-/**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages
- *
- * @param cls NULL
- * @param client identification of the client
- * @param message the actual message
- */
-static void
-handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client,
-                       const struct GNUNET_MessageHeader *message)
-{
-  const struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
-  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 */
-  free_mctxq ();
-  GST_free_occq ();
-  GST_free_roccq ();
-  clear_fopcq ();
-  /* Forward to all slaves which we have started */
-  op_id = GNUNET_ntohll (msg->operation_id);
-  hc = GNUNET_malloc (sizeof (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++)
-  {
-    slave = GST_slave_list[cnt];
-    if (NULL == slave)
-      continue;
-    if (NULL == slave->controller_proc) /* We didn't start the slave */
-      continue;
-    LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n");
-    hc->nslaves++;
-    fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext));
-    GNUNET_SERVER_client_keep (client);
-    fo_ctxt->client = client;
-    fo_ctxt->operation_id = op_id;
-    fo_ctxt->cls = hc;
-    fo_ctxt->type = OP_SHUTDOWN_PEERS;
-    fo_ctxt->opc =
-        GNUNET_TESTBED_forward_operation_msg_ (slave->controller,
-                                               fo_ctxt->operation_id,
-                                               &msg->header,
-                                               shutdown_peers_reply_cb,
-                                               fo_ctxt);
-    fo_ctxt->timeout_task =
-        GNUNET_SCHEDULER_add_delayed (GST_timeout, &shutdown_peers_timeout_cb,
-                                      fo_ctxt);
-    GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt);
-  }
-  LOG_DEBUG ("Shutting down peers\n");
-  destroy_peers ();
-  if (0 == hc->nslaves)
-  {
-    send_operation_success_msg (client, op_id);
-    GNUNET_free (hc);
-  }
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);  
-}
-
-
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-ss_map_free_iterator (void *cls, const struct GNUNET_HashCode *key, void *value)
-{
-  struct SharedService *ss = value;
-
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multihashmap_remove (ss_map, key, value));
-  GNUNET_free (ss->name);
-  GNUNET_free (ss);
-  return GNUNET_YES;
-}
-
-
-/**
- * Iterator for freeing hash map entries in a slave's reghost_map
- *
- * @param cls handle to the slave
- * @param key current key code
- * @param value value in the hash map
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key,
-                       void *value)
-{
-  struct Slave *slave = cls;
-  struct RegisteredHostContext *rhc = value;
-  struct ForwardedOverlayConnectContext *focc;
-
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multihashmap_remove (slave->reghost_map, key,
-                                                       value));
-  while (NULL != (focc = rhc->focc_dll_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (rhc->focc_dll_head, rhc->focc_dll_tail, focc);
-    GST_cleanup_focc (focc);
-  }
-  if (NULL != rhc->sub_op)
-    GNUNET_TESTBED_operation_done (rhc->sub_op);
-  if (NULL != rhc->client)
-    GNUNET_SERVER_client_drop (rhc->client);
-  GNUNET_free (value);
-  return GNUNET_YES;
-}
-
-
 /**
  * Task to clean up and shutdown nicely
  *
 /**
  * Task to clean up and shutdown nicely
  *
@@ -2558,77 +781,31 @@ reghost_free_iterator (void *cls, const struct GNUNET_HashCode *key,
 static void
 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
 static void
 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct LCFContextQueue *lcfq;
   struct MessageQueue *mq_entry;
   uint32_t id;
 
   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
   struct MessageQueue *mq_entry;
   uint32_t id;
 
   shutdown_task_id = GNUNET_SCHEDULER_NO_TASK;
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down testbed service\n");
-  (void) GNUNET_CONTAINER_multihashmap_iterate (ss_map, &ss_map_free_iterator,
-                                                NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (ss_map);
+  LOG_DEBUG ("Shutting down testbed service\n");
   /* cleanup any remaining forwarded operations */
   /* cleanup any remaining forwarded operations */
-  clear_fopcq ();
-  if (NULL != lcfq_head)
-  {
-    if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id)
-    {
-      GNUNET_SCHEDULER_cancel (lcf_proc_task_id);
-      lcf_proc_task_id = GNUNET_SCHEDULER_NO_TASK;
-    }
-  }
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == lcf_proc_task_id);
-  for (lcfq = lcfq_head; NULL != lcfq; lcfq = lcfq_head)
-  {
-    GNUNET_SERVER_client_drop (lcfq->lcf->client);
-    GNUNET_assert (NULL != lcfq->lcf->cfg);
-    GNUNET_CONFIGURATION_destroy (lcfq->lcf->cfg);
-    GNUNET_free (lcfq->lcf);
-    GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq);
-    GNUNET_free (lcfq);
-  }
-  free_mctxq ();
+  GST_clear_fopcq ();
+  GST_free_lcfq ();
+  GST_free_mctxq ();
   GST_free_occq ();
   GST_free_roccq ();
   GST_free_occq ();
   GST_free_roccq ();
+  GST_free_nccq ();
+  GST_neighbour_list_clean();
+  GST_free_prcq ();
   /* Clear peer list */
   /* Clear peer list */
-  destroy_peers ();
+  GST_destroy_peers ();
+  /* Clear route list */
+  GST_route_list_clear ();
+  /* Clear GST_slave_list */
+  GST_slave_list_clear ();
   /* Clear host list */
   for (id = 0; id < GST_host_list_size; id++)
     if (NULL != GST_host_list[id])
       GNUNET_TESTBED_host_destroy (GST_host_list[id]);
   GNUNET_free_non_null (GST_host_list);
   /* Clear host list */
   for (id = 0; id < GST_host_list_size; id++)
     if (NULL != GST_host_list[id])
       GNUNET_TESTBED_host_destroy (GST_host_list[id]);
   GNUNET_free_non_null (GST_host_list);
-  /* Clear route list */
-  for (id = 0; id < route_list_size; id++)
-    if (NULL != route_list[id])
-      GNUNET_free (route_list[id]);
-  GNUNET_free_non_null (route_list);
-  /* Clear GST_slave_list */
-  for (id = 0; id < GST_slave_list_size; id++)
-    if (NULL != GST_slave_list[id])
-    {
-      struct HostRegistration *hr_entry;
-
-      while (NULL != (hr_entry = GST_slave_list[id]->hr_dll_head))
-      {
-        GNUNET_CONTAINER_DLL_remove (GST_slave_list[id]->hr_dll_head,
-                                     GST_slave_list[id]->hr_dll_tail, hr_entry);
-        GNUNET_free (hr_entry);
-      }
-      if (NULL != GST_slave_list[id]->rhandle)
-        GNUNET_TESTBED_cancel_registration (GST_slave_list[id]->rhandle);
-      (void)
-          GNUNET_CONTAINER_multihashmap_iterate (GST_slave_list
-                                                 [id]->reghost_map,
-                                                 reghost_free_iterator,
-                                                 GST_slave_list[id]);
-      GNUNET_CONTAINER_multihashmap_destroy (GST_slave_list[id]->reghost_map);
-      if (NULL != GST_slave_list[id]->controller)
-        GNUNET_TESTBED_controller_disconnect (GST_slave_list[id]->controller);
-      if (NULL != GST_slave_list[id]->controller_proc)
-        GNUNET_TESTBED_controller_stop (GST_slave_list[id]->controller_proc);
-      GNUNET_free (GST_slave_list[id]);
-    }
-  GNUNET_free_non_null (GST_slave_list);
   if (NULL != GST_context)
   {
     GNUNET_free_non_null (GST_context->master_ip);
   if (NULL != GST_context)
   {
     GNUNET_free_non_null (GST_context->master_ip);
@@ -2648,11 +825,14 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_free (mq_entry);
   }
   GNUNET_free_non_null (hostname);
     GNUNET_free (mq_entry);
   }
   GNUNET_free_non_null (hostname);
-  GNUNET_CONFIGURATION_destroy (our_config);
   /* Free hello cache */
   GST_cache_clear ();
   /* Free hello cache */
   GST_cache_clear ();
+  GST_connection_pool_destroy ();
   GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds);
   GST_opq_openfds = NULL;
   GNUNET_TESTBED_operation_queue_destroy_ (GST_opq_openfds);
   GST_opq_openfds = NULL;
+  GST_stats_destroy ();
+  GST_barriers_destroy ();
+  GNUNET_CONFIGURATION_destroy (GST_config);
 }
 
 
 }
 
 
@@ -2694,37 +874,45 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
   static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
     {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
     {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0},
   static const struct GNUNET_SERVER_MessageHandler message_handlers[] = {
     {&handle_init, NULL, GNUNET_MESSAGE_TYPE_TESTBED_INIT, 0},
     {&handle_add_host, NULL, GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST, 0},
-    {&handle_configure_shared_service, NULL,
-     GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0},
-    {&handle_link_controllers, NULL,
-     GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 0},
-    {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0},
-    {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER,
+    {&GST_handle_link_controllers, NULL,
+     GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
+     sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)},
+    {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0},
+    {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER,
      sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
      sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)},
-    {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER,
+    {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER,
      sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
      sizeof (struct GNUNET_TESTBED_PeerStartMessage)},
-    {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER,
+    {&GST_handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER,
      sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
      sizeof (struct GNUNET_TESTBED_PeerStopMessage)},
-    {&handle_peer_get_config, NULL,
-     GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION,
+    {&GST_handle_peer_get_config, NULL,
+     GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_INFORMATION,
      sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
     {&GST_handle_overlay_connect, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT,
      sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
     {&GST_handle_remote_overlay_connect, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0},
      sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)},
     {&GST_handle_overlay_connect, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_OVERLAY_CONNECT,
      sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)},
     {&GST_handle_remote_overlay_connect, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0},
-    {&handle_manage_peer_service, NULL,
+    {&GST_handle_manage_peer_service, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0},
     {&handle_slave_get_config, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION,
      sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
      GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0},
     {&handle_slave_get_config, NULL,
      GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION,
      sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)},
-    {&handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS,
+    {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS,
      sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)},
      sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)},
-    {NULL}
+    {&GST_handle_peer_reconfigure, NULL,
+     GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER, 0},
+    {&GST_handle_barrier_init, NULL,
+     GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT, 0},
+    {&GST_handle_barrier_cancel, NULL,
+     GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL, 0},
+    {&GST_handle_barrier_status, NULL,
+     GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS, 0},
+    {NULL, NULL, 0, 0}
   };
   char *logfile;
   unsigned long long num;
 
   };
   char *logfile;
   unsigned long long num;
 
+  LOG_DEBUG ("Starting testbed\n");
   if (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE",
                                                &logfile))
   if (GNUNET_OK ==
       GNUNET_CONFIGURATION_get_value_filename (cfg, "TESTBED", "LOG_FILE",
                                                &logfile))
@@ -2736,10 +924,12 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
                  GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
                                                         "CACHE_SIZE", &num));
   GST_cache_init ((unsigned int) num);
                  GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
                                                         "CACHE_SIZE", &num));
   GST_cache_init ((unsigned int) num);
+  GST_connection_pool_init ((unsigned int) num);
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
                                                         "MAX_OPEN_FDS", &num));
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_number (cfg, "TESTBED",
                                                         "MAX_OPEN_FDS", &num));
-  GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_ ((unsigned int) num);
+  GST_opq_openfds = GNUNET_TESTBED_operation_queue_create_
+      (OPERATION_QUEUE_TYPE_FIXED, (unsigned int) num);
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
                                                       "OPERATION_TIMEOUT",
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
                                                       "OPERATION_TIMEOUT",
@@ -2749,19 +939,16 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server,
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
                                                         "HOSTNAME", &hostname));
   GNUNET_assert (GNUNET_OK ==
                  GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
                                                         "HOSTNAME", &hostname));
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
-                                             "STATS_DIR", &GST_stats_dir));
-  our_config = GNUNET_CONFIGURATION_dup (cfg);
+  GST_config = GNUNET_CONFIGURATION_dup (cfg);
   GNUNET_SERVER_add_handlers (server, message_handlers);
   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
   GNUNET_SERVER_add_handlers (server, message_handlers);
   GNUNET_SERVER_disconnect_notify (server, &client_disconnect_cb, NULL);
-  ss_map = GNUNET_CONTAINER_multihashmap_create (5, GNUNET_NO);
   shutdown_task_id =
       GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
                                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
                                                   &shutdown_task, NULL);
   LOG_DEBUG ("Testbed startup complete\n");
   shutdown_task_id =
       GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_UNIT_FOREVER_REL,
                                                   GNUNET_SCHEDULER_PRIORITY_IDLE,
                                                   &shutdown_task, NULL);
   LOG_DEBUG ("Testbed startup complete\n");
-  event_mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
+  GST_stats_init (GST_config);
+  GST_barriers_init (GST_config);
 }
 
 
 }