shutdown
[oweals/gnunet.git] / src / testing / testing_group.c
index f1e5ba1e5c92469e1a280419c3ac565ab7beddd1..be9743b1f5b5ec2af46700e22f113bb4f435ea6a 100644 (file)
  *
  */
 #include "platform.h"
+#include "gnunet_constants.h"
 #include "gnunet_arm_service.h"
 #include "gnunet_testing_lib.h"
 #include "gnunet_core_service.h"
 
 #define VERBOSE_TESTING GNUNET_NO
 
-#define VERBOSE_TOPOLOGY GNUNET_YES
+#define VERBOSE_TOPOLOGY GNUNET_NO
 
 #define DEBUG_CHURN GNUNET_NO
 
+#define USE_START_HELPER GNUNET_YES
+
 #define OLD 1
 
+/* Before connecting peers, send all of the HELLOs */
 #define USE_SEND_HELLOS GNUNET_NO
 
 #define TOPOLOGY_HACK GNUNET_YES
 
+
 /**
  * Lowest port used for GNUnet testing.  Should be high enough to not
  * conflict with other applications running on the hosts but be low
@@ -84,8 +89,8 @@ enum PeerLists
  */
 typedef unsigned int
 (*GNUNET_TESTING_ConnectionProcessor)(struct GNUNET_TESTING_PeerGroup * pg,
-    unsigned int first, unsigned int second, enum PeerLists list,
-    unsigned int check);
+                                      unsigned int first, unsigned int second,
+                                      enum PeerLists list, unsigned int check);
 
 /**
  * Context for handling churning a peer group
@@ -1014,6 +1019,8 @@ create_meter(unsigned int total, char * start_string, int print)
   ret->print = print;
   ret->total = total;
   ret->modnum = total / 4;
+  if (ret->modnum == 0) /* Divide by zero check */
+    ret->modnum = 1;
   ret->dotnum = (total / 50) + 1;
   if (start_string != NULL)
     ret->startup_string = GNUNET_strdup(start_string);
@@ -1103,7 +1110,7 @@ free_meter(struct ProgressMeter *meter)
  */
 int
 GNUNET_TESTING_topology_get(enum GNUNET_TESTING_Topology *topology,
-    const char *topology_string)
+                            const char *topology_string)
 {
   /**
    * Strings representing topologies in enum
@@ -1195,8 +1202,8 @@ GNUNET_TESTING_topology_get(enum GNUNET_TESTING_Topology *topology,
  */
 int
 GNUNET_TESTING_topology_option_get(
-    enum GNUNET_TESTING_TopologyOption *topology_option,
-    const char *topology_string)
+                                   enum GNUNET_TESTING_TopologyOption *topology_option,
+                                   const char *topology_string)
 {
   /**
    * Options for connecting a topology as strings.
@@ -1268,7 +1275,7 @@ GNUNET_TESTING_topology_option_get(
  */
 static void
 update_config(void *cls, const char *section, const char *option,
-    const char *value)
+              const char *value)
 {
   struct UpdateContext *ctx = cls;
   unsigned int ival;
@@ -1354,7 +1361,8 @@ update_config(void *cls, const char *section, const char *option,
  */
 static struct GNUNET_CONFIGURATION_Handle *
 make_config(const struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t off,
-    uint16_t * port, uint32_t * upnum, const char *hostname, uint32_t * fdnum)
+            uint16_t * port, uint32_t * upnum, const char *hostname,
+            uint32_t * fdnum)
 {
   struct UpdateContext uc;
   uint16_t orig;
@@ -1448,7 +1456,7 @@ make_config(const struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t off,
  */
 static unsigned int
 remove_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
-    unsigned int second, enum PeerLists list, unsigned int check)
+                   unsigned int second, enum PeerLists list, unsigned int check)
 {
   int removed;
 #if OLD
@@ -1561,12 +1569,12 @@ remove_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
  */
 static unsigned int
 add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
-    unsigned int second, enum PeerLists list, unsigned int check)
+                unsigned int second, enum PeerLists list, unsigned int check)
 {
   int added;
   int add_first;
   int add_second;
-#if OLD
+
   struct PeerConnection **first_list;
   struct PeerConnection **second_list;
   struct PeerConnection *first_iter;
@@ -1575,15 +1583,7 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
   struct PeerConnection *new_second;
   struct PeerConnection **first_tail;
   struct PeerConnection **second_tail;
-#else
-  GNUNET_HashCode hash_first;
-  GNUNET_HashCode hash_second;
-
-  hash_from_uid (first, &hash_first);
-  hash_from_uid (second, &hash_second);
-#endif
 
-#if OLD
   switch (list)
     {
   case ALLOWED:
@@ -1642,59 +1642,22 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
           second_iter = second_iter->next;
         }
     }
-#else
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (pg->peers[first].blacklisted_peers,
-          &hash_second))
-    {
-      add_first = GNUNET_YES;
-    }
-
-  if (GNUNET_NO ==
-      GNUNET_CONTAINER_multihashmap_contains (pg->peers[second].blacklisted_peers,
-          &hash_first))
-    {
-      add_second = GNUNET_YES;
-    }
-#endif
 
   added = 0;
   if (add_first)
     {
-#if OLD
       new_first = GNUNET_malloc (sizeof (struct PeerConnection));
       new_first->index = second;
       GNUNET_CONTAINER_DLL_insert(*first_list, *first_tail, new_first);
-#else
-      GNUNET_assert (GNUNET_OK ==
-          GNUNET_CONTAINER_multihashmap_put (pg->
-              peers
-              [first].blacklisted_peers,
-              &hash_second,
-              pg->
-              peers[second].daemon,
-              GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-#endif
       pg->peers[first].num_connections++;
       added++;
     }
 
   if (add_second)
     {
-#if OLD
       new_second = GNUNET_malloc (sizeof (struct PeerConnection));
       new_second->index = first;
       GNUNET_CONTAINER_DLL_insert(*second_list, *second_tail, new_second);
-#else
-      GNUNET_assert (GNUNET_OK ==
-          GNUNET_CONTAINER_multihashmap_put (pg->
-              peers
-              [second].blacklisted_peers,
-              &hash_first,
-              pg->
-              peers[first].daemon,
-              GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-#endif
       pg->peers[second].num_connections++;
       added++;
     }
@@ -1720,7 +1683,7 @@ add_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
  */
 static unsigned int
 create_scale_free(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                  GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
 
   unsigned int total_connections;
@@ -1794,7 +1757,8 @@ create_scale_free(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                        GNUNET_TESTING_ConnectionProcessor proc,
+                        enum PeerLists list)
 {
   unsigned int i, j;
   int nodeToConnect;
@@ -1919,7 +1883,8 @@ create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_nated_internet(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                      GNUNET_TESTING_ConnectionProcessor proc,
+                      enum PeerLists list)
 {
   unsigned int outer_count, inner_count;
   unsigned int cutoff;
@@ -1977,7 +1942,8 @@ create_nated_internet(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_nated_internet_copy(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                           GNUNET_TESTING_ConnectionProcessor proc,
+                           enum PeerLists list)
 {
   unsigned int outer_count, inner_count;
   unsigned int cutoff;
@@ -2053,7 +2019,7 @@ create_nated_internet_copy(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_small_world(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                   GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
   unsigned int i, j, k;
   unsigned int square;
@@ -2228,7 +2194,7 @@ create_small_world(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_erdos_renyi(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                   GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
   double temp_rand;
   unsigned int outer_count;
@@ -2291,7 +2257,7 @@ create_erdos_renyi(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_2d_torus(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
   unsigned int i;
   unsigned int square;
@@ -2385,8 +2351,8 @@ create_2d_torus(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_clique(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list,
-    unsigned int check)
+              GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list,
+              unsigned int check)
 {
   unsigned int outer_count;
   unsigned int inner_count;
@@ -2395,7 +2361,7 @@ create_clique(struct GNUNET_TESTING_PeerGroup *pg,
   connect_attempts = 0;
 
   conn_meter = create_meter ((((pg->total * pg->total) + pg->total) / 2)
-      - pg->total, "Create Clique ", GNUNET_YES);
+      - pg->total, "Create Clique ", GNUNET_NO);
   for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
     {
       for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
@@ -2409,8 +2375,6 @@ create_clique(struct GNUNET_TESTING_PeerGroup *pg,
           update_meter (conn_meter);
         }
     }
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Meter has %d left\n",
-              conn_meter->total - conn_meter->completed);
   reset_meter (conn_meter);
   free_meter (conn_meter);
   return connect_attempts;
@@ -2458,7 +2422,7 @@ unblacklist_iterator (void *cls,
  */
 static unsigned int
 copy_allowed(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc)
+             GNUNET_TESTING_ConnectionProcessor proc)
 {
   struct UnblacklistContext un_ctx;
   unsigned int count;
@@ -2500,7 +2464,7 @@ copy_allowed(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_line(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+            GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
   unsigned int count;
   int connect_attempts;
@@ -2535,7 +2499,7 @@ create_line(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+                 GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
   int connect_attempts;
   unsigned int first_peer_index;
@@ -2573,6 +2537,7 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
 
   buf = data;
   count = 0;
+  first_peer_index = 0;
   /* First line should contain a single integer, specifying the number of peers */
   /* Each subsequent line should contain this format PEER_INDEX:OTHER_PEER_INDEX[,...] */
   curr_state = NUM_PEERS;
@@ -2587,7 +2552,9 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
       switch (curr_state)
         {
       case NUM_PEERS:
-        if (1 != sscanf (&buf[count], "%u", &total_peers))
+        errno = 0;
+        total_peers = strtoul(&buf[count], NULL, 10);
+        if (errno != 0)
           {
             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                         "Failed to read number of peers from topology file!\n");
@@ -2603,7 +2570,9 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
         count++;
         break;
       case PEER_INDEX:
-        if (1 != sscanf (&buf[count], "%u", &first_peer_index))
+        errno = 0;
+        first_peer_index = strtoul(&buf[count], NULL, 10);
+        if (errno != 0)
           {
             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                         "Failed to read peer index from topology file!\n");
@@ -2621,7 +2590,9 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
         count++;
         break;
       case OTHER_PEER_INDEX:
-        if (1 != sscanf (&buf[count], "%u", &second_peer_index))
+        errno = 0;
+        second_peer_index = strtoul(&buf[count], NULL, 10);
+        if (errno != 0)
           {
             GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                         "Failed to peer index from topology file!\n");
@@ -2630,7 +2601,7 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
           }
         /* Assume file is written with first peer 1, but array index is 0 */
         connect_attempts += proc (pg, first_peer_index - 1, second_peer_index
-            - 1, list, GNUNET_YES);
+                                  - 1, list, GNUNET_YES);
         while ((buf[count] != '\n') && (buf[count] != ',') && (count
             < frstat.st_size - 1))
           count++;
@@ -2653,17 +2624,6 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
         }
 
     }
-#if 0
-  /* Connect each peer to the next highest numbered peer */
-  for (count = 0; count < pg->total - 1; count++)
-    {
-#if VERBOSE_TESTING
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-          "Connecting peer %d to peer %d\n", first_peer_index, second_peer_index);
-#endif
-      connect_attempts += proc (pg, first_peer_index, second_peer_index);
-    }
-#endif
   return connect_attempts;
 }
 
@@ -2681,7 +2641,7 @@ create_from_file(struct GNUNET_TESTING_PeerGroup *pg, char *filename,
  */
 static unsigned int
 create_ring(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+            GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
 {
   unsigned int count;
   int connect_attempts;
@@ -2853,6 +2813,7 @@ create_and_copy_friend_files(struct GNUNET_TESTING_PeerGroup *pg)
           GNUNET_asprintf (&arg, "%s/friends", temp_service_path);
           procarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "mv", "mv",
                                                       mytemp, arg, NULL);
+          GNUNET_assert(procarr[pg_iter] != NULL);
 #if VERBOSE_TESTING
           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               _("Copying file with command cp %s %s\n"), mytemp, arg);
@@ -2874,7 +2835,7 @@ create_and_copy_friend_files(struct GNUNET_TESTING_PeerGroup *pg)
                              temp_service_path);
           procarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp", "scp",
                                                       mytemp, arg, NULL);
-
+          GNUNET_assert(procarr[pg_iter] != NULL);
           ret = GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: schedule this, throttle! */
           GNUNET_OS_process_close (procarr[pg_iter]);
           if (ret != GNUNET_OK)
@@ -2953,7 +2914,7 @@ create_and_copy_friend_files(struct GNUNET_TESTING_PeerGroup *pg)
  */
 static int
 create_and_copy_blacklist_files(struct GNUNET_TESTING_PeerGroup *pg,
-    const char *transports)
+                                const char *transports)
 {
   FILE *temp_file_handle;
   unsigned int pg_iter;
@@ -3072,7 +3033,7 @@ create_and_copy_blacklist_files(struct GNUNET_TESTING_PeerGroup *pg,
                              temp_service_path);
           procarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp", "scp",
                                                       mytemp, arg, NULL);
-
+          GNUNET_assert(procarr[pg_iter] != NULL);
           GNUNET_OS_process_wait (procarr[pg_iter]); /* FIXME: add scheduled blacklist file copy that parallelizes file copying! */
 
 #if VERBOSE_TESTING
@@ -3427,7 +3388,7 @@ hello_sent_callback (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   {
     struct SendHelloContext *send_hello_context = cls;
     //unsigned int pg_iter;
-    if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+    if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
       {
         GNUNET_free(send_hello_context);
         return;
@@ -3485,7 +3446,7 @@ static void schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskC
     struct SendHelloContext *send_hello_context = cls;
     struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
 
-    if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+    if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
       {
         GNUNET_free(send_hello_context);
         return;
@@ -3516,12 +3477,9 @@ static void schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskC
         if (send_hello_context->peer->daemon->th == NULL)
           {
             pg->outstanding_connects++; /* Actual TRANSPORT, CORE connections! */
-            send_hello_context->peer->daemon->th = GNUNET_TRANSPORT_connect(send_hello_context->peer->cfg,
-                NULL,
-                send_hello_context,
-                NULL,
-                NULL,
-                NULL);
+            send_hello_context->peer->daemon->th
+                = GNUNET_TRANSPORT_connect (send_hello_context->peer->cfg, NULL,
+                                            send_hello_context, NULL, NULL, NULL);
           }
 #if DEBUG_TESTING
         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -3544,11 +3502,13 @@ static void schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskC
  */
 static void
 internal_connect_notify(void *cls, const struct GNUNET_PeerIdentity *first,
-    const struct GNUNET_PeerIdentity *second, uint32_t distance,
-    const struct GNUNET_CONFIGURATION_Handle *first_cfg,
-    const struct GNUNET_CONFIGURATION_Handle *second_cfg,
-    struct GNUNET_TESTING_Daemon *first_daemon,
-    struct GNUNET_TESTING_Daemon *second_daemon, const char *emsg)
+                        const struct GNUNET_PeerIdentity *second,
+                        uint32_t distance,
+                        const struct GNUNET_CONFIGURATION_Handle *first_cfg,
+                        const struct GNUNET_CONFIGURATION_Handle *second_cfg,
+                        struct GNUNET_TESTING_Daemon *first_daemon,
+                        struct GNUNET_TESTING_Daemon *second_daemon,
+                        const char *emsg)
 {
   struct ConnectContext *connect_ctx = cls;
   struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx;
@@ -3614,7 +3574,7 @@ schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct ConnectContext *connect_context = cls;
   struct GNUNET_TESTING_PeerGroup *pg = connect_context->ct_ctx->pg;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     return;
 
   if ((pg->outstanding_connects > pg->max_outstanding_connections)
@@ -3646,7 +3606,7 @@ schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                                       connect_context->ct_ctx->connect_timeout,
                                       connect_context->ct_ctx->connect_attempts,
 #if USE_SEND_HELLOS
-                                       GNUNET_NO,
+                                      GNUNET_NO,
 #else
                                       GNUNET_YES,
 #endif
@@ -3735,7 +3695,7 @@ copy_allowed_topology(struct GNUNET_TESTING_PeerGroup *pg)
                       "Creating connection between %d and %d\n", pg_iter,
                       iter->index);
           total += add_connections (pg, pg_iter, iter->index, CONNECT,
-                                    GNUNET_NO);
+                                    GNUNET_YES);
           //total += add_actual_connections(pg, pg_iter, iter->index);
           iter = iter->next;
         }
@@ -3769,8 +3729,10 @@ copy_allowed_topology(struct GNUNET_TESTING_PeerGroup *pg)
  */
 static int
 connect_topology(struct GNUNET_TESTING_PeerGroup *pg,
-    struct GNUNET_TIME_Relative connect_timeout, unsigned int connect_attempts,
-    GNUNET_TESTING_NotifyCompletion notify_callback, void *notify_cls)
+                 struct GNUNET_TIME_Relative connect_timeout,
+                 unsigned int connect_attempts,
+                 GNUNET_TESTING_NotifyCompletion notify_callback,
+                 void *notify_cls)
 {
   unsigned int pg_iter;
   unsigned int total;
@@ -3779,7 +3741,7 @@ connect_topology(struct GNUNET_TESTING_PeerGroup *pg,
   struct PeerConnection *connection_iter;
 #endif
 #if USE_SEND_HELLOS
-  struct SendHelloContext *send_hello_context
+  struct SendHelloContext *send_hello_context;
 #endif
 
   total = 0;
@@ -3853,9 +3815,9 @@ connect_topology(struct GNUNET_TESTING_PeerGroup *pg,
  */
 unsigned int
 GNUNET_TESTING_create_topology(struct GNUNET_TESTING_PeerGroup *pg,
-    enum GNUNET_TESTING_Topology topology,
-    enum GNUNET_TESTING_Topology restrict_topology,
-    const char *restrict_transports)
+                               enum GNUNET_TESTING_Topology topology,
+                               enum GNUNET_TESTING_Topology restrict_topology,
+                               const char *restrict_transports)
 {
   int ret;
 
@@ -3997,6 +3959,8 @@ GNUNET_TESTING_create_topology(struct GNUNET_TESTING_PeerGroup *pg,
   if ((restrict_topology != GNUNET_TESTING_TOPOLOGY_NONE) && (restrict_topology
       != GNUNET_TESTING_TOPOLOGY_FROM_FILE))
     create_clique (pg, &add_connections, BLACKLIST, GNUNET_NO);
+  else
+    return num_connections;
 
   unblacklisted_connections = 0;
   /* Un-blacklist connections as per the topology specified */
@@ -4300,7 +4264,7 @@ dfs_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
  */
 void
 choose_random_connections(struct GNUNET_TESTING_PeerGroup *pg,
-    double percentage)
+                          double percentage)
 {
   struct RandomContext random_ctx;
   uint32_t pg_iter;
@@ -4802,7 +4766,7 @@ perform_dfs(struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
  */
 static void
 internal_topology_callback(void *cls, const struct GNUNET_PeerIdentity *peer,
-    const struct GNUNET_TRANSPORT_ATS_Information *atsi)
+                           const struct GNUNET_TRANSPORT_ATS_Information *atsi)
 {
   struct CoreContext *core_ctx = cls;
   struct TopologyIterateContext *iter_ctx = core_ctx->iter_context;
@@ -4837,7 +4801,7 @@ schedule_get_topology(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   struct CoreContext *core_context = cls;
   struct TopologyIterateContext *topology_context =
       (struct TopologyIterateContext *) core_context->iter_context;
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     return;
 
   if (topology_context->connected
@@ -4879,7 +4843,7 @@ schedule_get_topology(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  */
 void
 GNUNET_TESTING_get_topology(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_NotifyTopology cb, void *cls)
+                            GNUNET_TESTING_NotifyTopology cb, void *cls)
 {
   struct TopologyIterateContext *topology_context;
   struct CoreContext *core_ctx;
@@ -4930,7 +4894,7 @@ GNUNET_TESTING_get_topology(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static int
 internal_stats_callback(void *cls, const char *subsystem, const char *name,
-    uint64_t value, int is_persistent)
+                        uint64_t value, int is_persistent)
 {
   struct StatsCoreContext *core_context = cls;
   struct StatsIterateContext *stats_context =
@@ -4975,13 +4939,13 @@ internal_stats_cont(void *cls, int success)
  */
 static void
 schedule_get_statistics(void *cls,
-    const struct GNUNET_SCHEDULER_TaskContext *tc)
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct StatsCoreContext *core_context = cls;
   struct StatsIterateContext *stats_context =
       (struct StatsIterateContext *) core_context->iter_context;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     return;
 
   if (stats_context->connected > stats_context->pg->max_outstanding_connections)
@@ -5051,7 +5015,8 @@ struct DuplicateStats
  */
 static int
 stats_check_existing(struct GNUNET_TESTING_PeerGroup *pg,
-    struct PeerData *specific_peer, struct DuplicateStats **stats_list)
+                     struct PeerData *specific_peer,
+                     struct DuplicateStats **stats_list)
 {
   struct DuplicateStats *pos;
   char *unix_domain_socket;
@@ -5107,8 +5072,9 @@ stats_check_existing(struct GNUNET_TESTING_PeerGroup *pg,
  */
 void
 GNUNET_TESTING_get_statistics(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_STATISTICS_Callback cont, GNUNET_TESTING_STATISTICS_Iterator proc,
-    void *cls)
+                              GNUNET_STATISTICS_Callback cont,
+                              GNUNET_TESTING_STATISTICS_Iterator proc,
+                              void *cls)
 {
   struct StatsIterateContext *stats_context;
   struct StatsCoreContext *core_ctx;
@@ -5203,11 +5169,15 @@ GNUNET_TESTING_resume_connections(struct GNUNET_TESTING_PeerGroup *pg)
  * @return the number of connections that will be attempted, GNUNET_SYSERR on error
  */
 int
-GNUNET_TESTING_connect_topology(struct GNUNET_TESTING_PeerGroup *pg,
-    enum GNUNET_TESTING_Topology topology,
-    enum GNUNET_TESTING_TopologyOption options, double option_modifier,
-    struct GNUNET_TIME_Relative connect_timeout, unsigned int connect_attempts,
-    GNUNET_TESTING_NotifyCompletion notify_callback, void *notify_cls)
+GNUNET_TESTING_connect_topology(
+                                struct GNUNET_TESTING_PeerGroup *pg,
+                                enum GNUNET_TESTING_Topology topology,
+                                enum GNUNET_TESTING_TopologyOption options,
+                                double option_modifier,
+                                struct GNUNET_TIME_Relative connect_timeout,
+                                unsigned int connect_attempts,
+                                GNUNET_TESTING_NotifyCompletion notify_callback,
+                                void *notify_cls)
 {
   switch (topology)
     {
@@ -5346,7 +5316,7 @@ GNUNET_TESTING_connect_topology(struct GNUNET_TESTING_PeerGroup *pg,
  */
 static unsigned int
 count_outstanding_at_host(const char *hostname,
-    struct GNUNET_TESTING_PeerGroup *pg)
+                          struct GNUNET_TESTING_PeerGroup *pg)
 {
   struct OutstandingSSH *pos;
   pos = pg->ssh_head;
@@ -5365,7 +5335,7 @@ count_outstanding_at_host(const char *hostname,
  */
 static void
 increment_outstanding_at_host(const char *hostname,
-    struct GNUNET_TESTING_PeerGroup *pg)
+                              struct GNUNET_TESTING_PeerGroup *pg)
 {
   struct OutstandingSSH *pos;
   pos = pg->ssh_head;
@@ -5384,7 +5354,7 @@ increment_outstanding_at_host(const char *hostname,
  */
 static void
 decrement_outstanding_at_host(const char *hostname,
-    struct GNUNET_TESTING_PeerGroup *pg)
+                              struct GNUNET_TESTING_PeerGroup *pg)
 {
   struct OutstandingSSH *pos;
   pos = pg->ssh_head;
@@ -5406,7 +5376,7 @@ decrement_outstanding_at_host(const char *hostname,
  */
 static void
 internal_hostkey_callback(void *cls, const struct GNUNET_PeerIdentity *id,
-    struct GNUNET_TESTING_Daemon *d, const char *emsg)
+                          struct GNUNET_TESTING_Daemon *d, const char *emsg)
 {
   struct InternalStartContext *internal_context = cls;
   internal_context->peer->pg->starting--;
@@ -5438,8 +5408,8 @@ internal_hostkey_callback(void *cls, const struct GNUNET_PeerIdentity *id,
  */
 static void
 internal_startup_callback(void *cls, const struct GNUNET_PeerIdentity *id,
-    const struct GNUNET_CONFIGURATION_Handle *cfg,
-    struct GNUNET_TESTING_Daemon *d, const char *emsg)
+                          const struct GNUNET_CONFIGURATION_Handle *cfg,
+                          struct GNUNET_TESTING_Daemon *d, const char *emsg)
 {
   struct InternalStartContext *internal_context = cls;
   internal_context->peer->pg->starting--;
@@ -5453,11 +5423,11 @@ internal_startup_callback(void *cls, const struct GNUNET_PeerIdentity *id,
 
 static void
 internal_continue_startup(void *cls,
-    const struct GNUNET_SCHEDULER_TaskContext *tc)
+                          const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct InternalStartContext *internal_context = cls;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     {
       return;
     }
@@ -5499,8 +5469,8 @@ internal_continue_startup(void *cls,
  */
 void
 churn_start_callback(void *cls, const struct GNUNET_PeerIdentity *id,
-    const struct GNUNET_CONFIGURATION_Handle *cfg,
-    struct GNUNET_TESTING_Daemon *d, const char *emsg)
+                     const struct GNUNET_CONFIGURATION_Handle *cfg,
+                     struct GNUNET_TESTING_Daemon *d, const char *emsg)
 {
   struct ChurnRestartContext *startup_ctx = cls;
   struct ChurnContext *churn_ctx = startup_ctx->churn_ctx;
@@ -5564,12 +5534,13 @@ schedule_churn_restart(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     }
 }
 
+
 static void
 internal_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct InternalStartContext *internal_context = cls;
 
-  if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
+  if ( (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
     {
       return;
     }
@@ -5588,6 +5559,7 @@ internal_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
       internal_context->peer->daemon
           = GNUNET_TESTING_daemon_start (internal_context->peer->cfg,
                                          internal_context->timeout,
+                                         GNUNET_NO,
                                          internal_context->hostname,
                                          internal_context->username,
                                          internal_context->sshport,
@@ -5606,6 +5578,89 @@ internal_start(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
                                     &internal_start, internal_context);
     }
 }
+#if USE_START_HELPER
+
+struct PeerStartHelperContext
+{
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  struct HostData *host;
+
+  struct GNUNET_OS_Process *proc;
+};
+
+static void
+check_peers_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerStartHelperContext *helper = cls;
+  enum GNUNET_OS_ProcessStatusType type;
+  unsigned long code;
+  unsigned int i;
+  GNUNET_TESTING_NotifyDaemonRunning cb;
+
+  if (GNUNET_NO == GNUNET_OS_process_status (helper->proc, &type, &code)) /* Still running, wait some more! */
+  {
+    GNUNET_SCHEDULER_add_delayed(GNUNET_CONSTANTS_EXEC_WAIT, &check_peers_started, helper);
+    return;
+  }
+
+  helper->pg->starting--;
+  if (helper->pg->starting == 0) /* All peers have finished starting! */
+    {
+      /* Call the peer started callback for each peer, set proper FSM state (?) */
+      for (i = 0; i < helper->pg->total; i++)
+        {
+          cb = helper->pg->peers[i].daemon->cb;
+          helper->pg->peers[i].daemon->cb = NULL;
+          helper->pg->peers[i].daemon->running = GNUNET_YES;
+          helper->pg->peers[i].daemon->phase = SP_START_DONE;
+          if (NULL != cb)
+          {
+            if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+              cb (helper->pg->peers[i].daemon->cb_cls,
+                  &helper->pg->peers[i].daemon->id,
+                  helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon,
+                  "Failed to execute peerStartHelper.pl, or return code bad!");
+            else
+              cb (helper->pg->peers[i].daemon->cb_cls,
+                  &helper->pg->peers[i].daemon->id,
+                  helper->pg->peers[i].daemon->cfg, helper->pg->peers[i].daemon,
+                  NULL);
+
+          }
+
+        }
+    }
+  GNUNET_OS_process_close(helper->proc);
+}
+
+static void
+start_peer_helper (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerStartHelperContext *helper = cls;
+  char *baseservicehome;
+  char *tempdir;
+  char *arg;
+  /* ssh user@host peerStartHelper /path/to/basedirectory */
+  GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (helper->pg->cfg, "PATHS", "SERVICEHOME",
+                                                                    &baseservicehome));
+  GNUNET_asprintf(&tempdir, "%s/%s/", baseservicehome, helper->host->hostname);
+  if (NULL != helper->host->username)
+    GNUNET_asprintf (&arg, "%s@%s", helper->host->username, helper->host->hostname);
+  else
+    GNUNET_asprintf (&arg, "%s", helper->host->hostname);
+
+  /* FIXME: Doesn't support ssh_port option! */
+  helper->proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", arg,
+                                  "peerStartHelper.pl", tempdir,  NULL);
+  GNUNET_assert(helper->proc != NULL);
+  GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "starting peers with cmd ssh %s %s %s\n", arg, "peerStartHelper.pl", tempdir);
+  GNUNET_SCHEDULER_add_now (&check_peers_started, helper);
+  GNUNET_free (tempdir);
+  GNUNET_free (baseservicehome);
+  GNUNET_free (arg);
+}
+#endif
 
 /**
  * Function which continues a peer group starting up
@@ -5619,14 +5674,57 @@ GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg)
 {
   unsigned int i;
 
+#if USE_START_HELPER
+  if ((pg->num_hosts > 0) && (pg->hostkey_data != NULL))
+    {
+      struct PeerStartHelperContext *helper;
+      pg->starting = pg->num_hosts;
+      for (i = 0; i < pg->num_hosts; i++)
+        {
+          helper = GNUNET_malloc(sizeof(struct PeerStartHelperContext));
+          helper->pg = pg;
+          helper->host = &pg->hosts[i];
+          GNUNET_SCHEDULER_add_now(&start_peer_helper, helper);
+        }
+    }
+  else
+    {
+      pg->starting = 0;
+      for (i = 0; i < pg->total; i++)
+        {
+          GNUNET_SCHEDULER_add_now (&internal_continue_startup,
+                                    &pg->peers[i].internal_context);
+        }
+    }
+#else
   pg->starting = 0;
   for (i = 0; i < pg->total; i++)
     {
       GNUNET_SCHEDULER_add_now (&internal_continue_startup,
                                 &pg->peers[i].internal_context);
-      //GNUNET_TESTING_daemon_continue_startup(pg->peers[i].daemon);
     }
+#endif
+}
+
+#if USE_START_HELPER
+static void
+call_hostkey_callbacks (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_PeerGroup *pg = cls;
+  unsigned int i;
+  for (i = 0; i < pg->total; i++)
+    {
+      if (pg->peers[i].internal_context.hostkey_callback != NULL)
+        pg->peers[i].internal_context.hostkey_callback (pg->peers[i].internal_context.hostkey_cls,
+                                                           &pg->peers[i].daemon->id,
+                                                           pg->peers[i].daemon,
+                                                           NULL);
+    }
+
+  if (pg->peers[0].internal_context.hostkey_callback == NULL)
+    GNUNET_TESTING_daemons_continue_startup (pg);
 }
+#endif
 
 /**
  * Start count gnunet instances with the same set of transports and
@@ -5657,20 +5755,20 @@ GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg)
  */
 struct GNUNET_TESTING_PeerGroup *
 GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
-    unsigned int total, unsigned int max_concurrent_connections,
-    unsigned int max_concurrent_ssh, struct GNUNET_TIME_Relative timeout,
-    GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback, void *hostkey_cls,
-    GNUNET_TESTING_NotifyDaemonRunning cb, void *cb_cls,
-    GNUNET_TESTING_NotifyConnection connect_callback,
-    void *connect_callback_cls, const struct GNUNET_TESTING_Host *hostnames)
+                             unsigned int total,
+                             unsigned int max_concurrent_connections,
+                             unsigned int max_concurrent_ssh,
+                             struct GNUNET_TIME_Relative timeout,
+                             GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
+                             void *hostkey_cls,
+                             GNUNET_TESTING_NotifyDaemonRunning cb,
+                             void *cb_cls,
+                             GNUNET_TESTING_NotifyConnection connect_callback,
+                             void *connect_callback_cls,
+                             const struct GNUNET_TESTING_Host *hostnames)
 {
   struct GNUNET_TESTING_PeerGroup *pg;
   const struct GNUNET_TESTING_Host *hostpos;
-#if 0
-  char *pos;
-  const char *rpos;
-  char *start;
-#endif
   const char *hostname;
   const char *username;
   char *baseservicehome;
@@ -5682,6 +5780,7 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
   struct GNUNET_DISK_FileHandle *fd;
   struct GNUNET_CONFIGURATION_Handle *pcfg;
   unsigned int off;
+  struct OutstandingSSH *ssh_entry;
   unsigned int hostcnt;
   unsigned int i;
   uint16_t minport;
@@ -5692,6 +5791,7 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
   uint64_t total_hostkeys;
   struct GNUNET_OS_Process *proc;
 
+  username = NULL;
   if (0 == total)
     {
       GNUNET_break (0);
@@ -5740,51 +5840,6 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
       hostcnt = off;
       minport = 0;
       pg->num_hosts = off;
-
-#if NO_LL
-      off = 2;
-      /* skip leading spaces */
-      while ((0 != *hostnames) && (isspace ((unsigned char) *hostnames)))
-      hostnames++;
-      rpos = hostnames;
-      while ('\0' != *rpos)
-        {
-          if (isspace ((unsigned char) *rpos))
-          off++;
-          rpos++;
-        }
-      pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
-      off = 0;
-      start = GNUNET_strdup (hostnames);
-      pos = start;
-      while ('\0' != *pos)
-        {
-          if (isspace ((unsigned char) *pos))
-            {
-              *pos = '\0';
-              if (strlen (start) > 0)
-                {
-                  pg->hosts[off].minport = LOW_PORT;
-                  pg->hosts[off++].hostname = start;
-                }
-              start = pos + 1;
-            }
-          pos++;
-        }
-      if (strlen (start) > 0)
-        {
-          pg->hosts[off].minport = LOW_PORT;
-          pg->hosts[off++].hostname = start;
-        }
-      if (off == 0)
-        {
-          GNUNET_free (start);
-          GNUNET_free (pg->hosts);
-          pg->hosts = NULL;
-        }
-      hostcnt = off;
-      minport = 0; /* make gcc happy */
-#endif
     }
   else
     {
@@ -5794,13 +5849,13 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
 
   /* Create the servicehome directory for each remote peer */
   GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
-          &baseservicehome));
+                                                                    &baseservicehome));
   for (i = 0; i < pg->num_hosts; i++)
     {
-      struct OutstandingSSH *ssh_entry;
       ssh_entry = GNUNET_malloc(sizeof(struct OutstandingSSH));
       ssh_entry->hostname = pg->hosts[i].hostname; /* Don't free! */
       GNUNET_CONTAINER_DLL_insert(pg->ssh_head, pg->ssh_tail, ssh_entry);
+      GNUNET_asprintf(&tmpdir, "%s/%s", baseservicehome, pg->hosts[i].hostname);
       if (NULL != pg->hosts[i].username)
         GNUNET_asprintf (&arg, "%s@%s", pg->hosts[i].username,
                          pg->hosts[i].hostname);
@@ -5814,16 +5869,20 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
 #if !DEBUG_TESTING
                                           "-q",
 #endif
-                                          arg, "mkdir -p", baseservicehome,
+                                          arg, "mkdir -p", tmpdir,
                                           NULL);
         }
       else
         proc = GNUNET_OS_start_process (NULL, NULL, "ssh", "ssh", arg,
-                                        "mkdir -p", baseservicehome, NULL);
+                                        "mkdir -p", tmpdir, NULL);
+      GNUNET_assert(proc != NULL);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                   "Creating remote dir with command ssh %s %s %s\n", arg,
-                  " mkdir -p ", baseservicehome);
+                  " mkdir -p ", tmpdir);
+      GNUNET_free(tmpdir);
+      GNUNET_free(arg);
       GNUNET_OS_process_wait (proc);
+      GNUNET_OS_process_close(proc);
     }
   GNUNET_free(baseservicehome);
 
@@ -5849,7 +5908,7 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
             fs = 0;
 
           GNUNET_log (
-                      GNUNET_ERROR_TYPE_WARNING,
+                      GNUNET_ERROR_TYPE_DEBUG,
                       "Found file size %llu for hostkeys, expect hostkeys to be size %d\n",
                       fs, HOSTKEYFILESIZE);
 
@@ -5862,7 +5921,7 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
           else
             {
               total_hostkeys = fs / HOSTKEYFILESIZE;
-              GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
                           "Will read %llu hostkeys from file\n", total_hostkeys);
               pg->hostkey_data = GNUNET_malloc_large (fs);
               GNUNET_assert (fs == GNUNET_DISK_file_read (fd, pg->hostkey_data, fs));
@@ -5903,30 +5962,29 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
                                                     "SERVICEHOME",
                                                     &baseservicehome))
         {
-          GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off);
+          if (hostname != NULL)
+            GNUNET_asprintf (&newservicehome, "%s/%s/%d/", baseservicehome, hostname, off);
+          else
+            GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off);
+#if !USE_START_HELPER
           GNUNET_free (baseservicehome);
+#endif
         }
       else
         {
           tmpdir = getenv ("TMPDIR");
           tmpdir = tmpdir ? tmpdir : "/tmp";
-          GNUNET_asprintf (&newservicehome, "%s/%s/%d/", tmpdir,
-                           "gnunet-testing-test-test", off);
+          if (hostname != NULL)
+            GNUNET_asprintf (&newservicehome, "%s/%s/%s/%d/", tmpdir, hostname,
+                             "gnunet-testing-test-test", off);
+          else
+            GNUNET_asprintf (&newservicehome, "%s/%s/%d/", tmpdir,
+                             "gnunet-testing-test-test", off);
         }
       GNUNET_CONFIGURATION_set_value_string (pcfg, "PATHS", "SERVICEHOME",
                                              newservicehome);
       GNUNET_free (newservicehome);
       pg->peers[off].cfg = pcfg;
-#if DEFER
-      /* Can we do this later? */
-      pg->peers[off].allowed_peers =
-      GNUNET_CONTAINER_multihashmap_create (total);
-      pg->peers[off].connect_peers =
-      GNUNET_CONTAINER_multihashmap_create (total);
-      pg->peers[off].blacklisted_peers =
-      GNUNET_CONTAINER_multihashmap_create (total);
-
-#endif
       pg->peers[off].pg = pg;
       pg->peers[off].internal_context.peer = &pg->peers[off];
       pg->peers[off].internal_context.timeout = timeout;
@@ -5940,11 +5998,77 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
       pg->peers[off].internal_context.hostkey_cls = hostkey_cls;
       pg->peers[off].internal_context.start_cb = cb;
       pg->peers[off].internal_context.start_cb_cls = cb_cls;
-
+#if !USE_START_HELPER
       GNUNET_SCHEDULER_add_now (&internal_start,
                                 &pg->peers[off].internal_context);
+#else
+      if ((pg->hostkey_data != NULL) && (hostcnt > 0))
+        {
+          pg->peers[off].daemon = GNUNET_TESTING_daemon_start (pcfg,
+                                       timeout,
+                                       GNUNET_YES,
+                                       hostname,
+                                       username,
+                                       sshport,
+                                       pg->peers[off].internal_context.hostkey,
+                                       &internal_hostkey_callback,
+                                       &pg->peers[off].internal_context,
+                                       &internal_startup_callback,
+                                       &pg->peers[off].internal_context);
+          /**
+           * At this point, given that we had a hostkeyfile,
+           * we can call the hostkey callback!
+           * But first, we should copy (rsync) all of the configs
+           * and hostkeys to the remote peers.  Then let topology
+           * creation happen, then call the peer start helper processes,
+           * then set pg->whatever_phase for each peer and let them
+           * enter the fsm to get the HELLO's for peers and start connecting.
+           */
+        }
+      else
+        {
+          GNUNET_SCHEDULER_add_now (&internal_start,
+                                    &pg->peers[off].internal_context);
+        }
 
+#endif
     }
+
+#if USE_START_HELPER /* Now the peergroup has been set up, hostkeys and configs written to files. */
+  if ((pg->hostkey_data != NULL) && (hostcnt > 0))
+    {
+      for (off = 0; off < hostcnt; off++)
+        {
+          GNUNET_asprintf(&newservicehome, "%s/%s/", baseservicehome, pg->hosts[off].hostname);
+
+          if (NULL != username)
+            GNUNET_asprintf (&arg, "%s@%s:%s/%s", username, pg->hosts[off].hostname, baseservicehome, pg->hosts[off].hostname);
+          else
+            GNUNET_asprintf (&arg, "%s:%s/%s", pg->hosts[off].hostname, baseservicehome, pg->hosts[off].hostname);
+
+          /* FIXME: Doesn't support ssh_port option! */
+          proc = GNUNET_OS_start_process (NULL, NULL, "rsync", "rsync", "-r", newservicehome, arg, NULL);
+
+          GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "copying directory with command rsync -r %s %s\n", newservicehome, arg);
+
+          GNUNET_free (arg);
+          if (NULL == proc)
+            {
+              GNUNET_log (
+                          GNUNET_ERROR_TYPE_ERROR,
+                          _
+                          ("Could not start `%s' process to copy configuration directory.\n"),
+                          "scp");
+              GNUNET_assert(0);
+            }
+          GNUNET_OS_process_wait (proc);
+          GNUNET_OS_process_close (proc);
+        }
+      /* Now all the configuration files and hostkeys are copied to the remote host.  Call the hostkey callback for each peer! */
+      GNUNET_SCHEDULER_add_now(&call_hostkey_callbacks, pg);
+    }
+  GNUNET_free (baseservicehome);
+#endif
   return pg;
 }
 
@@ -5954,7 +6078,7 @@ GNUNET_TESTING_daemons_start(const struct GNUNET_CONFIGURATION_Handle *cfg,
  */
 struct GNUNET_TESTING_Daemon *
 GNUNET_TESTING_daemon_get(struct GNUNET_TESTING_PeerGroup *pg,
-    unsigned int position)
+                          unsigned int position)
 {
   if (position < pg->total)
     return pg->peers[position].daemon;
@@ -5973,7 +6097,7 @@ GNUNET_TESTING_daemon_get(struct GNUNET_TESTING_PeerGroup *pg,
  */
 struct GNUNET_TESTING_Daemon *
 GNUNET_TESTING_daemon_get_by_id(struct GNUNET_TESTING_PeerGroup *pg,
-    struct GNUNET_PeerIdentity *peer_id)
+                                struct GNUNET_PeerIdentity *peer_id)
 {
   unsigned int i;
 
@@ -5999,8 +6123,8 @@ GNUNET_TESTING_daemon_get_by_id(struct GNUNET_TESTING_PeerGroup *pg,
  */
 void
 restart_callback(void *cls, const struct GNUNET_PeerIdentity *id,
-    const struct GNUNET_CONFIGURATION_Handle *cfg,
-    struct GNUNET_TESTING_Daemon *d, const char *emsg)
+                 const struct GNUNET_CONFIGURATION_Handle *cfg,
+                 struct GNUNET_TESTING_Daemon *d, const char *emsg)
 {
   struct RestartContext *restart_context = cls;
 
@@ -6114,7 +6238,7 @@ GNUNET_TESTING_daemons_running(struct GNUNET_TESTING_PeerGroup *pg)
  */
 static void
 schedule_churn_shutdown_task(void *cls,
-    const struct GNUNET_SCHEDULER_TaskContext *tc)
+                             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct PeerShutdownContext *peer_shutdown_ctx = cls;
   struct ShutdownContext *shutdown_ctx;
@@ -6162,8 +6286,9 @@ schedule_churn_shutdown_task(void *cls,
  */
 void
 GNUNET_TESTING_daemons_churn(struct GNUNET_TESTING_PeerGroup *pg,
-    unsigned int voff, unsigned int von, struct GNUNET_TIME_Relative timeout,
-    GNUNET_TESTING_NotifyCompletion cb, void *cb_cls)
+                             unsigned int voff, unsigned int von,
+                             struct GNUNET_TIME_Relative timeout,
+                             GNUNET_TESTING_NotifyCompletion cb, void *cb_cls)
 {
   struct ChurnContext *churn_ctx;
   struct ShutdownContext *shutdown_ctx;
@@ -6181,6 +6306,11 @@ GNUNET_TESTING_daemons_churn(struct GNUNET_TESTING_PeerGroup *pg,
   unsigned int *running_permute;
   unsigned int *stopped_permute;
 
+  shutdown_ctx = NULL;
+  peer_shutdown_ctx = NULL;
+  peer_restart_ctx = NULL;
+  churn_startup_ctx = NULL;
+
   running = 0;
   stopped = 0;
 
@@ -6338,7 +6468,8 @@ GNUNET_TESTING_daemons_churn(struct GNUNET_TESTING_PeerGroup *pg,
  */
 void
 GNUNET_TESTING_daemons_restart(struct GNUNET_TESTING_PeerGroup *pg,
-    GNUNET_TESTING_NotifyCompletion callback, void *callback_cls)
+                               GNUNET_TESTING_NotifyCompletion callback,
+                               void *callback_cls)
 {
   struct RestartContext *restart_context;
   unsigned int off;
@@ -6371,9 +6502,9 @@ GNUNET_TESTING_daemons_restart(struct GNUNET_TESTING_PeerGroup *pg,
  */
 void
 GNUNET_TESTING_daemons_vary(struct GNUNET_TESTING_PeerGroup *pg,
-    unsigned int offset, int desired_status,
-    struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyCompletion cb,
-    void *cb_cls)
+                            unsigned int offset, int desired_status,
+                            struct GNUNET_TIME_Relative timeout,
+                            GNUNET_TESTING_NotifyCompletion cb, void *cb_cls)
 {
   struct ShutdownContext *shutdown_ctx;
   struct ChurnRestartContext *startup_ctx;
@@ -6424,10 +6555,16 @@ GNUNET_TESTING_daemons_vary(struct GNUNET_TESTING_PeerGroup *pg,
 void
 internal_shutdown_callback(void *cls, const char *emsg)
 {
-  struct ShutdownContext *shutdown_ctx = cls;
+  struct PeerShutdownContext *peer_shutdown_ctx = cls;
+  struct ShutdownContext *shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
   unsigned int off;
+  struct OutstandingSSH *ssh_pos;
 
   shutdown_ctx->outstanding--;
+  if (peer_shutdown_ctx->daemon->hostname != NULL)
+    decrement_outstanding_at_host (peer_shutdown_ctx->daemon->hostname,
+                                   shutdown_ctx->pg);
+
   if (emsg == NULL)
     {
       shutdown_ctx->peers_down++;
@@ -6454,10 +6591,15 @@ internal_shutdown_callback(void *cls, const char *emsg)
           GNUNET_free_non_null (shutdown_ctx->pg->hosts[off].username);
         }
       GNUNET_free_non_null (shutdown_ctx->pg->hosts);
+      while (NULL != (ssh_pos = shutdown_ctx->pg->ssh_head))
+        {
+          GNUNET_CONTAINER_DLL_remove(shutdown_ctx->pg->ssh_head, shutdown_ctx->pg->ssh_tail, ssh_pos);
+          GNUNET_free(ssh_pos);
+        }
       GNUNET_free (shutdown_ctx->pg);
-
       GNUNET_free (shutdown_ctx);
     }
+  GNUNET_free(peer_shutdown_ctx);
 }
 
 /**
@@ -6477,21 +6619,26 @@ schedule_shutdown_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
   GNUNET_assert (shutdown_ctx != NULL);
 
-  if (shutdown_ctx->outstanding > shutdown_ctx->pg->max_concurrent_ssh)
-    GNUNET_SCHEDULER_add_delayed (
-                                  GNUNET_TIME_relative_multiply (
-                                                                 GNUNET_TIME_UNIT_MILLISECONDS,
-                                                                 100),
-                                  &schedule_shutdown_task, peer_shutdown_ctx);
-  else
+  if ((shutdown_ctx->outstanding < shutdown_ctx->pg->max_concurrent_ssh)
+      || ((peer_shutdown_ctx->daemon->hostname != NULL)
+          && (count_outstanding_at_host (peer_shutdown_ctx->daemon->hostname,
+                                         shutdown_ctx->pg)
+              < shutdown_ctx->pg->max_concurrent_ssh)))
     {
+      if (peer_shutdown_ctx->daemon->hostname != NULL)
+        increment_outstanding_at_host (peer_shutdown_ctx->daemon->hostname,
+                                       shutdown_ctx->pg);
       shutdown_ctx->outstanding++;
       GNUNET_TESTING_daemon_stop (peer_shutdown_ctx->daemon,
                                   shutdown_ctx->timeout,
-                                  &internal_shutdown_callback, shutdown_ctx,
+                                  &internal_shutdown_callback, peer_shutdown_ctx,
                                   GNUNET_YES, GNUNET_NO);
-      GNUNET_free (peer_shutdown_ctx);
     }
+  else
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS,
+                                                                 100),
+                                  &schedule_shutdown_task, peer_shutdown_ctx);
+
 }
 
 /**
@@ -6504,8 +6651,8 @@ schedule_shutdown_task(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  */
 void
 GNUNET_TESTING_daemons_stop(struct GNUNET_TESTING_PeerGroup *pg,
-    struct GNUNET_TIME_Relative timeout, GNUNET_TESTING_NotifyCompletion cb,
-    void *cb_cls)
+                            struct GNUNET_TIME_Relative timeout,
+                            GNUNET_TESTING_NotifyCompletion cb, void *cb_cls)
 {
   unsigned int off;
   struct ShutdownContext *shutdown_ctx;
@@ -6534,7 +6681,10 @@ GNUNET_TESTING_daemons_stop(struct GNUNET_TESTING_PeerGroup *pg,
       GNUNET_SCHEDULER_add_now (&schedule_shutdown_task, peer_shutdown_ctx);
 
       if (NULL != pg->peers[off].cfg)
+      {
         GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
+        pg->peers[off].cfg = NULL;
+      }
 #if OLD
       conn_iter = pg->peers[off].allowed_peers_head;
       while (conn_iter != NULL)
@@ -6577,7 +6727,6 @@ GNUNET_TESTING_daemons_stop(struct GNUNET_TESTING_PeerGroup *pg,
           peers[off].blacklisted_peers);
 #endif
     }
-
 }
 
 /* end of testing_group.c */