-moving old testing code to legacy location
authorChristian Grothoff <christian@grothoff.org>
Sat, 9 Jun 2012 15:35:06 +0000 (15:35 +0000)
committerChristian Grothoff <christian@grothoff.org>
Sat, 9 Jun 2012 15:35:06 +0000 (15:35 +0000)
88 files changed:
configure.ac
src/Makefile.am
src/dht/Makefile.am
src/fs/Makefile.am
src/mesh/Makefile.am
src/nse/Makefile.am
src/testing/Makefile.am
src/testing/gnunet-testing-remote-peer-start.pl [deleted file]
src/testing/gnunet-testing.c [deleted file]
src/testing/helper.c [deleted file]
src/testing/test_testing.c [deleted file]
src/testing/test_testing_2dtorus.c [deleted file]
src/testing/test_testing_2dtorus.conf [deleted file]
src/testing/test_testing_connect.c [deleted file]
src/testing/test_testing_connect_peer1.conf [deleted file]
src/testing/test_testing_connect_peer2.conf [deleted file]
src/testing/test_testing_data.conf [deleted file]
src/testing/test_testing_data_remote.conf [deleted file]
src/testing/test_testing_data_topology_2d_torus.conf [deleted file]
src/testing/test_testing_data_topology_blacklist.conf [deleted file]
src/testing/test_testing_data_topology_churn.conf [deleted file]
src/testing/test_testing_data_topology_clique.conf [deleted file]
src/testing/test_testing_data_topology_clique_dfs.conf [deleted file]
src/testing/test_testing_data_topology_clique_minimum.conf [deleted file]
src/testing/test_testing_data_topology_clique_random.conf [deleted file]
src/testing/test_testing_data_topology_erdos_renyi.conf [deleted file]
src/testing/test_testing_data_topology_internat.conf [deleted file]
src/testing/test_testing_data_topology_none.conf [deleted file]
src/testing/test_testing_data_topology_ring.conf [deleted file]
src/testing/test_testing_data_topology_scale_free.conf [deleted file]
src/testing/test_testing_data_topology_small_world_ring.conf [deleted file]
src/testing/test_testing_data_topology_small_world_torus.conf [deleted file]
src/testing/test_testing_data_topology_stability.conf [deleted file]
src/testing/test_testing_defaults.conf [deleted file]
src/testing/test_testing_group.c [deleted file]
src/testing/test_testing_group_remote.c [deleted file]
src/testing/test_testing_large_topology.c [deleted file]
src/testing/test_testing_peergroup.c [deleted file]
src/testing/test_testing_peergroup_data.conf [deleted file]
src/testing/test_testing_reconnect.c [deleted file]
src/testing/test_testing_topology.c [deleted file]
src/testing/test_testing_topology_blacklist.c [deleted file]
src/testing/test_testing_topology_churn.c [deleted file]
src/testing/testing.c [deleted file]
src/testing/testing_group.c [deleted file]
src/testing/testing_peergroup.c [deleted file]
src/testing_old/Makefile.am [new file with mode: 0644]
src/testing_old/gnunet-testing-remote-peer-start.pl [new file with mode: 0755]
src/testing_old/gnunet-testing.c [new file with mode: 0644]
src/testing_old/helper.c [new file with mode: 0644]
src/testing_old/test_testing.c [new file with mode: 0644]
src/testing_old/test_testing_2dtorus.c [new file with mode: 0644]
src/testing_old/test_testing_2dtorus.conf [new file with mode: 0644]
src/testing_old/test_testing_connect.c [new file with mode: 0644]
src/testing_old/test_testing_connect_peer1.conf [new file with mode: 0644]
src/testing_old/test_testing_connect_peer2.conf [new file with mode: 0644]
src/testing_old/test_testing_data.conf [new file with mode: 0644]
src/testing_old/test_testing_data_remote.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_2d_torus.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_blacklist.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_churn.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_clique.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_clique_dfs.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_clique_minimum.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_clique_random.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_erdos_renyi.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_internat.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_none.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_ring.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_scale_free.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_small_world_ring.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_small_world_torus.conf [new file with mode: 0644]
src/testing_old/test_testing_data_topology_stability.conf [new file with mode: 0644]
src/testing_old/test_testing_defaults.conf [new file with mode: 0644]
src/testing_old/test_testing_group.c [new file with mode: 0644]
src/testing_old/test_testing_group_remote.c [new file with mode: 0644]
src/testing_old/test_testing_large_topology.c [new file with mode: 0644]
src/testing_old/test_testing_peergroup.c [new file with mode: 0644]
src/testing_old/test_testing_peergroup_data.conf [new file with mode: 0644]
src/testing_old/test_testing_reconnect.c [new file with mode: 0644]
src/testing_old/test_testing_topology.c [new file with mode: 0644]
src/testing_old/test_testing_topology_blacklist.c [new file with mode: 0644]
src/testing_old/test_testing_topology_churn.c [new file with mode: 0644]
src/testing_old/testing.c [new file with mode: 0644]
src/testing_old/testing.conf [new file with mode: 0644]
src/testing_old/testing_group.c [new file with mode: 0644]
src/testing_old/testing_peergroup.c [new file with mode: 0644]
src/topology/Makefile.am

index e7418a6675e77a5dabd020e707cf2509199f2aa9..e711a12a9c19445c0f7dc97a5e9abff4cf7648bf 100644 (file)
@@ -1058,6 +1058,7 @@ src/stream/Makefile
 src/template/Makefile
 src/testbed/Makefile
 src/testing/Makefile
+src/testing_old/Makefile
 src/topology/Makefile
 src/transport/Makefile
 src/transport/transport.conf
index 37bcbf676e50f2bce4bf70df6f1784000aa0e8d1..0afd180635af667074f20b9d96e512af6c162b8c 100644 (file)
@@ -28,6 +28,7 @@ SUBDIRS = \
   block \
   statistics \
   arm \
+  testing \
   peerinfo \
   $(MYSQL_DIR) \
   $(POSTGRES_DIR) \
@@ -41,7 +42,7 @@ SUBDIRS = \
   transport \
   peerinfo-tool \
   core \
-  testing \
+  testing_old \
   testbed \
   nse \
   dht \
index 0ea452db1f9741ca929093595792df7a8d01a3fd..0b840dc9af5a4aa42352150e8cd8bf063d79abc7 100644 (file)
@@ -141,7 +141,7 @@ test_dht_twopeer_SOURCES = \
  test_dht_twopeer.c
 test_dht_twopeer_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la    
 test_dht_twopeer_DEPENDENCIES = \
   libgnunetdht.la                          
@@ -150,21 +150,21 @@ test_dht_twopeer_put_get_SOURCES = \
  test_dht_twopeer_put_get.c
 test_dht_twopeer_put_get_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la   
 
 test_dht_twopeer_get_put_SOURCES = \
  test_dht_twopeer_get_put.c
 test_dht_twopeer_get_put_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la   
 
 test_dht_twopeer_path_tracking_SOURCES = \
  test_dht_twopeer_path_tracking.c
 test_dht_twopeer_path_tracking_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la   
 
 test_dht_multipeer_SOURCES = \
@@ -172,7 +172,7 @@ test_dht_multipeer_SOURCES = \
 test_dht_multipeer_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(top_builddir)/src/statistics/libgnunetstatistics.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la  
 test_dht_multipeer_DEPENDENCIES = \
   libgnunetdht.la                          
@@ -181,7 +181,7 @@ test_dht_2dtorus_SOURCES = \
  test_dht_topo.c
 test_dht_2dtorus_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la
 test_dht_2dtorus_DEPENDENCIES = \
   libgnunetdht.la
@@ -190,7 +190,7 @@ test_dht_line_SOURCES = \
  test_dht_topo.c
 test_dht_line_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la
 test_dht_line_DEPENDENCIES = \
   libgnunetdht.la
@@ -198,7 +198,7 @@ test_dht_line_DEPENDENCIES = \
 test_dht_monitor_SOURCES = test_dht_monitor.c
 test_dht_monitor_LDADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/dht/libgnunetdht.la
 test_dht_monitor_DEPENDENCIES = \
   libgnunetdht.la
index f68cad75b7fd6205b8335190355709326d445155..c88427d832c4e1dcc1e177e0c01723a876252497 100644 (file)
@@ -57,7 +57,7 @@ libgnunetfstest_a_SOURCES = \
   fs_test_lib.c fs_test_lib.h
 
 libgnunetfstest_a_LIBADD = \
-  $(top_builddir)/src/testing/libgnunettesting.la 
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la 
 
 bin_PROGRAMS = \
   gnunet-directory \
@@ -375,7 +375,7 @@ test_fs_test_lib_SOURCES = \
  test_fs_test_lib.c
 test_fs_test_lib_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
@@ -383,7 +383,7 @@ test_gnunet_service_fs_p2p_SOURCES = \
  test_gnunet_service_fs_p2p.c
 test_gnunet_service_fs_p2p_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
@@ -391,7 +391,7 @@ test_gnunet_service_fs_migration_SOURCES = \
  test_gnunet_service_fs_migration.c
 test_gnunet_service_fs_migration_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
@@ -400,7 +400,7 @@ perf_gnunet_service_fs_p2p_SOURCES = \
 perf_gnunet_service_fs_p2p_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
@@ -409,7 +409,7 @@ perf_gnunet_service_fs_p2p_index_SOURCES = \
 perf_gnunet_service_fs_p2p_index_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
@@ -418,7 +418,7 @@ perf_gnunet_service_fs_p2p_dht_SOURCES = \
 perf_gnunet_service_fs_p2p_dht_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
@@ -427,7 +427,7 @@ perf_gnunet_service_fs_p2p_trust_SOURCES = \
 perf_gnunet_service_fs_p2p_trust_LDADD = \
   $(top_builddir)/src/fs/libgnunetfstest.a \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(top_builddir)/src/fs/libgnunetfs.la  \
   $(top_builddir)/src/util/libgnunetutil.la  
 
index 4c5dbb5d95b711d8888d16d98d5f6271719fc835..e116b889a59913df8241e30a6908ea5a7b648ae9 100644 (file)
@@ -105,14 +105,14 @@ test_mesh_2dtorus_SOURCES = \
  test_mesh_2dtorus.c
 test_mesh_2dtorus_LDADD = \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la
 
 test_mesh_small_unicast_SOURCES = \
  test_mesh_small.c
 test_mesh_small_unicast_LDADD = \
   $(top_builddir)/src/mesh/libgnunetmesh.la \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la
 test_mesh_small_unicast_DEPENDENCIES = \
   libgnunetmesh.la
 
@@ -121,7 +121,7 @@ test_mesh_small_multicast_SOURCES = \
 test_mesh_small_multicast_LDADD = \
   $(top_builddir)/src/mesh/libgnunetmesh.la \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la
 test_mesh_small_multicast_DEPENDENCIES = \
   libgnunetmesh.la
 
@@ -130,7 +130,7 @@ test_mesh_small_speed_SOURCES = \
 test_mesh_small_speed_LDADD = \
   $(top_builddir)/src/mesh/libgnunetmesh.la \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la
 test_mesh_small_speed_DEPENDENCIES = \
   libgnunetmesh.la
 
@@ -139,7 +139,7 @@ test_mesh_small_speed_ack_SOURCES = \
 test_mesh_small_speed_ack_LDADD = \
   $(top_builddir)/src/mesh/libgnunetmesh.la \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la
 test_mesh_small_speed_ack_DEPENDENCIES = \
   libgnunetmesh.la
 
index 054a77663e2754c06a9143b5fbd18fcd4ca606a4..2011661cf9ad1527879563f1c0b929c6c022be94 100644 (file)
@@ -39,7 +39,7 @@ gnunet_nse_profiler_LDADD = -lm \
   $(top_builddir)/src/nse/libgnunetnse.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   $(GN_LIBINTL)
 gnunet_nse_profiler_DEPENDENCIES = \
   libgnunetnse.la                               
@@ -80,7 +80,7 @@ test_nse_multipeer_SOURCES = \
 test_nse_multipeer_LDADD = \
   $(top_builddir)/src/nse/libgnunetnse.la \
   $(top_builddir)/src/util/libgnunetutil.la \
-  $(top_builddir)/src/testing/libgnunettesting.la \
+  $(top_builddir)/src/testing_old/libgnunettesting_old.la \
   -lm
 
 EXTRA_DIST = \
index 455df6989d67c3dad40ec1556f5a0e3b837fbc83..dcefc34d1775ff764f5c199377e32c7a84c8b2db 100644 (file)
@@ -14,301 +14,46 @@ pkgcfgdir= $(pkgdatadir)/config.d/
 dist_pkgcfg_DATA = \
   testing.conf
 
-if HAVE_EXPENSIVE_TESTS
-  EXPENSIVE_TESTS = \
-   test_testing_topology_stability \
-   test_testing_topology_clique_random \
-   test_testing_topology_clique_minimum \
-   test_testing_topology_clique_dfs \
-   test_testing_topology_churn \
-   test_testing_topology_line \
-   test_testing_topology_blacklist \
-   test_testing_group_remote \
-   test_testing_topology_ring \
-   test_testing_topology_2d_torus \
-   test_testing_topology_small_world_ring \
-   test_testing_topology_small_world_torus \
-   test_testing_topology_erdos_renyi \
-   test_testing_topology_internat \
-   test_testing_topology_scale_free
-endif
-
 lib_LTLIBRARIES = \
-  libgnunettesting.la \
-  libgnunettesting_new.la
+  libgnunettesting.la 
 
 libgnunettesting_la_SOURCES = \
-  helper.c \
-  testing.c  \
-  testing_group.c \
-  testing_peergroup.c
-libgnunettesting_la_LIBADD = $(XLIB) \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/statistics/libgnunetstatistics.la \
- $(top_builddir)/src/transport/libgnunettransport.la \
- $(top_builddir)/src/hello/libgnunethello.la \
- -lm \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(LTLIBINTL)
-libgnunettesting_la_LDFLAGS = \
- $(GN_LIB_LDFLAGS) \
- -version-info 0:1:0
-
-
-libgnunettesting_new_la_SOURCES = \
   testing_new.c  
-libgnunettesting_new_la_LIBADD = \
+libgnunettesting_la_LIBADD = \
  $(top_builddir)/src/util/libgnunetutil.la \
  $(LTLIBINTL)
-libgnunettesting_new_la_LDFLAGS = \
+libgnunettesting_la_LDFLAGS = \
  $(GN_LIB_LDFLAGS) \
  -version-info 0:1:0
 
 
-bin_PROGRAMS = \
- gnunet-testing
-
 check_PROGRAMS = \
- test_testing \
- test_testing_connect \
- test_testing_reconnect \
- test_testing_group \
- test_testing_peergroup \
- test_testing_topology_stability \
- test_testing_topology_clique \
- test_testing_topology_clique_random \
- test_testing_topology_clique_minimum \
- test_testing_topology_clique_dfs \
- test_testing_topology_churn \
- test_testing_topology_line \
- test_testing_topology_blacklist \
- test_testing_group_remote \
- test_testing_2dtorus \
- test_testing_topology_ring \
- test_testing_topology_2d_torus \
- test_testing_topology_small_world_ring \
- test_testing_topology_small_world_torus \
- test_testing_topology_erdos_renyi \
- test_testing_topology_internat \
- test_testing_topology_none \
- test_testing_topology_scale_free \
  test_testing_new_portreservation \
  test_testing_new_peerstartup \
  test_testing_new_servicestartup
 
 if ENABLE_TEST_RUN 
 TESTS = \
- test_testing \
- test_testing_connect \
- test_testing_reconnect \
- test_testing_group \
- test_testing_peergroup \
  test_testing_new_portreservation \
  test_testing_new_peerstartup \
  test_testing_new_servicestartup
 endif
 
-gnunet_testing_SOURCES = \
- gnunet-testing.c         
-gnunet_testing_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la \
- $(GN_LIBINTL)
-gnunet_testing_DEPENDENCIES = \
- libgnunettesting.la
-
-
-test_testing_SOURCES = \
- test_testing.c
-test_testing_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_connect_SOURCES = \
- test_testing_connect.c
-test_testing_connect_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_reconnect_SOURCES = \
- test_testing_reconnect.c
-test_testing_reconnect_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_group_SOURCES = \
- test_testing_group.c
-test_testing_group_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_peergroup_SOURCES = \
- test_testing_peergroup.c
-test_testing_peergroup_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_testing_topology_clique_SOURCES = \
- test_testing_topology.c
-test_testing_topology_clique_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_stability_SOURCES = \
- test_testing_topology.c
-test_testing_topology_stability_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_blacklist_SOURCES = \
- test_testing_topology_blacklist.c
-test_testing_topology_blacklist_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_testing_topology_churn_SOURCES = \
- test_testing_topology_churn.c
-test_testing_topology_churn_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_testing_topology_clique_random_SOURCES = \
- test_testing_topology.c
-test_testing_topology_clique_random_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_topology_clique_minimum_SOURCES = \
- test_testing_topology.c
-test_testing_topology_clique_minimum_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_clique_dfs_SOURCES = \
- test_testing_topology.c
-test_testing_topology_clique_dfs_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_topology_line_SOURCES = \
- test_testing_topology.c
-test_testing_topology_line_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-
-test_testing_group_remote_SOURCES = \
- test_testing_group_remote.c
-test_testing_group_remote_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_2dtorus_SOURCES = \
-  test_testing_2dtorus.c
-test_testing_2dtorus_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_testing_topology_ring_SOURCES = \
- test_testing_topology.c
-test_testing_topology_ring_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la  
-
-test_testing_topology_2d_torus_SOURCES = \
-  test_testing_topology.c
-test_testing_topology_2d_torus_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la 
-
-test_testing_topology_small_world_ring_SOURCES = \
-  test_testing_topology.c
-test_testing_topology_small_world_ring_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_small_world_torus_SOURCES = \
-  test_testing_topology.c
-test_testing_topology_small_world_torus_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_internat_SOURCES = \
-  test_testing_topology.c
-test_testing_topology_internat_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_erdos_renyi_SOURCES = \
-  test_testing_topology.c
-test_testing_topology_erdos_renyi_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_scale_free_SOURCES = \
-  test_testing_topology.c
-test_testing_topology_scale_free_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
-test_testing_topology_none_SOURCES = \
- test_testing_topology.c
-test_testing_topology_none_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
- $(top_builddir)/src/core/libgnunetcore.la \
- $(top_builddir)/src/util/libgnunetutil.la
-
 test_testing_new_portreservation_SOURCES = \
  test_testing_new_portreservation.c
 test_testing_new_portreservation_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting_new.la \
+ $(top_builddir)/src/testing/libgnunettesting.la \
  $(top_builddir)/src/util/libgnunetutil.la
 
 test_testing_new_peerstartup_SOURCES = \
  test_testing_new_peerstartup.c
 test_testing_new_peerstartup_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting_new.la \
+ $(top_builddir)/src/testing/libgnunettesting.la \
  $(top_builddir)/src/util/libgnunetutil.la
 
 test_testing_new_servicestartup_SOURCES = \
  test_testing_new_servicestartup.c
 test_testing_new_servicestartup_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting_new.la \
+ $(top_builddir)/src/testing/libgnunettesting.la \
  $(top_builddir)/src/util/libgnunetutil.la
 
-EXTRA_DIST = \
- test_testing_defaults.conf \
- test_testing_data.conf \
- test_testing_connect_peer1.conf \
- test_testing_connect_peer2.conf \
- test_testing_2dtorus.conf \
- test_testing_data_topology_clique.conf \
- test_testing_data_topology_clique_random.conf \
- test_testing_data_topology_clique_minimum.conf \
- test_testing_data_topology_clique_dfs.conf \
- test_testing_data_topology_ring.conf \
- test_testing_data_topology_2d_torus.conf \
- test_testing_data_topology_small_world_ring.conf \
- test_testing_data_topology_small_world_torus.conf \
- test_testing_data_topology_erdos_renyi.conf \
- test_testing_data_topology_internat.conf \
- test_testing_data_topology_scale_free.conf \
- test_testing_data_topology_blacklist.conf \
- test_testing_data_topology_churn.conf \
- test_testing_data_topology_none.conf \
- test_testing_data_remote.conf \
- test_testing_data_topology_stability.conf \
- test_testing_peergroup_data.conf
diff --git a/src/testing/gnunet-testing-remote-peer-start.pl b/src/testing/gnunet-testing-remote-peer-start.pl
deleted file mode 100755 (executable)
index e4f72e9..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-# 
-#  This file is part of GNUnet
-#  (C) 2008, 2009 Christian Grothoff (and other contributing authors)
-# 
-#  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 3, or (at your
-#  option) any later version.
-# 
-#  GNUnet is distributed in the hope that it will be useful, but
-#  WITHOUT ANY WARRANTY; without even the implied warranty of
-#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-#  General Public License for more details.
-# 
-#  You should have received a copy of the GNU General Public License
-#  along with GNUnet; see the file COPYING.  If not, write to the
-#  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-#  Boston, MA 02111-1307, USA.
-# 
-# 
-# 
-#  @file contrib/peerStartHelper.pl
-#  @brief Helper process for starting gnunet-testing peers.
-#  @author Nathan Evans
-#
-# Finds configuration files (or any files) of the format
-# /path/*/gnunet-testing-config* and runs gnunet-arm with
-# each as the given configuration.
-#
-# usage: peerStartHelper.pl /path/to/testing_dir/
-#!/usr/bin/perl
-use strict;
-
-my $max_outstanding = 300;
-
-$ARGV[0] || die "No directory provided for peer information, exiting!\n";
-
-my $directory = $ARGV[0];
-my @config_files = `find $directory -iname gnunet-testing-config*`;
-my @child_arr = {};
-my $count = 0;
-my $outstanding = 0;
-foreach my $file (@config_files)
-{
-  chomp($file);
-  #print "Starting GNUnet peer with config file $file\n";
-  my $pid = fork();
-  if ($pid == -1) 
-  {
-   die;
-  } 
-  elsif ($pid == 0) 
-  {
-    exec "gnunet-arm -q -c $file -s"  or die;
-  }
-
-  if ($pid != 0)
-  {
-    push @child_arr, $pid;
-    $count++;
-    $outstanding++;
-    if ($outstanding > $max_outstanding)
-    {
-      for (my $i = 0; $i < $max_outstanding / 5; $i++)
-      {
-       #print "Too many outstanding peers, waiting!\n";
-       waitpid($child_arr[0], 0);
-       shift(@child_arr);
-       $outstanding--;
-      }
-    }
-  }
-}
-
-print "All $count peers started (waiting for them to finish!\n";
-
-while ($outstanding > 0)
-{
-  waitpid($child_arr[0], 0);
-  shift(@child_arr);
-  $outstanding--;
-  if ($outstanding % 50 == 0)
-  {
-    print "All $count peers started (waiting for $outstanding to finish!\n";
-  }
-}
-
-while (wait() != -1) {sleep 1}
-
-print "All $count peers started!\n";
-
-
diff --git a/src/testing/gnunet-testing.c b/src/testing/gnunet-testing.c
deleted file mode 100644 (file)
index bdbb5e8..0000000
+++ /dev/null
@@ -1,291 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-
-/**
- * @file testing/gnunet-testing.c
- * @brief tool to use testing functionality from cmd line
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_getopt_lib.h"
-#include "gnunet_program_lib.h"
-#include "gnunet_testing_lib.h"
-
-#define HOSTKEYFILESIZE 914
-
-/**
- * Final status code.
- */
-static int ret;
-
-static unsigned int create_hostkey;
-
-static unsigned int create_cfg;
-
-static int create_no;
-
-static char * create_cfg_template;
-
-static char * create_hostkey_file;
-
-static int
-create_unique_cfgs (const char * template, const unsigned int no)
-{
-  int fail = GNUNET_NO;
-
-  uint16_t port = 20000;
-  uint32_t upnum = 1;
-  uint32_t fdnum = 1;
-
-  if (GNUNET_NO == GNUNET_DISK_file_test(template))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template);
-    return 1;
-  }
-
-  int cur = 0;
-  char * cur_file;
-  char *service_home = NULL;
-  char *cur_service_home = NULL;
-
-  struct GNUNET_CONFIGURATION_Handle *cfg_new = NULL;
-  struct GNUNET_CONFIGURATION_Handle *cfg_tmpl = GNUNET_CONFIGURATION_create();
-
-  /* load template */
-  if ((create_cfg_template != NULL) && (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, create_cfg_template)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
-    GNUNET_CONFIGURATION_destroy(cfg_tmpl);
-
-    return 1;
-  }
-  /* load defaults */
-  else if (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl,  NULL))
-  {
-    GNUNET_break (0);
-    return 1;
-  }
-
-  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg_tmpl, "PATHS", "SERVICEHOME", &service_home))
-  {
-    GNUNET_asprintf(&service_home, "%s", "/tmp/testing");
-  }
-  else
-  {
-    int s = strlen (service_home);
-    if (service_home[s-1] == DIR_SEPARATOR)
-      service_home[s-1] = '\0';
-  }
-
-  while (cur < no)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur);
-    if (create_cfg_template != NULL)
-      GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template);
-    else
-      GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf");
-
-
-    GNUNET_asprintf (&cur_service_home, "%s-%04u%c",service_home, cur, DIR_SEPARATOR);
-    GNUNET_CONFIGURATION_set_value_string (cfg_tmpl,"PATHS","SERVICEHOME", cur_service_home);
-    GNUNET_CONFIGURATION_set_value_string (cfg_tmpl,"PATHS","DEFAULTCONFIG", cur_file);
-    GNUNET_free (cur_service_home);
-
-    cfg_new = GNUNET_TESTING_create_cfg(cfg_tmpl, cur, &port, &upnum, NULL, &fdnum);
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing configuration no. %u to file `%s' \n", cur, cur_file);
-    if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur);
-      fail = GNUNET_YES;
-    }
-
-    GNUNET_CONFIGURATION_destroy (cfg_new);
-    GNUNET_free (cur_file);
-    if (fail == GNUNET_YES)
-      break;
-    cur ++;
-  }
-
-  GNUNET_CONFIGURATION_destroy(cfg_tmpl);
-  GNUNET_free (service_home);
-  if (fail == GNUNET_NO)
-    return 0;
-  else
-    return 1;
-}
-
-static int
-create_hostkeys (const unsigned int no)
-{
-  struct GNUNET_DISK_FileHandle *fd;
-  int cur = 0;
-  uint64_t fs;
-  uint64_t total_hostkeys;
-  char *hostkey_data;
-  char *hostkey_src_file;
-  char *hostkey_dest_file;
-
-  /* prepare hostkeys */
-  if (create_hostkey_file == NULL)
-    hostkey_src_file = "../../contrib/testing_hostkeys.dat";
-  else
-  {
-    hostkey_src_file = create_hostkey_file;
-  }
-
-  if (GNUNET_YES != GNUNET_DISK_file_test (hostkey_src_file))
-  {
-    if (create_hostkey_file == NULL)
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not read hostkeys file, specify hostkey file with -H!\n"));
-    else
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Specified hostkey file `%s' not found!\n"), create_hostkey_file);
-    return 1;
-  }
-  else
-  {
-    /* Check hostkey file size, read entire thing into memory */
-    fd = GNUNET_DISK_file_open (hostkey_src_file, GNUNET_DISK_OPEN_READ,
-                                GNUNET_DISK_PERM_NONE);
-    if (NULL == fd)
-    {
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", hostkey_src_file);
-      return 1;
-    }
-
-    if (GNUNET_OK != GNUNET_DISK_file_size (hostkey_src_file, &fs, GNUNET_YES, GNUNET_YES))
-      fs = 0;
-
-    if (0 != (fs % HOSTKEYFILESIZE))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "File size %llu seems incorrect for hostkeys...\n", fs);
-    }
-    else
-    {
-      total_hostkeys = fs / HOSTKEYFILESIZE;
-      hostkey_data = GNUNET_malloc_large (fs);
-      GNUNET_assert (fs == GNUNET_DISK_file_read (fd, hostkey_data, fs));
-      GNUNET_log  (GNUNET_ERROR_TYPE_DEBUG,
-                       "Read %llu hostkeys from file\n", total_hostkeys);
-    }
-    GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
-  }
-
-  while (cur < no)
-  {
-    GNUNET_asprintf (&hostkey_dest_file, "%04u-hostkey",cur);
-    GNUNET_assert (GNUNET_OK ==
-                   GNUNET_DISK_directory_create_for_file (hostkey_dest_file));
-    fd = GNUNET_DISK_file_open (hostkey_dest_file,
-                                GNUNET_DISK_OPEN_READWRITE |
-                                GNUNET_DISK_OPEN_CREATE,
-                                GNUNET_DISK_PERM_USER_READ |
-                                GNUNET_DISK_PERM_USER_WRITE);
-    GNUNET_assert (fd != NULL);
-    GNUNET_assert (HOSTKEYFILESIZE ==
-                   GNUNET_DISK_file_write (fd, &hostkey_data[cur * HOSTKEYFILESIZE], HOSTKEYFILESIZE));
-    GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
-                     "Wrote hostkey to file: `%s' \n", hostkey_dest_file);
-    GNUNET_free (hostkey_dest_file);
-    cur ++;
-  }
-
-  GNUNET_free (hostkey_data);
-
-  return 0;
-}
-
-/**
- * Main function that will be run by the scheduler.
- *
- * @param cls closure
- * @param args remaining command-line arguments
- * @param cfgfile name of the configuration file used (for saving, can be NULL!)
- * @param cfg configuration
- */
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  /* main code here */
-  if (create_cfg == GNUNET_YES)
-  {
-    if (create_no > 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template);
-      ret = create_unique_cfgs (create_cfg_template, create_no);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
-      ret = 1;
-    }
-  }
-
-  if (create_hostkey == GNUNET_YES)
-  {
-    if  (create_no > 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u hostkeys \n", create_no);
-      ret = create_hostkeys (create_no);
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
-      ret = 1;
-    }
-  }
-
-  GNUNET_free_non_null (create_cfg_template);
-}
-
-
-/**
- * The main function.
- *
- * @param argc number of arguments from the command line
- * @param argv command line arguments
- * @return 0 ok, 1 on error
- */
-int
-main (int argc, char *const *argv)
-{
-  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
-    {'C', "cfg", NULL, gettext_noop ("create unique configuration files"),
-     GNUNET_NO, &GNUNET_GETOPT_set_one, &create_cfg},
-     {'k', "key", NULL, gettext_noop ("create hostkey files from pre-computed hostkey list"),
-     GNUNET_NO, &GNUNET_GETOPT_set_one, &create_hostkey},
-     {'H', "hostkeys", NULL, gettext_noop ("host key file"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &create_hostkey_file},
-    {'n', "number", NULL, gettext_noop ("number of unique configuration files or hostkeys to create"),
-     GNUNET_YES, &GNUNET_GETOPT_set_uint, &create_no},
-    {'t', "template", NULL, gettext_noop ("configuration template"),
-     GNUNET_YES, &GNUNET_GETOPT_set_string, &create_cfg_template},
-    GNUNET_GETOPT_OPTION_END
-  };
-  return (GNUNET_OK ==
-          GNUNET_PROGRAM_run (argc, argv, "gnunet-testing",
-                              gettext_noop ("Command line tool to access the testing library"), options, &run,
-                              NULL)) ? ret : 1;
-}
-
-/* end of gnunet-testing.c */
diff --git a/src/testing/helper.c b/src/testing/helper.c
deleted file mode 100644 (file)
index ebb37eb..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
-      This file is part of GNUnet
-      (C) 2012 Christian Grothoff (and other contributing authors)
-
-      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 3, or (at your
-      option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      General Public License for more details.
-
-      You should have received a copy of the GNU General Public License
-      along with GNUnet; see the file COPYING.  If not, write to the
-      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-      Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file testing/helper.c
- * @brief helper functions for testing
- * @author Christian Grothoff
- *
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-
-
-
-/**
- * Obtain the peer identity of the peer with the given configuration
- * handle.  This function reads the private key of the peer, obtains
- * the public key and hashes it.
- *
- * @param cfg configuration of the peer
- * @param pid where to store the peer identity
- * @return GNUNET_OK on success, GNUNET_SYSERR on failure
- */
-int
-GNUNET_TESTING_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                 struct GNUNET_PeerIdentity *pid)
-{
-  char *keyfile;
-  struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
-                                               &keyfile))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _
-                ("Peer is lacking HOSTKEY configuration setting.\n"));
-    return GNUNET_SYSERR;
-  }
-  my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
-  GNUNET_free (keyfile);
-  if (my_private_key == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Could not access hostkey.\n"));
-    return GNUNET_SYSERR;
-  }
-  GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
-  GNUNET_CRYPTO_rsa_key_free (my_private_key);
-  GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
-                      &pid->hashPubKey);
-  return GNUNET_OK;
-}
-
-
-/* end of helper.c */
diff --git a/src/testing/test_testing.c b/src/testing/test_testing.c
deleted file mode 100644 (file)
index 3e2cd65..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing.c
- * @brief testcase for testing.c
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_YES
-
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-static int ok;
-
-static void
-end_cb (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
-    ok = 1;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon terminated, will now exit.\n");
-#endif
-    ok = 0;
-  }
-}
-
-
-
-void
-do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TESTING_Daemon *d = cls;
-
-  GNUNET_TESTING_daemon_stop (d, TIMEOUT, &end_cb, NULL, GNUNET_YES, GNUNET_NO);
-}
-
-
-static void
-my_cb (void *cls, const struct GNUNET_PeerIdentity *id,
-       const struct GNUNET_CONFIGURATION_Handle *cfg,
-       struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  GNUNET_assert (id != NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Daemon `%s' started, will now stop it.\n", GNUNET_i2s (id));
-#endif
-  GNUNET_SCHEDULER_add_now (&do_shutdown, d);
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_TESTING_Daemon *d;
-
-  ok = 1;
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
-#endif
-  d = GNUNET_TESTING_daemon_start (cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
-                                   NULL, NULL, &my_cb, NULL);
-  GNUNET_assert (d != NULL);
-}
-
-static int
-check ()
-{
-  char *const argv[] = { "test-testing",
-    "-c",
-    "test_testing_data.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                      "test-testing", "nohelp", options, &run, &ok);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test-testing",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-
-  return ret;
-}
-
-/* end of test_testing.c */
diff --git a/src/testing/test_testing_2dtorus.c b/src/testing/test_testing_2dtorus.c
deleted file mode 100644 (file)
index 00a66d6..0000000
+++ /dev/null
@@ -1,372 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2011 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_2dtorus.c
- *
- * @brief Test for creating a 2dtorus.
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_YES
-#define REMOVE_DIR GNUNET_YES
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
-
-/**
- * Time to wait for stuff that should be rather fast
- */
-#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-
-
-/**
- * How many events have happened
- */
-static int ok;
-
-/**
- * Be verbose
- */
-static int verbose;
-
-/**
- * Total number of peers in the test.
- */
-static unsigned long long num_peers;
-
-/**
- * Global configuration file
- */
-static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
-
-/**
- * Total number of currently running peers.
- */
-static unsigned long long peers_running;
-
-/**
- * Total number of successful connections in the whole network.
- */
-static unsigned int total_connections;
-
-/**
- * Total number of counted topo connections
- */
-static unsigned int topo_connections;
-
-/**
- * Total number of failed connections in the whole network.
- */
-static unsigned int failed_connections;
-
-/**
- * The currently running peer group.
- */
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-/**
- * Task called to disconnect peers
- */
-static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-/**
- * Task called to shutdown test.
- */
-static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
-
-
-/**
- * Check whether peers successfully shut down.
- */
-static void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Shutdown of peers failed!\n");
-#endif
-    ok--;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "test: All peers successfully shut down!\n");
-#endif
-  }
-}
-
-
-static void
-shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n");
-#endif
-
-  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-  GNUNET_CONFIGURATION_destroy (testing_cfg);
-}
-
-
-static void
-disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n");
-
-  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
-  {
-    GNUNET_SCHEDULER_cancel (shutdown_handle);
-    shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
-  }
-}
-
-
-/**
- * Prototype of a callback function indicating that two peers
- * are currently connected.
- *
- * @param cls closure
- * @param first peer id for first daemon
- * @param second peer id for the second daemon
- * @param distance distance between the connected peers
- * @param emsg error message (NULL on success)
- */
-void
-topo_cb (void *cls, const struct GNUNET_PeerIdentity *first,
-         const struct GNUNET_PeerIdentity *second, const char *emsg)
-{
-  topo_connections++;
-  if (NULL != emsg)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: Error by topo %u: %s\n",
-                topo_connections, emsg);
-  }
-  else
-  {
-    if (first == NULL || second == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u NULL\n",
-                  topo_connections);
-      if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-      {
-        GNUNET_SCHEDULER_cancel (disconnect_task);
-        GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
-      }
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u ok\n",
-                topo_connections);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   %s\n", GNUNET_i2s (first));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   %s\n", GNUNET_i2s (second));
-  }
-}
-
-
-/**
- * peergroup_ready: start test when all peers are connected
- * @param cls closure
- * @param emsg error message
- */
-static void
-peergroup_ready (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "test: Peergroup callback called with error, aborting test!\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n",
-                emsg);
-    ok--;
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    return;
-  }
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "************************************************************\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "test: Peer Group started successfully!\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Have %u connections\n",
-              total_connections);
-#endif
-
-  peers_running = GNUNET_TESTING_daemons_running (pg);
-  if (0 < failed_connections)
-  {
-    ok = GNUNET_SYSERR;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: %u connections have FAILED!\n",
-                failed_connections);
-    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
-
-  }
-  else
-  {
-    GNUNET_TESTING_get_topology (pg, &topo_cb, NULL);
-    disconnect_task =
-        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_peers, NULL);
-    ok = GNUNET_OK;
-  }
-
-}
-
-
-/**
- * Function that will be called whenever two daemons are connected by
- * the testing library.
- *
- * @param cls closure
- * @param first peer id for first daemon
- * @param second peer id for the second daemon
- * @param distance distance between the connected peers
- * @param first_cfg config for the first daemon
- * @param second_cfg config for the second daemon
- * @param first_daemon handle for the first daemon
- * @param second_daemon handle for the second daemon
- * @param emsg error message (NULL on success)
- */
-static void
-connect_cb (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)
-{
-  if (emsg == NULL)
-  {
-    total_connections++;
-  }
-  else
-  {
-    failed_connections++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "test: Problem with new connection (%s)\n", emsg);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   (%s)\n", GNUNET_i2s (first));
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   (%s)\n", GNUNET_i2s (second));
-  }
-
-}
-
-
-/**
- * run: load configuration options and schedule test to run (start peergroup)
- * @param cls closure
- * @param args argv
- * @param cfgfile configuration file name (can be NULL)
- * @param cfg configuration handle
- */
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_TESTING_Host *hosts;
-
-  ok = GNUNET_NO;
-  total_connections = 0;
-  failed_connections = 0;
-  testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
-
-  GNUNET_log_setup ("test_testing_2dtorus",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n");
-  GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
-                                         "use_progressbars", "YES");
-#endif
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing",
-                                             "num_peers", &num_peers))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Option TESTING:NUM_PEERS is required!\n");
-    return;
-  }
-
-  hosts = GNUNET_TESTING_hosts_load (testing_cfg);
-
-  pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
-                                       &connect_cb, &peergroup_ready, NULL,
-                                       hosts);
-  GNUNET_assert (pg != NULL);
-  shutdown_handle =
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
-                                    &shutdown_task, NULL);
-}
-
-
-/**
- * test_testing_2dtorus command line options
- */
-static struct GNUNET_GETOPT_CommandLineOption options[] = {
-  {'V', "verbose", NULL,
-   gettext_noop ("be verbose (print progress information)"),
-   0, &GNUNET_GETOPT_set_one, &verbose},
-  GNUNET_GETOPT_OPTION_END
-};
-
-
-/**
- * Main: start test
- */
-int
-main (int argc, char *argv[])
-{
-  char *const argv2[] = {
-    argv[0],
-    "-c",
-    "test_testing_2dtorus.conf",
-#if VERBOSE
-    "-L",
-    "DEBUG",
-#endif
-    NULL
-  };
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n");
-
-
-  GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
-                      "test_testing_2dtorus",
-                      gettext_noop ("Test testing 2d torus."), options, &run,
-                      NULL);
-#if REMOVE_DIR
-  GNUNET_DISK_directory_remove ("/tmp/test_testing_2dtorus");
-#endif
-  if (GNUNET_OK != ok)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n");
-    return 1;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n");
-  return 0;
-}
-
-/* end of test_testing_2dtorus.c */
diff --git a/src/testing/test_testing_2dtorus.conf b/src/testing/test_testing_2dtorus.conf
deleted file mode 100644 (file)
index 54bb7c5..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-SERVICEHOME = /tmp/test_testing_2dtorus/
-DEFAULTCONFIG = test_testing_2dtorus.conf
-
-[arm]
-PORT = 10010
-DEFAULTSERVICES = core
-#DEBUG = YES
-
-[statistics]
-AUTOSTART = YES
-PORT = 10000
-
-[dht]
-DEBUG = NO
-AUTOSTART = YES
-ACCEPT_FROM6 = ::1;
-ACCEPT_FROM = 127.0.0.1;
-HOSTNAME = localhost
-PORT = 10001
-
-[nse]
-WORKBITS = 0
-
-[dns]
-AUTOSTART = NO
-PORT = 10011
-
-[transport]
-PORT = 10002
-AUTOSTART = YES
-PLUGINS = tcp
-
-[nat]
-DISABLEV6 = YES 
-BINDTO = 127.0.0.1
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-
-[ats]
-WAN_QUOTA_IN = 1 GB
-WAN_QUOTA_OUT = 1 GB
-
-[core]
-AUTOSTART = YES
-PORT = 10003
-
-[peerinfo]
-AUTOSTART = YES
-PORT = 10004
-
-[testing]
-NUM_PEERS = 16
-WEAKRANDOM = YES
-TOPOLOGY = 2D_TORUS
-CONNECT_TOPOLOGY = 2D_TORUS
-#TOPOLOGY_FILE = small.dat
-CONNECT_TOPOLOGY = 2D_TORUS
-#CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM
-#CONNECT_TOPOLOGY_OPTION_MODIFIER = 25
-#PERCENTAGE = 3
-#PROBABILITY = .1
-F2F = NO
-CONNECT_TIMEOUT = 600 s
-CONNECT_ATTEMPTS = 2
-DEBUG = YES
-HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
-MAX_CONCURRENT_SSH = 10
-USE_PROGRESSBARS = YES
-PEERGROUP_TIMEOUT = 2400 s
-TOPOLOGY_OUTPUT_FILE = testing_topo_initial
-MAX_OUTSTANDING_CONNECTIONS = 75
-#SINGLE_PEERINFO_PER_HOST = YES
-#NUM_PEERINFO_PER_HOST = 10
-#SINGLE_STATISTICS_PER_HOST = YES
-#NUM_STATISTICS_PER_HOST = 10
-DELETE_FILES = YES
diff --git a/src/testing/test_testing_connect.c b/src/testing/test_testing_connect.c
deleted file mode 100644 (file)
index c69c203..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_connect.c
- * @brief testcase for functions to connect two peers in testing.c
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_NO
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-#define CONNECT_ATTEMPTS 3
-
-static int ok;
-
-static struct GNUNET_TESTING_Daemon *d1;
-
-static struct GNUNET_TESTING_Daemon *d2;
-
-static struct GNUNET_CONFIGURATION_Handle *c1;
-
-static struct GNUNET_CONFIGURATION_Handle *c2;
-
-static struct GNUNET_TESTING_ConnectContext *cc;
-
-static void
-end2_cb (void *cls, const char *emsg)
-{
-
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
-    ok = 1;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Both daemons terminated, will now exit.\n");
-#endif
-    ok = 0;
-  }
-}
-
-static void
-end1_cb (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n",
-                emsg);
-    ok = 1;
-  }
-  else
-  {
-    ok = 0;
-  }
-
-  GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL, GNUNET_YES,
-                              GNUNET_NO);
-  d2 = NULL;
-}
-
-static void
-finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL, GNUNET_YES,
-                              GNUNET_NO);
-  d1 = NULL;
-}
-
-static void
-my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first,
-                     const struct GNUNET_PeerIdentity *second,
-                     unsigned int 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)
-{
-  cc = NULL;
-  GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-}
-
-
-static void
-my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id,
-        const struct GNUNET_CONFIGURATION_Handle *cfg,
-        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  GNUNET_assert (id != NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
-              GNUNET_i2s (id));
-#endif
-  cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS,
-                                       GNUNET_YES, &my_connect_complete, NULL);
-}
-
-
-static void
-my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id,
-        const struct GNUNET_CONFIGURATION_Handle *cfg,
-        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  GNUNET_assert (id != NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
-              GNUNET_i2s (id));
-#endif
-  d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
-                                    NULL, NULL, &my_cb2, NULL);
-  GNUNET_assert (d2 != NULL);
-
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  ok = 1;
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
-#endif
-  c1 = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (c1,
-                                            "test_testing_connect_peer1.conf"));
-  c2 = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (c2,
-                                            "test_testing_connect_peer2.conf"));
-  d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
-                                    NULL, NULL, &my_cb1, NULL);
-  GNUNET_assert (d1 != NULL);
-}
-
-static int
-check ()
-{
-  char *const argv[] = { "test-testing",
-    "-c",
-    "test_testing_data.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                      "test-testing-connect", "nohelp", options, &run, &ok);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test-testing-connect",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-  return ret;
-}
-
-/* end of test_testing_connect.c */
diff --git a/src/testing/test_testing_connect_peer1.conf b/src/testing/test_testing_connect_peer1.conf
deleted file mode 100644 (file)
index cccda5e..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-SERVICEHOME = /tmp/test-gnunet-testing-connect-peer1/
-DEFAULTCONFIG = test_testing_connect_peer1.conf
-
-[transport-tcp]
-PORT = 12568
-
-[arm]
-PORT = 12566
-DEFAULTSERVICES = core
-UNIXPATH = /tmp/gnunet-p1-service-arm.sock
-
-[statistics]
-PORT = 12567
-UNIXPATH = /tmp/gnunet-p1-service-statistics.sock
-
-[resolver]
-PORT = 12564
-UNIXPATH = /tmp/gnunet-p1-service-resolver.sock
-
-[peerinfo]
-PORT = 12569
-UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
-
-[transport]
-PORT = 12565
-UNIXPATH = /tmp/gnunet-p1-service-transport.sock
-
-[core]
-PORT = 12570
-UNIXPATH = /tmp/gnunet-p1-service-core.sock
-
-[ats]
-PORT = 12571
-UNIXPATH = /tmp/gnunet-p1-service-ats.sock
-
diff --git a/src/testing/test_testing_connect_peer2.conf b/src/testing/test_testing_connect_peer2.conf
deleted file mode 100644 (file)
index 08ec551..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-SERVICEHOME = /tmp/test-gnunet-testing-connect-peer2/
-DEFAULTCONFIG = test_testing_connect_peer2.conf
-
-[transport-tcp]
-PORT = 22568
-
-[arm]
-PORT = 22566
-DEFAULTSERVICES = core
-UNIXPATH = /tmp/gnunet-p2-service-arm.sock
-
-[statistics]
-PORT = 22567
-UNIXPATH = /tmp/gnunet-p2-service-statistics.sock
-
-[resolver]
-PORT = 22564
-UNIXPATH = /tmp/gnunet-p2-service-resolver.sock
-
-[peerinfo]
-PORT = 22569
-UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
-
-[transport]
-PORT = 22565
-UNIXPATH = /tmp/gnunet-p2-service-transport.sock
-
-[core]
-PORT = 22570
-UNIXPATH = /tmp/gnunet-p2-service-core.sock
-
-[ats]
-PORT = 22571
-UNIXPATH = /tmp/gnunet-p2-service-ats.sock
-
diff --git a/src/testing/test_testing_data.conf b/src/testing/test_testing_data.conf
deleted file mode 100644 (file)
index c46cb0d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data.conf
-
-[arm]
-DEFAULTSERVICES = core
-
diff --git a/src/testing/test_testing_data_remote.conf b/src/testing/test_testing_data_remote.conf
deleted file mode 100644 (file)
index d58666f..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_remote.conf
-
-[TESTING]
-CONTROL_HOST = 127.0.0.1
-HOSTFILE = remote_hosts.txt
-MAX_OUTSTANDING_SSH = 5
-
-[statistics]
-AUTOSTART = NO
-
diff --git a/src/testing/test_testing_data_topology_2d_torus.conf b/src/testing/test_testing_data_topology_2d_torus.conf
deleted file mode 100644 (file)
index cbdaceb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_2d_torus.conf
-
-[TESTING]
-NUM_PEERS = 13
-TOPOLOGY = 2D_TORUS
diff --git a/src/testing/test_testing_data_topology_blacklist.conf b/src/testing/test_testing_data_topology_blacklist.conf
deleted file mode 100644 (file)
index 36e378d..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_blacklist.conf
-
-[TESTING]
-NUM_PEERS = 4
-TOPOLOGY = CLIQUE
-BLACKLIST_TOPOLOGY = RING
-BLACKLIST_TRANSPORTS = tcp udp http
-
-[transport-udp]
-PORT = 2568
-
diff --git a/src/testing/test_testing_data_topology_churn.conf b/src/testing/test_testing_data_topology_churn.conf
deleted file mode 100644 (file)
index b337165..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_churn.conf
-
-[TESTING]
-NUM_PEERS = 12
-
-[arm]
-DEFAULTSERVICES = peerinfo transport core
-
diff --git a/src/testing/test_testing_data_topology_clique.conf b/src/testing/test_testing_data_topology_clique.conf
deleted file mode 100644 (file)
index 69cecb7..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-CONNECT_TIMEOUT = 180 s
-CONNECT_ATTEMPTS = 14
-NUM_PEERS = 4
-TOPOLOGY = CLIQUE
-SETTLE_TIME = 0
diff --git a/src/testing/test_testing_data_topology_clique_dfs.conf b/src/testing/test_testing_data_topology_clique_dfs.conf
deleted file mode 100644 (file)
index c7abeae..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-NUM_PEERS = 7
-TOPOLOGY = CLIQUE
-CONNECT_TOPOLOGY_OPTION = CONNECT_DFS
-CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0
-
-[arm]
-DEFAULTSERVICES = peerinfo transport core
-
diff --git a/src/testing/test_testing_data_topology_clique_minimum.conf b/src/testing/test_testing_data_topology_clique_minimum.conf
deleted file mode 100644 (file)
index ef95cb1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-NUM_PEERS = 20
-TOPOLOGY = CLIQUE
-CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM
-CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0
-
diff --git a/src/testing/test_testing_data_topology_clique_random.conf b/src/testing/test_testing_data_topology_clique_random.conf
deleted file mode 100644 (file)
index cd44b65..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-NUM_PEERS = 20
-TOPOLOGY = CLIQUE
-CONNECT_TOPOLOGY_OPTION = CONNECT_RANDOM_SUBSET
-CONNECT_TOPOLOGY_OPTION_MODIFIER = .15
-
-[statistics]
-AUTOSTART = NO
-
-[resolver]
-AUTOSTART = NO
-
diff --git a/src/testing/test_testing_data_topology_erdos_renyi.conf b/src/testing/test_testing_data_topology_erdos_renyi.conf
deleted file mode 100644 (file)
index 8e17413..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-TOPOLOGY = ERDOS_RENYI
-
diff --git a/src/testing/test_testing_data_topology_internat.conf b/src/testing/test_testing_data_topology_internat.conf
deleted file mode 100644 (file)
index af3f62f..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-TOPOLOGY = INTERNAT
-
diff --git a/src/testing/test_testing_data_topology_none.conf b/src/testing/test_testing_data_topology_none.conf
deleted file mode 100644 (file)
index dbee5d0..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-NUM_PEERS = 1000
-TOPOLOGY = NONE
-F2F = NO
-BLACKLIST_TOPOLOGY = NONE
-CONNECT_TOPOLOGY = RING
-
-[arm]
-PORT = 0
-
-[statistics]
-AUTOSTART = NO
-PORT = 0
-
-[resolver]
-AUTOSTART = NO
-PORT = 0
-
-[peerinfo]
-PORT = 0
-
-[transport]
-PORT = 0
-
-[core]
-PORT = 0
-
-[topology]
-PORT = 0
-
-[hostlist]
-PORT = 0
-
diff --git a/src/testing/test_testing_data_topology_ring.conf b/src/testing/test_testing_data_topology_ring.conf
deleted file mode 100644 (file)
index 6159030..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-TOPOLOGY = RING
-
diff --git a/src/testing/test_testing_data_topology_scale_free.conf b/src/testing/test_testing_data_topology_scale_free.conf
deleted file mode 100644 (file)
index 7690eac..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_scale_free.conf
-
-[TESTING]
-NUM_PEERS = 50
-TOPOLOGY = SCALE_FREE
-
-[arm]
-DEFAULTSERVICES = peerinfo transport core
-
diff --git a/src/testing/test_testing_data_topology_small_world_ring.conf b/src/testing/test_testing_data_topology_small_world_ring.conf
deleted file mode 100644 (file)
index 01931df..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-NUM_PEERS = 25
-TOPOLOGY = SMALL_WORLD_RING
-
diff --git a/src/testing/test_testing_data_topology_small_world_torus.conf b/src/testing/test_testing_data_topology_small_world_torus.conf
deleted file mode 100644 (file)
index 7c35454..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-TOPOLOGY = SMALL_WORLD
-
diff --git a/src/testing/test_testing_data_topology_stability.conf b/src/testing/test_testing_data_topology_stability.conf
deleted file mode 100644 (file)
index 1bfcd1b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_data_topology_clique.conf
-
-[TESTING]
-SETTLE_TIME = 600 s
-NUM_PEERS = 2
-TOPOLOGY = CLIQUE
-
diff --git a/src/testing/test_testing_defaults.conf b/src/testing/test_testing_defaults.conf
deleted file mode 100644 (file)
index ba7e269..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-[PATHS]
-SERVICEHOME = /tmp/test-gnunet-testing/
-DEFAULTCONFIG = test_testing_defaults.conf
-
-[resolver]
-PORT = 2564
-
-[transport]
-PORT = 2565
-PLUGINS = tcp
-
-[arm]
-PORT = 2566
-DEFAULTSERVICES = 
-
-[statistics]
-PORT = 2567
-
-[transport-tcp]
-PORT = 2568
-BINDTO = 127.0.0.1
-
-[peerinfo]
-PORT = 2569
-
-[core]
-PORT = 2570
-
-[testing]
-NUM_PEERS = 5
-WEAKRANDOM = YES
-F2F = YES
-HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
-
-[dht]
-AUTOSTART = NO
-
-[nat]
-DISABLEV6 = YES
-ENABLE_UPNP = NO
-BEHIND_NAT = NO
-ALLOW_NAT = NO
-INTERNAL_ADDRESS = 127.0.0.1
-EXTERNAL_ADDRESS = 127.0.0.1
-USE_LOCALADDR = NO
-
-[dns]
-AUTOSTART = NO
-
-[nse]
-AUTOSTART = NO
-
-[mesh]
-AUTOSTART = NO
-
-[datastore]
-AUTOSTART = NO
-
-[fs]
-AUTOSTART = NO
-
-[dv]
-AUTOSTART = NO
-
-[chat]
-AUTOSTART = NO
-
-[vpn]
-AUTOSTART = NO
-
-[gns]
-AUTOSTART = NO
-
-[namestore]
-AUTOSTART = NO
-
-[lockmanager]
-AUTOSTART = NO
diff --git a/src/testing/test_testing_group.c b/src/testing/test_testing_group.c
deleted file mode 100644 (file)
index f5df45b..0000000
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_group.c
- * @brief testcase for functions to connect peers in testing.c
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_NO
-
-#define NUM_PEERS 4
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-static int ok;
-
-static int peers_left;
-
-static int failed_peers;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
-#endif
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-#endif
-  }
-}
-
-
-static void
-my_cb (void *cls, const struct GNUNET_PeerIdentity *id,
-       const struct GNUNET_CONFIGURATION_Handle *cfg,
-       struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (id == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Start callback called with error (too long starting peers), aborting test!\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
-    failed_peers++;
-    if (failed_peers == peers_left)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Too many peers failed, ending test!\n");
-      ok = 1;
-      GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    }
-    return;
-  }
-
-  peers_left--;
-  if (peers_left == 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All peers started successfully, ending test!\n");
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    ok = 0;
-  }
-  else if (failed_peers == peers_left)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Too many peers failed, ending test!\n");
-    ok = 1;
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-  }
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  ok = 1;
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
-#endif
-  peers_left = NUM_PEERS;
-  pg = GNUNET_TESTING_daemons_start (cfg, peers_left,   /* Total number of peers */
-                                     peers_left,        /* Number of outstanding connections */
-                                     peers_left,        /* Number of parallel ssh connections, or peers being started at once */
-                                     TIMEOUT, NULL, NULL, &my_cb, NULL, NULL,
-                                     NULL, NULL);
-  GNUNET_assert (pg != NULL);
-}
-
-static int
-check ()
-{
-  char *const argv[] = { "test-testing",
-    "-c",
-    "test_testing_data.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                      "test-testing-group", "nohelp", options, &run, &ok);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test-testing-group",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-  /**
-   * Still need to remove the base testing directory here,
-   * because group starts will create subdirectories under this
-   * main dir.  However, we no longer need to sleep, as the
-   * shutdown sequence won't return until everything is cleaned
-   * up.
-   */
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
-  return ret;
-}
-
-/* end of test_testing_group.c */
diff --git a/src/testing/test_testing_group_remote.c b/src/testing/test_testing_group_remote.c
deleted file mode 100644 (file)
index b06655c..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_group_remote.c
- * @brief testcase for testing remote and local starting and connecting
- *        of hosts from the testing library.  The test_testing_data_remote.conf
- *        file should be modified if this testcase is intended to be used.
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_YES
-
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-#define DEFAULT_NUM_PEERS 8;
-
-static int ok;
-
-static int peers_left;
-
-static int peers_failed;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-static unsigned long long num_peers;
-
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Shutdown of peers failed (error %s)!\n", emsg);
-#endif
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-#endif
-  }
-}
-
-
-static void
-my_cb (void *cls, const struct GNUNET_PeerIdentity *id,
-       const struct GNUNET_CONFIGURATION_Handle *cfg,
-       struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    peers_failed++;
-  }
-
-  peers_left--;
-  if (peers_left == 0)
-  {
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    ok = 0;
-  }
-  else if (peers_failed == peers_left)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Too many peers failed, ending test!\n");
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-  }
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_TESTING_Host *hosts;
-  struct GNUNET_TESTING_Host *hostpos;
-  struct GNUNET_TESTING_Host *temphost;
-  char *hostfile;
-  struct stat frstat;
-  char *buf;
-  char *data;
-  int count;
-  int ret;
-
-  ok = 1;
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
-#endif
-
-  if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
-                                             &num_peers))
-    num_peers = DEFAULT_NUM_PEERS;
-
-  GNUNET_assert (num_peers > 0 && num_peers < (unsigned long long) -1);
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile",
-                                             &hostfile))
-    hostfile = NULL;
-
-  hosts = NULL;
-  data = NULL;
-  if (hostfile != NULL)
-  {
-    if (GNUNET_OK != GNUNET_DISK_file_test (hostfile))
-      GNUNET_DISK_fn_write (hostfile, NULL, 0,
-                            GNUNET_DISK_PERM_USER_READ |
-                            GNUNET_DISK_PERM_USER_WRITE);
-    if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Could not open file specified for host list, ending test!");
-      ok = 1119;
-      GNUNET_free (hostfile);
-      return;
-    }
-
-    data = GNUNET_malloc_large (frstat.st_size);
-    GNUNET_assert (data != NULL);
-    if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Could not read file %s specified for host list, ending test!",
-                  hostfile);
-      GNUNET_free (hostfile);
-      GNUNET_free (data);
-      return;
-    }
-
-    GNUNET_free_non_null (hostfile);
-
-    buf = data;
-    count = 0;
-    while (count < frstat.st_size)
-    {
-      count++;
-      if (count >= frstat.st_size)
-        break;
-
-      /* if (((data[count] == '\n') || (data[count] == '\0')) && (buf != &data[count])) */
-      if (((data[count] == '\n')) && (buf != &data[count]))
-      {
-        data[count] = '\0';
-        temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host));
-        ret =
-            SSCANF (buf, "%a[a-zA-Z0-9]@%a[a-zA-Z0-9.]:%hd",
-                    &temphost->username, &temphost->hostname, &temphost->port);
-        if (3 == ret)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Successfully read host %s, port %d and user %s from file\n",
-                      temphost->hostname, temphost->port, temphost->username);
-        }
-        else
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Error reading line `%s' in hostfile\n", buf);
-          GNUNET_free (temphost);
-          buf = &data[count + 1];
-          continue;
-        }
-        /* temphost->hostname = buf; */
-        temphost->next = hosts;
-        hosts = temphost;
-        buf = &data[count + 1];
-      }
-      else if ((data[count] == '\n') || (data[count] == '\0'))
-        buf = &data[count + 1];
-    }
-  }
-
-  peers_left = num_peers;
-  pg = GNUNET_TESTING_daemons_start (cfg, peers_left,   /* Total number of peers */
-                                     peers_left,        /* Number of outstanding connections */
-                                     peers_left,        /* Number of parallel ssh connections, or peers being started at once */
-                                     TIMEOUT, NULL, NULL, &my_cb, NULL, NULL,
-                                     NULL, hosts);
-  hostpos = hosts;
-  while (hostpos != NULL)
-  {
-    temphost = hostpos->next;
-    GNUNET_free (hostpos->hostname);
-    GNUNET_free (hostpos->username);
-    GNUNET_free (hostpos);
-    hostpos = temphost;
-  }
-  GNUNET_free_non_null (data);
-  GNUNET_assert (pg != NULL);
-
-}
-
-static int
-check ()
-{
-  char *const argv[] = { "test-testing",
-    "-c",
-    "test_testing_data_remote.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                      "test-testing-group", "nohelp", options, &run, &ok);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test-testing-group",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-  /**
-   * Still need to remove the base testing directory here,
-   * because group starts will create subdirectories under this
-   * main dir.  However, we no longer need to sleep, as the
-   * shutdown sequence won't return until everything is cleaned
-   * up.
-   */
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
-  return ret;
-}
-
-/* end of test_testing_group.c */
diff --git a/src/testing/test_testing_large_topology.c b/src/testing/test_testing_large_topology.c
deleted file mode 100644 (file)
index cd80db1..0000000
+++ /dev/null
@@ -1,1197 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_topology.c
- * @brief base testcase for testing all the topologies provided
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_os_lib.h"
-
-#define VERBOSE GNUNET_YES
-
-#define DELAY_FOR_LOGGING GNUNET_NO
-
-#define SECONDS_PER_PEER_START 120
-
-#define DEFAULT_NUM_PEERS 4
-
-#define MAX_OUTSTANDING_CONNECTIONS 100
-
-static float fail_percentage = 0.05;
-
-static int ok;
-
-struct GNUNET_TIME_Relative connect_timeout;
-
-static unsigned long long connect_attempts;
-
-static unsigned long long num_peers;
-
-static unsigned int topology_connections;
-
-static unsigned int total_connections;
-
-static unsigned int failed_connections;
-
-static unsigned int total_server_connections;
-
-static unsigned int total_messages_received;
-
-static unsigned int expected_messages;
-
-static unsigned int expected_connections;
-
-static unsigned long long peers_left;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-const struct GNUNET_CONFIGURATION_Handle *main_cfg;
-
-GNUNET_SCHEDULER_TaskIdentifier die_task;
-
-static char *dotOutFileName;
-
-static struct GNUNET_TIME_Relative settle_time;
-
-static FILE *dotOutFile;
-
-static char *topology_string;
-
-static char *blacklist_transports;
-
-static int transmit_ready_scheduled;
-
-static int transmit_ready_failed;
-
-static int transmit_ready_called;
-
-struct GNUNET_TIME_Relative test_timeout;
-
-struct GNUNET_TIME_Relative timeout;
-
-static unsigned int modnum;
-
-static unsigned int dotnum;
-
-static enum GNUNET_TESTING_Topology topology;
-
-static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE;  /* Don't do any blacklisting */
-
-static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
-
-static enum GNUNET_TESTING_TopologyOption connect_topology_option =
-    GNUNET_TESTING_TOPOLOGY_OPTION_ALL;
-
-static double connect_topology_option_modifier = 0.0;
-
-static char *test_directory;
-
-#define MTYPE 12345
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-struct GNUNET_TestMessage
-{
-  /**
-   * Header of the message
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this message.
-   */
-  uint32_t uid;
-};
-GNUNET_NETWORK_STRUCT_END
-
-struct TestMessageContext
-{
-  /* This is a linked list */
-  struct TestMessageContext *next;
-
-  /* Handle to the sending peer core */
-  struct GNUNET_CORE_Handle *peer1handle;
-
-  /* Handle to the receiving peer core */
-  struct GNUNET_CORE_Handle *peer2handle;
-
-  /* Handle to the sending peer daemon */
-  struct GNUNET_TESTING_Daemon *peer1;
-
-  /* Handle to the receiving peer daemon */
-  struct GNUNET_TESTING_Daemon *peer2;
-
-  /* Identifier for this message, so we don't disconnect other peers! */
-  uint32_t uid;
-
-  /* Has peer1 been notified already of a connection to peer2? */
-  int peer1notified;
-
-  /* Has the core of peer2 been connected already? */
-  int peer2connected;
-
-  /* Task for disconnecting cores, allow task to be cancelled on shutdown */
-  GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-};
-
-static struct TestMessageContext *test_messages;
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
-#endif
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-#endif
-  }
-}
-
-#if DELAY_FOR_LOGGING
-static void
-gather_log_data ()
-{
-  char *peer_number;
-  char *connect_number;
-  struct GNUNET_OS_Process *mem_process;
-
-  GNUNET_asprintf (&peer_number, "%llu", num_peers);
-  GNUNET_asprintf (&connect_number, "%llu", expected_connections);
-  mem_process =
-      GNUNET_OS_start_process (NULL, NULL, "./memsize.pl", "memsize.pl",
-                               "totals.txt", peer_number, connect_number, NULL);
-  GNUNET_OS_process_wait (mem_process);
-  GNUNET_OS_process_destroy (mem_process);
-  mem_process = NULL;
-}
-
-#endif
-
-static void
-finish_testing ()
-{
-  GNUNET_assert (pg != NULL);
-  struct TestMessageContext *pos;
-  struct TestMessageContext *free_pos;
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Called finish testing, stopping daemons.\n");
-#endif
-
-  pos = test_messages;
-  while (pos != NULL)
-  {
-    if (pos->peer1handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer1handle);
-      pos->peer1handle = NULL;
-    }
-    if (pos->peer2handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer2handle);
-      pos->peer2handle = NULL;
-    }
-    free_pos = pos;
-    pos = pos->next;
-    if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-    {
-      GNUNET_SCHEDULER_cancel (free_pos->disconnect_task);
-    }
-    GNUNET_free (free_pos);
-  }
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
-              transmit_ready_scheduled, transmit_ready_failed,
-              transmit_ready_called);
-#endif
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
-#endif
-  GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL);
-
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "}");
-    FCLOSE (dotOutFile);
-  }
-
-  ok = 0;
-}
-
-
-static void
-disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct TestMessageContext *pos = cls;
-
-  /* Disconnect from the respective cores */
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n",
-              GNUNET_i2s (&pos->peer1->id));
-#endif
-  if (pos->peer1handle != NULL)
-    GNUNET_CORE_disconnect (pos->peer1handle);
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n",
-              GNUNET_i2s (&pos->peer2->id));
-#endif
-  if (pos->peer2handle != NULL)
-    GNUNET_CORE_disconnect (pos->peer2handle);
-  /* Set handles to NULL so test case can be ended properly */
-  pos->peer1handle = NULL;
-  pos->peer2handle = NULL;
-  pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  /* Decrement total connections so new can be established */
-  total_server_connections -= 2;
-}
-
-
-static void
-topology_cb (void *cls, const struct GNUNET_PeerIdentity *first,
-             const struct GNUNET_PeerIdentity *second, const char *emsg)
-{
-  FILE *outfile = cls;
-
-  if (first != NULL)
-  {
-    if (outfile != NULL)
-    {
-      FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first));
-      FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second));
-    }
-    topology_connections++;
-  }
-  else
-  {
-    FPRINTF (stderr,
-             "Finished iterating over topology, %d total connections!\n",
-             topology_connections);
-    if (outfile != NULL)
-    {
-      FPRINTF (outfile, "%s",  "}\n");
-      FCLOSE (outfile);
-      GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-    }
-  }
-}
-
-static int
-process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_ATS_Information *atsi)
-{
-  char *dotOutFileNameFinished;
-  FILE *dotOutFileFinished;
-  struct TestMessageContext *pos = cls;
-  struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message;
-
-  if (pos->uid != ntohl (msg->uid))
-    return GNUNET_OK;
-
-#if VERBOSE
-  if ((total_messages_received) % modnum == 0)
-  {
-    if (total_messages_received == 0)
-      FPRINTF (stdout, "%s",  "0%%");
-    else
-      FPRINTF (stdout, "%d%%",
-               (int) (((float) total_messages_received / expected_messages) *
-                      100));
-
-  }
-  else if (total_messages_received % dotnum == 0)
-  {
-    FPRINTF (stdout, "%s",  ".");
-  }
-  fflush (stdout);
-#endif
-
-  total_messages_received++;
-
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received message from `%4s', type %d.\n", GNUNET_i2s (peer),
-              ntohs (message->type));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Total messages received %d, expected %d.\n",
-              total_messages_received, expected_messages);
-#endif
-
-  if (total_messages_received == expected_messages)
-  {
-#if VERBOSE
-    FPRINTF (stdout, "%s",  "100%%]\n");
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology");
-    dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w");
-    GNUNET_free (dotOutFileNameFinished);
-    if (dotOutFileFinished != NULL)
-    {
-      FPRINTF (dotOutFileFinished, "%s",  "strict graph G {\n");
-    }
-    topology_connections = 0;
-    GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished);
-    //GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-  }
-  else
-  {
-    pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos);
-  }
-
-  return GNUNET_OK;
-}
-
-static void
-end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char *msg = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "End badly was called (%s)... stopping daemons.\n", msg);
-  struct TestMessageContext *pos;
-  struct TestMessageContext *free_pos;
-
-  pos = test_messages;
-  while (pos != NULL)
-  {
-    if (pos->peer1handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer1handle);
-      pos->peer1handle = NULL;
-    }
-    if (pos->peer2handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer2handle);
-      pos->peer2handle = NULL;
-    }
-    free_pos = pos;
-    pos = pos->next;
-    GNUNET_free (free_pos);
-  }
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
-              transmit_ready_scheduled, transmit_ready_failed,
-              transmit_ready_called);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Total messages received %d, expected %d.\n",
-              total_messages_received, expected_messages);
-#endif
-
-  if (pg != NULL)
-  {
-    GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL);
-    ok = 7331;                  /* Opposite of leet */
-  }
-  else
-    ok = 401;                   /* Never got peers started */
-
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "}");
-    FCLOSE (dotOutFile);
-  }
-}
-
-static size_t
-transmit_ready (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_TestMessage *m;
-  struct TestMessageContext *pos = cls;
-
-  GNUNET_assert (buf != NULL);
-  m = (struct GNUNET_TestMessage *) buf;
-  m->header.type = htons (MTYPE);
-  m->header.size = htons (sizeof (struct GNUNET_TestMessage));
-  m->uid = htonl (pos->uid);
-  transmit_ready_called++;
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n",
-              GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled,
-              transmit_ready_called);
-#endif
-  return sizeof (struct GNUNET_TestMessage);
-}
-
-
-static struct GNUNET_CORE_MessageHandler no_handlers[] = {
-  {NULL, 0, 0}
-};
-
-static struct GNUNET_CORE_MessageHandler handlers[] = {
-  {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)},
-  {NULL, 0, 0}
-};
-
-static void
-init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server,
-                   const struct GNUNET_PeerIdentity *my_identity)
-{
-  struct TestMessageContext *pos = cls;
-
-  total_server_connections++;
-
-  pos->peer2connected = GNUNET_YES;
-  if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */
-  {
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
-                GNUNET_i2s (my_identity),
-                GNUNET_h2s (&pos->peer1->id.hashPubKey));
-#endif
-    if (NULL ==
-        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout,
-                                           &pos->peer2->id,
-                                           sizeof (struct GNUNET_TestMessage),
-                                           &transmit_ready, pos))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
-                  GNUNET_i2s (&pos->peer2->id));
-      transmit_ready_failed++;
-    }
-    else
-    {
-      transmit_ready_scheduled++;
-    }
-  }
-}
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- * @param atsi performance data for the connection
- */
-static void
-connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_ATS_Information *atsi)
-{
-  struct TestMessageContext *pos = cls;
-
-  if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    pos->peer1notified = GNUNET_YES;
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Peer `%s' notified of connection to peer `%s'\n",
-                GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey));
-#endif
-  }
-  else
-    return;
-
-  if (pos->peer2connected == GNUNET_YES)        /* Already connected and notified of connection, send message! */
-  {
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
-                GNUNET_i2s (&pos->peer2->id),
-                GNUNET_h2s (&pos->peer1->id.hashPubKey));
-#endif
-    if (NULL ==
-        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout,
-                                           &pos->peer2->id,
-                                           sizeof (struct GNUNET_TestMessage),
-                                           &transmit_ready, pos))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
-                  GNUNET_i2s (&pos->peer2->id));
-      transmit_ready_failed++;
-    }
-    else
-    {
-      transmit_ready_scheduled++;
-    }
-  }
-}
-
-static void
-init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server,
-                   const struct GNUNET_PeerIdentity *my_identity)
-{
-  struct TestMessageContext *pos = cls;
-
-  total_server_connections++;
-
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Core connection to `%4s' established, setting up handles\n",
-              GNUNET_i2s (my_identity));
-#endif
-
-  /*
-   * Connect to the receiving peer
-   */
-  pos->peer2handle =
-      GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL,
-                           NULL, NULL, NULL, GNUNET_YES, NULL, GNUNET_YES,
-                           handlers);
-
-}
-
-
-static void
-send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct TestMessageContext *pos = cls;
-
-  if ((pos == test_messages) && (settle_time.rel_value > 0))
-  {
-    topology_connections = 0;
-    GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
-  }
-  if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL))
-    return;
-
-  if (die_task == GNUNET_SCHEDULER_NO_TASK)
-  {
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
-                                      "from send test messages (timeout)");
-  }
-
-  if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS)
-  {
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 1),
-                                  &send_test_messages, pos);
-    return;                     /* Otherwise we'll double schedule messages here! */
-  }
-
-  /*
-   * Connect to the sending peer
-   */
-  pos->peer1handle =
-      GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1,
-                           &connect_notify_peers, NULL, NULL, NULL, GNUNET_NO,
-                           NULL, GNUNET_NO, no_handlers);
-
-  GNUNET_assert (pos->peer1handle != NULL);
-
-  if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS)
-  {
-    GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next);
-  }
-  else
-  {
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 1),
-                                  &send_test_messages, pos->next);
-  }
-}
-
-
-void
-topology_callback (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)
-{
-  struct TestMessageContext *temp_context;
-
-  if (emsg == NULL)
-  {
-#if VERBOSE
-    if ((total_connections) % modnum == 0)
-    {
-      if (total_connections == 0)
-        FPRINTF (stdout, "%s",  "0%%");
-      else
-        FPRINTF (stdout, "%d%%",
-                 (int) (((float) total_connections / expected_connections) *
-                        100));
-
-    }
-    else if (total_connections % dotnum == 0)
-    {
-      FPRINTF (stdout, "%s",  ".");
-    }
-    fflush (stdout);
-#endif
-    total_connections++;
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n",
-                first_daemon->shortname, second_daemon->shortname);
-#endif
-    temp_context = GNUNET_malloc (sizeof (struct TestMessageContext));
-    temp_context->peer1 = first_daemon;
-    temp_context->peer2 = second_daemon;
-    temp_context->next = test_messages;
-    temp_context->uid = total_connections;
-    temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-    test_messages = temp_context;
-
-    expected_messages++;
-    if (dotOutFile != NULL)
-      FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname,
-               second_daemon->shortname);
-  }
-#if VERBOSE
-  else
-  {
-    failed_connections++;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to connect peer %s to peer %s with error :\n%s\n",
-                first_daemon->shortname, second_daemon->shortname, emsg);
-  }
-#endif
-
-  if (total_connections == expected_connections)
-  {
-#if VERBOSE
-    FPRINTF (stdout, "%s",  "100%%]\n");
-#endif
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Created %d total connections, which is our target number!  Calling send messages.\n",
-                total_connections);
-#endif
-    modnum = expected_messages / 4;
-    dotnum = (expected_messages / 50) + 1;
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task = GNUNET_SCHEDULER_NO_TASK;
-#if DELAY_FOR_LOGGING
-    FPRINTF (stdout, "%s",  "Sending test messages in 10 seconds.\n");
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 10),
-                                  &send_test_messages, test_messages);
-    gather_log_data ();
-#else
-    if (settle_time.rel_value > 0)
-    {
-      GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
-    }
-    GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages,
-                                  test_messages);
-#endif
-#if VERBOSE
-    FPRINTF (stdout, "%s",  "Test message progress: [");
-#endif
-
-  }
-  else if (total_connections + failed_connections == expected_connections)
-  {
-    if (failed_connections <
-        (unsigned int) (fail_percentage * total_connections))
-    {
-      GNUNET_SCHEDULER_cancel (die_task);
-      die_task = GNUNET_SCHEDULER_NO_TASK;
-      GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages);
-    }
-    else
-    {
-      GNUNET_SCHEDULER_cancel (die_task);
-      die_task =
-          GNUNET_SCHEDULER_add_now (&end_badly,
-                                    "from topology_callback (too many failed connections)");
-    }
-  }
-  else
-  {
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Have %d total connections, %d failed connections, Want %d (at least %d)\n",
-                total_connections, failed_connections, expected_connections,
-                expected_connections -
-                (unsigned int) (fail_percentage * expected_connections));
-#endif
-  }
-}
-
-static void
-topology_creation_finished (void *cls, const char *emsg)
-{
-#if VERBOSE
-  if (emsg == NULL)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All topology connections created successfully!\n");
-#endif
-}
-
-static void
-connect_topology ()
-{
-  expected_connections = -1;
-  if ((pg != NULL) && (peers_left == 0))
-  {
-    expected_connections =
-        GNUNET_TESTING_connect_topology (pg, connection_topology,
-                                         connect_topology_option,
-                                         connect_topology_option_modifier,
-                                         connect_timeout, connect_attempts,
-                                         &topology_creation_finished, NULL);
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
-                expected_connections);
-#endif
-  }
-
-  GNUNET_SCHEDULER_cancel (die_task);
-  if (expected_connections == GNUNET_SYSERR)
-  {
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from connect topology (bad return)");
-  }
-
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
-                                    "from connect topology (timeout)");
-  modnum = expected_connections / 4;
-  dotnum = (expected_connections / 50) + 1;
-#if VERBOSE
-  FPRINTF (stdout, "%s",  "Peer connection progress: [");
-#endif
-}
-
-static void
-create_topology ()
-{
-  peers_left = num_peers;       /* Reset counter */
-  if (GNUNET_TESTING_create_topology
-      (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Topology set up, now starting peers!\n");
-    FPRINTF (stdout, "%s",  "Daemon start progress [");
-#endif
-    GNUNET_TESTING_daemons_continue_startup (pg);
-  }
-  else
-  {
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from create topology (bad return)");
-  }
-  GNUNET_SCHEDULER_cancel (die_task);
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
-                                    "from continue startup (timeout)");
-}
-
-
-static void
-peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                        const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to start daemon with error: `%s'\n", emsg);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
-              (num_peers - peers_left) + 1, num_peers);
-#endif
-#if VERBOSE
-  if ((num_peers - peers_left) % modnum == 0)
-  {
-    if (num_peers - peers_left == 0)
-      FPRINTF (stdout, "%s",  "0%%");
-    else
-      FPRINTF (stdout, "%d%%",
-               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
-
-  }
-  else if ((num_peers - peers_left) % dotnum == 0)
-  {
-    FPRINTF (stdout, "%s",  ".");
-  }
-  fflush (stdout);
-#endif
-  peers_left--;
-  if (peers_left == 0)
-  {
-#if VERBOSE
-    FPRINTF (stdout, "%s",  "100%%]\n");
-#endif
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d daemons started, now connecting peers!\n", num_peers);
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (timeout, &end_badly,
-                                      "from peers_started_callback");
-#if DELAY_FOR_LOGGING
-    FPRINTF (stdout, "%s",  "Connecting topology in 10 seconds\n");
-    gather_log_data ();
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 10),
-                                  &connect_topology, NULL);
-#else
-    connect_topology ();
-#endif
-    ok = 0;
-  }
-}
-
-/**
- * Callback indicating that the hostkey was created for a peer.
- *
- * @param cls NULL
- * @param id the peer identity
- * @param d the daemon handle (pretty useless at this point, remove?)
- * @param emsg non-null on failure
- */
-void
-hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Hostkey callback received error: %s\n", emsg);
-  }
-
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left,
-              num_peers, GNUNET_i2s (id));
-#endif
-
-#if VERBOSE
-  if ((num_peers - peers_left) % modnum == 0)
-  {
-    if (num_peers - peers_left == 0)
-      FPRINTF (stdout, "%s",  "0%%");
-    else
-      FPRINTF (stdout, "%d%%",
-               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
-
-  }
-  else if ((num_peers - peers_left) % dotnum == 0)
-  {
-    FPRINTF (stdout, "%s",  ".");
-  }
-  fflush (stdout);
-#endif
-  peers_left--;
-  if (peers_left == 0)
-  {
-#if VERBOSE
-    FPRINTF (stdout, "%s",  "100%%]\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d hostkeys created, now creating topology!\n", num_peers);
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
-                                      "from create_topology");
-    GNUNET_SCHEDULER_add_now (&create_topology, NULL);
-    ok = 0;
-  }
-}
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  char *topology_str;
-  char *connect_topology_str;
-  char *blacklist_topology_str;
-  char *connect_topology_option_str;
-  char *connect_topology_option_modifier_string;
-  unsigned long long temp_settle;
-
-  ok = 1;
-
-  dotOutFile = FOPEN (dotOutFileName, "w");
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "strict graph G {\n");
-  }
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting daemons based on config file %s\n", cfgfile);
-#endif
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
-                                             &test_directory))
-  {
-    ok = 404;
-    return;
-  }
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology",
-                                              &topology_str)) &&
-      (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid topology `%s' given for section %s option %s\n",
-                topology_str, "TESTING", "TOPOLOGY");
-    topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;  /* Defaults to NONE, so set better default here */
-  }
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "connect_topology",
-                                              &connect_topology_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_get (&connection_topology,
-                                    connect_topology_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid connect topology `%s' given for section %s option %s\n",
-                connect_topology_str, "TESTING", "CONNECT_TOPOLOGY");
-  }
-  GNUNET_free_non_null (connect_topology_str);
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "connect_topology_option",
-                                              &connect_topology_option_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_option_get (&connect_topology_option,
-                                           connect_topology_option_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid connect topology option `%s' given for section %s option %s\n",
-                connect_topology_option_str, "TESTING",
-                "CONNECT_TOPOLOGY_OPTION");
-    connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL;       /* Defaults to NONE, set to ALL */
-  }
-  GNUNET_free_non_null (connect_topology_option_str);
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "connect_topology_option_modifier",
-                                             &connect_topology_option_modifier_string))
-  {
-    if (SSCANF
-        (connect_topology_option_modifier_string, "%lf",
-         &connect_topology_option_modifier) != 1)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  connect_topology_option_modifier_string,
-                  "connect_topology_option_modifier", "TESTING");
-    }
-    GNUNET_free (connect_topology_option_modifier_string);
-  }
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "blacklist_transports",
-                                             &blacklist_transports))
-    blacklist_transports = NULL;
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "blacklist_topology",
-                                              &blacklist_topology_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_get (&blacklist_topology,
-                                    blacklist_topology_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid topology `%s' given for section %s option %s\n",
-                topology_str, "TESTING", "BLACKLIST_TOPOLOGY");
-  }
-  GNUNET_free_non_null (topology_str);
-  GNUNET_free_non_null (blacklist_topology_str);
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME",
-                                           &settle_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "SETTLE_TIME");
-    return;
-  }
-  if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
-                                             &num_peers))
-    num_peers = DEFAULT_NUM_PEERS;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "CONNECT_TIMEOUT",
-                                             &connect_timeout))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "CONNECT_TIMEOUT");
-    return;
-  }
-
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
-                                             &connect_attempts))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "connect_attempts");
-    return;
-  }
-
-  main_cfg = cfg;
-
-  peers_left = num_peers;
-
-  /**
-   * How long until we fail the whole testcase?
-   */
-  test_timeout =
-      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply
-                                     (GNUNET_TIME_UNIT_SECONDS,
-                                      SECONDS_PER_PEER_START), num_peers * 2);
-
-  /**
-   * How long until we give up on starting the peers?
-   */
-  timeout =
-      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply
-                                     (GNUNET_TIME_UNIT_SECONDS,
-                                      SECONDS_PER_PEER_START), num_peers);
-
-  modnum = num_peers / 4;
-  dotnum = (num_peers / 50) + 1;
-#if VERBOSE
-  FPRINTF (stdout, "%s",  "Hostkey generation progress: [");
-#endif
-  /* Set up a task to end testing if peer start fails */
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (timeout, &end_badly,
-                                    "didn't generate all hostkeys within a reasonable amount of time!!!");
-
-  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
-  pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left / 2,
-                                     peers_left, timeout, &hostkey_callback,
-                                     NULL, &peers_started_callback, NULL,
-                                     &topology_callback, NULL, NULL);
-
-}
-
-static int
-check ()
-{
-  char *binary_name;
-  char *config_file_name;
-
-  GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string);
-  GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf",
-                   topology_string);
-  int ret;
-
-  char *const argv[] = { binary_name,
-    "-c",
-    config_file_name,
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  ret =
-      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                          binary_name, "nohelp", options, &run, &ok);
-  if (ret != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "`test-testing-topology-%s': Failed with error code %d\n",
-                topology_string, ret);
-  }
-  GNUNET_free (binary_name);
-  GNUNET_free (config_file_name);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-  char *binary_start_pos;
-  char *our_binary_name;
-
-  binary_start_pos = rindex (argv[0], '/');
-  GNUNET_assert (binary_start_pos != NULL);
-  topology_string = strstr (binary_start_pos, "_topology");
-  GNUNET_assert (topology_string != NULL);
-  topology_string++;
-  topology_string = strstr (topology_string, "_");
-  GNUNET_assert (topology_string != NULL);
-  topology_string++;
-
-  GNUNET_asprintf (&our_binary_name, "test-testing-large-topology_%s",
-                   topology_string);
-  GNUNET_asprintf (&dotOutFileName, "large_topology_%s.dot", topology_string);
-
-  GNUNET_log_setup (our_binary_name,
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-
-  /**
-   * Need to remove base directory, subdirectories taken care
-   * of by the testing framework.
-   */
-  if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to remove testing directory %s\n", test_directory);
-  }
-  GNUNET_free (our_binary_name);
-  return ret;
-}
-
-/* end of test_testing_topology.c */
diff --git a/src/testing/test_testing_peergroup.c b/src/testing/test_testing_peergroup.c
deleted file mode 100644 (file)
index 061a0ca..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_peergroup.c
- * @brief testcase for functions to connect peers in testing_peergroup.c
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_NO
-
-#define NUM_PEERS 4
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-static int ok;
-
-static int peers_left;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
-#endif
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-#endif
-    ok = 0;
-  }
-}
-
-
-static void
-my_cb (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Peergroup callback called with error, aborting test!\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
-    ok = 1;
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    return;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Peer Group started successfully, ending test!\n");
-  /**
-   * If something is to actually be DONE with the testcase, it should
-   * be put in here.  Usually there will be a struct declared (or global
-   * variables can be used) to keep track of the state, statistics,
-   * handles to peers, etc.  The example here is the opaque "TestCaseData"
-   * struct that could be passed into a function "additional_code_for_testing"
-   * which can be used to perform actions on the peers in the peergroup.
-   * Also, the GNUNET_TESTING_daemons_stop call would need to be removed,
-   * and only called once all of the testing is complete.
-   */
-
-  /**
-   * struct TestcaseData *state_closure;
-   * GNUNET_SCHEDULER_add_now(&additional_code_for_testing, state_closure);
-   */
-
-  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_CONFIGURATION_Handle *testing_cfg;
-
-  ok = 1;
-  testing_cfg = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (testing_cfg, cfgfile));
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
-  GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
-                                         "use_progressbars", "YES");
-#endif
-  peers_left = NUM_PEERS;
-  pg = GNUNET_TESTING_peergroup_start (testing_cfg, peers_left, TIMEOUT, NULL,
-                                       &my_cb, NULL, NULL);
-  GNUNET_assert (pg != NULL);
-}
-
-static int
-check ()
-{
-  char *const argv[] = { "test-testing-peergroup",
-    "-c",
-    "test_testing_peergroup_data.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                      "test-testing-peergroup", "nohelp", options, &run, &ok);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test-testing-peergroup",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
-  return ret;
-}
-
-/* end of test_testing_peergroup.c */
diff --git a/src/testing/test_testing_peergroup_data.conf b/src/testing/test_testing_peergroup_data.conf
deleted file mode 100644 (file)
index 6eadede..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-@INLINE@ test_testing_defaults.conf
-[PATHS]
-DEFAULTCONFIG = test_testing_peergroup_data.conf
-
-[TESTING]
-CONNECT_ATTEMPTS = 2
-MAX_OUTSTANDING_CONNECTIONS = 20
-MAX_CONCURRENT_SSH = 1
-PEERGROUP_TIMEOUT = 300 s
-TOPOLOGY = CLIQUE
-PERCENTAGE = 0.5
-PROBABILITY = 0.5
-CONNECT_TOPOLOGY = CLIQUE
-CONNECT_TOPOLOGY_OPTION = CONNECT_NONE
-CONNECT_TOPOLOGY_OPTION_MODIFIER = 0.0
-BLACKLIST_TOPOLOGY = NONE
-BLACKLIST_TRANSPORTS = tcp udp
-USE_PROGRESSBARS = NO
-
-[arm]
-DEFAULTSERVICES = core
-
diff --git a/src/testing/test_testing_reconnect.c b/src/testing/test_testing_reconnect.c
deleted file mode 100644 (file)
index bcee386..0000000
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2010 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_reconnect.c
- * @brief testcase for functions to connect two peers in testing.c
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-
-#define VERBOSE GNUNET_YES
-
-/**
- * How long until we give up on connecting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-#define CONNECT_ATTEMPTS 3
-
-static int ok;
-
-static struct GNUNET_TESTING_Daemon *d1;
-
-static struct GNUNET_TESTING_Daemon *d2;
-
-static struct GNUNET_CONFIGURATION_Handle *c1;
-
-static struct GNUNET_CONFIGURATION_Handle *c2;
-
-static struct GNUNET_TESTING_ConnectContext *cc;
-
-/**
- * How many start-connect-stop iterations should we do?
- */
-#define NUM_PHASES 2
-
-static int phase;
-
-/**
- * Run the next phase of starting daemons, connecting them and
- * stopping them again.
- */
-static void
-run_phase (void);
-
-static void
-end2_cb (void *cls, const char *emsg)
-{
-
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
-    ok = 1;
-  }
-  else
-  {
-    if (phase < NUM_PHASES)
-    {
-      FPRINTF (stderr, "%s",  ".");
-      run_phase ();
-      return;
-    }
-    FPRINTF (stderr, "%s",  ".\n");
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Both daemons terminated, will now exit.\n");
-#endif
-    ok = 0;
-  }
-}
-
-static void
-end1_cb (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n",
-                emsg);
-    ok = 1;
-  }
-  else
-  {
-    ok = 0;
-  }
-  if (d2 != NULL)
-  {
-    GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL,
-                                (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO,
-                                GNUNET_NO);
-    d2 = NULL;
-  }
-}
-
-static void
-finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL,
-                              (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO,
-                              GNUNET_NO);
-  d1 = NULL;
-}
-
-
-static void
-my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first,
-                     const struct GNUNET_PeerIdentity *second,
-                     unsigned int 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)
-{
-  cc = NULL;
-#if VERBOSE
-  FPRINTF (stderr, "Peer %s ", GNUNET_i2s (first));
-  FPRINTF (stderr, "connected to %s\n", GNUNET_i2s (second));
-#endif
-  GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-}
-
-
-
-
-static void
-my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id,
-        const struct GNUNET_CONFIGURATION_Handle *cfg,
-        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 2 gave: %s\n",
-                emsg);
-    GNUNET_assert (0);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
-              GNUNET_i2s (id));
-#endif
-  cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS,
-                                       GNUNET_YES, &my_connect_complete, NULL);
-}
-
-
-static void
-my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id,
-        const struct GNUNET_CONFIGURATION_Handle *cfg,
-        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 1 gave: %s\n",
-                emsg);
-    GNUNET_assert (0);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
-              GNUNET_i2s (id));
-#endif
-  d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
-                                    NULL, NULL, &my_cb2, NULL);
-  GNUNET_assert (d2 != NULL);
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  ok = 1;
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
-#endif
-  c1 = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (c1,
-                                            "test_testing_connect_peer1.conf"));
-  c2 = GNUNET_CONFIGURATION_create ();
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_load (c2,
-                                            "test_testing_connect_peer2.conf"));
-  run_phase ();
-}
-
-static void
-run_phase ()
-{
-  phase++;
-  d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
-                                    NULL, NULL, &my_cb1, NULL);
-  GNUNET_assert (d1 != NULL);
-}
-
-static int
-check ()
-{
-  char *const argv[] = { "test-testing-reconnect",
-    "-c",
-    "test_testing_data.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                      "test-testing-reconnect", "nohelp", options, &run, &ok);
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test-testing-reconnect",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-  return ret;
-}
-
-/* end of test_testing_reconnect.c */
diff --git a/src/testing/test_testing_topology.c b/src/testing/test_testing_topology.c
deleted file mode 100644 (file)
index 94cbc0d..0000000
+++ /dev/null
@@ -1,1220 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_topology.c
- * @brief base testcase for testing all the topologies provided
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_os_lib.h"
-
-
-#define PROGRESS_BARS GNUNET_YES
-
-#define DELAY_FOR_LOGGING GNUNET_NO
-
-/**
- * How long until we fail the whole testcase?
- */
-#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 240)
-
-/**
- * How long until we give up on starting the peers?
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 500)
-
-#define SECONDS_PER_PEER_START 120
-
-#define DEFAULT_NUM_PEERS 4
-
-#define MAX_OUTSTANDING_CONNECTIONS 100
-
-static float fail_percentage = 0.05;
-
-static int ok;
-
-static unsigned long long num_peers;
-
-struct GNUNET_TIME_Relative connect_timeout;
-
-static unsigned long long connect_attempts;
-
-static unsigned int topology_connections;
-
-static unsigned int total_connections;
-
-static unsigned int failed_connections;
-
-static unsigned int total_server_connections;
-
-static unsigned int total_messages_received;
-
-static unsigned int expected_messages;
-
-static unsigned int expected_connections;
-
-static unsigned long long peers_left;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-const struct GNUNET_CONFIGURATION_Handle *main_cfg;
-
-GNUNET_SCHEDULER_TaskIdentifier die_task;
-
-static char *dotOutFileName;
-
-static struct GNUNET_TIME_Relative settle_time;
-
-static FILE *dotOutFile;
-
-static char *topology_string;
-
-static char *blacklist_transports;
-
-static int transmit_ready_scheduled;
-
-static int transmit_ready_failed;
-
-static int transmit_ready_called;
-
-static unsigned int modnum;
-
-static unsigned int dotnum;
-
-static enum GNUNET_TESTING_Topology topology;
-
-static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE;  /* Don't do any blacklisting */
-
-static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
-
-static enum GNUNET_TESTING_TopologyOption connect_topology_option =
-    GNUNET_TESTING_TOPOLOGY_OPTION_ALL;
-
-static double connect_topology_option_modifier = 0.0;
-
-static char *test_directory;
-
-#define MTYPE 12345
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-struct GNUNET_TestMessage
-{
-  /**
-   * Header of the message
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this message.
-   */
-  uint32_t uid;
-};
-GNUNET_NETWORK_STRUCT_END
-
-struct TestMessageContext
-{
-  /* This is a linked list */
-  struct TestMessageContext *next;
-
-  /* Handle to the sending peer core */
-  struct GNUNET_CORE_Handle *peer1handle;
-
-  /* Handle to the receiving peer core */
-  struct GNUNET_CORE_Handle *peer2handle;
-
-  /* Handle to the sending peer daemon */
-  struct GNUNET_TESTING_Daemon *peer1;
-
-  /* Handle to the receiving peer daemon */
-  struct GNUNET_TESTING_Daemon *peer2;
-
-  /* Identifier for this message, so we don't disconnect other peers! */
-  uint32_t uid;
-
-  /* Has peer1 been notified already of a connection to peer2? */
-  int peer1notified;
-
-  /* Has the core of peer2 been connected already? */
-  int peer2connected;
-
-  /* Task for disconnecting cores, allow task to be cancelled on shutdown */
-  GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
-
-};
-
-static struct TestMessageContext *test_messages;
-
-/**
- * Check whether peers successfully shut down.
- */
-static void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Shutdown of peers failed: %s!\n",
-               emsg);
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-  }
-}
-
-
-#if DELAY_FOR_LOGGING
-static void
-gather_log_data ()
-{
-  char *peer_number;
-  char *connect_number;
-  struct GNUNET_OS_Process *mem_process;
-
-  GNUNET_asprintf (&peer_number, "%llu", num_peers);
-  GNUNET_asprintf (&connect_number, "%llu", expected_connections);
-  mem_process =
-      GNUNET_OS_start_process (NULL, NULL, "./memsize.pl", "memsize.pl",
-                               "totals.txt", peer_number, connect_number, NULL);
-  GNUNET_OS_process_wait (mem_process);
-  GNUNET_OS_process_destroy (mem_process);
-  mem_process = NULL;
-}
-#endif
-
-
-static void
-finish_testing ()
-{
-  GNUNET_assert (pg != NULL);
-  struct TestMessageContext *pos;
-  struct TestMessageContext *free_pos;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Called finish testing, stopping daemons.\n");
-  pos = test_messages;
-  while (pos != NULL)
-  {
-    if (pos->peer1handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer1handle);
-      pos->peer1handle = NULL;
-    }
-    if (pos->peer2handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer2handle);
-      pos->peer2handle = NULL;
-    }
-    free_pos = pos;
-    pos = pos->next;
-    if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK)
-    {
-      GNUNET_SCHEDULER_cancel (free_pos->disconnect_task);
-    }
-    GNUNET_free (free_pos);
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
-              transmit_ready_scheduled, transmit_ready_failed,
-              transmit_ready_called);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
-  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "}");
-    FCLOSE (dotOutFile);
-  }
-  ok = 0;
-}
-
-
-static void
-disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct TestMessageContext *pos = cls;
-
-  /* Disconnect from the respective cores */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n",
-              GNUNET_i2s (&pos->peer1->id));
-  if (pos->peer1handle != NULL)
-  {
-    GNUNET_CORE_disconnect (pos->peer1handle);
-    pos->peer1handle = NULL;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n",
-              GNUNET_i2s (&pos->peer2->id));
-  if (pos->peer2handle != NULL)
-  {
-    GNUNET_CORE_disconnect (pos->peer2handle);
-    pos->peer2handle = NULL;
-  }
-  pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-  /* Decrement total connections so new can be established */
-  total_server_connections -= 2;
-}
-
-#if DO_STATS
-static void
-stats_finished (void *cls, int result)
-{
-  GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-}
-
-/**
- * Callback function to process statistic values.
- *
- * @param cls closure
- * @param peer the peer the statistics belong to
- * @param subsystem name of subsystem that created the statistic
- * @param name the name of the datum
- * @param value the current value
- * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
- * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
- */
-static int
-stats_print (void *cls, const struct GNUNET_PeerIdentity *peer,
-             const char *subsystem, const char *name, uint64_t value,
-             int is_persistent)
-{
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s:%s -- %llu\n", GNUNET_i2s (peer),
-              subsystem, name, value);
-  return GNUNET_OK;
-}
-#endif
-
-
-static void
-topology_cb (void *cls, const struct GNUNET_PeerIdentity *first,
-             const struct GNUNET_PeerIdentity *second, const char *emsg)
-{
-  FILE *outfile = cls;
-
-  if (first != NULL)
-  {
-    if (outfile != NULL)
-    {
-      FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first));
-      FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second));
-    }
-    topology_connections++;
-  }
-  else
-  {
-    FPRINTF (stderr,
-             "Finished iterating over topology, %d total connections!\n",
-             topology_connections);
-    if (outfile != NULL)
-    {
-      FPRINTF (outfile, "%s",  "}\n");
-      FCLOSE (outfile);
-#if DO_STATS
-      GNUNET_TESTING_get_statistics (pg, &stats_finished, &stats_print, NULL);
-#endif
-      GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-    }
-  }
-}
-
-
-static int
-process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer,
-               const struct GNUNET_MessageHeader *message,
-               const struct GNUNET_ATS_Information *atsi,
-               unsigned int atsi_count)
-{
-  char *dotOutFileNameFinished;
-  FILE *dotOutFileFinished;
-  struct TestMessageContext *pos = cls;
-  struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message;
-
-  if (pos->uid != ntohl (msg->uid))
-    return GNUNET_OK;
-
-#if PROGRESS_BARS
-  if ((total_messages_received) % modnum == 0)
-  {
-    if (total_messages_received == 0)
-      FPRINTF (stdout, "%s",  "0%%");
-    else
-      FPRINTF (stdout, "%d%%",
-               (int) (((float) total_messages_received / expected_messages) *
-                      100));
-
-  }
-  else if (total_messages_received % dotnum == 0)
-  {
-    FPRINTF (stdout, "%s",  ".");
-  }
-  fflush (stdout);
-#endif
-
-  total_messages_received++;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received message from `%4s', type %d.\n", GNUNET_i2s (peer),
-              ntohs (message->type));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Total messages received %d, expected %d.\n",
-              total_messages_received, expected_messages);
-
-  if (total_messages_received == expected_messages)
-  {
-#if PROGRESS_BARS
-    FPRINTF (stdout, "%s",  "100%%]\n");
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology");
-    dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w");
-    GNUNET_free (dotOutFileNameFinished);
-    if (dotOutFileFinished != NULL)
-    {
-      FPRINTF (dotOutFileFinished, "%s",  "strict graph G {\n");
-    }
-    topology_connections = 0;
-    GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished);
-    //GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-  }
-  else
-  {
-    pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos);
-  }
-
-  return GNUNET_OK;
-}
-
-
-static void
-end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char *msg = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Ending with error: %s\n", msg);
-  struct TestMessageContext *pos;
-  struct TestMessageContext *free_pos;
-
-  pos = test_messages;
-  while (pos != NULL)
-  {
-    if (pos->peer1handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer1handle);
-      pos->peer1handle = NULL;
-    }
-    if (pos->peer2handle != NULL)
-    {
-      GNUNET_CORE_disconnect (pos->peer2handle);
-      pos->peer2handle = NULL;
-    }
-    free_pos = pos;
-    pos = pos->next;
-    GNUNET_free (free_pos);
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
-              transmit_ready_scheduled, transmit_ready_failed,
-              transmit_ready_called);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Total messages received %d, expected %d.\n",
-              total_messages_received, expected_messages);
-
-  if (pg != NULL)
-  {
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    ok = 7331;                  /* Opposite of leet */
-  }
-  else
-    ok = 401;                   /* Never got peers started */
-
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "}");
-    FCLOSE (dotOutFile);
-  }
-}
-
-
-static size_t
-transmit_ready (void *cls, size_t size, void *buf)
-{
-  struct GNUNET_TestMessage *m;
-  struct TestMessageContext *pos = cls;
-
-  GNUNET_assert (buf != NULL);
-  m = (struct GNUNET_TestMessage *) buf;
-  m->header.type = htons (MTYPE);
-  m->header.size = htons (sizeof (struct GNUNET_TestMessage));
-  m->uid = htonl (pos->uid);
-  transmit_ready_called++;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n",
-              GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled,
-              transmit_ready_called);
-  return sizeof (struct GNUNET_TestMessage);
-}
-
-
-static struct GNUNET_CORE_MessageHandler no_handlers[] = {
-  {NULL, 0, 0}
-};
-
-
-static struct GNUNET_CORE_MessageHandler handlers[] = {
-  {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)},
-  {NULL, 0, 0}
-};
-
-
-static void
-init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server,
-                   const struct GNUNET_PeerIdentity *my_identity)
-{
-  struct TestMessageContext *pos = cls;
-
-  total_server_connections++;
-
-  pos->peer2connected = GNUNET_YES;
-  if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
-                GNUNET_i2s (my_identity),
-                GNUNET_h2s (&pos->peer1->id.hashPubKey));
-    if (NULL ==
-        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0,
-                                           TIMEOUT, &pos->peer2->id,
-                                           sizeof (struct GNUNET_TestMessage),
-                                           &transmit_ready, pos))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
-                  GNUNET_i2s (&pos->peer2->id));
-      transmit_ready_failed++;
-    }
-    else
-    {
-      transmit_ready_scheduled++;
-    }
-  }
-}
-
-
-/**
- * Method called whenever a given peer connects.
- *
- * @param cls closure
- * @param peer peer identity this notification is about
- * @param atsi performance data for the connection
- * @param atsi_count number of records in 'atsi'
- */
-static void
-connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer,
-                      const struct GNUNET_ATS_Information *atsi,
-                      unsigned int atsi_count)
-{
-  struct TestMessageContext *pos = cls;
-
-  if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity)))
-  {
-    pos->peer1notified = GNUNET_YES;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Peer `%s' notified of connection to peer `%s'\n",
-                GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey));
-  }
-  else
-    return;
-
-  if (pos->peer2connected == GNUNET_YES)        /* Already connected and notified of connection, send message! */
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
-                GNUNET_i2s (&pos->peer2->id),
-                GNUNET_h2s (&pos->peer1->id.hashPubKey));
-    if (NULL ==
-        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0,
-                                           TIMEOUT, &pos->peer2->id,
-                                           sizeof (struct GNUNET_TestMessage),
-                                           &transmit_ready, pos))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
-                  GNUNET_i2s (&pos->peer2->id));
-      transmit_ready_failed++;
-    }
-    else
-    {
-      transmit_ready_scheduled++;
-    }
-  }
-}
-
-
-static void
-init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server,
-                   const struct GNUNET_PeerIdentity *my_identity)
-{
-  struct TestMessageContext *pos = cls;
-
-  total_server_connections++;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Core connection to `%4s' established, setting up handles\n",
-              GNUNET_i2s (my_identity));
-  /*
-   * Connect to the receiving peer
-   */
-  pos->peer2handle =
-      GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL,
-                           NULL, NULL, GNUNET_YES, NULL, GNUNET_YES, handlers);
-
-}
-
-
-static void
-send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct TestMessageContext *pos = cls;
-
-  if ((pos == test_messages) && (settle_time.rel_value > 0))
-  {
-    topology_connections = 0;
-    GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
-  }
-  if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL))
-    return;
-
-  if (die_task == GNUNET_SCHEDULER_NO_TASK)
-  {
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly,
-                                      "from send test messages (timeout)");
-  }
-
-  if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS)
-  {
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 1),
-                                  &send_test_messages, pos);
-    return;                     /* Otherwise we'll double schedule messages here! */
-  }
-
-  /*
-   * Connect to the sending peer
-   */
-  pos->peer1handle =
-      GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1,
-                           &connect_notify_peers, NULL, NULL, GNUNET_NO, NULL,
-                           GNUNET_NO, no_handlers);
-
-  GNUNET_assert (pos->peer1handle != NULL);
-
-  if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS)
-  {
-    GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next);
-  }
-  else
-  {
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 1),
-                                  &send_test_messages, pos->next);
-  }
-}
-
-
-static void
-topology_callback (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)
-{
-  struct TestMessageContext *temp_context;
-
-  if (emsg == NULL)
-  {
-#if PROGRESS_BARS
-    if ((total_connections) % modnum == 0)
-    {
-      if (total_connections == 0)
-        FPRINTF (stdout, "%s",  "0%%");
-      else
-        FPRINTF (stdout, "%d%%",
-                 (int) (((float) total_connections / expected_connections) *
-                        100));
-
-    }
-    else if (total_connections % dotnum == 0)
-    {
-      FPRINTF (stdout, "%s",  ".");
-    }
-    fflush (stdout);
-#endif
-    total_connections++;
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n",
-                first_daemon->shortname, second_daemon->shortname);
-    temp_context = GNUNET_malloc (sizeof (struct TestMessageContext));
-    temp_context->peer1 = first_daemon;
-    temp_context->peer2 = second_daemon;
-    temp_context->next = test_messages;
-    temp_context->uid = total_connections;
-    temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
-    test_messages = temp_context;
-
-    expected_messages++;
-    if (dotOutFile != NULL)
-      FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname,
-               second_daemon->shortname);
-  }
-  else
-  {
-    failed_connections++;
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Failed to connect peer %s to peer %s with error :\n%s\n",
-                first_daemon->shortname, second_daemon->shortname, emsg);
-  }
-
-  if (total_connections == expected_connections)
-  {
-#if PROGRESS_BARS
-    FPRINTF (stdout, "%s",  "100%%]\n");
-#endif
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Created %d total connections, which is our target number!  Calling send messages.\n",
-                total_connections);
-    modnum = expected_messages / 4;
-    dotnum = (expected_messages / 50) + 1;
-    if (modnum == 0)
-      modnum = 1;
-    if (dotnum == 0)
-      dotnum = 1;
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task = GNUNET_SCHEDULER_NO_TASK;
-#if DELAY_FOR_LOGGING
-    FPRINTF (stdout, "%s",  "Sending test messages in 10 seconds.\n");
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 10),
-                                  &send_test_messages, test_messages);
-    gather_log_data ();
-#else
-    if (settle_time.rel_value > 0)
-    {
-      GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
-    }
-    GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages,
-                                  test_messages);
-#endif
-#if PROGRESS_BARS
-    FPRINTF (stdout, "%s",  "Test message progress: [");
-#endif
-
-  }
-  else if (total_connections + failed_connections == expected_connections)
-  {
-    if (failed_connections <
-        (unsigned int) (fail_percentage * total_connections))
-    {
-      GNUNET_SCHEDULER_cancel (die_task);
-      die_task = GNUNET_SCHEDULER_NO_TASK;
-      GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages);
-    }
-    else
-    {
-      GNUNET_SCHEDULER_cancel (die_task);
-      die_task =
-          GNUNET_SCHEDULER_add_now (&end_badly,
-                                    "from topology_callback (too many failed connections)");
-    }
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Have %d total connections, %d failed connections, Want %d (at least %d)\n",
-                total_connections, failed_connections, expected_connections,
-                expected_connections -
-                (unsigned int) (fail_percentage * expected_connections));
-  }
-}
-
-
-static void
-topology_creation_finished (void *cls, const char *emsg)
-{
-  if (emsg == NULL)
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All topology connections created successfully!\n");
-}
-
-
-static void
-connect_topology ()
-{
-  expected_connections = -1;
-  if ((pg != NULL) && (peers_left == 0))
-  {
-    expected_connections =
-        GNUNET_TESTING_connect_topology (pg, connection_topology,
-                                         connect_topology_option,
-                                         connect_topology_option_modifier,
-                                         connect_timeout, connect_attempts,
-                                         &topology_creation_finished, NULL);
-#if PROGRESS_BARS
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
-                expected_connections);
-#endif
-  }
-
-  GNUNET_SCHEDULER_cancel (die_task);
-  if (expected_connections < 1)
-  {
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from connect topology (bad return)");
-    return;
-  }
-
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS,
-                                     SECONDS_PER_PEER_START * num_peers),
-                                    &end_badly,
-                                    "from connect topology (timeout)");
-  modnum = expected_connections / 4;
-  dotnum = (expected_connections / 50) + 1;
-  if (modnum == 0)
-    modnum = 1;
-  if (dotnum == 0)
-    dotnum = 1;
-#if PROGRESS_BARS
-  FPRINTF (stdout, "%s",  "Peer connection progress: [");
-#endif
-}
-
-static void
-create_topology ()
-{
-  peers_left = num_peers;       /* Reset counter */
-  if (GNUNET_TESTING_create_topology
-      (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
-  {
-#if PROGRESS_BARS
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Topology set up, now starting peers!\n");
-    FPRINTF (stdout, "%s",  "Daemon start progress [");
-#endif
-    GNUNET_TESTING_daemons_continue_startup (pg);
-  }
-  else
-  {
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from create topology (bad return)");
-  }
-  GNUNET_SCHEDULER_cancel (die_task);
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS,
-                                     SECONDS_PER_PEER_START * num_peers),
-                                    &end_badly,
-                                    "from continue startup (timeout)");
-}
-
-
-static void
-peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                        const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to start daemon with error: `%s'\n", emsg);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
-              (num_peers - peers_left) + 1, num_peers);
-#if PROGRESS_BARS
-  if ((num_peers - peers_left) % modnum == 0)
-  {
-    if (num_peers - peers_left == 0)
-      FPRINTF (stdout, "%s",  "0%%");
-    else
-      FPRINTF (stdout, "%d%%",
-               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
-
-  }
-  else if ((num_peers - peers_left) % dotnum == 0)
-  {
-    FPRINTF (stdout, "%s",  ".");
-  }
-  fflush (stdout);
-#endif
-  peers_left--;
-  if (peers_left == 0)
-  {
-#if PROGRESS_BARS
-    FPRINTF (stdout, "%s",  "100%%]\n");
-#endif
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d daemons started, now connecting peers!\n", num_peers);
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_TIME_UNIT_MINUTES, 8), &end_badly,
-                                      "from peers_started_callback");
-#if DELAY_FOR_LOGGING
-    FPRINTF (stdout, "%s",  "Connecting topology in 10 seconds\n");
-    gather_log_data ();
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_SECONDS, 10),
-                                  &connect_topology, NULL);
-#else
-    connect_topology ();
-#endif
-    ok = 0;
-  }
-}
-
-/**
- * Callback indicating that the hostkey was created for a peer.
- *
- * @param cls NULL
- * @param id the peer identity
- * @param d the daemon handle (pretty useless at this point, remove?)
- * @param emsg non-null on failure
- */
-void
-hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Hostkey callback received error: %s\n", emsg);
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left,
-              num_peers, GNUNET_i2s (id));
-#if PROGRESS_BARS
-  if ((num_peers - peers_left) % modnum == 0)
-  {
-    if (num_peers - peers_left == 0)
-      FPRINTF (stdout, "%s",  "0%%");
-    else
-      FPRINTF (stdout, "%d%%",
-               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
-
-  }
-  else if ((num_peers - peers_left) % dotnum == 0)
-  {
-    FPRINTF (stdout, "%s",  ".");
-  }
-  fflush (stdout);
-#endif
-  peers_left--;
-  if (peers_left == 0)
-  {
-#if PROGRESS_BARS
-    FPRINTF (stdout, "%s",  "100%%]\n");
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d hostkeys created, now creating topology!\n", num_peers);
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
-                                      "from create_topology");
-    GNUNET_SCHEDULER_add_now (&create_topology, NULL);
-    ok = 0;
-  }
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  char *topology_str;
-  char *connect_topology_str;
-  char *blacklist_topology_str;
-  char *connect_topology_option_str;
-  char *connect_topology_option_modifier_string;
-  unsigned long long max_outstanding_connections;
-
-  ok = 1;
-
-  dotOutFile = FOPEN (dotOutFileName, "w");
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "strict graph G {\n");
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting daemons based on config file %s\n", cfgfile);
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
-                                             &test_directory))
-  {
-    ok = 404;
-    return;
-  }
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology",
-                                              &topology_str)) &&
-      (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid topology `%s' given for section %s option %s\n",
-                topology_str, "TESTING", "TOPOLOGY");
-    topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;  /* Defaults to NONE, so set better default here */
-  }
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "connect_topology",
-                                              &connect_topology_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_get (&connection_topology,
-                                    connect_topology_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid connect topology `%s' given for section %s option %s\n",
-                connect_topology_str, "TESTING", "CONNECT_TOPOLOGY");
-  }
-  GNUNET_free_non_null (connect_topology_str);
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "connect_topology_option",
-                                              &connect_topology_option_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_option_get (&connect_topology_option,
-                                           connect_topology_option_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid connect topology option `%s' given for section %s option %s\n",
-                connect_topology_option_str, "TESTING",
-                "CONNECT_TOPOLOGY_OPTION");
-    connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL;       /* Defaults to NONE, set to ALL */
-  }
-  GNUNET_free_non_null (connect_topology_option_str);
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "connect_topology_option_modifier",
-                                             &connect_topology_option_modifier_string))
-  {
-    if (SSCANF
-        (connect_topology_option_modifier_string, "%lf",
-         &connect_topology_option_modifier) != 1)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  connect_topology_option_modifier_string,
-                  "connect_topology_option_modifier", "TESTING");
-    }
-    GNUNET_free (connect_topology_option_modifier_string);
-  }
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "blacklist_transports",
-                                             &blacklist_transports))
-    blacklist_transports = NULL;
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "blacklist_topology",
-                                              &blacklist_topology_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_get (&blacklist_topology,
-                                    blacklist_topology_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid topology `%s' given for section %s option %s\n",
-                topology_str, "TESTING", "BLACKLIST_TOPOLOGY");
-  }
-  GNUNET_free_non_null (topology_str);
-  GNUNET_free_non_null (blacklist_topology_str);
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME",
-                                           &settle_time))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "SETTLE_TIME");
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT",
-                                           &connect_timeout))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "CONNECT_TIMEOUT");
-    return;
-  }
-
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
-                                             &connect_attempts))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "connect_attempts");
-    return;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
-                                             "max_outstanding_connections",
-                                             &max_outstanding_connections))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "max_outstanding_connections");
-    return;
-  }
-
-  if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
-                                             &num_peers))
-    num_peers = DEFAULT_NUM_PEERS;
-
-  main_cfg = cfg;
-
-  peers_left = num_peers;
-  modnum = num_peers / 4;
-  dotnum = (num_peers / 50) + 1;
-  if (modnum == 0)
-    modnum = 1;
-  if (dotnum == 0)
-    dotnum = 1;
-#if PROGRESS_BARS
-  FPRINTF (stdout, "%s",  "Hostkey generation progress: [");
-#endif
-  /* Set up a task to end testing if peer start fails */
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_SECONDS,
-                                     SECONDS_PER_PEER_START * num_peers),
-                                    &end_badly,
-                                    "didn't generate all hostkeys within a reasonable amount of time!!!");
-
-  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
-  pg = GNUNET_TESTING_daemons_start (cfg, peers_left,
-                                     max_outstanding_connections, peers_left,
-                                     GNUNET_TIME_relative_multiply
-                                     (GNUNET_TIME_UNIT_SECONDS,
-                                      SECONDS_PER_PEER_START * num_peers),
-                                     &hostkey_callback, NULL,
-                                     &peers_started_callback, NULL,
-                                     &topology_callback, NULL, NULL);
-
-}
-
-
-static int
-check ()
-{
-  char *binary_name;
-  char *config_file_name;
-
-  GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string);
-  GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf",
-                   topology_string);
-  int ret;
-
-  char *const argv[] = { binary_name,
-    "-c",
-    config_file_name,
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  ret =
-      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                          binary_name, "nohelp", options, &run, &ok);
-  if (ret != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "`test-testing-topology-%s': Failed with error code %d\n",
-                topology_string, ret);
-  }
-  GNUNET_free (binary_name);
-  GNUNET_free (config_file_name);
-  return ok;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-  char *binary_start_pos;
-  char *our_binary_name;
-  char *dotexe;
-
-  binary_start_pos = strchr (argv[0], '/');
-  GNUNET_assert (binary_start_pos != NULL);
-  topology_string = strstr (binary_start_pos, "_topology");
-  GNUNET_assert (topology_string != NULL);
-  topology_string++;
-  topology_string = strstr (topology_string, "_");
-  GNUNET_assert (topology_string != NULL);
-  topology_string++;
-  topology_string = GNUNET_strdup (topology_string);
-  if (NULL != (dotexe = strstr (topology_string, ".exe")))
-    dotexe[0] = '\0';
-  GNUNET_asprintf (&our_binary_name, "test-testing-topology_%s",
-                   topology_string);
-  GNUNET_asprintf (&dotOutFileName, "topology_%s.dot", topology_string);
-
-  GNUNET_log_setup (our_binary_name,
-                    "WARNING",
-                    NULL);
-  ret = check ();
-  GNUNET_free (topology_string);
-
-  /**
-   * Need to remove base directory, subdirectories taken care
-   * of by the testing framework.
-   */
-  if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to remove testing directory %s\n", test_directory);
-  }
-  GNUNET_free (our_binary_name);
-  return ret;
-}
-
-/* end of test_testing_topology.c */
diff --git a/src/testing/test_testing_topology_blacklist.c b/src/testing/test_testing_topology_blacklist.c
deleted file mode 100644 (file)
index c90f48d..0000000
+++ /dev/null
@@ -1,595 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_topology_blacklist.c
- * @brief base testcase for testing transport level blacklisting
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-
-#define VERBOSE GNUNET_NO
-
-/**
- * How long until we fail the whole testcase?
- */
-#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
-
-/**
- * How long until we give up on starting the peers? (Must be longer than the connect timeout!)
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-#define DEFAULT_NUM_PEERS 4
-
-#define MAX_OUTSTANDING_CONNECTIONS 300
-
-static int ok;
-
-struct GNUNET_TIME_Relative connect_timeout;
-
-static unsigned long long connect_attempts;
-
-static unsigned long long num_peers;
-
-static unsigned int total_connections;
-
-static unsigned int failed_connections;
-
-static unsigned int expected_connections;
-
-static unsigned int expected_failed_connections;
-
-static unsigned long long peers_left;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-const struct GNUNET_CONFIGURATION_Handle *main_cfg;
-
-GNUNET_SCHEDULER_TaskIdentifier die_task;
-
-static char *dotOutFileName;
-
-static FILE *dotOutFile;
-
-static char *blacklist_transports;
-
-static enum GNUNET_TESTING_Topology topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;  /* Overlay should allow all connections */
-
-static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_RING;  /* Blacklist underlay into a ring */
-
-static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
-
-static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Try to connect all possible OVERLAY connections */
-
-static double connect_topology_option_modifier = 0.0;
-
-static char *test_directory;
-
-#define MTYPE 12345
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-struct GNUNET_TestMessage
-{
-  /**
-   * Header of the message
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this message.
-   */
-  uint32_t uid;
-};
-GNUNET_NETWORK_STRUCT_END
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
-#endif
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-#endif
-  }
-}
-
-static void
-finish_testing ()
-{
-  GNUNET_assert (pg != NULL);
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Called finish testing, stopping daemons.\n");
-#endif
-  sleep (1);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
-#endif
-  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n");
-#endif
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "}");
-    FCLOSE (dotOutFile);
-  }
-
-  ok = 0;
-}
-
-static void
-end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char *msg = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "End badly was called (%s)... stopping daemons.\n", msg);
-
-  if (pg != NULL)
-  {
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    ok = 7331;                  /* Opposite of leet */
-  }
-  else
-    ok = 401;                   /* Never got peers started */
-
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "}");
-    FCLOSE (dotOutFile);
-  }
-}
-
-
-
-void
-topology_callback (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)
-{
-  if (emsg == NULL)
-  {
-    total_connections++;
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n",
-                first_daemon->shortname, second_daemon->shortname);
-#endif
-    if (dotOutFile != NULL)
-      FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname,
-               second_daemon->shortname);
-  }
-
-  else
-  {
-    failed_connections++;
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to connect peer %s to peer %s with error :\n%s\n",
-                first_daemon->shortname, second_daemon->shortname, emsg);
-#endif
-  }
-
-
-  if (total_connections == expected_connections)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Created %d total connections, which is our target number (that's bad)!\n",
-                total_connections);
-#endif
-
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task = GNUNET_SCHEDULER_NO_TASK;
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from topology_callback (too many successful connections)");
-  }
-  else if (total_connections + failed_connections == expected_connections)
-  {
-    if ((failed_connections == expected_failed_connections) &&
-        (total_connections ==
-         expected_connections - expected_failed_connections))
-    {
-      GNUNET_SCHEDULER_cancel (die_task);
-      die_task = GNUNET_SCHEDULER_NO_TASK;
-      die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
-    }
-    else
-    {
-      GNUNET_SCHEDULER_cancel (die_task);
-      die_task =
-          GNUNET_SCHEDULER_add_now (&end_badly,
-                                    "from topology_callback (wrong number of failed connections)");
-    }
-  }
-  else
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Have %d total connections, %d failed connections, Want %d (failed) and %d (successful)\n",
-                total_connections, failed_connections,
-                expected_failed_connections,
-                expected_connections - expected_failed_connections);
-#endif
-  }
-}
-
-static void
-connect_topology ()
-{
-  expected_connections = -1;
-  if ((pg != NULL) && (peers_left == 0))
-  {
-    expected_connections =
-        GNUNET_TESTING_connect_topology (pg, connection_topology,
-                                         connect_topology_option,
-                                         connect_topology_option_modifier,
-                                         connect_timeout, connect_attempts,
-                                         NULL, NULL);
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
-                expected_connections);
-#endif
-  }
-
-  GNUNET_SCHEDULER_cancel (die_task);
-  if (expected_connections == GNUNET_SYSERR)
-  {
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from connect topology (bad return)");
-  }
-
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly,
-                                    "from connect topology (timeout)");
-}
-
-static void
-create_topology ()
-{
-  peers_left = num_peers;       /* Reset counter */
-  if (GNUNET_TESTING_create_topology
-      (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Topology set up, now starting peers!\n");
-#endif
-    GNUNET_TESTING_daemons_continue_startup (pg);
-  }
-  else
-  {
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task =
-        GNUNET_SCHEDULER_add_now (&end_badly,
-                                  "from create topology (bad return)");
-  }
-  GNUNET_SCHEDULER_cancel (die_task);
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly,
-                                    "from continue startup (timeout)");
-}
-
-
-static void
-peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                        const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to start daemon with error: `%s'\n", emsg);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
-              (num_peers - peers_left) + 1, num_peers);
-#endif
-  peers_left--;
-  if (peers_left == 0)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d daemons started, now creating topology!\n", num_peers);
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
-                                      "from peers_started_callback");
-    connect_topology ();
-    ok = 0;
-  }
-}
-
-/**
- * Callback indicating that the hostkey was created for a peer.
- *
- * @param cls NULL
- * @param id the peer identity
- * @param d the daemon handle (pretty useless at this point, remove?)
- * @param emsg non-null on failure
- */
-void
-hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Hostkey callback received error: %s\n", emsg);
-  }
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostkey created for peer `%s'\n",
-              GNUNET_i2s (id));
-#endif
-  peers_left--;
-  if (peers_left == 0)
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d hostkeys created, now creating topology!\n", num_peers);
-#endif
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
-                                      "from hostkey_callback");
-    GNUNET_SCHEDULER_add_now (&create_topology, NULL);
-    ok = 0;
-  }
-}
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  unsigned long long topology_num;
-  unsigned long long connect_topology_num;
-  unsigned long long blacklist_topology_num;
-  unsigned long long connect_topology_option_num;
-  char *connect_topology_option_modifier_string;
-
-  ok = 1;
-
-  dotOutFile = FOPEN (dotOutFileName, "w");
-  if (dotOutFile != NULL)
-  {
-    FPRINTF (dotOutFile, "%s",  "strict graph G {\n");
-  }
-
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting daemons based on config file %s\n", cfgfile);
-#endif
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
-                                             &test_directory))
-  {
-    ok = 404;
-    if (dotOutFile != NULL)
-    {
-      FCLOSE (dotOutFile);
-    }
-    return;
-  }
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "topology",
-                                             &topology_num))
-    topology = topology_num;
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology",
-                                             &connect_topology_num))
-    connection_topology = connect_topology_num;
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
-                                             "connect_topology_option",
-                                             &connect_topology_option_num))
-    connect_topology_option = connect_topology_option_num;
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "connect_topology_option_modifier",
-                                             &connect_topology_option_modifier_string))
-  {
-    if (SSCANF
-        (connect_topology_option_modifier_string, "%lf",
-         &connect_topology_option_modifier) != 1)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  connect_topology_option_modifier_string,
-                  "connect_topology_option_modifier", "TESTING");
-      GNUNET_free (connect_topology_option_modifier_string);
-      ok = 707;
-      if (dotOutFile != NULL)
-      {
-        FCLOSE (dotOutFile);
-      }
-      return;
-    }
-    GNUNET_free (connect_topology_option_modifier_string);
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "blacklist_transports",
-                                             &blacklist_transports))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "No transports specified for blacklisting in blacklist testcase (this shouldn't happen!)\n");
-    ok = 808;
-    if (dotOutFile != NULL)
-    {
-      FCLOSE (dotOutFile);
-    }
-    return;
-  }
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
-                                             "blacklist_topology",
-                                             &blacklist_topology_num))
-    blacklist_topology = blacklist_topology_num;
-
-  if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
-                                             &num_peers))
-    num_peers = DEFAULT_NUM_PEERS;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT",
-                                           &connect_timeout))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "CONNECT_TIMEOUT");
-    return;
-  }
-
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
-                                             &connect_attempts))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "connect_attempts");
-    return;
-  }
-
-  main_cfg = cfg;
-
-  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
-  peers_left = num_peers;
-
-  /* For this specific test we only really want a CLIQUE topology as the
-   * overlay allowed topology, and a RING topology as the underlying connection
-   * allowed topology.  So we will expect only num_peers * 2 connections to
-   * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail.
-   */
-  expected_connections = num_peers * (num_peers - 1);
-  expected_failed_connections = expected_connections - (num_peers * 2);
-
-
-  /* Set up a task to end testing if peer start fails */
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
-                                    "didn't start all daemons in reasonable amount of time!!!");
-
-  pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left,
-                                     TIMEOUT, &hostkey_callback, NULL,
-                                     &peers_started_callback, NULL,
-                                     &topology_callback, NULL, NULL);
-
-}
-
-static int
-check ()
-{
-  int ret;
-
-  char *const argv[] = { "test-testing-topology-blacklist",
-    "-c",
-    "test_testing_data_topology_blacklist.conf",
-#if VERBOSE
-    "-L", "DEBUG",
-#endif
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  ret =
-      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                          "test-testing-topology-blacklist", "nohelp", options,
-                          &run, &ok);
-  if (ret != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "`test-testing-topology-blacklist': Failed with error code %d\n",
-                ret);
-  }
-
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test_testing_topology_blacklist",
-#if VERBOSE
-                    "DEBUG",
-#else
-                    "WARNING",
-#endif
-                    NULL);
-  ret = check ();
-
-  /**
-   * Need to remove base directory, subdirectories taken care
-   * of by the testing framework.
-   */
-  if (test_directory != NULL)
-  {
-    if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to remove testing directory %s\n", test_directory);
-    }
-  }
-
-  return ret;
-}
-
-/* end of test_testing_topology_blacklist.c */
diff --git a/src/testing/test_testing_topology_churn.c b/src/testing/test_testing_topology_churn.c
deleted file mode 100644 (file)
index 9c0bbf2..0000000
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
-     This file is part of GNUnet.
-     (C) 2009 Christian Grothoff (and other contributing authors)
-
-     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 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
-/**
- * @file testing/test_testing_topology_churn.c
- * @brief base testcase for testing simple churn functionality
- */
-#include "platform.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-
-
-/**
- * How long until we fail the whole testcase?
- */
-#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
-
-/**
- * How long until we give up on starting the peers? (Must be longer than the connect timeout!)
- */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
-
-#define DEFAULT_NUM_PEERS 4
-
-static int ok;
-
-static unsigned long long num_peers;
-
-static unsigned int expected_connections;
-
-static unsigned int expected_failed_connections;
-
-static unsigned long long peers_left;
-
-static struct GNUNET_TESTING_PeerGroup *pg;
-
-const struct GNUNET_CONFIGURATION_Handle *main_cfg;
-
-GNUNET_SCHEDULER_TaskIdentifier die_task;
-
-static char *test_directory;
-
-#define MTYPE 12345
-
-GNUNET_NETWORK_STRUCT_BEGIN
-
-struct GNUNET_TestMessage
-{
-  /**
-   * Header of the message
-   */
-  struct GNUNET_MessageHeader header;
-
-  /**
-   * Unique identifier for this message.
-   */
-  uint32_t uid;
-};
-GNUNET_NETWORK_STRUCT_END
-
-/**
- * Check whether peers successfully shut down.
- */
-void
-shutdown_callback (void *cls, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
-    if (ok == 0)
-      ok = 666;
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
-  }
-}
-
-static void
-finish_testing ()
-{
-  GNUNET_assert (pg != NULL);
-
-  if (die_task != GNUNET_SCHEDULER_NO_TASK)
-    GNUNET_SCHEDULER_cancel (die_task);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Called finish testing, stopping daemons.\n");
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
-  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n");
-  ok = 0;
-}
-
-static void
-end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  char *msg = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "End badly was called (%s)... stopping daemons.\n", msg);
-
-  if (pg != NULL)
-  {
-    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
-    ok = 7331;                  /* Opposite of leet */
-  }
-  else
-    ok = 401;                   /* Never got peers started */
-
-}
-
-struct ChurnTestContext
-{
-  GNUNET_SCHEDULER_Task next_task;
-
-};
-
-static struct ChurnTestContext churn_ctx;
-
-/**
- * Churn callback, report on success or failure of churn operation.
- *
- * @param cls closure
- * @param emsg NULL on success
- */
-void
-churn_callback (void *cls, const char *emsg)
-{
-  if (emsg == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Successfully churned peers!\n",
-                emsg);
-    GNUNET_SCHEDULER_add_now (churn_ctx.next_task, NULL);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to churn peers with error `%s'\n", emsg);
-    GNUNET_SCHEDULER_cancel (die_task);
-    die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
-  }
-}
-
-
-static void
-churn_peers_both ()
-{
-  churn_ctx.next_task = &finish_testing;
-  GNUNET_TESTING_daemons_churn (pg, NULL, 1, 1, TIMEOUT, &churn_callback, NULL);
-}
-
-static void
-churn_peers_off_again ()
-{
-  churn_ctx.next_task = &churn_peers_both;
-  GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL);
-}
-
-static void
-churn_peers_on ()
-{
-  churn_ctx.next_task = &churn_peers_off_again;
-  GNUNET_TESTING_daemons_churn (pg, NULL, 0, 2, TIMEOUT, &churn_callback, NULL);
-}
-
-static void
-churn_peers_off ()
-{
-  churn_ctx.next_task = &churn_peers_on;
-  GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL);
-}
-
-static void
-peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                        const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to start daemon with error: `%s'\n", emsg);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
-              (num_peers - peers_left) + 1, num_peers);
-  peers_left--;
-  if (peers_left == 0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d daemons started, now testing churn!\n", num_peers);
-    GNUNET_SCHEDULER_cancel (die_task);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
-                                      "from peers_started_callback");
-    churn_peers_off ();
-    ok = 0;
-  }
-}
-
-
-static void
-run (void *cls, char *const *args, const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  ok = 1;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Starting daemons based on config file %s\n", cfgfile);
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
-                                             &test_directory))
-  {
-    ok = 404;
-    return;
-  }
-
-  if (GNUNET_SYSERR ==
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
-                                             &num_peers))
-    num_peers = DEFAULT_NUM_PEERS;
-
-  main_cfg = cfg;
-
-  peers_left = num_peers;
-  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
-
-  /* For this specific test we only really want a CLIQUE topology as the
-   * overlay allowed topology, and a RING topology as the underlying connection
-   * allowed topology.  So we will expect only num_peers * 2 connections to
-   * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail.
-   */
-  expected_connections = num_peers * (num_peers - 1);
-  expected_failed_connections = expected_connections - (num_peers * 2);
-
-
-  /* Set up a task to end testing if peer start fails */
-  die_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                    (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
-                                    "didn't start all daemons in reasonable amount of time!!!");
-
-  pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left,
-                                     TIMEOUT, NULL, NULL,
-                                     &peers_started_callback, NULL, NULL, NULL,
-                                     NULL);
-
-}
-
-static int
-check ()
-{
-  int ret;
-
-  char *const argv[] = { "test-testing-topology-churn",
-    "-c",
-    "test_testing_data_topology_churn.conf",
-    NULL
-  };
-  struct GNUNET_GETOPT_CommandLineOption options[] = {
-    GNUNET_GETOPT_OPTION_END
-  };
-  ret =
-      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
-                          "test-testing-topology-churn", "nohelp", options,
-                          &run, &ok);
-  if (ret != GNUNET_OK)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "`test-testing-topology-churn': Failed with error code %d\n",
-                ret);
-  }
-
-  return ok;
-}
-
-int
-main (int argc, char *argv[])
-{
-  int ret;
-
-  GNUNET_log_setup ("test_testing_topology_churn",
-                    "WARNING",
-                    NULL);
-  ret = check ();
-
-  /**
-   * Need to remove base directory, subdirectories taken care
-   * of by the testing framework.
-   */
-  if (test_directory != NULL)
-  {
-    if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Failed to remove testing directory %s\n", test_directory);
-    }
-  }
-
-  return ret;
-}
-
-/* end of test_testing_topology_churn.c */
diff --git a/src/testing/testing.c b/src/testing/testing.c
deleted file mode 100644 (file)
index a80ad25..0000000
+++ /dev/null
@@ -1,2204 +0,0 @@
-/*
-      This file is part of GNUnet
-      (C) 2008, 2009 Christian Grothoff (and other contributing authors)
-
-      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 3, or (at your
-      option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      General Public License for more details.
-
-      You should have received a copy of the GNU General Public License
-      along with GNUnet; see the file COPYING.  If not, write to the
-      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-      Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file testing/testing.c
- * @brief convenience API for writing testcases for GNUnet
- *        Many testcases need to start and stop gnunetd,
- *        and this library is supposed to make that easier
- *        for TESTCASES.  Normal programs should always
- *        use functions from gnunet_{util,arm}_lib.h.  This API is
- *        ONLY for writing testcases!
- * @author Christian Grothoff
- *
- */
-#include "platform.h"
-#include "gnunet_arm_service.h"
-#include "gnunet_core_service.h"
-#include "gnunet_constants.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_transport_service.h"
-#include "gnunet_hello_lib.h"
-
-/**
- * Hack to deal with initial HELLO's being often devoid of addresses.
- * This hack causes 'process_hello' to ignore HELLOs without addresses.
- * The correct implementation would continue with 'process_hello' until
- * the connection could be established...
- */
-#define EMPTY_HACK GNUNET_YES
-
-/**
- * How long do we wait after starting gnunet-service-arm
- * for the core service to be alive?
- */
-#define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
-
-/**
- * How many times are we willing to try to wait for "scp" or
- * "gnunet-service-arm" to complete (waitpid) before giving up?
- */
-#define MAX_EXEC_WAIT_RUNS 250
-
-static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
-
-#if EMPTY_HACK
-static int
-test_address (void *cls, const struct GNUNET_HELLO_Address *address,
-              struct GNUNET_TIME_Absolute expiration)
-{
-  int *empty = cls;
-
-  *empty = GNUNET_NO;
-  return GNUNET_OK;
-}
-#endif
-
-/**
- * Receive the HELLO from one peer, give it to the other
- * and ask them to connect.
- *
- * @param cls Closure (daemon whose hello is this).
- * @param message HELLO message of peer
- */
-static void
-process_hello (void *cls, const struct GNUNET_MessageHeader *message)
-{
-  struct GNUNET_TESTING_Daemon *daemon = cls;
-  int msize;
-
-#if EMPTY_HACK
-  int empty;
-
-  empty = GNUNET_YES;
-  GNUNET_assert (message != NULL);
-  GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) message,
-                                  GNUNET_NO, &test_address, &empty);
-  if (GNUNET_YES == empty)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Skipping empty HELLO address of peer %s\n",
-                GNUNET_i2s (&daemon->id));
-    return;
-  }
-#endif
-  GNUNET_assert (daemon->phase == SP_GET_HELLO ||
-                 daemon->phase == SP_START_DONE);
-  daemon->cb = NULL;            // FIXME: why??? (see fsm:SP_START_CORE, notify_daemon_started)
-  if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */
-    GNUNET_SCHEDULER_cancel (daemon->task);
-
-  if (daemon->server != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Received `%s' from transport service of `%4s', disconnecting core!\n",
-                "HELLO", GNUNET_i2s (&daemon->id));
-    GNUNET_CORE_disconnect (daemon->server);
-    daemon->server = NULL;
-  }
-
-  msize = ntohs (message->size);
-  if (msize < 1)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "HELLO message of peer %s is of size 0\n",
-                GNUNET_i2s (&daemon->id));
-    return;
-  }
-  if (daemon->ghh != NULL)
-  {
-    GNUNET_TRANSPORT_get_hello_cancel (daemon->ghh);
-    daemon->ghh = NULL;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Received `%s' from transport service of `%4s'\n", "HELLO",
-              GNUNET_i2s (&daemon->id));
-  GNUNET_free_non_null (daemon->hello);
-  daemon->hello = GNUNET_malloc (msize);
-  memcpy (daemon->hello, message, msize);
-
-  if (daemon->th != NULL)
-  {
-    GNUNET_TRANSPORT_disconnect (daemon->th);
-    daemon->th = NULL;
-  }
-  daemon->phase = SP_START_DONE;
-}
-
-
-/**
- * Notify of a peer being up and running.  Scheduled as a task
- * so that variables which may need to be set are set before
- * the connect callback can set up new operations.
- * FIXME: what variables?????? where from????
- *
- * @param cls the testing daemon
- * @param tc task scheduler context
- */
-static void
-notify_daemon_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TESTING_Daemon *d = cls;
-  GNUNET_TESTING_NotifyDaemonRunning cb;
-
-  cb = d->cb;
-  d->cb = NULL;
-  if (NULL != cb)
-    cb (d->cb_cls, &d->id, d->cfg, d, NULL);
-}
-
-
-/**
- * Finite-state machine for starting GNUnet.
- *
- * @param cls our "struct GNUNET_TESTING_Daemon"
- * @param tc unused
- */
-static void
-start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TESTING_Daemon *d = cls;
-  GNUNET_TESTING_NotifyDaemonRunning cb;
-  enum GNUNET_OS_ProcessStatusType type;
-  unsigned long code;
-  char *dst;
-  int bytes_read;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s FSM is in phase %u.\n",
-              GNUNET_i2s (&d->id), d->phase);
-  d->task = GNUNET_SCHEDULER_NO_TASK;
-  switch (d->phase)
-  {
-  case SP_COPYING:
-    /* confirm copying complete */
-    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code))
-    {
-      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
-      {
-        cb = d->cb;
-        d->cb = NULL;
-        if (NULL != cb)
-          cb (d->cb_cls, NULL, d->cfg, d,
-              _
-              ("`scp' does not seem to terminate (timeout copying config).\n"));
-        return;
-      }
-      /* wait some more */
-      d->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        d);
-      return;
-    }
-    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
-    {
-      cb = d->cb;
-      d->cb = NULL;
-      if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d, _("`scp' did not complete cleanly.\n"));
-      return;
-    }
-    GNUNET_OS_process_destroy (d->proc_arm_copying);
-    d->proc_arm_copying = NULL;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Successfully copied configuration file.\n");
-    d->phase = SP_COPIED;
-    /* fall-through */
-  case SP_COPIED:
-    /* Start create hostkey process if we don't already know the peer identity! */
-    if (GNUNET_NO == d->have_hostkey)
-    {
-      GNUNET_assert (NULL == d->proc_arm_peerinfo);
-      d->pipe_stdout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_YES);
-      if (d->pipe_stdout == NULL)
-      {
-        cb = d->cb;
-        d->cb = NULL;
-        if (NULL != cb)
-          cb (d->cb_cls, NULL, d->cfg, d,
-              (NULL ==
-               d->hostname) ?
-              _("Failed to create pipe for `gnunet-peerinfo' process.\n") :
-              _("Failed to create pipe for `ssh' process.\n"));
-        return;
-      }
-      if (NULL == d->hostname)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Starting `%s', with command `%s %s %s %s'.\n",
-                    "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile,
-                    "-sq");
-        d->proc_arm_peerinfo =
-           GNUNET_OS_start_process (GNUNET_YES, NULL, d->pipe_stdout, "gnunet-peerinfo",
-                                     "gnunet-peerinfo", "-c", d->cfgfile, "-sq",
-                                     NULL);
-        GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
-      }
-      else
-      {
-        if (d->username != NULL)
-          GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
-        else
-          dst = GNUNET_strdup (d->hostname);
-
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "Starting `%s', with command `%s %s %s %s %s %s'.\n",
-                    "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c",
-                    d->cfgfile, "-sq");
-        if (d->ssh_port_str == NULL)
-        {
-          d->proc_arm_peerinfo = GNUNET_OS_start_process (GNUNET_NO, NULL, d->pipe_stdout, "ssh", "ssh",
-                                             "-q",
-                                             dst, "gnunet-peerinfo", "-c",
-                                             d->cfgfile, "-sq", NULL);
-        }
-        else
-        {
-          d->proc_arm_peerinfo =
-             GNUNET_OS_start_process (GNUNET_NO, NULL, d->pipe_stdout, "ssh", "ssh", "-p",
-                                       d->ssh_port_str,
-                                       "-q",
-                                       dst, "gnunet-peerinfo", "-c", d->cfgfile,
-                                       "-sq", NULL);
-        }
-        GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
-        GNUNET_free (dst);
-      }
-      if (NULL == d->proc_arm_peerinfo)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    _("Could not start `%s' process to create hostkey.\n"),
-                    (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh");
-        cb = d->cb;
-        d->cb = NULL;
-        if (NULL != cb)
-          cb (d->cb_cls, NULL, d->cfg, d,
-              (NULL ==
-               d->hostname) ? _("Failed to start `gnunet-peerinfo' process.\n")
-              : _("Failed to start `ssh' process.\n"));
-        GNUNET_DISK_pipe_close (d->pipe_stdout);
-        return;
-      }
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Started `%s', waiting for hostkey.\n", "gnunet-peerinfo");
-      d->phase = SP_HOSTKEY_CREATE;
-      d->task =
-          GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
-                                          (d->max_timeout),
-                                          GNUNET_DISK_pipe_handle
-                                          (d->pipe_stdout,
-                                           GNUNET_DISK_PIPE_END_READ),
-                                          &start_fsm, d);
-    }
-    else                        /* Already have a hostkey! */
-    {
-      if (d->hostkey_callback != NULL)
-      {
-        d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL);
-        d->hostkey_callback = NULL;
-        d->phase = SP_HOSTKEY_CREATED;
-      }
-      else
-        d->phase = SP_TOPOLOGY_SETUP;
-
-      /* wait some more */
-      d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
-    }
-    break;
-  case SP_HOSTKEY_CREATE:
-    bytes_read =
-        GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle
-                               (d->pipe_stdout, GNUNET_DISK_PIPE_END_READ),
-                               &d->hostkeybuf[d->hostkeybufpos],
-                               sizeof (d->hostkeybuf) - d->hostkeybufpos);
-    if (bytes_read > 0)
-      d->hostkeybufpos += bytes_read;
-
-    if ((d->hostkeybufpos < 104) && (bytes_read > 0))
-    {
-      /* keep reading */
-      d->task =
-          GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
-                                          (d->max_timeout),
-                                          GNUNET_DISK_pipe_handle
-                                          (d->pipe_stdout,
-                                           GNUNET_DISK_PIPE_END_READ),
-                                          &start_fsm, d);
-      return;
-    }
-    d->hostkeybuf[103] = '\0';
-
-    if ((bytes_read < 0) ||
-        (GNUNET_OK !=
-         GNUNET_CRYPTO_hash_from_string (d->hostkeybuf, &d->id.hashPubKey)))
-    {
-      /* error */
-      if (bytes_read < 0)
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    _("Error reading from gnunet-peerinfo: %s\n"),
-                    STRERROR (errno));
-      else
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    _("Malformed output from gnunet-peerinfo!\n"));
-      cb = d->cb;
-      d->cb = NULL;
-      GNUNET_DISK_pipe_close (d->pipe_stdout);
-      d->pipe_stdout = NULL;
-      (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL);      
-      GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo));
-      GNUNET_OS_process_destroy (d->proc_arm_peerinfo);
-      d->proc_arm_peerinfo = NULL;
-      if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d, _("Failed to get hostkey!\n"));
-      return;
-    }
-    d->shortname = GNUNET_strdup (GNUNET_i2s (&d->id));
-    GNUNET_DISK_pipe_close (d->pipe_stdout);
-    d->pipe_stdout = NULL;
-    (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL);
-    GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo));
-    GNUNET_OS_process_destroy (d->proc_arm_peerinfo);
-    d->proc_arm_peerinfo = NULL;
-    d->have_hostkey = GNUNET_YES;
-    if (d->hostkey_callback != NULL)
-    {
-      d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL);
-      d->hostkey_callback = NULL;
-      d->phase = SP_HOSTKEY_CREATED;
-    }
-    else
-    {
-      d->phase = SP_TOPOLOGY_SETUP;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully got hostkey!\n");
-    /* Fall through */
-  case SP_HOSTKEY_CREATED:
-    /* wait for topology finished */
-    if ((GNUNET_YES == d->dead) ||
-        (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0))
-    {
-      cb = d->cb;
-      d->cb = NULL;
-      if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d,
-            _("`Failed while waiting for topology setup!\n"));
-      return;
-    }
-
-    d->task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                      d);
-    break;
-  case SP_TOPOLOGY_SETUP:      /* Indicates topology setup has completed! */
-    /* start GNUnet on remote host */
-    if (NULL == d->hostname)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Starting `%s', with command `%s %s %s %s'.\n",
-                  "gnunet-arm", "gnunet-arm", "-c", d->cfgfile, 
-                  "-s");
-      d->proc_arm_start =
-         GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", "-c",
-                                   d->cfgfile,
-                                   "-s", "-q", "-T",
-                                   GNUNET_TIME_relative_to_string
-                                   (GNUNET_TIME_absolute_get_remaining
-                                    (d->max_timeout)), NULL);
-    }
-    else
-    {
-      if (d->username != NULL)
-        GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
-      else
-        dst = GNUNET_strdup (d->hostname);
-
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Starting `%s', with command `%s %s %s %s %s %s %s'.\n",
-                  "gnunet-arm", "ssh", dst, "gnunet-arm", "-c", d->cfgfile,
-                  "-s", "-q");
-      if (d->ssh_port_str == NULL)
-      {
-        d->proc_arm_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
-                                           "-q",
-                                           dst, "gnunet-arm",
-                                           "-c", d->cfgfile, "-s", "-q", "-T",
-                                           GNUNET_TIME_relative_to_string
-                                           (GNUNET_TIME_absolute_get_remaining
-                                            (d->max_timeout)), NULL);
-      }
-      else
-      {
-
-        d->proc_arm_start =
-           GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", "-p",
-                                     d->ssh_port_str,
-                                     "-q",
-                                     dst, "gnunet-arm",
-                                     "-c", d->cfgfile, "-s", "-q", "-T",
-                                     GNUNET_TIME_relative_to_string
-                                     (GNUNET_TIME_absolute_get_remaining
-                                      (d->max_timeout)), NULL);
-      }
-      GNUNET_free (dst);
-    }
-    if (NULL == d->proc_arm_start)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  _("Could not start `%s' process to start GNUnet.\n"),
-                  (NULL == d->hostname) ? "gnunet-arm" : "ssh");
-      cb = d->cb;
-      d->cb = NULL;
-      if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d,
-            (NULL ==
-             d->hostname) ? _("Failed to start `gnunet-arm' process.\n") :
-            _("Failed to start `ssh' process.\n"));
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Started `%s', waiting for `%s' to be up.\n", "gnunet-arm",
-                "gnunet-service-core");
-    d->phase = SP_START_ARMING;
-    d->task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                      d);
-        // FIXME: busy wait?
-    break;
-  case SP_START_ARMING:
-    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_start, &type, &code))
-    {
-      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
-      {
-        cb = d->cb;
-        d->cb = NULL;
-        if (NULL != cb)
-          cb (d->cb_cls, NULL, d->cfg, d,
-              (NULL ==
-               d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") :
-              _("`ssh' does not seem to terminate.\n"));
-        if (d->cfg != NULL)
-        {
-          GNUNET_CONFIGURATION_destroy (d->cfg);
-          d->cfg = NULL;
-        }
-        if (d->cfgfile != NULL)
-        {
-          GNUNET_free (d->cfgfile);
-          d->cfgfile = NULL;
-        }
-        GNUNET_free_non_null (d->hostname);
-        GNUNET_free_non_null (d->username);
-        GNUNET_OS_process_destroy (d->proc_arm_start);
-       d->proc_arm_start = NULL;
-       d->username = NULL;
-        d->hostname = NULL;     // Quick hack to avoid crashing (testing need to be
-        d->cfg = NULL;          // overhauled anyway, and the error managing is
-       // GNUNET_free (d); // FIXME (could this leak)
-        // pretty broken anyway.
-        return;
-      }
-      /* wait some more */
-      d->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        d);
-          // FIXME: busy wait?
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully started `%s'.\n",
-                "gnunet-arm");
-    GNUNET_OS_process_destroy (d->proc_arm_start);
-    d->proc_arm_start = NULL;
-    d->phase = SP_START_CORE;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling CORE_connect\n");
-    /* Fall through */
-  case SP_START_CORE:
-    if (d->server != NULL)
-      GNUNET_CORE_disconnect (d->server);
-
-    d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL);
-    if (d->th == NULL)
-    {
-      if (GNUNET_YES == d->dead)
-        GNUNET_TESTING_daemon_stop (d,
-                                    GNUNET_TIME_absolute_get_remaining
-                                    (d->max_timeout), d->dead_cb,
-                                    d->dead_cb_cls, GNUNET_YES, GNUNET_NO);
-      else if (NULL != d->cb)
-        d->cb (d->cb_cls, &d->id, d->cfg, d,
-               _("Failed to connect to transport service!\n"));
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Connected to transport service `%s', getting HELLO\n",
-                GNUNET_i2s (&d->id));
-    d->ghh = GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d);
-    /* FIXME: store task ID somewhere! */
-    GNUNET_SCHEDULER_add_now (&notify_daemon_started, d);
-    /*cb = d->cb;
-     * d->cb = NULL;
-     * if (NULL != cb)
-     * cb (d->cb_cls, &d->id, d->cfg, d, NULL); */
-    d->running = GNUNET_YES;
-    d->phase = SP_GET_HELLO;
-    break;
-  case SP_GET_HELLO:
-    if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
-    {
-      if (d->server != NULL)
-        GNUNET_CORE_disconnect (d->server);
-      if (d->th != NULL)
-        GNUNET_TRANSPORT_disconnect (d->th);
-      cb = d->cb;
-      d->cb = NULL;
-      if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d, _("Unable to get HELLO for peer!\n"));
-      GNUNET_CONFIGURATION_destroy (d->cfg);
-      GNUNET_free (d->cfgfile);
-      GNUNET_free_non_null (d->hostname);
-      GNUNET_free_non_null (d->username);
-      GNUNET_free (d);
-      return;
-    }
-    if (d->hello != NULL)
-      return;
-    GNUNET_assert (d->task == GNUNET_SCHEDULER_NO_TASK);
-    d->task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_CONSTANTS_SERVICE_RETRY, 2),
-                                      &start_fsm, d);
-    break;
-  case SP_START_DONE:
-    GNUNET_break (0);
-    break;
-  case SP_SERVICE_START:
-    /* confirm gnunet-arm exited */
-    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_start, &type, &code))
-    {
-      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
-      {
-        cb = d->cb;
-        d->cb = NULL;
-        if (NULL != cb)
-          cb (d->cb_cls, NULL, d->cfg, d,
-              (NULL ==
-               d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") :
-              _("`ssh' does not seem to terminate.\n"));
-        return;
-      }
-      /* wait some more */
-      d->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        d);
-      return;
-    }
-#if EXTRA_CHECKS
-    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
-    {
-      cb = d->cb;
-      d->cb = NULL;
-      if (NULL != cb)
-        cb (d->cb_cls, NULL, d->cfg, d,
-            (NULL ==
-             d->hostname) ?
-            _
-            ("`gnunet-arm' terminated with non-zero exit status (or timed out)!\n")
-            : _("`ssh' does not seem to terminate.\n"));
-      return;
-    }
-#endif
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service startup complete!\n");
-    cb = d->cb;
-    d->cb = NULL;
-    d->phase = SP_START_DONE;
-    if (NULL != cb)
-      cb (d->cb_cls, &d->id, d->cfg, d, NULL);
-    GNUNET_OS_process_destroy (d->proc_arm_srv_start);
-    d->proc_arm_srv_start = NULL;
-    break;
-  case SP_SERVICE_SHUTDOWN_START:
-    /* confirm copying complete */
-    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_stop, &type, &code))
-    {
-      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
-      {
-        if (NULL != d->dead_cb)
-          d->dead_cb (d->dead_cb_cls,
-                      _
-                      ("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
-        return;
-      }
-      /* wait some more */
-      d->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        d);
-      return;
-    }
-#if EXTRA_CHECKS
-    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
-    {
-      if (NULL != d->dead_cb)
-        d->dead_cb (d->dead_cb_cls,
-                    _
-                    ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n"));
-      return;
-    }
-#endif
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n");
-    if (NULL != d->dead_cb)
-      d->dead_cb (d->dead_cb_cls, NULL);
-    break;
-  case SP_SHUTDOWN_START:
-    /* confirm copying complete !??? */
-    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_stop, &type, &code))
-    {
-      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
-      {
-        if (NULL != d->dead_cb)
-          d->dead_cb (d->dead_cb_cls,
-                      _
-                      ("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
-        if (d->th != NULL)
-        {
-          GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
-          d->ghh = NULL;
-          GNUNET_TRANSPORT_disconnect (d->th);
-          d->th = NULL;
-        }
-        if (d->cfg != NULL)
-        {
-          GNUNET_CONFIGURATION_destroy (d->cfg);
-          d->cfg = NULL;
-        }
-        if (d->cfgfile != NULL)
-        {
-          GNUNET_free (d->cfgfile);
-          d->cfgfile = NULL;
-        }
-        GNUNET_free_non_null (d->hello);
-        GNUNET_free_non_null (d->hostname);
-        GNUNET_free_non_null (d->username);
-        GNUNET_free_non_null (d->shortname);
-        GNUNET_OS_process_destroy (d->proc_arm_stop);
-        d->proc_arm_stop = NULL;
-        GNUNET_free (d);
-        return;
-      }
-      /* wait some more */
-      d->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        d);
-      return;
-    }
-    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
-    {
-      if (NULL != d->dead_cb)
-        d->dead_cb (d->dead_cb_cls,
-                    _
-                    ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n"));
-      if (d->th != NULL)
-      {
-        GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
-        d->ghh = NULL;
-        GNUNET_TRANSPORT_disconnect (d->th);
-        d->th = NULL;
-      }
-      if (d->server != NULL)
-      {
-        GNUNET_CORE_disconnect (d->server);
-        d->server = NULL;
-      }
-      GNUNET_CONFIGURATION_destroy (d->cfg);
-      d->cfg = NULL;
-      GNUNET_free (d->cfgfile);
-      GNUNET_free_non_null (d->hello);
-      GNUNET_free_non_null (d->hostname);
-      GNUNET_free_non_null (d->username);
-      GNUNET_free_non_null (d->shortname);
-      GNUNET_OS_process_destroy (d->proc_arm_stop);
-      d->proc_arm_stop = NULL;
-      GNUNET_free (d);
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer shutdown complete.\n");
-    if (d->server != NULL)
-    {
-      GNUNET_CORE_disconnect (d->server);
-      d->server = NULL;
-    }
-
-    if (d->th != NULL)
-    {
-      GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
-      d->ghh = NULL;
-      GNUNET_TRANSPORT_disconnect (d->th);
-      d->th = NULL;
-    }
-
-    if (NULL != d->dead_cb)
-      d->dead_cb (d->dead_cb_cls, NULL);
-
-    /* state clean up and notifications */
-    if (d->churn == GNUNET_NO)
-    {
-      GNUNET_CONFIGURATION_destroy (d->cfg);
-      d->cfg = NULL;
-      GNUNET_free (d->cfgfile);
-      GNUNET_free_non_null (d->hostname);
-      GNUNET_free_non_null (d->username);
-    }
-
-    GNUNET_free_non_null (d->hello);
-    d->hello = NULL;
-    GNUNET_free_non_null (d->shortname);
-    GNUNET_OS_process_destroy (d->proc_arm_stop);
-    d->proc_arm_stop = NULL;
-    d->shortname = NULL;
-    if (d->churn == GNUNET_NO)
-      GNUNET_free (d);
-
-    break;
-  case SP_CONFIG_UPDATE:
-    /* confirm copying complete */
-    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code))
-    {
-      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)   /* FIXME: config update should take timeout parameter! */
-      {
-        cb = d->cb;
-        d->cb = NULL;
-        if (NULL != cb)
-          cb (d->cb_cls, NULL, d->cfg, d,
-              _("`scp' does not seem to terminate.\n"));
-        return;
-      }
-      /* wait some more */
-      d->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        d);
-      return;
-    }
-    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
-    {
-      if (NULL != d->update_cb)
-        d->update_cb (d->update_cb_cls, _("`scp' did not complete cleanly.\n"));
-      return;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Successfully copied configuration file.\n");
-    if (NULL != d->update_cb)
-      d->update_cb (d->update_cb_cls, NULL);
-    d->phase = SP_START_DONE;
-    break;
-  }
-}
-
-/**
- * Continues GNUnet daemon startup when user wanted to be notified
- * once a hostkey was generated (for creating friends files, blacklists,
- * etc.).
- *
- * @param daemon the daemon to finish starting
- */
-void
-GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon)
-{
-  GNUNET_assert (daemon->phase == SP_HOSTKEY_CREATED);
-  daemon->phase = SP_TOPOLOGY_SETUP;
-}
-
-/**
- * Check whether the given daemon is running.
- *
- * @param daemon the daemon to check
- *
- * @return GNUNET_YES if the daemon is up, GNUNET_NO if the
- *         daemon is down, GNUNET_SYSERR on error.
- */
-int
-GNUNET_TESTING_test_daemon_running (struct GNUNET_TESTING_Daemon *daemon)
-{
-  if (daemon == NULL)
-    return GNUNET_SYSERR;
-
-  if (daemon->running == GNUNET_YES)
-    return GNUNET_YES;
-  return GNUNET_NO;
-}
-
-
-/**
- * Starts a GNUnet daemon service which has been previously stopped.
- *
- * @param d the daemon for which the service should be started
- * @param service the name of the service to start
- * @param timeout how long to wait for process for shutdown to complete
- * @param cb function called once the service starts
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemon_start_stopped_service (struct GNUNET_TESTING_Daemon *d,
-                                             char *service,
-                                             struct GNUNET_TIME_Relative
-                                             timeout,
-                                             GNUNET_TESTING_NotifyDaemonRunning
-                                             cb, void *cb_cls)
-{
-  char *arg;
-
-  d->cb = cb;
-  d->cb_cls = cb_cls;
-
-  GNUNET_assert (d->running == GNUNET_YES);
-
-  if (d->phase == SP_CONFIG_UPDATE)
-  {
-    GNUNET_SCHEDULER_cancel (d->task);
-    d->phase = SP_START_DONE;
-  }
-
-  if (d->churned_services == NULL)
-  {
-    d->cb (d->cb_cls, &d->id, d->cfg, d,
-           "No service has been churned off yet!!");
-    return;
-  }
-  d->phase = SP_SERVICE_START;
-  GNUNET_free (d->churned_services);
-  d->churned_services = NULL;
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  /* Check if this is a local or remote process */
-  if (NULL != d->hostname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with config `%s' on host `%s'.\n",
-                d->cfgfile, d->hostname);
-    if (d->username != NULL)
-      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
-    else
-      arg = GNUNET_strdup (d->hostname);
-
-    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
-                                       "-q",
-                                       arg, "gnunet-arm",
-                                       "-c", d->cfgfile, "-i", service, "-q",
-                                       "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q\n",
-                arg, "gnunet-arm", d->cfgfile, service);
-    GNUNET_free (arg);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile);
-    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
-                                       "-c", d->cfgfile, "-i", service, "-q",
-                                       "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       NULL);
-  }
-
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
-}
-
-/**
- * Starts a GNUnet daemon's service.
- *
- * @param d the daemon for which the service should be started
- * @param service the name of the service to start
- * @param timeout how long to wait for process for startup
- * @param cb function called once gnunet-arm returns
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d,
-                                     const char *service,
-                                     struct GNUNET_TIME_Relative timeout,
-                                     GNUNET_TESTING_NotifyDaemonRunning cb,
-                                     void *cb_cls)
-{
-  char *arg;
-
-  d->cb = cb;
-  d->cb_cls = cb_cls;
-
-  GNUNET_assert (service != NULL);
-  GNUNET_assert (d->running == GNUNET_YES);
-  GNUNET_assert (d->phase == SP_START_DONE);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              _("Starting service %s for peer `%4s'\n"), service,
-              GNUNET_i2s (&d->id));
-  d->phase = SP_SERVICE_START;
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  /* Check if this is a local or remote process */
-  if (NULL != d->hostname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with config `%s' on host `%s'.\n",
-                d->cfgfile, d->hostname);
-    if (d->username != NULL)
-      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
-    else
-      arg = GNUNET_strdup (d->hostname);
-
-    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
-                                       "-q",
-                                       arg, "gnunet-arm",
-                                       "-c", d->cfgfile, "-i", service, "-q",
-                                       "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q -T %s\n",
-                arg, "gnunet-arm", d->cfgfile, service,
-                GNUNET_TIME_relative_to_string (timeout));
-    GNUNET_free (arg);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile);
-    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
-                                       "-c", d->cfgfile, "-i", service, "-q",
-                                       "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Starting gnunet-arm with command %s -c %s -i %s -q -T %s\n",
-                "gnunet-arm", d->cfgfile, service,
-                GNUNET_TIME_relative_to_string (timeout));
-  }
-
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
-}
-
-/**
- * Start a peer that has previously been stopped using the daemon_stop
- * call (and files weren't deleted and the allow restart flag)
- *
- * @param daemon the daemon to start (has been previously stopped)
- * @param timeout how long to wait for restart
- * @param cb the callback for notification when the peer is running
- * @param cb_cls closure for the callback
- */
-void
-GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon,
-                                     struct GNUNET_TIME_Relative timeout,
-                                     GNUNET_TESTING_NotifyDaemonRunning cb,
-                                     void *cb_cls)
-{
-  if (daemon->running == GNUNET_YES)
-  {
-    cb (cb_cls, &daemon->id, daemon->cfg, daemon,
-        "Daemon already running, can't restart!");
-    return;
-  }
-
-  daemon->cb = cb;
-  daemon->cb_cls = cb_cls;
-  daemon->phase = SP_TOPOLOGY_SETUP;
-  daemon->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  /* FIXME: why add_continuation? */
-  GNUNET_SCHEDULER_add_continuation (&start_fsm, daemon,
-                                     GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-}
-
-/**
- * Starts a GNUnet daemon.  GNUnet must be installed on the target
- * system and available in the PATH.  The machine must furthermore be
- * reachable via "ssh" (unless the hostname is "NULL") without the
- * need to enter a password.
- *
- * @param cfg configuration to use
- * @param timeout how long to wait starting up peers
- * @param pretend GNUNET_YES to set up files but not start peer GNUNET_NO
- *                to really start the peer (default)
- * @param hostname name of the machine where to run GNUnet
- *        (use NULL for localhost).
- * @param ssh_username ssh username to use when connecting to hostname
- * @param sshport port to pass to ssh process when connecting to hostname
- * @param hostkey pointer to a hostkey to be written to disk (instead of being generated)
- * @param hostkey_callback function to call once the hostkey has been
- *        generated for this peer, but it hasn't yet been started
- *        (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start)
- * @param hostkey_cls closure for hostkey callback
- * @param cb function to call once peer is up, or failed to start
- * @param cb_cls closure for cb
- * @return handle to the daemon (actual start will be completed asynchronously)
- */
-struct GNUNET_TESTING_Daemon *
-GNUNET_TESTING_daemon_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                             struct GNUNET_TIME_Relative timeout, int pretend,
-                             const char *hostname, const char *ssh_username,
-                             uint16_t sshport, const char *hostkey,
-                             GNUNET_TESTING_NotifyHostkeyCreated
-                             hostkey_callback, void *hostkey_cls,
-                             GNUNET_TESTING_NotifyDaemonRunning cb,
-                             void *cb_cls)
-{
-  struct GNUNET_TESTING_Daemon *ret;
-  char *arg;
-  char *username;
-  char *servicehome;
-  char *baseservicehome;
-  char *slash;
-  char *hostkeyfile;
-  char *temp_file_name;
-  struct GNUNET_DISK_FileHandle *fn;
-  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
-  struct GNUNET_CRYPTO_RsaPrivateKey *private_key;
-
-  ret = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Daemon));
-  ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname);
-  if (sshport != 0)
-  {
-    GNUNET_asprintf (&ret->ssh_port_str, "%d", sshport);
-  }
-  else
-    ret->ssh_port_str = NULL;
-
-  /* Find service home and base service home directories, create it if it doesn't exist */
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
-                                                        "SERVICEHOME",
-                                                        &servicehome));
-
-  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_create (servicehome));
-  GNUNET_asprintf (&temp_file_name, "%s/gnunet-testing-config", servicehome);
-  ret->cfgfile = GNUNET_DISK_mktemp (temp_file_name);
-  GNUNET_free (temp_file_name);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Setting up peer with configuration file `%s'.\n", ret->cfgfile);
-  if (NULL == ret->cfgfile)
-  {
-    GNUNET_free_non_null (ret->ssh_port_str);
-    GNUNET_free_non_null (ret->hostname);
-    GNUNET_free (ret);
-    return NULL;
-  }
-  ret->hostkey_callback = hostkey_callback;
-  ret->hostkey_cls = hostkey_cls;
-  ret->cb = cb;
-  ret->cb_cls = cb_cls;
-  ret->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
-  GNUNET_CONFIGURATION_set_value_string (ret->cfg, "PATHS", "DEFAULTCONFIG",
-                                         ret->cfgfile);
-
-  if (hostkey != NULL)          /* Get the peer identity from the hostkey */
-  {
-    private_key = GNUNET_CRYPTO_rsa_decode_key (hostkey, HOSTKEYFILESIZE);
-    GNUNET_assert (private_key != NULL);
-    GNUNET_CRYPTO_rsa_key_get_public (private_key, &public_key);
-    GNUNET_CRYPTO_hash (&public_key,
-                        sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
-                        &ret->id.hashPubKey);
-    ret->shortname = GNUNET_strdup (GNUNET_i2s (&ret->id));
-    ret->have_hostkey = GNUNET_YES;
-    GNUNET_CRYPTO_rsa_key_free (private_key);
-  }
-
-  /* Write hostkey to file, if we were given one */
-  hostkeyfile = NULL;
-  if (hostkey != NULL)
-  {
-    GNUNET_asprintf (&hostkeyfile, "%s/.hostkey", servicehome);
-    fn = GNUNET_DISK_file_open (hostkeyfile,
-                                GNUNET_DISK_OPEN_READWRITE |
-                                GNUNET_DISK_OPEN_CREATE,
-                                GNUNET_DISK_PERM_USER_READ |
-                                GNUNET_DISK_PERM_USER_WRITE);
-    GNUNET_assert (fn != NULL);
-    GNUNET_assert (HOSTKEYFILESIZE ==
-                   GNUNET_DISK_file_write (fn, hostkey, HOSTKEYFILESIZE));
-    GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fn));
-  }
-
-  /* write configuration to temporary file */
-  if (GNUNET_OK != GNUNET_CONFIGURATION_write (ret->cfg, ret->cfgfile))
-  {
-    if (0 != UNLINK (ret->cfgfile))
-      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
-                                ret->cfgfile);
-    GNUNET_CONFIGURATION_destroy (ret->cfg);
-    GNUNET_free_non_null (ret->hostname);
-    GNUNET_free (ret->cfgfile);
-    GNUNET_free (ret);
-    return NULL;
-  }
-  if (ssh_username != NULL)
-    username = GNUNET_strdup (ssh_username);
-  if ((ssh_username == NULL) &&
-      (GNUNET_OK !=
-       GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "USERNAME",
-                                              &username)))
-  {
-    if (NULL != getenv ("USER"))
-      username = GNUNET_strdup (getenv ("USER"));
-    else
-      username = NULL;
-  }
-  ret->username = username;
-
-  if (GNUNET_NO == pretend)     /* Copy files, enter finite state machine */
-  {
-    /* copy directory to remote host */
-    if (NULL != hostname)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Copying configuration directory to host `%s'.\n", hostname);
-      baseservicehome = GNUNET_strdup (servicehome);
-      /* Remove trailing /'s */
-      while (baseservicehome[strlen (baseservicehome) - 1] == '/')
-        baseservicehome[strlen (baseservicehome) - 1] = '\0';
-      /* Find next directory /, jump one ahead */
-      slash = strrchr (baseservicehome, '/');
-      if (slash != NULL)
-        *(++slash) = '\0';
-
-      ret->phase = SP_COPYING;
-      if (NULL != username)
-        GNUNET_asprintf (&arg, "%s@%s:%s", username, hostname, baseservicehome);
-      else
-        GNUNET_asprintf (&arg, "%s:%s", hostname, baseservicehome);
-      GNUNET_free (baseservicehome);
-      if (ret->ssh_port_str == NULL)
-      {
-        ret->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", "-r",
-                                             "-q",
-                                             servicehome, arg, NULL);
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                    "copying directory with command scp -r %s %s\n",
-                    servicehome, arg);
-      }
-      else
-      {
-        ret->proc_arm_copying =
-           GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", "-r", "-P",
-                                     ret->ssh_port_str,
-                                     "-q",
-                                     servicehome, arg, NULL);
-      }
-      GNUNET_free (arg);
-      if (NULL == ret->proc_arm_copying)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                    _
-                    ("Could not start `%s' process to copy configuration directory.\n"),
-                    "scp");
-        if (0 != UNLINK (ret->cfgfile))
-          GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
-                                    ret->cfgfile);
-        GNUNET_CONFIGURATION_destroy (ret->cfg);
-        GNUNET_free_non_null (ret->hostname);
-        GNUNET_free_non_null (ret->username);
-        GNUNET_free (ret->cfgfile);
-        GNUNET_free (ret);
-        if ((hostkey != NULL) && (0 != UNLINK (hostkeyfile)))
-          GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
-                                    hostkeyfile);
-        GNUNET_free_non_null (hostkeyfile);
-        GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (servicehome));
-        GNUNET_free (servicehome);
-        return NULL;
-      }
-
-      ret->task =
-          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
-                                        ret);
-      GNUNET_free_non_null (hostkeyfile);
-      GNUNET_free (servicehome);
-      return ret;
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "No need to copy configuration file since we are running locally.\n");
-    ret->phase = SP_COPIED;
-    /* FIXME: why add_cont? */
-    GNUNET_SCHEDULER_add_continuation (&start_fsm, ret,
-                                       GNUNET_SCHEDULER_REASON_PREREQ_DONE);
-  }
-  GNUNET_free_non_null (hostkeyfile);
-  GNUNET_free (servicehome);
-  return ret;
-}
-
-
-/**
- * Restart (stop and start) a GNUnet daemon.
- *
- * @param d the daemon that should be restarted
- * @param cb function called once the daemon is (re)started
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
-                               GNUNET_TESTING_NotifyDaemonRunning cb,
-                               void *cb_cls)
-{
-  char *arg;
-  char *del_arg;
-
-  del_arg = NULL;
-  if (NULL != d->cb)
-  {
-    d->dead = GNUNET_YES;
-    return;
-  }
-
-  d->cb = cb;
-  d->cb_cls = cb_cls;
-
-  if (d->phase == SP_CONFIG_UPDATE)
-  {
-    GNUNET_SCHEDULER_cancel (d->task);
-    d->phase = SP_START_DONE;
-  }
-  if (d->server != NULL)
-  {
-    GNUNET_CORE_disconnect (d->server);
-    d->server = NULL;
-  }
-
-  if (d->th != NULL)
-  {
-    GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
-    d->ghh = NULL;
-    GNUNET_TRANSPORT_disconnect (d->th);
-    d->th = NULL;
-  }
-  /* state clean up and notifications */
-  GNUNET_free_non_null (d->hello);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
-              GNUNET_i2s (&d->id));
-  d->phase = SP_START_ARMING;
-
-  /* Check if this is a local or remote process */
-  if (NULL != d->hostname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with config `%s' on host `%s'.\n",
-                d->cfgfile, d->hostname);
-    if (d->username != NULL)
-      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
-    else
-      arg = GNUNET_strdup (d->hostname);
-
-    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
-                                       "-q",
-                                       arg, "gnunet-arm",
-                                       "-c", d->cfgfile, "-e", "-r", NULL);
-    /* Use -r to restart arm and all services */
-
-    GNUNET_free (arg);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
-    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
-                                       "-c", d->cfgfile, "-e", "-r", NULL);
-  }
-
-  GNUNET_free_non_null (del_arg);
-  d->task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
-
-}
-
-
-/**
- * Stops a GNUnet daemon.
- *
- * @param d the daemon that should be stopped
- * @param service the name of the service to stop
- * @param timeout how long to wait for process for shutdown to complete
- * @param cb function called once the daemon was stopped
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d,
-                                    const char *service,
-                                    struct GNUNET_TIME_Relative timeout,
-                                    GNUNET_TESTING_NotifyCompletion cb,
-                                    void *cb_cls)
-{
-  char *arg;
-
-  d->dead_cb = cb;
-  d->dead_cb_cls = cb_cls;
-
-  GNUNET_assert (d->running == GNUNET_YES);
-
-  if (d->phase == SP_CONFIG_UPDATE)
-  {
-    GNUNET_SCHEDULER_cancel (d->task);
-    d->phase = SP_START_DONE;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
-              GNUNET_i2s (&d->id));
-  if (d->churned_services != NULL)
-  {
-    d->dead_cb (d->dead_cb_cls, "A service has already been turned off!!");
-    return;
-  }
-  d->phase = SP_SERVICE_SHUTDOWN_START;
-  d->churned_services = GNUNET_strdup (service);
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  /* Check if this is a local or remote process */
-  if (NULL != d->hostname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with config `%s' on host `%s'.\n",
-                d->cfgfile, d->hostname);
-    if (d->username != NULL)
-      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
-    else
-      arg = GNUNET_strdup (d->hostname);
-    
-    d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
-                                       "-q",
-                                       arg, "gnunet-arm",
-                                       "-c", d->cfgfile, "-k", service, "-q",
-                                       "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -k %s -q\n",
-                arg, "gnunet-arm", d->cfgfile, service);
-    GNUNET_free (arg);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
-    d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
-                                       "-c", d->cfgfile, "-k", service, "-q",
-                                       "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       NULL);
-  }
-
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
-}
-
-
-/**
- * Forcefully terminate a process and clean up the child.
- *
- * @param proc handle to process to kill
- */
-static void
-kill_and_close_process (struct GNUNET_OS_Process *proc)
-{
-  (void) GNUNET_OS_process_kill (proc, SIGKILL); 
-  GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
-  GNUNET_OS_process_destroy (proc);
-}
-
-
-/**
- * Stops a GNUnet daemon.
- *
- * @param d the daemon that should be stopped
- * @param timeout how long to wait for process for shutdown to complete
- * @param cb function called once the daemon was stopped
- * @param cb_cls closure for cb
- * @param delete_files GNUNET_YES to remove files, GNUNET_NO
- *        to leave them
- * @param allow_restart GNUNET_YES to restart peer later (using this API)
- *        GNUNET_NO to kill off and clean up for good
- */
-void
-GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
-                            struct GNUNET_TIME_Relative timeout,
-                            GNUNET_TESTING_NotifyCompletion cb, void *cb_cls,
-                            int delete_files, int allow_restart)
-{
-  char *arg;
-  char *del_arg;
-
-  d->dead_cb = cb;
-  d->dead_cb_cls = cb_cls;
-
-  if (NULL != d->cb)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Setting d->dead on peer `%4s'\n"),
-                GNUNET_i2s (&d->id));
-    d->dead = GNUNET_YES;
-    return;
-  }
-  if (NULL != d->proc_arm_start)
-  {
-    kill_and_close_process (d->proc_arm_start);
-    d->proc_arm_start = NULL;
-  }
-  if (NULL != d->proc_arm_srv_start)
-  {
-    kill_and_close_process (d->proc_arm_srv_start);
-    d->proc_arm_srv_start = NULL;
-  }
-  if (NULL != d->proc_arm_srv_stop)
-  {
-    kill_and_close_process (d->proc_arm_srv_stop);
-    d->proc_arm_srv_stop = NULL;
-  }
-  if (NULL != d->proc_arm_copying)
-  {
-    kill_and_close_process (d->proc_arm_copying);
-    d->proc_arm_copying = NULL;
-  }
-  if (NULL != d->proc_arm_peerinfo)
-  {
-    kill_and_close_process (d->proc_arm_peerinfo);
-    d->proc_arm_peerinfo = NULL;
-  }
-  if ((d->running == GNUNET_NO) && (d->churn == GNUNET_YES))
-  {
-    /* Peer has already been stopped in churn context!
-     * Free what was left from churning! */
-    GNUNET_assert (d->cfg != NULL);
-    GNUNET_CONFIGURATION_destroy (d->cfg);
-    if (delete_files == GNUNET_YES)
-    {
-      if (0 != UNLINK (d->cfgfile))
-      {
-        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "unlink");
-      }
-    }
-    GNUNET_free (d->cfgfile);
-    GNUNET_free_non_null (d->hostname);
-    GNUNET_free_non_null (d->username);
-    if (NULL != d->dead_cb)
-      d->dead_cb (d->dead_cb_cls, NULL);
-    /* FIXME: this should be an assert and the test below
-       should not be required, but testing is broken... */
-    GNUNET_break (NULL == d->proc_arm_stop);
-    if (NULL == d->proc_arm_stop) 
-    GNUNET_free (d);
-    return;
-  }
-
-  del_arg = NULL;
-  if (delete_files == GNUNET_YES)
-  {
-    GNUNET_asprintf (&del_arg, "-d");
-  }
-
-  if (d->phase == SP_CONFIG_UPDATE)
-  {
-    GNUNET_SCHEDULER_cancel (d->task);
-    d->phase = SP_START_DONE;
-  }
-  /** Move this call to scheduled shutdown as fix for CORE_connect calling daemon_stop?
-  if (d->server != NULL)
-    {
-      GNUNET_CORE_disconnect (d->server);
-      d->server = NULL;
-    }
-    */
-  /* shutdown ARM process (will terminate others) */
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating peer `%4s'\n" ,
-              GNUNET_i2s (&d->id));
-  d->phase = SP_SHUTDOWN_START;
-  d->running = GNUNET_NO;
-  if (allow_restart == GNUNET_YES)
-    d->churn = GNUNET_YES;
-  if (d->th != NULL)
-  {
-    GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
-    d->ghh = NULL;
-    GNUNET_TRANSPORT_disconnect (d->th);
-    d->th = NULL;
-  }
-  /* Check if this is a local or remote process */
-
-
-  if (NULL != d->hostname)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with config `%s' on host `%s'.\n",
-                d->cfgfile, d->hostname);
-    if (d->username != NULL)
-      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
-    else
-      arg = GNUNET_strdup (d->hostname);
-
-    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
-                                       "-q",
-                                       arg, "gnunet-arm",
-                                       "-c", d->cfgfile, "-e", "-q", "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       del_arg, NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -e -q %s\n",
-                arg, "gnunet-arm", d->cfgfile, del_arg);
-    /* Use -e to end arm, and -d to remove temp files */
-    GNUNET_free (arg);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
-    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "gnunet-arm", "gnunet-arm",
-                                       "-c", d->cfgfile, "-e", "-q", "-T",
-                                       GNUNET_TIME_relative_to_string (timeout),
-                                       del_arg, NULL);
-    GNUNET_assert (NULL != d->proc_arm_stop);
-  }
-
-  GNUNET_free_non_null (del_arg);
-  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  if (GNUNET_SCHEDULER_NO_TASK != d->task)
-    GNUNET_SCHEDULER_cancel(d->task);
-  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
-}
-
-
-/**
- * Changes the configuration of a GNUnet daemon.
- *
- * @param d the daemon that should be modified
- * @param cfg the new configuration for the daemon
- * @param cb function called once the configuration was changed
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
-                                   struct GNUNET_CONFIGURATION_Handle *cfg,
-                                   GNUNET_TESTING_NotifyCompletion cb,
-                                   void *cb_cls)
-{
-  char *arg;
-
-  if (d->phase != SP_START_DONE)
-  {
-    if (NULL != cb)
-      cb (cb_cls,
-          _
-          ("Peer not yet running, can not change configuration at this point."));
-    return;
-  }
-
-  /* 1) write configuration to temporary file */
-  if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, d->cfgfile))
-  {
-    if (NULL != cb)
-      cb (cb_cls, _("Failed to write new configuration to disk."));
-    return;
-  }
-
-  /* 2) copy file to remote host (if necessary) */
-  if (NULL == d->hostname)
-  {
-    /* signal success */
-    if (NULL != cb)
-      cb (cb_cls, NULL);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Copying updated configuration file to remote host `%s'.\n",
-              d->hostname);
-  d->phase = SP_CONFIG_UPDATE;
-  if (NULL != d->username)
-    GNUNET_asprintf (&arg, "%s@%s:%s", d->username, d->hostname, d->cfgfile);
-  else
-    GNUNET_asprintf (&arg, "%s:%s", d->hostname, d->cfgfile);
-  d->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp",
-                                     "-q",
-                                     d->cfgfile, arg, NULL);
-  GNUNET_free (arg);
-  if (NULL == d->proc_arm_copying)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                _("Could not start `%s' process to copy configuration file.\n"),
-                "scp");
-    if (NULL != cb)
-      cb (cb_cls, _("Failed to copy new configuration to remote machine."));
-    d->phase = SP_START_DONE;
-    return;
-  }
-  d->update_cb = cb;
-  d->update_cb_cls = cb_cls;
-  d->task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
-}
-
-
-/**
- * Data kept for each pair of peers that we try
- * to connect.
- */
-struct GNUNET_TESTING_ConnectContext
-{
-  /**
-   * Testing handle to the first daemon.
-   */
-  struct GNUNET_TESTING_Daemon *d1;
-
-  /**
-   * Handle to core of first daemon (to check connect)
-   */
-  struct GNUNET_CORE_Handle *d1core;
-
-  /**
-   * Have we actually connected to the core of the first daemon yet?
-   */
-  int d1core_ready;
-
-  /**
-   * Testing handle to the second daemon.
-   */
-  struct GNUNET_TESTING_Daemon *d2;
-
-  /**
-   * Transport handle to the first daemon (to offer the HELLO of the second daemon to).
-   */
-  struct GNUNET_TRANSPORT_Handle *d1th;
-
-  /**
-   * Function to call once we are done (or have timed out).
-   */
-  GNUNET_TESTING_NotifyConnection cb;
-
-  /**
-   * Closure for "nb".
-   */
-  void *cb_cls;
-
-  /**
-   * The relative timeout from whence this connect attempt was
-   * started.  Allows for reconnect attempts.
-   */
-  struct GNUNET_TIME_Relative relative_timeout;
-
-  /**
-   * Maximum number of connect attempts, will retry connection
-   * this number of times on failures.
-   */
-  unsigned int connect_attempts;
-
-  /**
-   * Hello timeout task
-   */
-  GNUNET_SCHEDULER_TaskIdentifier hello_send_task;
-
-  /**
-   * Connect timeout task
-   */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
-
-  /**
-   * When should this operation be complete (or we must trigger
-   * a timeout).
-   */
-  struct GNUNET_TIME_Relative timeout_hello;
-
-  /**
-   * Was the connection attempt successful?
-   */
-  int connected;
-
-  /**
-   * When connecting, do we need to send the HELLO?
-   */
-  int send_hello;
-
-  /**
-   * The distance between the two connected peers
-   */
-  uint32_t distance;
-};
-
-
-/** Forward declaration **/
-static void
-reattempt_daemons_connect (void *cls,
-                           const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-
-/**
- * Notify callback about success or failure of the attempt
- * to connect the two peers
- *
- * @param cls our "struct GNUNET_TESTING_ConnectContext" (freed)
- * @param tc reason tells us if we succeeded or failed
- */
-static void
-notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TESTING_ConnectContext *ctx = cls;
-
-  ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (ctx->hello_send_task);
-    ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-
-  if (ctx->d1th != NULL)
-    GNUNET_TRANSPORT_disconnect (ctx->d1th);
-  ctx->d1th = NULL;
-  if (ctx->d1core != NULL)
-    GNUNET_CORE_disconnect (ctx->d1core);
-  ctx->d1core = NULL;
-
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-  {
-    GNUNET_free (ctx);
-    return;
-  }
-
-  if (ctx->connected == GNUNET_YES)
-  {
-    if (ctx->cb != NULL)
-    {
-      ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance,
-               ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
-    }
-  }
-  else if (ctx->connect_attempts > 0)
-  {
-    ctx->d1core_ready = GNUNET_NO;
-    ctx->timeout_task =
-        GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx);
-    return;
-  }
-  else
-  {
-    if (ctx->cb != NULL)
-    {
-      ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
-               ctx->d2->cfg, ctx->d1, ctx->d2, _("Peers failed to connect"));
-    }
-  }
-  GNUNET_free (ctx);
-}
-
-
-/**
- * Success, connection is up.  Signal client our success.
- *
- * @param cls our "struct GNUNET_TESTING_ConnectContext"
- * @param peer identity of the peer that has connected
- * @param atsi performance information
- * @param atsi_count number of records in 'atsi'
- *
- */
-static void
-connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
-                const struct GNUNET_ATS_Information *atsi,
-                unsigned int atsi_count)
-{
-  struct GNUNET_TESTING_ConnectContext *ctx = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n",
-              ctx->d1->shortname, GNUNET_i2s (peer));
-  if (0 != memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))
-    return;
-  ctx->connected = GNUNET_YES;
-  ctx->distance = 0;            /* FIXME: distance */
-  if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (ctx->hello_send_task);
-    ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  GNUNET_SCHEDULER_cancel (ctx->timeout_task);
-  ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
-}
-
-
-static void
-send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TESTING_ConnectContext *ctx = cls;
-  struct GNUNET_MessageHeader *hello;
-
-  ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-    return;
-  if ((ctx->d1core_ready == GNUNET_YES) && (ctx->d2->hello != NULL) &&
-      (NULL != GNUNET_HELLO_get_header (ctx->d2->hello)) &&
-      (ctx->d1->phase == SP_START_DONE) && (ctx->d2->phase == SP_START_DONE))
-  {
-    hello = GNUNET_HELLO_get_header (ctx->d2->hello);
-    GNUNET_assert (hello != NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Offering hello of %s to %s\n",
-                ctx->d2->shortname, ctx->d1->shortname);
-    GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL);
-    GNUNET_assert (ctx->d1core != NULL);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Sending connect request to TRANSPORT of %s for peer %s\n",
-                GNUNET_i2s (&ctx->d1->id),
-                GNUNET_h2s (&ctx->d2->id.hashPubKey));
-    GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id);
-    ctx->timeout_hello =
-        GNUNET_TIME_relative_add (ctx->timeout_hello,
-                                  GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 500));
-  }
-  ctx->hello_send_task =
-      GNUNET_SCHEDULER_add_delayed (ctx->timeout_hello, &send_hello, ctx);
-}
-
-/**
- * Notify of a successful connection to the core service.
- *
- * @param cls a ConnectContext
- * @param server handle to the core service
- * @param my_identity the peer identity of this peer
- */
-void
-core_init_notify (void *cls, struct GNUNET_CORE_Handle *server,
-                  const struct GNUNET_PeerIdentity *my_identity)
-{
-  struct GNUNET_TESTING_ConnectContext *connect_ctx = cls;
-
-  connect_ctx->d1core_ready = GNUNET_YES;
-
-  if (connect_ctx->send_hello == GNUNET_NO)
-  {
-    GNUNET_TRANSPORT_try_connect (connect_ctx->d1th, &connect_ctx->d2->id);
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Sending connect request to TRANSPORT of %s for peer %s\n",
-                connect_ctx->d1->shortname, connect_ctx->d2->shortname);
-  }
-}
-
-
-/**
- * Try to connect again some peers that failed in an earlier attempt. This will
- * be tried as many times as connection_attempts in the configuration file.
- *
- * @param cls Closure (connection context between the two peers).
- * @param tc TaskContext.
- */
-static void
-reattempt_daemons_connect (void *cls,
-                           const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_TESTING_ConnectContext *ctx = cls;
-
-  ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-    return;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "re-attempting connect of peer %s to peer %s\n",
-              ctx->d1->shortname, ctx->d2->shortname);
-  ctx->connect_attempts--;
-  GNUNET_assert (ctx->d1core == NULL);
-  ctx->d1core_ready = GNUNET_NO;
-  ctx->d1core =
-      GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify,
-                           &connect_notify, NULL, NULL, GNUNET_NO, NULL,
-                           GNUNET_NO, no_handlers);
-  if (ctx->d1core == NULL)
-  {
-    if (NULL != ctx->cb)
-      ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
-               ctx->d2->cfg, ctx->d1, ctx->d2,
-               _("Failed to connect to core service of first peer!\n"));
-    GNUNET_free (ctx);
-    return;
-  }
-
-  /* Don't know reason for initial connect failure, update the HELLO for the second peer */
-  if (NULL != ctx->d2->hello)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "updating %s's HELLO\n",
-                ctx->d2->shortname);
-    GNUNET_free (ctx->d2->hello);
-    ctx->d2->hello = NULL;
-    if (NULL != ctx->d2->th)
-    {
-      GNUNET_TRANSPORT_get_hello_cancel (ctx->d2->ghh);
-      ctx->d2->ghh = NULL;
-      GNUNET_TRANSPORT_disconnect (ctx->d2->th);
-    }
-    ctx->d2->th =
-        GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
-                                  NULL);
-    GNUNET_assert (ctx->d2->th != NULL);
-    ctx->d2->ghh =
-        GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "didn't have %s's HELLO\n",
-                ctx->d2->shortname);
-  }
-
-  if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "didn't have %s's HELLO, trying to get it now\n",
-                ctx->d2->shortname);
-    ctx->d2->th =
-        GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
-                                  NULL);
-    if (NULL == ctx->d2->th)
-    {
-      GNUNET_CORE_disconnect (ctx->d1core);
-      GNUNET_free (ctx);
-      if (NULL != ctx->cb)
-        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
-                 ctx->d2->cfg, ctx->d1, ctx->d2,
-                 _("Failed to connect to transport service!\n"));
-      return;
-    }
-    ctx->d2->ghh =
-        GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
-  }
-  else
-  {
-    if (NULL == ctx->d2->hello)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "didn't have %s's HELLO but th wasn't NULL, not trying!!\n",
-                  ctx->d2->shortname);
-    }
-  }
-
-  if (ctx->send_hello == GNUNET_YES)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s's HELLO to %s\n",
-                ctx->d1->shortname, ctx->d2->shortname);
-    ctx->d1th =
-        GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL,
-                                  NULL, NULL);
-    if (ctx->d1th == NULL)
-    {
-      GNUNET_CORE_disconnect (ctx->d1core);
-      GNUNET_free (ctx);
-      if (NULL != ctx->cb)
-        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
-                 ctx->d2->cfg, ctx->d1, ctx->d2,
-                 _("Failed to connect to transport service!\n"));
-      return;
-    }
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task);
-    ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to reconnect %s to %s\n",
-                ctx->d1->shortname, ctx->d2->shortname);
-    GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id);
-  }
-  ctx->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
-                                    &notify_connect_result, ctx);
-}
-
-/**
- * Iterator for currently known peers, to ensure
- * that we don't try to send duplicate connect
- * requests to core.
- *
- * @param cls our "struct GNUNET_TESTING_ConnectContext"
- * @param peer identity of the peer that has connected,
- *        NULL when iteration has finished
- * @param atsi performance information
- * @param atsi_count number of records in 'atsi'
- *
- */
-static void
-core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer,
-                        const struct GNUNET_ATS_Information *atsi,
-                        unsigned int atsi_count)
-{
-  struct GNUNET_TESTING_ConnectContext *ctx = cls;
-
-  if ((peer != NULL) &&
-      (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))))
-  {
-    ctx->connected = GNUNET_YES;
-    ctx->distance = 0;          /* FIXME: distance */
-    return;
-  }
-  if (peer != NULL)
-    return;                     /* ignore other peers */
-  /* peer == NULL: End of iteration over peers */
-
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->timeout_task);
-  if (ctx->connected == GNUNET_YES)
-  {
-    ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
-    return;
-  }
-
-  /* Peer not already connected, need to schedule connect request! */
-  if (ctx->d1core == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Peers are NOT connected, connecting to core!\n");
-    ctx->d1core =
-        GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify,
-                             &connect_notify, NULL, NULL, GNUNET_NO, NULL,
-                             GNUNET_NO, no_handlers);
-  }
-
-  if (ctx->d1core == NULL)
-  {
-    ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
-    return;
-  }
-
-  if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL))        /* Do not yet have the second peer's hello, set up a task to get it */
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Don't have d2's HELLO, trying to get it!\n");
-    ctx->d2->th =
-        GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
-                                  NULL);
-    if (ctx->d2->th == NULL)
-    {
-      GNUNET_CORE_disconnect (ctx->d1core);
-      ctx->d1core = NULL;
-      ctx->timeout_task =
-          GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
-      return;
-    }
-    ctx->d2->ghh =
-        GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
-  }
-
-  if (ctx->send_hello == GNUNET_YES)
-  {
-    ctx->d1th =
-        GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL,
-                                  NULL, NULL);
-    if (ctx->d1th == NULL)
-    {
-      GNUNET_CORE_disconnect (ctx->d1core);
-      ctx->d1core = NULL;
-      ctx->timeout_task =
-          GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
-      return;
-    }
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task);
-    ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
-  }
-
-  ctx->timeout_task =
-      GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
-                                    &notify_connect_result, ctx);
-
-}
-
-
-/**
- * Establish a connection between two GNUnet daemons.  The daemons
- * must both be running and not be stopped until either the
- * 'cb' callback is called OR the connection request has been
- * explicitly cancelled.
- *
- * @param d1 handle for the first daemon
- * @param d2 handle for the second daemon
- * @param timeout how long is the connection attempt
- *        allowed to take?
- * @param max_connect_attempts how many times should we try to reconnect
- *        (within timeout)
- * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
- *                   the HELLO has already been exchanged
- * @param cb function to call at the end
- * @param cb_cls closure for cb
- * @return handle to cancel the request
- */
-struct GNUNET_TESTING_ConnectContext *
-GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
-                                struct GNUNET_TESTING_Daemon *d2,
-                                struct GNUNET_TIME_Relative timeout,
-                                unsigned int max_connect_attempts,
-                                int send_hello,
-                                GNUNET_TESTING_NotifyConnection cb,
-                                void *cb_cls)
-{
-  struct GNUNET_TESTING_ConnectContext *ctx;
-
-  if ((d1->running == GNUNET_NO) || (d2->running == GNUNET_NO))
-  {
-    if (NULL != cb)
-      cb (cb_cls, &d1->id, &d2->id, 0, d1->cfg, d2->cfg, d1, d2,
-          _("Peers are not fully running yet, can not connect!\n"));
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers are not up!\n");
-    return NULL;
-  }
-
-  ctx = GNUNET_malloc (sizeof (struct GNUNET_TESTING_ConnectContext));
-  ctx->d1 = d1;
-  ctx->d2 = d2;
-  ctx->timeout_hello =
-      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500);
-  ctx->relative_timeout =
-      GNUNET_TIME_relative_divide (timeout, max_connect_attempts);
-  ctx->cb = cb;
-  ctx->cb_cls = cb_cls;
-  ctx->connect_attempts = max_connect_attempts;
-  ctx->connected = GNUNET_NO;
-  ctx->send_hello = send_hello;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to connect peer %s to peer %s\n",
-              d1->shortname, d2->shortname);
-  /* Core is up! Iterate over all _known_ peers first to check if we are already connected to the peer! */
-  GNUNET_assert (NULL !=
-                 GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id,
-                                                &core_initial_iteration, ctx));
-  return ctx;
-}
-
-
-/**
- * Cancel an attempt to connect two daemons.
- *
- * @param cc connect context
- */
-void
-GNUNET_TESTING_daemons_connect_cancel (struct GNUNET_TESTING_ConnectContext *cc)
-{
-  if (GNUNET_SCHEDULER_NO_TASK != cc->timeout_task)
-  {
-    GNUNET_SCHEDULER_cancel (cc->timeout_task);
-    cc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (GNUNET_SCHEDULER_NO_TASK != cc->hello_send_task)
-  {
-    GNUNET_SCHEDULER_cancel (cc->hello_send_task);
-    cc->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  if (NULL != cc->d1core)
-  {
-    GNUNET_CORE_disconnect (cc->d1core);
-    cc->d1core = NULL;
-  }
-  if (NULL != cc->d1th)
-  {
-    GNUNET_TRANSPORT_disconnect (cc->d1th);
-    cc->d1th = NULL;
-  }
-  GNUNET_free (cc);
-}
-
-
-/* end of testing.c */
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
deleted file mode 100644 (file)
index 75c0e61..0000000
+++ /dev/null
@@ -1,7038 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2008, 2009 Christian Grothoff (and other contributing authors)
-
- 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 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING.  If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file testing/testing_group.c
- * @brief convenience API for writing testcases for GNUnet
- * @author Nathan Evans
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_constants.h"
-#include "gnunet_arm_service.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-
-#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
- * enough to not conflict with client-ports (typically starting around
- * 32k).
- */
-#define LOW_PORT 12000
-
-/**
- * Highest port used for GNUnet testing.  Should be low enough to not
- * conflict with the port range for "local" ports (client apps; see
- * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
- */
-#define HIGH_PORT 56000
-
-/* Maximum time to delay connect attempt */
-#define MAX_CONNECT_DELAY 300
-
-/**
- * Which list of peers do we need to modify?
- */
-enum PeerLists
-{
-  /** Modify allowed peers */
-  ALLOWED,
-
-  /** Modify connect peers */
-  CONNECT,
-
-  /** Modify blacklist peers */
-  BLACKLIST,
-
-  /** Modify workingset peers */
-  WORKING_SET
-};
-
-/**
- * Prototype of a function called whenever two peers would be connected
- * in a certain topology.
- */
-typedef unsigned int (*GNUNET_TESTING_ConnectionProcessor) (struct
-                                                            GNUNET_TESTING_PeerGroup
-                                                            * pg,
-                                                            unsigned int first,
-                                                            unsigned int second,
-                                                            enum PeerLists list,
-                                                            unsigned int check);
-
-/**
- * Context for handling churning a peer group
- */
-struct ChurnContext
-{
-  /**
-   * The peergroup we are dealing with.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * Name of the service to churn on/off, NULL
-   * to churn entire peer.
-   */
-  char *service;
-
-  /**
-   * Callback used to notify of churning finished
-   */
-  GNUNET_TESTING_NotifyCompletion cb;
-
-  /**
-   * Closure for callback
-   */
-  void *cb_cls;
-
-  /**
-   * Number of peers that still need to be started
-   */
-  unsigned int num_to_start;
-
-  /**
-   * Number of peers that still need to be stopped
-   */
-  unsigned int num_to_stop;
-
-  /**
-   * Number of peers that failed to start
-   */
-  unsigned int num_failed_start;
-
-  /**
-   * Number of peers that failed to stop
-   */
-  unsigned int num_failed_stop;
-};
-
-struct RestartContext
-{
-  /**
-   * The group of peers being restarted
-   */
-  struct GNUNET_TESTING_PeerGroup *peer_group;
-
-  /**
-   * How many peers have been restarted thus far
-   */
-  unsigned int peers_restarted;
-
-  /**
-   * How many peers got an error when restarting
-   */
-  unsigned int peers_restart_failed;
-
-  /**
-   * The function to call once all peers have been restarted
-   */
-  GNUNET_TESTING_NotifyCompletion callback;
-
-  /**
-   * Closure for callback function
-   */
-  void *callback_cls;
-
-};
-
-struct SendHelloContext
-{
-  /**
-   * Global handle to the peer group.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * The data about this specific peer.
-   */
-  struct PeerData *peer;
-
-  /**
-   * The next HELLO that needs sent to this peer.
-   */
-  struct PeerConnection *peer_pos;
-
-  /**
-   * Are we connected to CORE yet?
-   */
-  unsigned int core_ready;
-
-  /**
-   * How many attempts should we make for failed connections?
-   */
-  unsigned int connect_attempts;
-
-  /**
-   * Task for scheduling core connect requests to be sent.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier core_connect_task;
-};
-
-struct ShutdownContext
-{
-  struct GNUNET_TESTING_PeerGroup *pg;
-  /**
-   * Total peers to wait for
-   */
-  unsigned int total_peers;
-
-  /**
-   * Number of peers successfully shut down
-   */
-  unsigned int peers_down;
-
-  /**
-   * Number of peers failed to shut down
-   */
-  unsigned int peers_failed;
-
-  /**
-   * Number of peers we have started shutting
-   * down.  If too many, wait on them.
-   */
-  unsigned int outstanding;
-
-  /**
-   * Timeout for shutdown.
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * Callback to call when all peers either
-   * shutdown or failed to shutdown
-   */
-  GNUNET_TESTING_NotifyCompletion cb;
-
-  /**
-   * Closure for cb
-   */
-  void *cb_cls;
-
-  /**
-   * Should we delete all of the files from the peers?
-   */
-  int delete_files;
-};
-
-/**
- * Individual shutdown context for a particular peer.
- */
-struct PeerShutdownContext
-{
-  /**
-   * Pointer to the high level shutdown context.
-   */
-  struct ShutdownContext *shutdown_ctx;
-
-  /**
-   * The daemon handle for the peer to shut down.
-   */
-  struct GNUNET_TESTING_Daemon *daemon;
-};
-
-/**
- * Individual shutdown context for a particular peer.
- */
-struct PeerRestartContext
-{
-  /**
-   * Pointer to the high level restart context.
-   */
-  struct ChurnRestartContext *churn_restart_ctx;
-
-  /**
-   * The daemon handle for the peer to shut down.
-   */
-  struct GNUNET_TESTING_Daemon *daemon;
-};
-
-struct ServiceStartContext
-{
-  struct GNUNET_TESTING_PeerGroup *pg;
-  unsigned int remaining;
-  GNUNET_TESTING_NotifyCompletion cb;
-  unsigned int outstanding;
-  char *service;
-  struct GNUNET_TIME_Relative timeout;
-  void *cb_cls;
-};
-
-/**
- * Individual shutdown context for a particular peer.
- */
-struct PeerServiceStartContext
-{
-  /**
-   * Pointer to the high level start context.
-   */
-  struct ServiceStartContext *start_ctx;
-
-  /**
-   * The daemon handle for the peer to start the service on.
-   */
-  struct GNUNET_TESTING_Daemon *daemon;
-};
-
-struct CreateTopologyContext
-{
-
-  /**
-   * Function to call with number of connections
-   */
-  GNUNET_TESTING_NotifyConnections cont;
-
-  /**
-   * Closure for connection notification
-   */
-  void *cls;
-};
-
-enum States
-{
-  /** Waiting to read number of peers */
-  NUM_PEERS,
-
-  /** Should find next peer index */
-  PEER_INDEX,
-
-  /** Should find colon */
-  COLON,
-
-  /** Should read other peer index, space, or endline */
-  OTHER_PEER_INDEX
-};
-
-#if OLD
-struct PeerConnection
-{
-  /**
-   * Doubly Linked list
-   */
-  struct PeerConnection *prev;
-
-  /*
-   * Doubly Linked list
-   */
-  struct PeerConnection *next;
-
-  /*
-   * Index of daemon in pg->peers
-   */
-  uint32_t index;
-
-};
-#endif
-
-struct InternalStartContext
-{
-  /**
-   * Pointer to peerdata
-   */
-  struct PeerData *peer;
-
-  /**
-   * Timeout for peer startup
-   */
-  struct GNUNET_TIME_Relative timeout;
-
-  /**
-   * Client callback for hostkey notification
-   */
-  GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback;
-
-  /**
-   * Closure for hostkey_callback
-   */
-  void *hostkey_cls;
-
-  /**
-   * Client callback for peer start notification
-   */
-  GNUNET_TESTING_NotifyDaemonRunning start_cb;
-
-  /**
-   * Closure for cb
-   */
-  void *start_cb_cls;
-
-  /**
-   * Hostname, where to start the peer
-   */
-  const char *hostname;
-
-  /**
-   * Username to use when connecting to the
-   * host via ssh.
-   */
-  const char *username;
-
-  /**
-   * Pointer to starting memory location of a hostkey
-   */
-  const char *hostkey;
-
-  /**
-   * Port to use for ssh.
-   */
-  uint16_t sshport;
-
-};
-
-struct ChurnRestartContext
-{
-  /**
-   * PeerGroup that we are working with.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * Number of restarts currently in flight.
-   */
-  unsigned int outstanding;
-
-  /**
-   * Handle to the underlying churn context.
-   */
-  struct ChurnContext *churn_ctx;
-
-  /**
-   * How long to allow the operation to take.
-   */
-  struct GNUNET_TIME_Relative timeout;
-};
-
-struct OutstandingSSH
-{
-  struct OutstandingSSH *next;
-
-  struct OutstandingSSH *prev;
-
-  /**
-   * Number of current ssh connections.
-   */
-  uint32_t outstanding;
-
-  /**
-   * The hostname of this peer.
-   */
-  const char *hostname;
-};
-
-/**
- * Data we keep per peer.
- */
-struct PeerData
-{
-  /**
-   * (Initial) configuration of the host.
-   * (initial because clients could change
-   *  it and we would not know about those
-   *  updates).
-   */
-  struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  /**
-   * Handle for controlling the daemon.
-   */
-  struct GNUNET_TESTING_Daemon *daemon;
-
-  /**
-   * The peergroup this peer belongs to.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-#if OLD
-  /**
-   * Linked list of allowed peer connections.
-   */
-  struct PeerConnection *allowed_peers_head;
-
-  /**
-   * Linked list of allowed peer connections.
-   */
-  struct PeerConnection *allowed_peers_tail;
-
-  /**
-   * Linked list of blacklisted peer connections.
-   */
-  struct PeerConnection *blacklisted_peers_head;
-
-  /**
-   * Linked list of blacklisted peer connections.
-   */
-  struct PeerConnection *blacklisted_peers_tail;
-
-  /**
-   * Linked list of connect peer connections.
-   */
-  struct PeerConnection *connect_peers_head;
-
-  /**
-   * Linked list of connect peer connections.
-   */
-  struct PeerConnection *connect_peers_tail;
-
-  /**
-   * Linked list of connect peer connections.
-   */
-  struct PeerConnection *connect_peers_working_set_head;
-
-  /**
-   * Linked list of connect peer connections.
-   */
-  struct PeerConnection *connect_peers_working_set_tail;
-
-#else
-  /**
-   * Hash map of allowed peer connections (F2F created topology)
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *allowed_peers;
-
-  /**
-   * Hash map of blacklisted peers
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers;
-
-  /**
-   * Hash map of peer connections
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *connect_peers;
-
-  /**
-   * Temporary hash map of peer connections
-   */
-  struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set;
-#endif
-
-  /**
-   * Temporary variable for topology creation, should be reset before
-   * creating any topology so the count is valid once finished.
-   */
-  int num_connections;
-
-  /**
-   * Context to keep track of peers being started, to
-   * stagger hostkey generation and peer startup.
-   */
-  struct InternalStartContext internal_context;
-
-  /**
-   * Task ID for the queued internal_continue_startup task
-   */
-  GNUNET_SCHEDULER_TaskIdentifier startup_task;
-
-};
-
-/**
- * Linked list of per-host data.
- */
-struct HostData
-{
-  /**
-   * Name of the host.
-   */
-  char *hostname;
-
-  /**
-   * SSH username to use when connecting to this host.
-   */
-  char *username;
-
-  /**
-   * SSH port to use when connecting to this host.
-   */
-  uint16_t sshport;
-
-  /**
-   * Lowest port that we have not yet used
-   * for GNUnet.
-   */
-  uint16_t minport;
-};
-
-struct TopologyIterateContext
-{
-  /**
-   * The peergroup we are working with.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * Callback for notifying of two connected peers.
-   */
-  GNUNET_TESTING_NotifyTopology topology_cb;
-
-  /**
-   * Closure for topology_cb
-   */
-  void *cls;
-
-  /**
-   * Number of peers currently connected to.
-   */
-  unsigned int connected;
-
-  /**
-   * Number of peers we have finished iterating.
-   */
-  unsigned int completed;
-
-  /**
-   * Number of peers total.
-   */
-  unsigned int total;
-};
-
-struct StatsIterateContext
-{
-  /**
-   * The peergroup that we are dealing with.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * Continuation to call once all stats information has been retrieved.
-   */
-  GNUNET_STATISTICS_Callback cont;
-
-  /**
-   * Proc function to call on each value received.
-   */
-  GNUNET_TESTING_STATISTICS_Iterator proc;
-
-  /**
-   * Closure for topology_cb
-   */
-  void *cls;
-
-  /**
-   * Number of peers currently connected to.
-   */
-  unsigned int connected;
-
-  /**
-   * Number of peers we have finished iterating.
-   */
-  unsigned int completed;
-
-  /**
-   * Number of peers total.
-   */
-  unsigned int total;
-};
-
-struct CoreContext
-{
-  void *iter_context;
-  struct GNUNET_TESTING_Daemon *daemon;
-};
-
-struct StatsCoreContext
-{
-  void *iter_context;
-  struct GNUNET_TESTING_Daemon *daemon;
-  /**
-   * Handle to the statistics service.
-   */
-  struct GNUNET_STATISTICS_Handle *stats_handle;
-
-  /**
-   * Handle for getting statistics.
-   */
-  struct GNUNET_STATISTICS_GetHandle *stats_get_handle;
-};
-
-struct ConnectTopologyContext
-{
-  /**
-   * How many connections are left to create.
-   */
-  unsigned int remaining_connections;
-
-  /**
-   * Handle to group of peers.
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * How long to try this connection before timing out.
-   */
-  struct GNUNET_TIME_Relative connect_timeout;
-
-  /**
-   * How many times to retry connecting the two peers.
-   */
-  unsigned int connect_attempts;
-
-  /**
-   * Temp value set for each iteration.
-   */
-  //struct PeerData *first;
-
-  /**
-   * Notification that all peers are connected.
-   */
-  GNUNET_TESTING_NotifyCompletion notify_connections_done;
-
-  /**
-   * Closure for notify.
-   */
-  void *notify_cls;
-};
-
-struct ConnectContext;
-
-/**
- * Handle to a group of GNUnet peers.
- */
-struct GNUNET_TESTING_PeerGroup
-{
-  /**
-   * Configuration template.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-
-  struct ConnectContext *cc_head;
-
-  struct ConnectContext *cc_tail;
-
-  /**
-   * Function to call on each started daemon.
-   */
-  //GNUNET_TESTING_NotifyDaemonRunning cb;
-
-  /**
-   * Closure for cb.
-   */
-  //void *cb_cls;
-
-  /*
-   * Function to call on each topology connection created
-   */
-  GNUNET_TESTING_NotifyConnection notify_connection;
-
-  /*
-   * Callback for notify_connection
-   */
-  void *notify_connection_cls;
-
-  /**
-   * Array of information about hosts.
-   */
-  struct HostData *hosts;
-
-  /**
-   * Number of hosts (size of HostData)
-   */
-  unsigned int num_hosts;
-
-  /**
-   * Array of "total" peers.
-   */
-  struct PeerData *peers;
-
-  /**
-   * Number of peers in this group.
-   */
-  unsigned int total;
-
-  /**
-   * At what time should we fail the peer startup process?
-   */
-  struct GNUNET_TIME_Absolute max_timeout;
-
-  /**
-   * How many peers are being started right now?
-   */
-  unsigned int starting;
-
-  /**
-   * How many peers have already been started?
-   */
-  unsigned int started;
-
-  /**
-   * Number of possible connections to peers
-   * at a time.
-   */
-  unsigned int max_outstanding_connections;
-
-  /**
-   * Number of ssh connections to peers (max).
-   */
-  unsigned int max_concurrent_ssh;
-
-  /**
-   * Number of connects we are waiting on, allows us to rate limit
-   * connect attempts.
-   */
-  unsigned int outstanding_connects;
-
-  /**
-   * Number of HELLOs we have yet to send.
-   */
-  unsigned int remaining_hellos;
-
-  /**
-   * How many connects have already been scheduled?
-   */
-  unsigned int total_connects_scheduled;
-
-  /**
-   * Hostkeys loaded from a file.
-   */
-  char *hostkey_data;
-
-  /**
-   * Head of DLL to keep track of the number of outstanding
-   * ssh connections per peer.
-   */
-  struct OutstandingSSH *ssh_head;
-
-  /**
-   * Tail of DLL to keep track of the number of outstanding
-   * ssh connections per peer.
-   */
-  struct OutstandingSSH *ssh_tail;
-
-  /**
-   * Stop scheduling peers connecting.
-   */
-  unsigned int stop_connects;
-
-  /**
-   * Connection context for peer group.
-   */
-  struct ConnectTopologyContext ct_ctx;
-};
-
-struct UpdateContext
-{
-  /**
-   * The altered configuration.
-   */
-  struct GNUNET_CONFIGURATION_Handle *ret;
-
-  /**
-   * The original configuration to alter.
-   */
-  const struct GNUNET_CONFIGURATION_Handle *orig;
-
-  /**
-   * The hostname that this peer will run on.
-   */
-  const char *hostname;
-
-  /**
-   * The next possible port to assign.
-   */
-  unsigned int nport;
-
-  /**
-   * Unique number for unix domain sockets.
-   */
-  unsigned int upnum;
-
-  /**
-   * Unique number for this peer/host to offset
-   * things that are grouped by host.
-   */
-  unsigned int fdnum;
-};
-
-struct ConnectContext
-{
-
-  struct ConnectContext *next;
-
-  struct ConnectContext *prev;
-
-  /**
-   * Index of peer to connect second to.
-   */
-  uint32_t first_index;
-
-  /**
-   * Index of peer to connect first to.
-   */
-  uint32_t second_index;
-
-  /**
-   * Task associated with the attempt to connect.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier task;
-
-  /**
-   * Context in 'testing.c', to cancel connection attempt.
-   */
-  struct GNUNET_TESTING_ConnectContext *cc;
-
-  /**
-   * Higher level topology connection context.
-   */
-  struct ConnectTopologyContext *ct_ctx;
-
-  /**
-   * Whether this connection has been accounted for in the schedule_connect call.
-   */
-  int counted;
-};
-
-struct UnblacklistContext
-{
-  /**
-   * The peergroup
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * uid of the first peer
-   */
-  uint32_t first_uid;
-};
-
-struct RandomContext
-{
-  /**
-   * The peergroup
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * uid of the first peer
-   */
-  uint32_t first_uid;
-
-  /**
-   * Peer data for first peer.
-   */
-  struct PeerData *first;
-
-  /**
-   * Random percentage to use
-   */
-  double percentage;
-};
-
-struct MinimumContext
-{
-  /**
-   * The peergroup
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * uid of the first peer
-   */
-  uint32_t first_uid;
-
-  /**
-   * Peer data for first peer.
-   */
-  struct PeerData *first;
-
-  /**
-   * Number of conns per peer
-   */
-  unsigned int num_to_add;
-
-  /**
-   * Permuted array of all possible connections.  Only add the Nth
-   * peer if it's in the Nth position.
-   */
-  unsigned int *pg_array;
-
-  /**
-   * What number is the current element we are iterating over?
-   */
-  unsigned int current;
-};
-
-struct DFSContext
-{
-  /**
-   * The peergroup
-   */
-  struct GNUNET_TESTING_PeerGroup *pg;
-
-  /**
-   * uid of the first peer
-   */
-  uint32_t first_uid;
-
-  /**
-   * uid of the second peer
-   */
-  uint32_t second_uid;
-
-  /**
-   * Peer data for first peer.
-   */
-  struct PeerData *first;
-
-  /**
-   * Which peer has been chosen as the one to add?
-   */
-  unsigned int chosen;
-
-  /**
-   * What number is the current element we are iterating over?
-   */
-  unsigned int current;
-};
-
-/**
- * Simple struct to keep track of progress, and print a
- * nice little percentage meter for long running tasks.
- */
-struct ProgressMeter
-{
-  unsigned int total;
-
-  unsigned int modnum;
-
-  unsigned int dotnum;
-
-  unsigned int completed;
-
-  int print;
-
-  char *startup_string;
-};
-
-#if !OLD
-/**
- * Convert unique ID to hash code.
- *
- * @param uid unique ID to convert
- * @param hash set to uid (extended with zeros)
- */
-static void
-hash_from_uid (uint32_t uid, GNUNET_HashCode * hash)
-{
-  memset (hash, 0, sizeof (GNUNET_HashCode));
-  *((uint32_t *) hash) = uid;
-}
-
-/**
- * Convert hash code to unique ID.
- *
- * @param uid unique ID to convert
- * @param hash set to uid (extended with zeros)
- */
-static void
-uid_from_hash (const GNUNET_HashCode * hash, uint32_t * uid)
-{
-  memcpy (uid, hash, sizeof (uint32_t));
-}
-#endif
-
-#if USE_SEND_HELLOS
-static struct GNUNET_CORE_MessageHandler no_handlers[] = {
-  {NULL, 0, 0}
-};
-#endif
-
-/**
- * Create a meter to keep track of the progress of some task.
- *
- * @param total the total number of items to complete
- * @param start_string a string to prefix the meter with (if printing)
- * @param print GNUNET_YES to print the meter, GNUNET_NO to count
- *              internally only
- *
- * @return the progress meter
- */
-static struct ProgressMeter *
-create_meter (unsigned int total, char *start_string, int print)
-{
-  struct ProgressMeter *ret;
-
-  ret = GNUNET_malloc (sizeof (struct ProgressMeter));
-  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);
-  else
-    ret->startup_string = GNUNET_strdup ("");
-
-  return ret;
-}
-
-/**
- * Update progress meter (increment by one).
- *
- * @param meter the meter to update and print info for
- *
- * @return GNUNET_YES if called the total requested,
- *         GNUNET_NO if more items expected
- */
-static int
-update_meter (struct ProgressMeter *meter)
-{
-  if (meter->print == GNUNET_YES)
-  {
-    if (meter->completed % meter->modnum == 0)
-    {
-      if (meter->completed == 0)
-      {
-        FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string);
-      }
-      else
-        FPRINTF (stdout, "%d%%",
-                 (int) (((float) meter->completed / meter->total) * 100));
-    }
-    else if (meter->completed % meter->dotnum == 0)
-      FPRINTF (stdout, "%s",  ".");
-
-    if (meter->completed + 1 == meter->total)
-      FPRINTF (stdout, "%d%%]\n", 100);
-    fflush (stdout);
-  }
-  meter->completed++;
-
-  if (meter->completed == meter->total)
-    return GNUNET_YES;
-  if (meter->completed > meter->total)
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n");
-  return GNUNET_NO;
-}
-
-/**
- * Reset progress meter.
- *
- * @param meter the meter to reset
- *
- * @return GNUNET_YES if meter reset,
- *         GNUNET_SYSERR on error
- */
-static int
-reset_meter (struct ProgressMeter *meter)
-{
-  if (meter == NULL)
-    return GNUNET_SYSERR;
-
-  meter->completed = 0;
-  return GNUNET_YES;
-}
-
-/**
- * Release resources for meter
- *
- * @param meter the meter to free
- */
-static void
-free_meter (struct ProgressMeter *meter)
-{
-  GNUNET_free_non_null (meter->startup_string);
-  GNUNET_free (meter);
-}
-
-/**
- * Get a topology from a string input.
- *
- * @param topology where to write the retrieved topology
- * @param topology_string The string to attempt to
- *        get a configuration value from
- * @return GNUNET_YES if topology string matched a
- *         known topology, GNUNET_NO if not
- */
-int
-GNUNET_TESTING_topology_get (enum GNUNET_TESTING_Topology *topology,
-                             const char *topology_string)
-{
-  /**
-   * Strings representing topologies in enum
-   */
-  static const char *topology_strings[] = {
-    /**
-     * A clique (everyone connected to everyone else).
-     */
-    "CLIQUE",
-
-    /**
-     * Small-world network (2d torus plus random links).
-     */
-    "SMALL_WORLD",
-
-    /**
-     * Small-world network (ring plus random links).
-     */
-    "SMALL_WORLD_RING",
-
-    /**
-     * Ring topology.
-     */
-    "RING",
-
-    /**
-     * 2-d torus.
-     */
-    "2D_TORUS",
-
-    /**
-     * Random graph.
-     */
-    "ERDOS_RENYI",
-
-    /**
-     * Certain percentage of peers are unable to communicate directly
-     * replicating NAT conditions
-     */
-    "INTERNAT",
-
-    /**
-     * Scale free topology.
-     */
-    "SCALE_FREE",
-
-    /**
-     * Straight line topology.
-     */
-    "LINE",
-
-    /**
-     * All peers are disconnected.
-     */
-    "NONE",
-
-    /**
-     * Read the topology from a file.
-     */
-    "FROM_FILE",
-
-    NULL
-  };
-
-  int curr = 0;
-
-  if (topology_string == NULL)
-    return GNUNET_NO;
-  while (topology_strings[curr] != NULL)
-  {
-    if (strcasecmp (topology_strings[curr], topology_string) == 0)
-    {
-      *topology = curr;
-      return GNUNET_YES;
-    }
-    curr++;
-  }
-  *topology = GNUNET_TESTING_TOPOLOGY_NONE;
-  return GNUNET_NO;
-}
-
-/**
- * Get connect topology option from string input.
- *
- * @param topology_option where to write the retrieved topology
- * @param topology_string The string to attempt to
- *        get a configuration value from
- * @return GNUNET_YES if string matched a known
- *         topology option, GNUNET_NO if not
- */
-int
-GNUNET_TESTING_topology_option_get (enum GNUNET_TESTING_TopologyOption
-                                    *topology_option,
-                                    const char *topology_string)
-{
-  /**
-   * Options for connecting a topology as strings.
-   */
-  static const char *topology_option_strings[] = {
-    /**
-     * Try to connect all peers specified in the topology.
-     */
-    "CONNECT_ALL",
-
-    /**
-     * Choose a random subset of connections to create.
-     */
-    "CONNECT_RANDOM_SUBSET",
-
-    /**
-     * Create at least X connections for each peer.
-     */
-    "CONNECT_MINIMUM",
-
-    /**
-     * Using a depth first search, create one connection
-     * per peer.  If any are missed (graph disconnected)
-     * start over at those peers until all have at least one
-     * connection.
-     */
-    "CONNECT_DFS",
-
-    /**
-     * Find the N closest peers to each allowed peer in the
-     * topology and make sure a connection to those peers
-     * exists in the connect topology.
-     */
-    "CONNECT_CLOSEST",
-
-    /**
-     * No options specified.
-     */
-    "CONNECT_NONE",
-
-    NULL
-  };
-  int curr = 0;
-
-  if (topology_string == NULL)
-    return GNUNET_NO;
-  while (NULL != topology_option_strings[curr])
-  {
-    if (strcasecmp (topology_option_strings[curr], topology_string) == 0)
-    {
-      *topology_option = curr;
-      return GNUNET_YES;
-    }
-    curr++;
-  }
-  *topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_NONE;
-  return GNUNET_NO;
-}
-
-/**
- * Function to iterate over options.  Copies
- * the options to the target configuration,
- * updating PORT values as needed.
- *
- * @param cls closure
- * @param section name of the section
- * @param option name of the option
- * @param value value of the option
- */
-static void
-update_config (void *cls, const char *section, const char *option,
-               const char *value)
-{
-  struct UpdateContext *ctx = cls;
-  unsigned int ival;
-  char cval[12];
-  char uval[128];
-  char *single_variable;
-  char *per_host_variable;
-  unsigned long long num_per_host;
-
-  GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
-  GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
-
-  if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
-  {
-    if ((ival != 0) &&
-        (GNUNET_YES !=
-         GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
-                                               single_variable)))
-    {
-      GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
-      value = cval;
-    }
-    else if ((ival != 0) &&
-             (GNUNET_YES ==
-              GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
-                                                    single_variable)) &&
-             GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing",
-                                                    per_host_variable,
-                                                    &num_per_host))
-    {
-      GNUNET_snprintf (cval, sizeof (cval), "%u",
-                       ival + ctx->fdnum % num_per_host);
-      value = cval;
-    }
-
-    /* FIXME: REMOVE FOREVER HACK HACK HACK */
-    if (0 == strcasecmp (section, "transport-tcp"))
-      GNUNET_CONFIGURATION_set_value_string (ctx->ret, section,
-                                             "ADVERTISED_PORT", value);
-  }
-
-  if (0 == strcmp (option, "UNIXPATH"))
-  {
-    if (GNUNET_YES !=
-        GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing",
-                                              single_variable))
-    {
-      GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section,
-                       ctx->upnum++);
-      value = uval;
-    }
-    else if ((GNUNET_YES ==
-              GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing",
-                                                     per_host_variable,
-                                                     &num_per_host)) &&
-             (num_per_host > 0))
-
-    {
-      GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section,
-                       ctx->fdnum % num_per_host);
-      value = uval;
-    }
-  }
-
-  if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL))
-  {
-    value = ctx->hostname;
-  }
-  GNUNET_free (single_variable);
-  GNUNET_free (per_host_variable);
-  GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value);
-}
-
-/**
- * Create a new configuration using the given configuration
- * as a template; however, each PORT in the existing cfg
- * must be renumbered by incrementing "*port".  If we run
- * out of "*port" numbers, return NULL.
- *
- * @param cfg template configuration
- * @param off the current peer offset
- * @param port port numbers to use, update to reflect
- *             port numbers that were used
- * @param upnum number to make unix domain socket names unique
- * @param hostname hostname of the controlling host, to allow control connections from
- * @param fdnum number used to offset the unix domain socket for grouped processes
- *              (such as statistics or peerinfo, which can be shared among others)
- *
- * @return new configuration, NULL on error
- */
-struct GNUNET_CONFIGURATION_Handle *
-GNUNET_TESTING_create_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t off,
-             uint16_t * port, uint32_t * upnum, const char *hostname,
-             uint32_t * fdnum)
-{
-  struct UpdateContext uc;
-  uint16_t orig;
-  char *control_host;
-  char *allowed_hosts;
-  unsigned long long skew_variance;
-  unsigned long long skew_offset;
-  long long actual_offset;
-
-  orig = *port;
-  uc.nport = *port;
-  uc.upnum = *upnum;
-  uc.fdnum = *fdnum;
-  uc.ret = GNUNET_CONFIGURATION_create ();
-  uc.hostname = hostname;
-  uc.orig = cfg;
-
-  GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
-  if (uc.nport >= HIGH_PORT)
-  {
-    *port = orig;
-    GNUNET_CONFIGURATION_destroy (uc.ret);
-    return NULL;
-  }
-
-  if ((GNUNET_OK ==
-       GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "skew_variance",
-                                              &skew_variance)) &&
-      (skew_variance > 0))
-  {
-    skew_offset =
-        GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                  skew_variance + 1);
-    actual_offset =
-        skew_offset - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                                skew_variance + 1);
-    /* Min is -skew_variance, Max is skew_variance */
-    skew_offset = skew_variance + actual_offset;        /* Normal distribution around 0 */
-    GNUNET_CONFIGURATION_set_value_number (uc.ret, "testing", "skew_offset",
-                                           skew_offset);
-  }
-
-  if (GNUNET_CONFIGURATION_get_value_string
-      (cfg, "testing", "control_host", &control_host) == GNUNET_OK)
-  {
-    if (hostname != NULL)
-      GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1; %s;", control_host,
-                       hostname);
-    else
-      GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", control_host);
-
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "ACCEPT_FROM",
-                                           allowed_hosts);
-
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "ACCEPT_FROM",
-                                           allowed_hosts);
-
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "ACCEPT_FROM",
-                                           allowed_hosts);
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "ACCEPT_FROM",
-                                           allowed_hosts);
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "ACCEPT_FROM",
-                                           allowed_hosts);
-
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "UNIXPATH", "");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "UNIXPATH", "");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "UNIXPATH", "");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "UNIXPATH",
-                                           "");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "UNIXPATH", "");
-
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat",
-                                           "USE_LOCALADDR", "YES");
-    GNUNET_free_non_null (control_host);
-    GNUNET_free (allowed_hosts);
-  }
-
-  /* arm needs to know to allow connections from the host on which it is running,
-   * otherwise gnunet-arm is unable to connect to it in some instances */
-  if (hostname != NULL)
-  {
-    GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", hostname);
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO", hostname);
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS",
-                                           hostname);
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS",
-                                           hostname);
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "disablev6", "BINDTO",
-                                           "YES");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-tcp",
-                                           "USE_LOCALADDR", "YES");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-udp",
-                                           "USE_LOCALADDR", "YES");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "arm", "ACCEPT_FROM",
-                                           allowed_hosts);
-    GNUNET_free (allowed_hosts);
-  }
-  else
-  {
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat",
-                                           "USE_LOCALADDR", "YES");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO",
-                                           "127.0.0.1");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS",
-                                           "127.0.0.1");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS",
-                                           "127.0.0.1");
-    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "disablev6",
-                                           "YES");
-  }
-
-  *port = (uint16_t) uc.nport;
-  *upnum = uc.upnum;
-  uc.fdnum++;
-  *fdnum = uc.fdnum;
-  return uc.ret;
-}
-
-/*
- * Remove entries from the peer connection list
- *
- * @param pg the peer group we are working with
- * @param first index of the first peer
- * @param second index of the second peer
- * @param list the peer list to use
- * @param check UNUSED
- *
- * @return the number of connections added (can be 0, 1 or 2)
- *
- */
-static unsigned int
-remove_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
-                    unsigned int second, enum PeerLists list,
-                    unsigned int check)
-{
-  int removed;
-
-#if OLD
-  struct PeerConnection **first_list;
-  struct PeerConnection **second_list;
-  struct PeerConnection *first_iter;
-  struct PeerConnection *second_iter;
-  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
-
-  removed = 0;
-#if OLD
-  switch (list)
-  {
-  case ALLOWED:
-    first_list = &pg->peers[first].allowed_peers_head;
-    second_list = &pg->peers[second].allowed_peers_head;
-    first_tail = &pg->peers[first].allowed_peers_tail;
-    second_tail = &pg->peers[second].allowed_peers_tail;
-    break;
-  case CONNECT:
-    first_list = &pg->peers[first].connect_peers_head;
-    second_list = &pg->peers[second].connect_peers_head;
-    first_tail = &pg->peers[first].connect_peers_tail;
-    second_tail = &pg->peers[second].connect_peers_tail;
-    break;
-  case BLACKLIST:
-    first_list = &pg->peers[first].blacklisted_peers_head;
-    second_list = &pg->peers[second].blacklisted_peers_head;
-    first_tail = &pg->peers[first].blacklisted_peers_tail;
-    second_tail = &pg->peers[second].blacklisted_peers_tail;
-    break;
-  case WORKING_SET:
-    first_list = &pg->peers[first].connect_peers_working_set_head;
-    second_list = &pg->peers[second].connect_peers_working_set_head;
-    first_tail = &pg->peers[first].connect_peers_working_set_tail;
-    second_tail = &pg->peers[second].connect_peers_working_set_tail;
-    break;
-  default:
-    GNUNET_break (0);
-    return 0;
-  }
-
-  first_iter = *first_list;
-  while (first_iter != NULL)
-  {
-    if (first_iter->index == second)
-    {
-      GNUNET_CONTAINER_DLL_remove (*first_list, *first_tail, first_iter);
-      GNUNET_free (first_iter);
-      removed++;
-      break;
-    }
-    first_iter = first_iter->next;
-  }
-
-  second_iter = *second_list;
-  while (second_iter != NULL)
-  {
-    if (second_iter->index == first)
-    {
-      GNUNET_CONTAINER_DLL_remove (*second_list, *second_tail, second_iter);
-      GNUNET_free (second_iter);
-      removed++;
-      break;
-    }
-    second_iter = second_iter->next;
-  }
-#else
-  if (GNUNET_YES ==
-      GNUNET_CONTAINER_multihashmap_contains (pg->
-                                              peers[first].blacklisted_peers,
-                                              &hash_second))
-  {
-    GNUNET_CONTAINER_multihashmap_remove_all (pg->
-                                              peers[first].blacklisted_peers,
-                                              &hash_second);
-  }
-
-  if (GNUNET_YES ==
-      GNUNET_CONTAINER_multihashmap_contains (pg->
-                                              peers[second].blacklisted_peers,
-                                              &hash_first))
-  {
-    GNUNET_CONTAINER_multihashmap_remove_all (pg->
-                                              peers[second].blacklisted_peers,
-                                              &hash_first);
-  }
-#endif
-
-  return removed;
-}
-
-/**
- * Add entries to the some list
- *
- * @param pg the peer group we are working with
- * @param first index of the first peer
- * @param second index of the second peer
- * @param list the list type that we should modify
- * @param check GNUNET_YES to check lists before adding
- *              GNUNET_NO to force add
- *
- * @return the number of connections added (can be 0, 1 or 2)
- *
- */
-static unsigned int
-add_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
-                 unsigned int second, enum PeerLists list, unsigned int check)
-{
-  int added;
-  int add_first;
-  int add_second;
-
-  struct PeerConnection **first_list;
-  struct PeerConnection **second_list;
-  struct PeerConnection *first_iter;
-  struct PeerConnection *second_iter;
-  struct PeerConnection *new_first;
-  struct PeerConnection *new_second;
-  struct PeerConnection **first_tail;
-  struct PeerConnection **second_tail;
-
-  switch (list)
-  {
-  case ALLOWED:
-    first_list = &pg->peers[first].allowed_peers_head;
-    second_list = &pg->peers[second].allowed_peers_head;
-    first_tail = &pg->peers[first].allowed_peers_tail;
-    second_tail = &pg->peers[second].allowed_peers_tail;
-    break;
-  case CONNECT:
-    first_list = &pg->peers[first].connect_peers_head;
-    second_list = &pg->peers[second].connect_peers_head;
-    first_tail = &pg->peers[first].connect_peers_tail;
-    second_tail = &pg->peers[second].connect_peers_tail;
-    break;
-  case BLACKLIST:
-    first_list = &pg->peers[first].blacklisted_peers_head;
-    second_list = &pg->peers[second].blacklisted_peers_head;
-    first_tail = &pg->peers[first].blacklisted_peers_tail;
-    second_tail = &pg->peers[second].blacklisted_peers_tail;
-    break;
-  case WORKING_SET:
-    first_list = &pg->peers[first].connect_peers_working_set_head;
-    second_list = &pg->peers[second].connect_peers_working_set_head;
-    first_tail = &pg->peers[first].connect_peers_working_set_tail;
-    second_tail = &pg->peers[second].connect_peers_working_set_tail;
-    break;
-  default:
-    GNUNET_break (0);
-    return 0;
-  }
-
-  add_first = GNUNET_YES;
-  add_second = GNUNET_YES;
-
-  if (check == GNUNET_YES)
-  {
-    first_iter = *first_list;
-    while (first_iter != NULL)
-    {
-      if (first_iter->index == second)
-      {
-        add_first = GNUNET_NO;
-        break;
-      }
-      first_iter = first_iter->next;
-    }
-
-    second_iter = *second_list;
-    while (second_iter != NULL)
-    {
-      if (second_iter->index == first)
-      {
-        add_second = GNUNET_NO;
-        break;
-      }
-      second_iter = second_iter->next;
-    }
-  }
-
-  added = 0;
-  if (add_first)
-  {
-    new_first = GNUNET_malloc (sizeof (struct PeerConnection));
-    new_first->index = second;
-    GNUNET_CONTAINER_DLL_insert (*first_list, *first_tail, new_first);
-    pg->peers[first].num_connections++;
-    added++;
-  }
-
-  if (add_second)
-  {
-    new_second = GNUNET_malloc (sizeof (struct PeerConnection));
-    new_second->index = first;
-    GNUNET_CONTAINER_DLL_insert (*second_list, *second_tail, new_second);
-    pg->peers[second].num_connections++;
-    added++;
-  }
-
-  return added;
-}
-
-/**
- * Scale free network construction as described in:
- *
- * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
- *
- * Start with a network of "one" peer, then progressively add
- * peers up to the total number.  At each step, iterate over
- * all possible peers and connect new peer based on number of
- * existing connections of the target peer.
- *
- * @param pg the peer group we are dealing with
- * @param proc the connection processor to use
- * @param list the peer list to use
- *
- * @return the number of connections created
- */
-static unsigned int
-create_scale_free (struct GNUNET_TESTING_PeerGroup *pg,
-                   GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
-{
-
-  unsigned int total_connections;
-  unsigned int outer_count;
-  unsigned int i;
-  unsigned int previous_total_connections;
-  double random;
-  double probability;
-
-  GNUNET_assert (pg->total > 1);
-
-  /* Add a connection between the first two nodes */
-  total_connections = proc (pg, 0, 1, list, GNUNET_YES);
-
-  for (outer_count = 1; outer_count < pg->total; outer_count++)
-  {
-    previous_total_connections = total_connections;
-    for (i = 0; i < outer_count; i++)
-    {
-      probability =
-          pg->peers[i].num_connections / (double) previous_total_connections;
-      random =
-          ((double)
-           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                     UINT64_MAX)) / ((double) UINT64_MAX);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Considering connecting peer %d to peer %d\n", outer_count,
-                  i);
-      if (random < probability)
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
-                    outer_count, i);
-        total_connections += proc (pg, outer_count, i, list, GNUNET_YES);
-      }
-    }
-  }
-
-  return total_connections;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.  Creates a small world topology
- * according to the rewired ring construction.  The basic
- * behavior is that a ring topology is created, but with some
- * probability instead of connecting a peer to the next
- * neighbor in the ring a connection will be created to a peer
- * selected uniformly at random.   We use the TESTING
- * PERCENTAGE option to specify what number of
- * connections each peer should have.  Default is 2,
- * which makes the ring, any given number is multiplied by
- * the log of the network size; i.e. a PERCENTAGE of 2 makes
- * each peer have on average 2logn connections.  The additional
- * connections are made at increasing distance around the ring
- * from the original peer, or to random peers based on the re-
- * wiring probability. The TESTING
- * PROBABILITY option is used as the probability that a given
- * connection is rewired.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_small_world_ring (struct GNUNET_TESTING_PeerGroup *pg,
-                         GNUNET_TESTING_ConnectionProcessor proc,
-                         enum PeerLists list)
-{
-  unsigned int i, j;
-  int nodeToConnect;
-  unsigned int natLog;
-  unsigned int randomPeer;
-  double random, logNModifier, probability;
-  unsigned int smallWorldConnections;
-  int connsPerPeer;
-  char *p_string;
-  int max;
-  int min;
-  unsigned int useAnd;
-  int connect_attempts;
-
-  logNModifier = 0.5;           /* FIXME: default value? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &logNModifier) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "LOGNMODIFIER", "TESTING");
-    GNUNET_free (p_string);
-  }
-  probability = 0.5;            /* FIXME: default percentage? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PROBABILITY",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &probability) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "PERCENTAGE", "TESTING");
-    GNUNET_free (p_string);
-  }
-  natLog = log (pg->total);
-  connsPerPeer = ceil (natLog * logNModifier);
-
-  if (connsPerPeer % 2 == 1)
-    connsPerPeer += 1;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Target is %d connections per peer.",
-              connsPerPeer);
-
-  smallWorldConnections = 0;
-  connect_attempts = 0;
-  for (i = 0; i < pg->total; i++)
-  {
-    useAnd = 0;
-    max = i + connsPerPeer / 2;
-    min = i - connsPerPeer / 2;
-
-    if (max > pg->total - 1)
-    {
-      max = max - pg->total;
-      useAnd = 1;
-    }
-
-    if (min < 0)
-    {
-      min = pg->total - 1 + min;
-      useAnd = 1;
-    }
-
-    for (j = 0; j < connsPerPeer / 2; j++)
-    {
-      random =
-          ((double)
-           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                     UINT64_MAX) / ((double) UINT64_MAX));
-      if (random < probability)
-      {
-        /* Connect to uniformly selected random peer */
-        randomPeer =
-            GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
-        while ((((randomPeer < max) && (randomPeer > min)) && (useAnd == 0)) ||
-               (((randomPeer > min) || (randomPeer < max)) && (useAnd == 1)))
-        {
-          randomPeer =
-              GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
-        }
-        smallWorldConnections += proc (pg, i, randomPeer, list, GNUNET_YES);
-      }
-      else
-      {
-        nodeToConnect = i + j + 1;
-        if (nodeToConnect > pg->total - 1)
-        {
-          nodeToConnect = nodeToConnect - pg->total;
-        }
-        connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
-      }
-    }
-
-  }
-
-  connect_attempts += smallWorldConnections;
-
-  return connect_attempts;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg,
-                       GNUNET_TESTING_ConnectionProcessor proc,
-                       enum PeerLists list)
-{
-  unsigned int outer_count, inner_count;
-  unsigned int cutoff;
-  int connect_attempts;
-  double nat_percentage;
-  char *p_string;
-
-  nat_percentage = 0.6;         /* FIXME: default percentage? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &nat_percentage) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "PERCENTAGE", "TESTING");
-    GNUNET_free (p_string);
-  }
-
-  cutoff = (unsigned int) (nat_percentage * pg->total);
-  connect_attempts = 0;
-  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
-  {
-    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
-    {
-      if ((outer_count > cutoff) || (inner_count > cutoff))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
-                    outer_count, inner_count);
-        connect_attempts +=
-            proc (pg, outer_count, inner_count, list, GNUNET_YES);
-      }
-    }
-  }
-  return connect_attempts;
-}
-
-#if TOPOLOGY_HACK
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_nated_internet_copy (struct GNUNET_TESTING_PeerGroup *pg,
-                            GNUNET_TESTING_ConnectionProcessor proc,
-                            enum PeerLists list)
-{
-  unsigned int outer_count, inner_count;
-  unsigned int cutoff;
-  int connect_attempts;
-  double nat_percentage;
-  char *p_string;
-  unsigned int count;
-  struct ProgressMeter *conn_meter;
-
-  nat_percentage = 0.6;         /* FIXME: default percentage? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &nat_percentage) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "PERCENTAGE", "TESTING");
-    GNUNET_free (p_string);
-  }
-
-  cutoff = (unsigned int) (nat_percentage * pg->total);
-  count = 0;
-  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
-  {
-    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
-    {
-      if ((outer_count > cutoff) || (inner_count > cutoff))
-      {
-        count++;
-      }
-    }
-  }
-  conn_meter = create_meter (count, "NAT COPY", GNUNET_YES);
-  connect_attempts = 0;
-  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
-  {
-    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
-    {
-      if ((outer_count > cutoff) || (inner_count > cutoff))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
-                    outer_count, inner_count);
-        connect_attempts +=
-            proc (pg, outer_count, inner_count, list, GNUNET_YES);
-        add_connections (pg, outer_count, inner_count, ALLOWED, GNUNET_NO);
-        update_meter (conn_meter);
-      }
-    }
-  }
-  free_meter (conn_meter);
-
-  return connect_attempts;
-}
-#endif
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_small_world (struct GNUNET_TESTING_PeerGroup *pg,
-                    GNUNET_TESTING_ConnectionProcessor proc,
-                    enum PeerLists list)
-{
-  unsigned int i, j, k;
-  unsigned int square;
-  unsigned int rows;
-  unsigned int cols;
-  unsigned int toggle = 1;
-  unsigned int nodeToConnect;
-  unsigned int natLog;
-  unsigned int node1Row;
-  unsigned int node1Col;
-  unsigned int node2Row;
-  unsigned int node2Col;
-  unsigned int distance;
-  double probability, random, percentage;
-  unsigned int smallWorldConnections;
-  unsigned int small_world_it;
-  char *p_string;
-  int connect_attempts;
-
-  square = floor (sqrt (pg->total));
-  rows = square;
-  cols = square;
-
-  percentage = 0.5;             /* FIXME: default percentage? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PERCENTAGE",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &percentage) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "PERCENTAGE", "TESTING");
-    GNUNET_free (p_string);
-  }
-  if (percentage < 0.0)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _
-                ("Invalid value `%s' for option `%s' in section `%s': got %f, needed value greater than 0\n"),
-                "PERCENTAGE", "TESTING", percentage);
-    percentage = 0.5;
-  }
-  probability = 0.5;            /* FIXME: default percentage? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PROBABILITY",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &probability) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "PROBABILITY", "TESTING");
-    GNUNET_free (p_string);
-  }
-  if (square * square != pg->total)
-  {
-    while (rows * cols < pg->total)
-    {
-      if (toggle % 2 == 0)
-        rows++;
-      else
-        cols++;
-
-      toggle++;
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting nodes in 2d torus topology: %u rows %u columns\n",
-              rows, cols);
-  connect_attempts = 0;
-  /* Rows and columns are all sorted out, now iterate over all nodes and connect each
-   * to the node to its right and above.  Once this is over, we'll have our torus!
-   * Special case for the last node (if the rows and columns are not equal), connect
-   * to the first in the row to maintain topology.
-   */
-  for (i = 0; i < pg->total; i++)
-  {
-    /* First connect to the node to the right */
-    if (((i + 1) % cols != 0) && (i + 1 != pg->total))
-      nodeToConnect = i + 1;
-    else if (i + 1 == pg->total)
-      nodeToConnect = rows * cols - cols;
-    else
-      nodeToConnect = i - cols + 1;
-
-    connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
-
-    if (i < cols)
-    {
-      nodeToConnect = (rows * cols) - cols + i;
-      if (nodeToConnect >= pg->total)
-        nodeToConnect -= cols;
-    }
-    else
-      nodeToConnect = i - cols;
-
-    if (nodeToConnect < pg->total)
-      connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
-  }
-  natLog = log (pg->total);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "natural log of %d is %d, will run %d iterations\n", pg->total,
-              natLog, (int) (natLog * percentage));
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Total connections added thus far: %u!\n", connect_attempts);
-  smallWorldConnections = 0;
-  small_world_it = (unsigned int) (natLog * percentage);
-  if (small_world_it < 1)
-    small_world_it = 1;
-  GNUNET_assert (small_world_it > 0 && small_world_it < (unsigned int) -1);
-  for (i = 0; i < small_world_it; i++)
-  {
-    for (j = 0; j < pg->total; j++)
-    {
-      /* Determine the row and column of node at position j on the 2d torus */
-      node1Row = j / cols;
-      node1Col = j - (node1Row * cols);
-      for (k = 0; k < pg->total; k++)
-      {
-        /* Determine the row and column of node at position k on the 2d torus */
-        node2Row = k / cols;
-        node2Col = k - (node2Row * cols);
-        /* Simple Cartesian distance */
-        distance = abs (node1Row - node2Row) + abs (node1Col - node2Col);
-        if (distance > 1)
-        {
-          /* Calculate probability as 1 over the square of the distance */
-          probability = 1.0 / (distance * distance);
-          /* Choose a random value between 0 and 1 */
-          random =
-              ((double)
-               GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                         UINT64_MAX)) / ((double) UINT64_MAX);
-          /* If random < probability, then connect the two nodes */
-          if (random < probability)
-            smallWorldConnections += proc (pg, j, k, list, GNUNET_YES);
-
-        }
-      }
-    }
-  }
-  connect_attempts += smallWorldConnections;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Total connections added for small world: %d!\n",
-              smallWorldConnections);
-  return connect_attempts;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg,
-                    GNUNET_TESTING_ConnectionProcessor proc,
-                    enum PeerLists list)
-{
-  double temp_rand;
-  unsigned int outer_count;
-  unsigned int inner_count;
-  int connect_attempts;
-  double probability;
-  char *p_string;
-
-  probability = 0.5;            /* FIXME: default percentage? */
-  if (GNUNET_OK ==
-      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING", "PROBABILITY",
-                                             &p_string))
-  {
-    if (SSCANF (p_string, "%lf", &probability) != 1)
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  p_string, "PROBABILITY", "TESTING");
-    GNUNET_free (p_string);
-  }
-  connect_attempts = 0;
-  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
-  {
-    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
-    {
-      temp_rand =
-          ((double)
-           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                     UINT64_MAX)) / ((double) UINT64_MAX);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "rand is %f probability is %f\n",
-                  temp_rand, probability);
-      if (temp_rand < probability)
-      {
-        connect_attempts +=
-            proc (pg, outer_count, inner_count, list, GNUNET_YES);
-      }
-    }
-  }
-
-  return connect_attempts;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.  This particular function creates
- * the connections for a 2d-torus, plus additional "closest"
- * connections per peer.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg,
-                 GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
-{
-  unsigned int i;
-  unsigned int square;
-  unsigned int rows;
-  unsigned int cols;
-  unsigned int toggle = 1;
-  unsigned int nodeToConnect;
-  int connect_attempts;
-
-  connect_attempts = 0;
-
-  square = floor (sqrt (pg->total));
-  rows = square;
-  cols = square;
-
-  if (square * square != pg->total)
-  {
-    while (rows * cols < pg->total)
-    {
-      if (toggle % 2 == 0)
-        rows++;
-      else
-        cols++;
-
-      toggle++;
-    }
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Connecting nodes in 2d torus topology: %u rows %u columns\n",
-              rows, cols);
-  /* Rows and columns are all sorted out, now iterate over all nodes and connect each
-   * to the node to its right and above.  Once this is over, we'll have our torus!
-   * Special case for the last node (if the rows and columns are not equal), connect
-   * to the first in the row to maintain topology.
-   */
-  for (i = 0; i < pg->total; i++)
-  {
-    /* First connect to the node to the right */
-    if (((i + 1) % cols != 0) && (i + 1 != pg->total))
-      nodeToConnect = i + 1;
-    else if (i + 1 == pg->total)
-      nodeToConnect = rows * cols - cols;
-    else
-      nodeToConnect = i - cols + 1;
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i,
-                nodeToConnect);
-    connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
-
-    /* Second connect to the node immediately above */
-    if (i < cols)
-    {
-      nodeToConnect = (rows * cols) - cols + i;
-      if (nodeToConnect >= pg->total)
-        nodeToConnect -= cols;
-    }
-    else
-      nodeToConnect = i - cols;
-
-    if (nodeToConnect < pg->total)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i,
-                  nodeToConnect);
-      connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
-    }
-
-  }
-
-  return connect_attempts;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- * @param check does the connection processor need to check before
- *              performing an action on the list?
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_clique (struct GNUNET_TESTING_PeerGroup *pg,
-               GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list,
-               unsigned int check)
-{
-  unsigned int outer_count;
-  unsigned int inner_count;
-  int connect_attempts;
-  struct ProgressMeter *conn_meter;
-
-  connect_attempts = 0;
-
-  conn_meter =
-      create_meter ((((pg->total * pg->total) + pg->total) / 2) - 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++)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
-                  outer_count, inner_count);
-      connect_attempts += proc (pg, outer_count, inner_count, list, check);
-      update_meter (conn_meter);
-    }
-  }
-  reset_meter (conn_meter);
-  free_meter (conn_meter);
-  return connect_attempts;
-}
-
-#if !OLD
-/**
- * Iterator over hash map entries.
- *
- * @param cls closure the peer group
- * @param key the key stored in the hashmap is the
- *            index of the peer to connect to
- * @param value value in the hash map, handle to the peer daemon
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-unblacklist_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct UnblacklistContext *un_ctx = cls;
-  uint32_t second_pos;
-
-  uid_from_hash (key, &second_pos);
-
-  unblacklist_connections (un_ctx->pg, un_ctx->first_uid, second_pos);
-
-  return GNUNET_YES;
-}
-#endif
-
-#if !OLD
-/**
- * Create a blacklist topology based on the allowed topology
- * which disallows any connections not in the allowed topology
- * at the transport level.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to allow
- *        up connections between two peers
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-copy_allowed (struct GNUNET_TESTING_PeerGroup *pg,
-              GNUNET_TESTING_ConnectionProcessor proc)
-{
-  unsigned int count;
-  unsigned int total;
-  struct PeerConnection *iter;
-
-#if !OLD
-  struct UnblacklistContext un_ctx;
-
-  un_ctx.pg = pg;
-#endif
-  total = 0;
-  for (count = 0; count < pg->total - 1; count++)
-  {
-#if OLD
-    iter = pg->peers[count].allowed_peers_head;
-    while (iter != NULL)
-    {
-      remove_connections (pg, count, iter->index, BLACKLIST, GNUNET_YES);
-      //unblacklist_connections(pg, count, iter->index);
-      iter = iter->next;
-    }
-#else
-    un_ctx.first_uid = count;
-    total +=
-        GNUNET_CONTAINER_multihashmap_iterate (pg->peers[count].allowed_peers,
-                                               &unblacklist_iterator, &un_ctx);
-#endif
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unblacklisted %u peers\n", total);
-  return total;
-}
-#endif
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list which list should be modified
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_line (struct GNUNET_TESTING_PeerGroup *pg,
-             GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
-{
-  unsigned int count;
-  unsigned int connect_attempts;
-
-  connect_attempts = 0;
-  /* Connect each peer to the next highest numbered peer */
-  for (count = 0; count < pg->total - 1; count++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
-                count, count + 1);
-    connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES);
-  }
-
-  return connect_attempts;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param filename the file to read topology information from
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_from_file (struct GNUNET_TESTING_PeerGroup *pg, char *filename,
-                  GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
-{
-  int connect_attempts;
-  unsigned int first_peer_index;
-  unsigned int second_peer_index;
-  struct stat frstat;
-  int count;
-  char *data;
-  const char *buf;
-  unsigned int total_peers;
-  enum States curr_state;
-
-  connect_attempts = 0;
-  if (GNUNET_OK != GNUNET_DISK_file_test (filename))
-    GNUNET_DISK_fn_write (filename, NULL, 0, GNUNET_DISK_PERM_USER_READ);
-
-  if ((0 != STAT (filename, &frstat)) || (frstat.st_size == 0))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Could not open file `%s' specified for topology!", filename);
-    return connect_attempts;
-  }
-
-  data = GNUNET_malloc_large (frstat.st_size);
-  GNUNET_assert (data != NULL);
-  if (frstat.st_size != GNUNET_DISK_fn_read (filename, data, frstat.st_size))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Could not read file %s specified for host list, ending test!",
-                filename);
-    GNUNET_free (data);
-    return connect_attempts;
-  }
-
-  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;
-  while (count < frstat.st_size - 1)
-  {
-    if ((buf[count] == '\n') || (buf[count] == ' '))
-    {
-      count++;
-      continue;
-    }
-
-    switch (curr_state)
-    {
-    case NUM_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");
-        GNUNET_free (data);
-        return connect_attempts;
-      }
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u total peers in topology\n",
-                  total_peers);
-      GNUNET_assert (total_peers == pg->total);
-      curr_state = PEER_INDEX;
-      while ((buf[count] != '\n') && (count < frstat.st_size - 1))
-        count++;
-      count++;
-      break;
-    case 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");
-        GNUNET_free (data);
-        return connect_attempts;
-      }
-      while ((buf[count] != ':') && (count < frstat.st_size - 1))
-        count++;
-      count++;
-      curr_state = OTHER_PEER_INDEX;
-      break;
-    case COLON:
-      if (1 == sscanf (&buf[count], ":"))
-        curr_state = OTHER_PEER_INDEX;
-      count++;
-      break;
-    case OTHER_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");
-        GNUNET_free (data);
-        return connect_attempts;
-      }
-      /* 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);
-      while ((buf[count] != '\n') && (buf[count] != ',') &&
-             (count < frstat.st_size - 1))
-        count++;
-      if (buf[count] == '\n')
-      {
-        curr_state = PEER_INDEX;
-      }
-      else if (buf[count] != ',')
-      {
-        curr_state = OTHER_PEER_INDEX;
-      }
-      count++;
-      break;
-    default:
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Found bad data in topology file while in state %d!\n",
-                  curr_state);
-      GNUNET_break (0);
-      GNUNET_free (data);
-      return connect_attempts;
-    }
-  }
-  GNUNET_free (data);
-  return connect_attempts;
-}
-
-/**
- * Create a topology given a peer group (set of running peers)
- * and a connection processor.
- *
- * @param pg the peergroup to create the topology on
- * @param proc the connection processor to call to actually set
- *        up connections between two peers
- * @param list the peer list to use
- *
- * @return the number of connections that were set up
- *
- */
-static unsigned int
-create_ring (struct GNUNET_TESTING_PeerGroup *pg,
-             GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
-{
-  unsigned int count;
-  int connect_attempts;
-
-  connect_attempts = 0;
-
-  /* Connect each peer to the next highest numbered peer */
-  for (count = 0; count < pg->total - 1; count++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
-                count, count + 1);
-    connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES);
-  }
-
-  /* Connect the last peer to the first peer */
-  connect_attempts += proc (pg, pg->total - 1, 0, list, GNUNET_YES);
-
-  return connect_attempts;
-}
-
-#if !OLD
-/**
- * Iterator for writing friends of a peer to a file.
- *
- * @param cls closure, an open writable file handle
- * @param key the key the daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that needs to be written.
- *
- * @return GNUNET_YES to continue iteration
- *
- * TODO: Could replace friend_file_iterator and blacklist_file_iterator
- *       with a single file_iterator that takes a closure which contains
- *       the prefix to write before the peer.  Then this could be used
- *       for blacklisting multiple transports and writing the friend
- *       file.  I'm sure *someone* will complain loudly about other
- *       things that negate these functions even existing so no point in
- *       "fixing" now.
- */
-static int
-friend_file_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  FILE *temp_friend_handle = cls;
-  struct GNUNET_TESTING_Daemon *peer = value;
-  struct GNUNET_PeerIdentity *temppeer;
-  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
-
-  temppeer = &peer->id;
-  GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc);
-  FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc);
-
-  return GNUNET_YES;
-}
-
-struct BlacklistContext
-{
-  /*
-   * The (open) file handle to write to
-   */
-  FILE *temp_file_handle;
-
-  /*
-   * The transport that this peer will be blacklisted on.
-   */
-  char *transport;
-};
-
-/**
- * Iterator for writing blacklist data to appropriate files.
- *
- * @param cls closure, an open writable file handle
- * @param key the key the daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that needs to be written.
- *
- * @return GNUNET_YES to continue iteration
- */
-static int
-blacklist_file_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct BlacklistContext *blacklist_ctx = cls;
-  struct GNUNET_TESTING_Daemon *peer = value;
-  struct GNUNET_PeerIdentity *temppeer;
-  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
-
-  temppeer = &peer->id;
-  GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing entry %s:%s to file\n",
-              blacklist_ctx->transport, (char *) &peer_enc);
-  FPRINTF (blacklist_ctx->temp_file_handle, "%s:%s\n", blacklist_ctx->transport,
-           (char *) &peer_enc);
-
-  return GNUNET_YES;
-}
-#endif
-
-/*
- * Create the friend files based on the PeerConnection's
- * of each peer in the peer group, and copy the files
- * to the appropriate place
- *
- * @param pg the peer group we are dealing with
- */
-static int
-create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  FILE *temp_friend_handle;
-  unsigned int pg_iter;
-  char *temp_service_path;
-  struct GNUNET_OS_Process **procarr;
-  char *arg;
-  char *mytemp;
-
-#if NOT_STUPID
-  enum GNUNET_OS_ProcessStatusType type;
-  unsigned long return_code;
-  int count;
-  int max_wait = 10;
-#endif
-  int ret;
-
-  ret = GNUNET_OK;
-#if OLD
-  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
-  struct PeerConnection *conn_iter;
-#endif
-  procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total);
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    mytemp = GNUNET_DISK_mktemp ("friends");
-    GNUNET_assert (mytemp != NULL);
-    temp_friend_handle = FOPEN (mytemp, "wt");
-    GNUNET_assert (temp_friend_handle != NULL);
-#if OLD
-    conn_iter = pg->peers[pg_iter].allowed_peers_head;
-    while (conn_iter != NULL)
-    {
-      GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon->
-                                 id.hashPubKey, &peer_enc);
-      FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc);
-      conn_iter = conn_iter->next;
-    }
-#else
-    GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers,
-                                           &friend_file_iterator,
-                                           temp_friend_handle);
-#endif
-    FCLOSE (temp_friend_handle);
-
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg,
-                                               "PATHS", "SERVICEHOME",
-                                               &temp_service_path))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
-                  "SERVICEHOME", "PATHS");
-      if (UNLINK (mytemp) != 0)
-        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
-      GNUNET_free (mytemp);
-      break;
-    }
-
-    if (pg->peers[pg_iter].daemon->hostname == NULL)    /* Local, just copy the file */
-    {
-      GNUNET_asprintf (&arg, "%s/friends", temp_service_path);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Copying file with RENAME(%s,%s)\n", mytemp, arg);
-      RENAME (mytemp, arg);
-      procarr[pg_iter] = NULL;
-      GNUNET_free (arg);
-    }
-    else                        /* Remote, scp the file to the correct place */
-    {
-      if (NULL != pg->peers[pg_iter].daemon->username)
-        GNUNET_asprintf (&arg, "%s@%s:%s/friends",
-                         pg->peers[pg_iter].daemon->username,
-                         pg->peers[pg_iter].daemon->hostname,
-                         temp_service_path);
-      else
-        GNUNET_asprintf (&arg, "%s:%s/friends",
-                         pg->peers[pg_iter].daemon->hostname,
-                         temp_service_path);
-      procarr[pg_iter] =
-       GNUNET_OS_start_process (GNUNET_NO, 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_destroy (procarr[pg_iter]);
-      if (ret != GNUNET_OK)
-      {
-        /* FIXME: free contents of 'procarr' array */
-        GNUNET_free (procarr);
-        GNUNET_free (temp_service_path);
-        GNUNET_free (mytemp);
-        GNUNET_free (arg);
-        return ret;
-      }
-      procarr[pg_iter] = NULL;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Copying file with command scp %s %s\n", mytemp, arg);
-      GNUNET_free (arg);
-    }
-    GNUNET_free (temp_service_path);
-    GNUNET_free (mytemp);
-  }
-
-#if NOT_STUPID
-  count = 0;
-  ret = GNUNET_SYSERR;
-  while ((count < max_wait) && (ret != GNUNET_OK))
-  {
-    ret = GNUNET_OK;
-    for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking copy status of file %d\n",
-                  pg_iter);
-      if (procarr[pg_iter] != NULL)     /* Check for already completed! */
-      {
-        if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) !=
-            GNUNET_OK)
-        {
-          ret = GNUNET_SYSERR;
-        }
-        else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
-        {
-          ret = GNUNET_SYSERR;
-        }
-        else
-        {
-          GNUNET_OS_process_destroy (procarr[pg_iter]);
-          procarr[pg_iter] = NULL;
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter);
-        }
-      }
-    }
-    count++;
-    if (ret == GNUNET_SYSERR)
-    {
-      /* FIXME: why sleep here? -CG */
-      sleep (1);
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finished copying all friend files!\n");
-#endif
-  GNUNET_free (procarr);
-  return ret;
-}
-
-/*
- * Create the blacklist files based on the PeerConnection's
- * of each peer in the peer group, and copy the files
- * to the appropriate place.
- *
- * @param pg the peer group we are dealing with
- * @param transports space delimited list of transports to blacklist
- */
-static int
-create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg,
-                                 const char *transports)
-{
-  FILE *temp_file_handle;
-  unsigned int pg_iter;
-  char *temp_service_path;
-  struct GNUNET_OS_Process **procarr;
-  char *arg;
-  char *mytemp;
-  enum GNUNET_OS_ProcessStatusType type;
-  unsigned long return_code;
-  int count;
-  int ret;
-  int max_wait = 10;
-  int transport_len;
-  unsigned int i;
-  char *pos;
-  char *temp_transports;
-
-#if OLD
-  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
-  struct PeerConnection *conn_iter;
-#else
-  static struct BlacklistContext blacklist_ctx;
-#endif
-
-  procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total);
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    mytemp = GNUNET_DISK_mktemp ("blacklist");
-    GNUNET_assert (mytemp != NULL);
-    temp_file_handle = FOPEN (mytemp, "wt");
-    GNUNET_assert (temp_file_handle != NULL);
-    temp_transports = GNUNET_strdup (transports);
-#if !OLD
-    blacklist_ctx.temp_file_handle = temp_file_handle;
-#endif
-    transport_len = strlen (temp_transports) + 1;
-    pos = NULL;
-
-    for (i = 0; i < transport_len; i++)
-    {
-      if ((temp_transports[i] == ' ') && (pos == NULL))
-        continue;               /* At start of string (whitespace) */
-      else if ((temp_transports[i] == ' ') || (temp_transports[i] == '\0'))     /* At end of string */
-      {
-        temp_transports[i] = '\0';
-#if OLD
-        conn_iter = pg->peers[pg_iter].blacklisted_peers_head;
-        while (conn_iter != NULL)
-        {
-          GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon->
-                                     id.hashPubKey, &peer_enc);
-          FPRINTF (temp_file_handle, "%s:%s\n", pos, (char *) &peer_enc);
-          conn_iter = conn_iter->next;
-        }
-#else
-        blacklist_ctx.transport = pos;
-        (void) GNUNET_CONTAINER_multihashmap_iterate (pg->
-                                                      peers
-                                                      [pg_iter].blacklisted_peers,
-                                                      &blacklist_file_iterator,
-                                                      &blacklist_ctx);
-#endif
-        pos = NULL;
-      }                         /* At beginning of actual string */
-      else if (pos == NULL)
-      {
-        pos = &temp_transports[i];
-      }
-    }
-
-    GNUNET_free (temp_transports);
-    FCLOSE (temp_file_handle);
-
-    if (GNUNET_OK !=
-        GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg,
-                                               "PATHS", "SERVICEHOME",
-                                               &temp_service_path))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
-                  "SERVICEHOME", "PATHS");
-      if (UNLINK (mytemp) != 0)
-        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
-      GNUNET_free (mytemp);
-      break;
-    }
-
-    if (pg->peers[pg_iter].daemon->hostname == NULL)    /* Local, just copy the file */
-    {
-      GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path);
-      RENAME (mytemp, arg);
-      procarr[pg_iter] = NULL;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Copying file with RENAME (%s,%s)\n", mytemp, arg);
-      GNUNET_free (arg);
-    }
-    else                        /* Remote, scp the file to the correct place */
-    {
-      if (NULL != pg->peers[pg_iter].daemon->username)
-        GNUNET_asprintf (&arg, "%s@%s:%s/blacklist",
-                         pg->peers[pg_iter].daemon->username,
-                         pg->peers[pg_iter].daemon->hostname,
-                         temp_service_path);
-      else
-        GNUNET_asprintf (&arg, "%s:%s/blacklist",
-                         pg->peers[pg_iter].daemon->hostname,
-                         temp_service_path);
-      procarr[pg_iter] =
-       GNUNET_OS_start_process (GNUNET_NO, 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! */
-
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Copying file with command scp %s %s\n", mytemp, arg);
-      GNUNET_free (arg);
-    }
-    GNUNET_free (temp_service_path);
-    GNUNET_free (mytemp);
-  }
-
-  count = 0;
-  ret = GNUNET_SYSERR;
-  while ((count < max_wait) && (ret != GNUNET_OK))
-  {
-    ret = GNUNET_OK;
-    for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Checking copy status of file %d\n", pg_iter);
-      if (procarr[pg_iter] != NULL)     /* Check for already completed! */
-      {
-        if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) !=
-            GNUNET_OK)
-        {
-          ret = GNUNET_SYSERR;
-        }
-        else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
-        {
-          ret = GNUNET_SYSERR;
-        }
-        else
-        {
-          GNUNET_OS_process_destroy (procarr[pg_iter]);
-          procarr[pg_iter] = NULL;
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter);
-        }
-      }
-    }
-    count++;
-    if (ret == GNUNET_SYSERR)
-    {
-      /* FIXME: why sleep here? -CG */
-      sleep (1);
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Finished copying all blacklist files!\n");
-  GNUNET_free (procarr);
-  return ret;
-}
-
-/* Forward Declaration */
-static void
-schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- * Choose a random peer's next connection to create, and
- * call schedule_connect to set up the connect task.
- *
- * @param pg the peer group to connect
- */
-static void
-preschedule_connect (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  struct ConnectTopologyContext *ct_ctx = &pg->ct_ctx;
-  struct PeerConnection *connection_iter;
-  struct ConnectContext *connect_context;
-  uint32_t random_peer;
-
-  if (ct_ctx->remaining_connections == 0)
-    return;
-  random_peer =
-      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
-  while (pg->peers[random_peer].connect_peers_head == NULL)
-    random_peer =
-        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
-
-  connection_iter = pg->peers[random_peer].connect_peers_head;
-  connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
-  connect_context->first_index = random_peer;
-  connect_context->second_index = connection_iter->index;
-  connect_context->ct_ctx = ct_ctx;
-  connect_context->task =
-      GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
-  GNUNET_CONTAINER_DLL_insert (pg->cc_head, pg->cc_tail, connect_context);
-  GNUNET_CONTAINER_DLL_remove (pg->peers[random_peer].connect_peers_head,
-                               pg->peers[random_peer].connect_peers_tail,
-                               connection_iter);
-  GNUNET_free (connection_iter);
-  ct_ctx->remaining_connections--;
-}
-
-#if USE_SEND_HELLOS
-/* Forward declaration */
-static void
-schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
-
-/**
- * Close connections and free the hello context.
- *
- * @param cls the 'struct SendHelloContext *'
- * @param tc scheduler context
- */
-static void
-free_hello_context (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct SendHelloContext *send_hello_context = cls;
-
-  if (send_hello_context->peer->daemon->server != NULL)
-  {
-    GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server);
-    send_hello_context->peer->daemon->server = NULL;
-  }
-  if (send_hello_context->peer->daemon->th != NULL)
-  {
-    GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th);
-    send_hello_context->peer->daemon->th = NULL;
-  }
-  if (send_hello_context->core_connect_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_SCHEDULER_cancel (send_hello_context->core_connect_task);
-    send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
-  }
-  send_hello_context->pg->outstanding_connects--;
-  GNUNET_free (send_hello_context);
-}
-
-/**
- * For peers that haven't yet connected, notify
- * the caller that they have failed (timeout).
- *
- * @param cls the 'struct SendHelloContext *'
- * @param tc scheduler context
- */
-static void
-notify_remaining_connections_failed (void *cls,
-                                     const struct GNUNET_SCHEDULER_TaskContext
-                                     *tc)
-{
-  struct SendHelloContext *send_hello_context = cls;
-  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
-  struct PeerConnection *connection;
-
-  GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server);
-  send_hello_context->peer->daemon->server = NULL;
-
-  connection = send_hello_context->peer->connect_peers_head;
-
-  while (connection != NULL)
-  {
-    if (pg->notify_connection != NULL)
-    {
-      pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, &pg->peers[connection->index].daemon->id, 0,     /* FIXME */
-                             send_hello_context->peer->daemon->cfg,
-                             pg->peers[connection->index].daemon->cfg,
-                             send_hello_context->peer->daemon,
-                             pg->peers[connection->index].daemon,
-                             "Peers failed to connect (timeout)");
-    }
-    GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head,
-                                 send_hello_context->peer->connect_peers_tail,
-                                 connection);
-    GNUNET_free (connection);
-    connection = connection->next;
-  }
-  GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context);
-#if BAD
-  other_peer = &pg->peers[connection->index];
-#endif
-}
-
-/**
- * For peers that haven't yet connected, send
- * CORE connect requests.
- *
- * @param cls the 'struct SendHelloContext *'
- * @param tc scheduler context
- */
-static void
-send_core_connect_requests (void *cls,
-                            const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct SendHelloContext *send_hello_context = cls;
-  struct PeerConnection *conn;
-
-  GNUNET_assert (send_hello_context->peer->daemon->server != NULL);
-
-  send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
-
-  send_hello_context->connect_attempts++;
-  if (send_hello_context->connect_attempts <
-      send_hello_context->pg->ct_ctx.connect_attempts)
-  {
-    conn = send_hello_context->peer->connect_peers_head;
-    while (conn != NULL)
-    {
-      GNUNET_TRANSPORT_try_connect (send_hello_context->peer->daemon->th,
-                                    &send_hello_context->pg->peers[conn->
-                                                                   index].daemon->
-                                    id);
-      conn = conn->next;
-    }
-    send_hello_context->core_connect_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
-                                      (send_hello_context->pg->
-                                       ct_ctx.connect_timeout,
-                                       send_hello_context->pg->
-                                       ct_ctx.connect_attempts),
-                                      &send_core_connect_requests,
-                                      send_hello_context);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Timeout before all connections created, marking rest as failed!\n");
-    GNUNET_SCHEDULER_add_now (&notify_remaining_connections_failed,
-                              send_hello_context);
-  }
-
-}
-
-/**
- * Success, connection is up.  Signal client our success.
- *
- * @param cls our "struct SendHelloContext"
- * @param peer identity of the peer that has connected
- * @param atsi performance information
- *
- * FIXME: remove peers from BOTH lists, call notify twice, should
- * double the speed of connections as long as the list iteration
- * doesn't take too long!
- */
-static void
-core_connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
-                     const struct GNUNET_ATS_Information *atsi)
-{
-  struct SendHelloContext *send_hello_context = cls;
-  struct PeerConnection *connection;
-  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
-
-#if BAD
-  struct PeerData *other_peer;
-#endif
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n",
-              ctx->d1->shortname, GNUNET_i2s (peer));
-  if (0 ==
-      memcmp (&send_hello_context->peer->daemon->id, peer,
-              sizeof (struct GNUNET_PeerIdentity)))
-    return;
-
-  connection = send_hello_context->peer->connect_peers_head;
-#if BAD
-  other_peer = NULL;
-#endif
-
-  while ((connection != NULL) &&
-         (0 !=
-          memcmp (&pg->peers[connection->index].daemon->id, peer,
-                  sizeof (struct GNUNET_PeerIdentity))))
-  {
-    connection = connection->next;
-  }
-
-  if (connection == NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Connected peer %s to %s, not in list (no problem(?))\n",
-                GNUNET_i2s (peer), send_hello_context->peer->daemon->shortname);
-  }
-  else
-  {
-#if BAD
-    other_peer = &pg->peers[connection->index];
-#endif
-    if (pg->notify_connection != NULL)
-    {
-      pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, peer, 0, /* FIXME */
-                             send_hello_context->peer->daemon->cfg,
-                             pg->peers[connection->index].daemon->cfg,
-                             send_hello_context->peer->daemon,
-                             pg->peers[connection->index].daemon, NULL);
-    }
-    GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head,
-                                 send_hello_context->peer->connect_peers_tail,
-                                 connection);
-    GNUNET_free (connection);
-  }
-
-#if BAD
-  /* Notify of reverse connection and remove from other peers list of outstanding */
-  if (other_peer != NULL)
-  {
-    connection = other_peer->connect_peers_head;
-    while ((connection != NULL) &&
-           (0 !=
-            memcmp (&send_hello_context->peer->daemon->id,
-                    &pg->peers[connection->index].daemon->id,
-                    sizeof (struct GNUNET_PeerIdentity))))
-    {
-      connection = connection->next;
-    }
-    if (connection != NULL)
-    {
-      if (pg->notify_connection != NULL)
-      {
-        pg->notify_connection (pg->notify_connection_cls, peer, &send_hello_context->peer->daemon->id, 0,       /* FIXME */
-                               pg->peers[connection->index].daemon->cfg,
-                               send_hello_context->peer->daemon->cfg,
-                               pg->peers[connection->index].daemon,
-                               send_hello_context->peer->daemon, NULL);
-      }
-
-      GNUNET_CONTAINER_DLL_remove (other_peer->connect_peers_head,
-                                   other_peer->connect_peers_tail, connection);
-      GNUNET_free (connection);
-    }
-  }
-#endif
-
-  if (send_hello_context->peer->connect_peers_head == NULL)
-  {
-    GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context);
-  }
-}
-
-/**
- * Notify of a successful connection to the core service.
- *
- * @param cls a struct SendHelloContext *
- * @param server handle to the core service
- * @param my_identity the peer identity of this peer
- */
-void
-core_init (void *cls, struct GNUNET_CORE_Handle *server,
-           struct GNUNET_PeerIdentity *my_identity)
-{
-  struct SendHelloContext *send_hello_context = cls;
-
-  send_hello_context->core_ready = GNUNET_YES;
-}
-
-/**
- * Function called once a hello has been sent
- * to the transport, move on to the next one
- * or go away forever.
- *
- * @param cls the 'struct SendHelloContext *'
- * @param tc scheduler context
- */
-static void
-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) != 0)
-  {
-    GNUNET_free (send_hello_context);
-    return;
-  }
-
-  send_hello_context->pg->remaining_hellos--;
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO, have %d remaining!\n",
-              send_hello_context->pg->remaining_hellos);
-  if (send_hello_context->peer_pos == NULL)     /* All HELLOs (for this peer!) have been transmitted! */
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All hellos for this peer sent, disconnecting transport!\n");
-    GNUNET_assert (send_hello_context->peer->daemon->th != NULL);
-    GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th);
-    send_hello_context->peer->daemon->th = NULL;
-    GNUNET_assert (send_hello_context->peer->daemon->server == NULL);
-    send_hello_context->peer->daemon->server =
-        GNUNET_CORE_connect (send_hello_context->peer->cfg, 1,
-                             send_hello_context, &core_init,
-                             &core_connect_notify, NULL, NULL, NULL, GNUNET_NO,
-                             NULL, GNUNET_NO, no_handlers);
-
-    send_hello_context->core_connect_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
-                                      (send_hello_context->pg->
-                                       ct_ctx.connect_timeout,
-                                       send_hello_context->pg->
-                                       ct_ctx.connect_attempts),
-                                      &send_core_connect_requests,
-                                      send_hello_context);
-  }
-  else
-    GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context);
-}
-
-/**
- * Connect to a peer, give it all the HELLO's of those peers
- * we will later ask it to connect to.
- *
- * @param ct_ctx the overall connection context
- */
-static void
-schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct SendHelloContext *send_hello_context = cls;
-  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
-
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-  {
-    GNUNET_free (send_hello_context);
-    return;
-  }
-
-  GNUNET_assert (send_hello_context->peer_pos != NULL); /* All of the HELLO sends to be scheduled have been scheduled! */
-
-  if (((send_hello_context->peer->daemon->th == NULL) &&
-       (pg->outstanding_connects > pg->max_outstanding_connections)) ||
-      (pg->stop_connects == GNUNET_YES))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Delaying connect, we have too many outstanding connections!\n");
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_send_hellos, send_hello_context);
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating connection, outstanding_connections is %d\n",
-                outstanding_connects);
-    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);
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Offering HELLO of peer %s to peer %s\n",
-                send_hello_context->peer->daemon->shortname,
-                pg->peers[send_hello_context->peer_pos->index].
-                daemon->shortname);
-    GNUNET_TRANSPORT_offer_hello (send_hello_context->peer->daemon->th,
-                                  (const struct GNUNET_MessageHeader *)
-                                  pg->peers[send_hello_context->peer_pos->
-                                            index].daemon->hello,
-                                  &hello_sent_callback, send_hello_context);
-    send_hello_context->peer_pos = send_hello_context->peer_pos->next;
-    GNUNET_assert (send_hello_context->peer->daemon->th != NULL);
-  }
-}
-#endif
-
-/**
- * Internal notification of a connection, kept so that we can ensure some connections
- * happen instead of flooding all testing daemons with requests to connect.
- */
-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)
-{
-  struct ConnectContext *connect_ctx = cls;
-  struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx;
-  struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
-  struct PeerConnection *connection;
-
-  GNUNET_assert (NULL != connect_ctx->cc);
-  connect_ctx->cc = NULL;
-  GNUNET_assert (0 < pg->outstanding_connects);
-  pg->outstanding_connects--;
-  GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, connect_ctx);
-  /*
-   * Check whether the inverse connection has been scheduled yet,
-   * if not, we can remove it from the other peers list and avoid
-   * even trying to connect them again!
-   */
-  connection = pg->peers[connect_ctx->second_index].connect_peers_head;
-#if BAD
-  other_peer = NULL;
-#endif
-
-  while ((connection != NULL) &&
-         (0 !=
-          memcmp (first, &pg->peers[connection->index].daemon->id,
-                  sizeof (struct GNUNET_PeerIdentity))))
-    connection = connection->next;
-
-  if (connection != NULL)       /* Can safely remove! */
-  {
-    GNUNET_assert (0 < ct_ctx->remaining_connections);
-    ct_ctx->remaining_connections--;
-    if (pg->notify_connection != NULL)  /* Notify of reverse connection */
-      pg->notify_connection (pg->notify_connection_cls, second, first, distance,
-                             second_cfg, first_cfg, second_daemon, first_daemon,
-                             emsg);
-
-    GNUNET_CONTAINER_DLL_remove (pg->
-                                 peers[connect_ctx->
-                                       second_index].connect_peers_head,
-                                 pg->peers[connect_ctx->
-                                           second_index].connect_peers_tail,
-                                 connection);
-    GNUNET_free (connection);
-  }
-
-  if (ct_ctx->remaining_connections == 0)
-  {
-    if (ct_ctx->notify_connections_done != NULL)
-    {
-      ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL);
-      ct_ctx->notify_connections_done = NULL;
-    }
-  }
-  else
-    preschedule_connect (pg);
-
-  if (pg->notify_connection != NULL)
-    pg->notify_connection (pg->notify_connection_cls, first, second, distance,
-                           first_cfg, second_cfg, first_daemon, second_daemon,
-                           emsg);
-  GNUNET_free (connect_ctx);
-}
-
-/**
- * Either delay a connection (because there are too many outstanding)
- * or schedule it for right now.
- *
- * @param cls a connection context
- * @param tc the task runtime context
- */
-static void
-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;
-
-  connect_context->task = GNUNET_SCHEDULER_NO_TASK;
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-    return;
-
-  if ((pg->outstanding_connects > pg->max_outstanding_connections) ||
-      (pg->stop_connects == GNUNET_YES))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Delaying connect, we have too many outstanding connections!\n");
-    connect_context->task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                      &schedule_connect, connect_context);
-    return;
-  }
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Creating connection, outstanding_connections is %d (max %d)\n",
-              pg->outstanding_connects, pg->max_outstanding_connections);
-  pg->outstanding_connects++;
-  pg->total_connects_scheduled++;
-  GNUNET_assert (NULL == connect_context->cc);
-  connect_context->cc =
-      GNUNET_TESTING_daemons_connect (pg->
-                                      peers[connect_context->
-                                            first_index].daemon,
-                                      pg->peers[connect_context->
-                                                second_index].daemon,
-                                      connect_context->ct_ctx->connect_timeout,
-                                      connect_context->ct_ctx->connect_attempts,
-#if USE_SEND_HELLOS
-                                      GNUNET_NO,
-#else
-                                      GNUNET_YES,
-#endif
-                                      &internal_connect_notify,
-                                      connect_context);
-
-}
-
-#if !OLD
-/**
- * Iterator for actually scheduling connections to be created
- * between two peers.
- *
- * @param cls closure, a GNUNET_TESTING_Daemon
- * @param key the key the second Daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that the first is to connect to
- *
- * @return GNUNET_YES to continue iteration
- */
-static int
-connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct ConnectTopologyContext *ct_ctx = cls;
-  struct PeerData *first = ct_ctx->first;
-  struct GNUNET_TESTING_Daemon *second = value;
-  struct ConnectContext *connect_context;
-
-  connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
-  connect_context->first = first->daemon;
-  connect_context->second = second;
-  connect_context->ct_ctx = ct_ctx;
-  connect_context->task =
-      GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
-  GNUNET_CONTAINER_DLL_insert (ct_ctx->pg->cc_head, ct_ctx->pg->cc_tail,
-                               connect_context);
-  return GNUNET_YES;
-}
-#endif
-
-#if !OLD
-/**
- * Iterator for copying all entries in the allowed hashmap to the
- * connect hashmap.
- *
- * @param cls closure, a GNUNET_TESTING_Daemon
- * @param key the key the second Daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that the first is to connect to
- *
- * @return GNUNET_YES to continue iteration
- */
-static int
-copy_topology_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct PeerData *first = cls;
-
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONTAINER_multihashmap_put (first->connect_peers, key,
-                                                    value,
-                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-
-  return GNUNET_YES;
-}
-#endif
-
-/**
- * Make the peers to connect the same as those that are allowed to be
- * connected.
- *
- * @param pg the peer group
- */
-static int
-copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  unsigned int pg_iter;
-  int ret;
-  int total;
-
-#if OLD
-  struct PeerConnection *iter;
-#endif
-  total = 0;
-  ret = 0;
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-#if OLD
-    iter = pg->peers[pg_iter].allowed_peers_head;
-    while (iter != NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Creating connection between %d and %d\n", pg_iter,
-                  iter->index);
-      total += add_connections (pg, pg_iter, iter->index, CONNECT, GNUNET_YES);
-      //total += add_actual_connections(pg, pg_iter, iter->index);
-      iter = iter->next;
-    }
-#else
-    ret =
-        GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers,
-                                               &copy_topology_iterator,
-                                               &pg->peers[pg_iter]);
-#endif
-    if (GNUNET_SYSERR == ret)
-      return GNUNET_SYSERR;
-
-    total = total + ret;
-  }
-
-  return total;
-}
-
-/**
- * Connect the topology as specified by the PeerConnection's
- * of each peer in the peer group
- *
- * @param pg the peer group we are dealing with
- * @param connect_timeout how long try connecting two peers
- * @param connect_attempts how many times (max) to attempt
- * @param notify_callback callback to notify when finished
- * @param notify_cls closure for notify callback
- *
- * @return the number of connections that will be attempted
- */
-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)
-{
-  unsigned int pg_iter;
-  unsigned int total;
-
-#if OLD
-  struct PeerConnection *connection_iter;
-#endif
-#if USE_SEND_HELLOS
-  struct SendHelloContext *send_hello_context;
-#endif
-
-  total = 0;
-  pg->ct_ctx.notify_connections_done = notify_callback;
-  pg->ct_ctx.notify_cls = notify_cls;
-  pg->ct_ctx.pg = pg;
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-#if OLD
-    connection_iter = pg->peers[pg_iter].connect_peers_head;
-    while (connection_iter != NULL)
-    {
-      connection_iter = connection_iter->next;
-      total++;
-    }
-#else
-    total +=
-        GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].connect_peers);
-#endif
-  }
-
-  if (total == 0)
-    return total;
-
-  pg->ct_ctx.connect_timeout = connect_timeout;
-  pg->ct_ctx.connect_attempts = connect_attempts;
-  pg->ct_ctx.remaining_connections = total;
-
-#if USE_SEND_HELLOS
-  /* First give all peers the HELLO's of other peers (connect to first peer's transport service, give HELLO's of other peers, continue...) */
-  pg->remaining_hellos = total;
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    send_hello_context = GNUNET_malloc (sizeof (struct SendHelloContext));
-    send_hello_context->peer = &pg->peers[pg_iter];
-    send_hello_context->peer_pos = pg->peers[pg_iter].connect_peers_head;
-    send_hello_context->pg = pg;
-    GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context);
-  }
-#else
-  for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++)
-  {
-    preschedule_connect (pg);
-  }
-#endif
-  return total;
-
-}
-
-/**
- * Takes a peer group and creates a topology based on the
- * one specified.  Creates a topology means generates friend
- * files for the peers so they can only connect to those allowed
- * by the topology.  This will only have an effect once peers
- * are started if the FRIENDS_ONLY option is set in the base
- * config.  Also takes an optional restrict topology which
- * disallows connections based on particular transports
- * UNLESS they are specified in the restricted topology.
- *
- * @param pg the peer group struct representing the running peers
- * @param topology which topology to connect the peers in
- * @param restrict_topology disallow restrict_transports transport
- *                          connections to peers NOT in this topology
- *                          use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions
- * @param restrict_transports space delimited list of transports to blacklist
- *                            to create restricted topology
- *
- * @return the maximum number of connections were all allowed peers
- *         connected to each other
- */
-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)
-{
-  int ret;
-
-  unsigned int num_connections;
-  int unblacklisted_connections;
-  char *filename;
-  struct PeerConnection *conn_iter;
-  struct PeerConnection *temp_conn;
-  unsigned int off;
-
-#if !OLD
-  unsigned int i;
-
-  for (i = 0; i < pg->total; i++)
-  {
-    pg->peers[i].allowed_peers = GNUNET_CONTAINER_multihashmap_create (100);
-    pg->peers[i].connect_peers = GNUNET_CONTAINER_multihashmap_create (100);
-    pg->peers[i].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create (100);
-    pg->peers[i].pg = pg;
-  }
-#endif
-
-  switch (topology)
-  {
-  case GNUNET_TESTING_TOPOLOGY_CLIQUE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating clique topology\n");
-    num_connections = create_clique (pg, &add_connections, ALLOWED, GNUNET_NO);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating small world (ring) topology\n");
-    num_connections = create_small_world_ring (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating small world (2d-torus) topology\n");
-    num_connections = create_small_world (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_RING:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring topology\n");
-    num_connections = create_ring (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating 2d torus topology\n");
-    num_connections = create_2d_torus (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Erdos-Renyi topology\n");
-    num_connections = create_erdos_renyi (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_INTERNAT:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating InterNAT topology\n");
-    num_connections = create_nated_internet (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Scale Free topology\n");
-    num_connections = create_scale_free (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_LINE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating straight line topology\n");
-    num_connections = create_line (pg, &add_connections, ALLOWED);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_FROM_FILE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating topology from file!\n");
-    if (GNUNET_OK ==
-        GNUNET_CONFIGURATION_get_value_string (pg->cfg, "testing",
-                                               "topology_file", &filename))
-      num_connections =
-          create_from_file (pg, filename, &add_connections, ALLOWED);
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  "Missing configuration option TESTING:TOPOLOGY_FILE for creating topology from file!\n");
-      num_connections = 0;
-    }
-    break;
-  case GNUNET_TESTING_TOPOLOGY_NONE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                _
-                ("Creating no allowed topology (all peers can connect at core level)\n"));
-    num_connections = pg->total * pg->total;    /* Clique is allowed! */
-    break;
-  default:
-    num_connections = 0;
-    break;
-  }
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F"))
-  {
-    ret = create_and_copy_friend_files (pg);
-    if (ret != GNUNET_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Failed during friend file copying!\n");
-      return GNUNET_SYSERR;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Friend files created/copied successfully!\n");
-    }
-  }
-
-  /* Use the create clique method to initially set all connections as blacklisted. */
-  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 */
-  switch (restrict_topology)
-  {
-  case GNUNET_TESTING_TOPOLOGY_CLIQUE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but clique topology\n");
-    unblacklisted_connections =
-        create_clique (pg, &remove_connections, BLACKLIST, GNUNET_NO);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but small world (ring) topology\n");
-    unblacklisted_connections =
-        create_small_world_ring (pg, &remove_connections, BLACKLIST);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but small world (2d-torus) topology\n");
-    unblacklisted_connections =
-        create_small_world (pg, &remove_connections, BLACKLIST);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_RING:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but ring topology\n");
-    unblacklisted_connections =
-        create_ring (pg, &remove_connections, BLACKLIST);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but 2d torus topology\n");
-    unblacklisted_connections =
-        create_2d_torus (pg, &remove_connections, BLACKLIST);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but Erdos-Renyi topology\n");
-    unblacklisted_connections =
-        create_erdos_renyi (pg, &remove_connections, BLACKLIST);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_INTERNAT:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but InterNAT topology\n");
-
-#if TOPOLOGY_HACK
-    for (off = 0; off < pg->total; off++)
-    {
-      conn_iter = pg->peers[off].allowed_peers_head;
-      while (conn_iter != NULL)
-      {
-        temp_conn = conn_iter->next;
-        GNUNET_free (conn_iter);
-        conn_iter = temp_conn;
-      }
-      pg->peers[off].allowed_peers_head = NULL;
-      pg->peers[off].allowed_peers_tail = NULL;
-
-      conn_iter = pg->peers[off].connect_peers_head;
-      while (conn_iter != NULL)
-      {
-        temp_conn = conn_iter->next;
-        GNUNET_free (conn_iter);
-        conn_iter = temp_conn;
-      }
-      pg->peers[off].connect_peers_head = NULL;
-      pg->peers[off].connect_peers_tail = NULL;
-    }
-    unblacklisted_connections =
-        create_nated_internet_copy (pg, &remove_connections, BLACKLIST);
-#else
-    unblacklisted_connections =
-        create_nated_internet (pg, &remove_connections, BLACKLIST);
-#endif
-
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but Scale Free topology\n");
-    unblacklisted_connections =
-        create_scale_free (pg, &remove_connections, BLACKLIST);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_LINE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Blacklisting all but straight line topology\n");
-    unblacklisted_connections =
-        create_line (pg, &remove_connections, BLACKLIST);
-  default:
-    break;
-  }
-
-  if ((unblacklisted_connections > 0) && (restrict_transports != NULL))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating blacklist with `%s'\n",
-                restrict_transports);
-    ret = create_and_copy_blacklist_files (pg, restrict_transports);
-    if (ret != GNUNET_OK)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Failed during blacklist file copying!\n");
-      return 0;
-    }
-    else
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Blacklist files created/copied successfully!\n");
-    }
-  }
-  return num_connections;
-}
-
-#if !OLD
-/**
- * Iterator for choosing random peers to connect.
- *
- * @param cls closure, a RandomContext
- * @param key the key the second Daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that the first is to connect to
- *
- * @return GNUNET_YES to continue iteration
- */
-static int
-random_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct RandomContext *random_ctx = cls;
-  double random_number;
-  uint32_t second_pos;
-  GNUNET_HashCode first_hash;
-
-  random_number =
-      ((double)
-       GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                 UINT64_MAX)) / ((double) UINT64_MAX);
-  if (random_number < random_ctx->percentage)
-  {
-    GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CONTAINER_multihashmap_put (random_ctx->
-                                                      first->connect_peers_working_set,
-                                                      key, value,
-                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-  }
-
-  /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */
-  uid_from_hash (key, &second_pos);
-  hash_from_uid (random_ctx->first_uid, &first_hash);
-  GNUNET_assert (random_ctx->pg->total > second_pos);
-  GNUNET_assert (GNUNET_YES ==
-                 GNUNET_CONTAINER_multihashmap_remove (random_ctx->
-                                                       pg->peers
-                                                       [second_pos].connect_peers,
-                                                       &first_hash,
-                                                       random_ctx->
-                                                       first->daemon));
-
-  return GNUNET_YES;
-}
-
-/**
- * Iterator for adding at least X peers to a peers connection set.
- *
- * @param cls closure, MinimumContext
- * @param key the key the second Daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that the first is to connect to
- *
- * @return GNUNET_YES to continue iteration
- */
-static int
-minimum_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct MinimumContext *min_ctx = cls;
-  uint32_t second_pos;
-  GNUNET_HashCode first_hash;
-  unsigned int i;
-
-  if (GNUNET_CONTAINER_multihashmap_size
-      (min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add)
-  {
-    for (i = 0; i < min_ctx->num_to_add; i++)
-    {
-      if (min_ctx->pg_array[i] == min_ctx->current)
-      {
-        GNUNET_assert (GNUNET_OK ==
-                       GNUNET_CONTAINER_multihashmap_put (min_ctx->
-                                                          first->connect_peers_working_set,
-                                                          key, value,
-                                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-        uid_from_hash (key, &second_pos);
-        hash_from_uid (min_ctx->first_uid, &first_hash);
-        GNUNET_assert (min_ctx->pg->total > second_pos);
-        GNUNET_assert (GNUNET_OK ==
-                       GNUNET_CONTAINER_multihashmap_put (min_ctx->
-                                                          pg->peers
-                                                          [second_pos].connect_peers_working_set,
-                                                          &first_hash,
-                                                          min_ctx->first->
-                                                          daemon,
-                                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-        /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */
-        GNUNET_assert (GNUNET_YES ==
-                       GNUNET_CONTAINER_multihashmap_remove (min_ctx->
-                                                             pg->peers
-                                                             [second_pos].connect_peers,
-                                                             &first_hash,
-                                                             min_ctx->
-                                                             first->daemon));
-      }
-    }
-    min_ctx->current++;
-    return GNUNET_YES;
-  }
-  else
-    return GNUNET_NO;           /* We can stop iterating, we have enough peers! */
-
-}
-
-/**
- * Iterator for adding peers to a connection set based on a depth first search.
- *
- * @param cls closure, MinimumContext
- * @param key the key the second daemon was stored under
- * @param value the GNUNET_TESTING_Daemon that the first is to connect to
- *
- * @return GNUNET_YES to continue iteration
- */
-static int
-dfs_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct DFSContext *dfs_ctx = cls;
-  GNUNET_HashCode first_hash;
-
-  if (dfs_ctx->current == dfs_ctx->chosen)
-  {
-    GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CONTAINER_multihashmap_put (dfs_ctx->
-                                                      first->connect_peers_working_set,
-                                                      key, value,
-                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-    uid_from_hash (key, &dfs_ctx->second_uid);
-    hash_from_uid (dfs_ctx->first_uid, &first_hash);
-    GNUNET_assert (GNUNET_OK ==
-                   GNUNET_CONTAINER_multihashmap_put (dfs_ctx->
-                                                      pg->peers[dfs_ctx->
-                                                                second_uid].connect_peers_working_set,
-                                                      &first_hash,
-                                                      dfs_ctx->first->daemon,
-                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (dfs_ctx->
-                                                         pg->peers
-                                                         [dfs_ctx->second_uid].connect_peers,
-                                                         &first_hash,
-                                                         dfs_ctx->
-                                                         first->daemon));
-    /* Can't remove second from first yet because we are currently iterating, hence the return value in the DFSContext! */
-    return GNUNET_NO;           /* We have found our peer, don't iterate more */
-  }
-
-  dfs_ctx->current++;
-  return GNUNET_YES;
-}
-#endif
-
-/**
- * From the set of connections possible, choose percentage percent of connections
- * to actually connect.
- *
- * @param pg the peergroup we are dealing with
- * @param percentage what percent of total connections to make
- */
-void
-choose_random_connections (struct GNUNET_TESTING_PeerGroup *pg,
-                           double percentage)
-{
-  uint32_t pg_iter;
-
-#if OLD
-  struct PeerConnection *conn_iter;
-  double random_number;
-#else
-  struct RandomContext random_ctx;
-#endif
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-#if OLD
-    conn_iter = pg->peers[pg_iter].connect_peers_head;
-    while (conn_iter != NULL)
-    {
-      random_number =
-          ((double)
-           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                     UINT64_MAX)) / ((double) UINT64_MAX);
-      if (random_number < percentage)
-      {
-        add_connections (pg, pg_iter, conn_iter->index, WORKING_SET,
-                         GNUNET_YES);
-      }
-      conn_iter = conn_iter->next;
-    }
-#else
-    random_ctx.first_uid = pg_iter;
-    random_ctx.first = &pg->peers[pg_iter];
-    random_ctx.percentage = percentage;
-    random_ctx.pg = pg;
-    pg->peers[pg_iter].connect_peers_working_set =
-        GNUNET_CONTAINER_multihashmap_create (pg->total);
-    GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers,
-                                           &random_connect_iterator,
-                                           &random_ctx);
-    /* Now remove the old connections */
-    GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers);
-    /* And replace with the random set */
-    pg->peers[pg_iter].connect_peers =
-        pg->peers[pg_iter].connect_peers_working_set;
-#endif
-  }
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    conn_iter = pg->peers[pg_iter].connect_peers_head;
-    while (pg->peers[pg_iter].connect_peers_head != NULL)
-      remove_connections (pg, pg_iter,
-                          pg->peers[pg_iter].connect_peers_head->index, CONNECT,
-                          GNUNET_YES);
-
-    pg->peers[pg_iter].connect_peers_head =
-        pg->peers[pg_iter].connect_peers_working_set_head;
-    pg->peers[pg_iter].connect_peers_tail =
-        pg->peers[pg_iter].connect_peers_working_set_tail;
-    pg->peers[pg_iter].connect_peers_working_set_head = NULL;
-    pg->peers[pg_iter].connect_peers_working_set_tail = NULL;
-  }
-}
-
-/**
- * Count the number of connections in a linked list of connections.
- *
- * @param conn_list the connection list to get the count of
- *
- * @return the number of elements in the list
- */
-static unsigned int
-count_connections (struct PeerConnection *conn_list)
-{
-  struct PeerConnection *iter;
-  unsigned int count;
-
-  count = 0;
-  iter = conn_list;
-  while (iter != NULL)
-  {
-    iter = iter->next;
-    count++;
-  }
-  return count;
-}
-
-static unsigned int
-count_workingset_connections (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  unsigned int count;
-  unsigned int pg_iter;
-
-#if OLD
-  struct PeerConnection *conn_iter;
-#endif
-  count = 0;
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-#if OLD
-    conn_iter = pg->peers[pg_iter].connect_peers_working_set_head;
-    while (conn_iter != NULL)
-    {
-      count++;
-      conn_iter = conn_iter->next;
-    }
-#else
-    count +=
-        GNUNET_CONTAINER_multihashmap_size (pg->
-                                            peers
-                                            [pg_iter].connect_peers_working_set);
-#endif
-  }
-
-  return count;
-}
-
-static unsigned int
-count_allowed_connections (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  unsigned int count;
-  unsigned int pg_iter;
-
-#if OLD
-  struct PeerConnection *conn_iter;
-#endif
-
-  count = 0;
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-#if OLD
-    conn_iter = pg->peers[pg_iter].allowed_peers_head;
-    while (conn_iter != NULL)
-    {
-      count++;
-      conn_iter = conn_iter->next;
-    }
-#else
-    count +=
-        GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].allowed_peers);
-#endif
-  }
-
-  return count;
-}
-
-/**
- * From the set of connections possible, choose at least num connections per
- * peer.
- *
- * @param pg the peergroup we are dealing with
- * @param num how many connections at least should each peer have (if possible)?
- */
-static void
-choose_minimum (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
-{
-#if !OLD
-  struct MinimumContext minimum_ctx;
-#else
-  struct PeerConnection *conn_iter;
-  unsigned int temp_list_size;
-  unsigned int i;
-  unsigned int count;
-  uint32_t random;              /* Random list entry to connect peer to */
-#endif
-  uint32_t pg_iter;
-
-#if OLD
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    temp_list_size = count_connections (pg->peers[pg_iter].connect_peers_head);
-    if (temp_list_size == 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peer %d has 0 connections!?!?\n",
-                  pg_iter);
-      break;
-    }
-    for (i = 0; i < num; i++)
-    {
-      random =
-          GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_list_size);
-      conn_iter = pg->peers[pg_iter].connect_peers_head;
-      for (count = 0; count < random; count++)
-        conn_iter = conn_iter->next;
-      /* We now have a random connection, connect it! */
-      GNUNET_assert (conn_iter != NULL);
-      add_connections (pg, pg_iter, conn_iter->index, WORKING_SET, GNUNET_YES);
-    }
-  }
-#else
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    pg->peers[pg_iter].connect_peers_working_set =
-        GNUNET_CONTAINER_multihashmap_create (num);
-  }
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    minimum_ctx.first_uid = pg_iter;
-    minimum_ctx.pg_array =
-        GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
-                                      GNUNET_CONTAINER_multihashmap_size
-                                      (pg->peers[pg_iter].connect_peers));
-    minimum_ctx.first = &pg->peers[pg_iter];
-    minimum_ctx.pg = pg;
-    minimum_ctx.num_to_add = num;
-    minimum_ctx.current = 0;
-    GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers,
-                                           &minimum_connect_iterator,
-                                           &minimum_ctx);
-  }
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    /* Remove the "old" connections */
-    GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers);
-    /* And replace with the working set */
-    pg->peers[pg_iter].connect_peers =
-        pg->peers[pg_iter].connect_peers_working_set;
-  }
-#endif
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    while (pg->peers[pg_iter].connect_peers_head != NULL)
-    {
-      conn_iter = pg->peers[pg_iter].connect_peers_head;
-      GNUNET_CONTAINER_DLL_remove (pg->peers[pg_iter].connect_peers_head,
-                                   pg->peers[pg_iter].connect_peers_tail,
-                                   conn_iter);
-      GNUNET_free (conn_iter);
-      /*remove_connections(pg, pg_iter, pg->peers[pg_iter].connect_peers_head->index, CONNECT, GNUNET_YES); */
-    }
-
-    pg->peers[pg_iter].connect_peers_head =
-        pg->peers[pg_iter].connect_peers_working_set_head;
-    pg->peers[pg_iter].connect_peers_tail =
-        pg->peers[pg_iter].connect_peers_working_set_tail;
-    pg->peers[pg_iter].connect_peers_working_set_head = NULL;
-    pg->peers[pg_iter].connect_peers_working_set_tail = NULL;
-  }
-}
-
-#if !OLD
-struct FindClosestContext
-{
-    /**
-     * The currently known closest peer.
-     */
-  struct GNUNET_TESTING_Daemon *closest;
-
-    /**
-     * The info for the peer we are adding connections for.
-     */
-  struct PeerData *curr_peer;
-
-    /**
-     * The distance (bits) between the current
-     * peer and the currently known closest.
-     */
-  unsigned int closest_dist;
-
-    /**
-     * The offset of the closest known peer in
-     * the peer group.
-     */
-  unsigned int closest_num;
-};
-
-/**
- * Iterator over hash map entries of the allowed
- * peer connections.  Find the closest, not already
- * connected peer and return it.
- *
- * @param cls closure (struct FindClosestContext)
- * @param key current key code (hash of offset in pg)
- * @param value value in the hash map - a GNUNET_TESTING_Daemon
- * @return GNUNET_YES if we should continue to
- *         iterate,
- *         GNUNET_NO if not.
- */
-static int
-find_closest_peers (void *cls, const GNUNET_HashCode * key, void *value)
-{
-  struct FindClosestContext *closest_ctx = cls;
-  struct GNUNET_TESTING_Daemon *daemon = value;
-
-  if (((closest_ctx->closest == NULL) ||
-       (GNUNET_CRYPTO_hash_matching_bits
-        (&daemon->id.hashPubKey,
-         &closest_ctx->curr_peer->daemon->id.hashPubKey) >
-        closest_ctx->closest_dist)) &&
-      (GNUNET_YES !=
-       GNUNET_CONTAINER_multihashmap_contains (closest_ctx->
-                                               curr_peer->connect_peers, key)))
-  {
-    closest_ctx->closest_dist =
-        GNUNET_CRYPTO_hash_matching_bits (&daemon->id.hashPubKey,
-                                          &closest_ctx->curr_peer->daemon->
-                                          id.hashPubKey);
-    closest_ctx->closest = daemon;
-    uid_from_hash (key, &closest_ctx->closest_num);
-  }
-  return GNUNET_YES;
-}
-
-/**
- * From the set of connections possible, choose at num connections per
- * peer based on depth which are closest out of those allowed.  Guaranteed
- * to add num peers to connect to, provided there are that many peers
- * in the underlay topology to connect to.
- *
- * @param pg the peergroup we are dealing with
- * @param num how many connections at least should each peer have (if possible)?
- * @param proc processor to actually add the connections
- * @param list the peer list to use
- */
-void
-add_closest (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num,
-             GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
-{
-#if OLD
-
-#else
-  struct FindClosestContext closest_ctx;
-#endif
-  uint32_t pg_iter;
-  uint32_t i;
-
-  for (i = 0; i < num; i++)     /* Each time find a closest peer (from those available) */
-  {
-    for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-    {
-      closest_ctx.curr_peer = &pg->peers[pg_iter];
-      closest_ctx.closest = NULL;
-      closest_ctx.closest_dist = 0;
-      closest_ctx.closest_num = 0;
-      GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers,
-                                             &find_closest_peers, &closest_ctx);
-      if (closest_ctx.closest != NULL)
-      {
-        GNUNET_assert (closest_ctx.closest_num < pg->total);
-        proc (pg, pg_iter, closest_ctx.closest_num, list);
-      }
-    }
-  }
-}
-#endif
-
-/**
- * From the set of connections possible, choose at least num connections per
- * peer based on depth first traversal of peer connections.  If DFS leaves
- * peers unconnected, ensure those peers get connections.
- *
- * @param pg the peergroup we are dealing with
- * @param num how many connections at least should each peer have (if possible)?
- */
-void
-perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
-{
-  uint32_t pg_iter;
-  uint32_t dfs_count;
-  uint32_t starting_peer;
-  uint32_t least_connections;
-  uint32_t random_connection;
-
-#if OLD
-  unsigned int temp_count;
-  struct PeerConnection *peer_iter;
-#else
-  struct DFSContext dfs_ctx;
-  GNUNET_HashCode second_hash;
-#endif
-
-#if OLD
-  starting_peer = 0;
-  dfs_count = 0;
-  while ((count_workingset_connections (pg) < num * pg->total) &&
-         (count_allowed_connections (pg) > 0))
-  {
-    if (dfs_count % pg->total == 0)     /* Restart the DFS at some weakly connected peer */
-    {
-      least_connections = -1;   /* Set to very high number */
-      for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-      {
-        temp_count =
-            count_connections (pg->
-                               peers[pg_iter].connect_peers_working_set_head);
-        if (temp_count < least_connections)
-        {
-          starting_peer = pg_iter;
-          least_connections = temp_count;
-        }
-      }
-    }
-
-    temp_count =
-        count_connections (pg->peers[starting_peer].connect_peers_head);
-    if (temp_count == 0)
-      continue;                 /* FIXME: infinite loop? */
-
-    random_connection =
-        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_count);
-    temp_count = 0;
-    peer_iter = pg->peers[starting_peer].connect_peers_head;
-    while (temp_count < random_connection)
-    {
-      peer_iter = peer_iter->next;
-      temp_count++;
-    }
-    GNUNET_assert (peer_iter != NULL);
-    add_connections (pg, starting_peer, peer_iter->index, WORKING_SET,
-                     GNUNET_NO);
-    remove_connections (pg, starting_peer, peer_iter->index, CONNECT,
-                        GNUNET_YES);
-    starting_peer = peer_iter->index;
-    dfs_count++;
-  }
-
-#else
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    pg->peers[pg_iter].connect_peers_working_set =
-        GNUNET_CONTAINER_multihashmap_create (num);
-  }
-
-  starting_peer = 0;
-  dfs_count = 0;
-  while ((count_workingset_connections (pg) < num * pg->total) &&
-         (count_allowed_connections (pg) > 0))
-  {
-    if (dfs_count % pg->total == 0)     /* Restart the DFS at some weakly connected peer */
-    {
-      least_connections = -1;   /* Set to very high number */
-      for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-      {
-        if (GNUNET_CONTAINER_multihashmap_size
-            (pg->peers[pg_iter].connect_peers_working_set) < least_connections)
-        {
-          starting_peer = pg_iter;
-          least_connections =
-              GNUNET_CONTAINER_multihashmap_size (pg->
-                                                  peers
-                                                  [pg_iter].connect_peers_working_set);
-        }
-      }
-    }
-
-    if (GNUNET_CONTAINER_multihashmap_size (pg->peers[starting_peer].connect_peers) == 0)       /* Ensure there is at least one peer left to connect! */
-    {
-      dfs_count = 0;
-      continue;
-    }
-
-    /* Choose a random peer from the chosen peers set of connections to add */
-    dfs_ctx.chosen =
-        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                  GNUNET_CONTAINER_multihashmap_size (pg->peers
-                                                                      [starting_peer].connect_peers));
-    dfs_ctx.first_uid = starting_peer;
-    dfs_ctx.first = &pg->peers[starting_peer];
-    dfs_ctx.pg = pg;
-    dfs_ctx.current = 0;
-
-    GNUNET_CONTAINER_multihashmap_iterate (pg->
-                                           peers[starting_peer].connect_peers,
-                                           &dfs_connect_iterator, &dfs_ctx);
-    /* Remove the second from the first, since we will be continuing the search and may encounter the first peer again! */
-    hash_from_uid (dfs_ctx.second_uid, &second_hash);
-    GNUNET_assert (GNUNET_YES ==
-                   GNUNET_CONTAINER_multihashmap_remove (pg->peers
-                                                         [starting_peer].connect_peers,
-                                                         &second_hash,
-                                                         pg->
-                                                         peers
-                                                         [dfs_ctx.second_uid].daemon));
-    starting_peer = dfs_ctx.second_uid;
-  }
-
-  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
-  {
-    /* Remove the "old" connections */
-    GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers);
-    /* And replace with the working set */
-    pg->peers[pg_iter].connect_peers =
-        pg->peers[pg_iter].connect_peers_working_set;
-  }
-#endif
-}
-
-/**
- * Internal callback for topology information for a particular peer.
- */
-static void
-internal_topology_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
-                            const struct GNUNET_ATS_Information *atsi,
-                            unsigned int atsi_count)
-{
-  struct CoreContext *core_ctx = cls;
-  struct TopologyIterateContext *iter_ctx = core_ctx->iter_context;
-
-  if (peer == NULL)             /* Either finished, or something went wrong */
-  {
-    iter_ctx->completed++;
-    iter_ctx->connected--;
-    /* One core context allocated per iteration, must free! */
-    GNUNET_free (core_ctx);
-  }
-  else
-  {
-    iter_ctx->topology_cb (iter_ctx->cls, &core_ctx->daemon->id, peer, NULL);
-  }
-
-  if (iter_ctx->completed == iter_ctx->total)
-  {
-    iter_ctx->topology_cb (iter_ctx->cls, NULL, NULL, NULL);
-    /* Once all are done, free the iteration context */
-    GNUNET_free (iter_ctx);
-  }
-}
-
-/**
- * Check running topology iteration tasks, if below max start a new one, otherwise
- * schedule for some time in the future.
- */
-static void
-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) != 0)
-    return;
-
-  if (topology_context->connected >
-      topology_context->pg->max_outstanding_connections)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Delaying connect, we have too many outstanding connections!\n");
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_get_topology, core_context);
-  }
-  else
-  {
-    topology_context->connected++;
-
-    if (GNUNET_OK !=
-        GNUNET_CORE_iterate_peers (core_context->daemon->cfg,
-                                   &internal_topology_callback, core_context))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Topology iteration failed.\n");
-      internal_topology_callback (core_context, NULL, NULL, 0);
-    }
-  }
-}
-
-/**
- * Iterate over all (running) peers in the peer group, retrieve
- * all connections that each currently has.
- */
-void
-GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg,
-                             GNUNET_TESTING_NotifyTopology cb, void *cls)
-{
-  struct TopologyIterateContext *topology_context;
-  struct CoreContext *core_ctx;
-  unsigned int i;
-  unsigned int total_count;
-
-  /* Allocate a single topology iteration context */
-  topology_context = GNUNET_malloc (sizeof (struct TopologyIterateContext));
-  topology_context->topology_cb = cb;
-  topology_context->cls = cls;
-  topology_context->pg = pg;
-  total_count = 0;
-  for (i = 0; i < pg->total; i++)
-  {
-    if (pg->peers[i].daemon->running == GNUNET_YES)
-    {
-      /* Allocate one core context per core we need to connect to */
-      core_ctx = GNUNET_malloc (sizeof (struct CoreContext));
-      core_ctx->daemon = pg->peers[i].daemon;
-      /* Set back pointer to topology iteration context */
-      core_ctx->iter_context = topology_context;
-      GNUNET_SCHEDULER_add_now (&schedule_get_topology, core_ctx);
-      total_count++;
-    }
-  }
-  if (total_count == 0)
-  {
-    cb (cls, NULL, NULL, "Cannot iterate over topology, no running peers!");
-    GNUNET_free (topology_context);
-  }
-  else
-    topology_context->total = total_count;
-  return;
-}
-
-/**
- * Callback function to process statistic values.
- * This handler is here only really to insert a peer
- * identity (or daemon) so the statistics can be uniquely
- * tied to a single running peer.
- *
- * @param cls closure
- * @param subsystem name of subsystem that created the statistic
- * @param name the name of the datum
- * @param value the current value
- * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
- * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
- */
-static int
-internal_stats_callback (void *cls, const char *subsystem, const char *name,
-                         uint64_t value, int is_persistent)
-{
-  struct StatsCoreContext *core_context = cls;
-  struct StatsIterateContext *stats_context =
-      (struct StatsIterateContext *) core_context->iter_context;
-
-  return stats_context->proc (stats_context->cls, &core_context->daemon->id,
-                              subsystem, name, value, is_persistent);
-}
-
-
-/**
- * We don't need the statistics handle anymore, destroy it.
- * 
- * @param cls Closure (the statistics handle to destroy)
- * @param tc Task Context
- */
-static void
-internal_destroy_statistics (void *cls,
-                             const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_STATISTICS_Handle *h = cls;
-
-  GNUNET_STATISTICS_destroy (h, GNUNET_NO);
-}
-
-
-/**
- * Internal continuation call for statistics iteration.
- *
- * @param cls closure, the CoreContext for this iteration
- * @param success whether or not the statistics iterations
- *        was canceled or not (we don't care)
- */
-static void
-internal_stats_cont (void *cls, int success)
-{
-  struct StatsCoreContext *core_context = cls;
-  struct StatsIterateContext *stats_context =
-      (struct StatsIterateContext *) core_context->iter_context;
-
-  stats_context->connected--;
-  stats_context->completed++;
-
-  if (stats_context->completed == stats_context->total)
-  {
-    stats_context->cont (stats_context->cls, GNUNET_YES);
-    GNUNET_free (stats_context);
-  }
-
-  if (core_context->stats_handle != NULL)
-    /* Cannot destroy handle inside the continuation */
-    GNUNET_SCHEDULER_add_now (&internal_destroy_statistics,
-                              core_context->stats_handle);
-
-  GNUNET_free (core_context);
-}
-
-/**
- * Check running topology iteration tasks, if below max start a new one, otherwise
- * schedule for some time in the future.
- */
-static void
-schedule_get_statistics (void *cls,
-                         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) != 0)
-    return;
-
-  if (stats_context->connected > stats_context->pg->max_outstanding_connections)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Delaying connect, we have too many outstanding connections!\n");
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_get_statistics, core_context);
-  }
-  else
-  {
-    stats_context->connected++;
-    core_context->stats_handle =
-        GNUNET_STATISTICS_create ("testing", core_context->daemon->cfg);
-    if (core_context->stats_handle == NULL)
-    {
-      internal_stats_cont (core_context, GNUNET_NO);
-      return;
-    }
-
-    core_context->stats_get_handle =
-        GNUNET_STATISTICS_get (core_context->stats_handle, NULL, NULL,
-                               GNUNET_TIME_UNIT_FOREVER_REL,
-                               &internal_stats_cont, &internal_stats_callback,
-                               core_context);
-    if (core_context->stats_get_handle == NULL)
-      internal_stats_cont (core_context, GNUNET_NO);
-
-  }
-}
-
-struct DuplicateStats
-{
-  /**
-   * Next item in the list
-   */
-  struct DuplicateStats *next;
-
-  /**
-   * Nasty string, concatenation of relevant information.
-   */
-  char *unique_string;
-};
-
-/**
- * Check whether the combination of port/host/unix domain socket
- * already exists in the list of peers being checked for statistics.
- *
- * @param pg the peergroup in question
- * @param specific_peer the peer we're concerned with
- * @param stats_list the list to return to the caller
- *
- * @return GNUNET_YES if the statistics instance has been seen already,
- *         GNUNET_NO if not (and we may have added it to the list)
- */
-static int
-stats_check_existing (struct GNUNET_TESTING_PeerGroup *pg,
-                      struct PeerData *specific_peer,
-                      struct DuplicateStats **stats_list)
-{
-  struct DuplicateStats *pos;
-  char *unix_domain_socket;
-  unsigned long long port;
-  char *to_match;
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "testing",
-                                            "single_statistics_per_host"))
-    return GNUNET_NO;           /* Each peer has its own statistics instance, do nothing! */
-
-  pos = *stats_list;
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (specific_peer->cfg, "statistics",
-                                             "unixpath", &unix_domain_socket))
-    return GNUNET_NO;
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (specific_peer->cfg, "statistics",
-                                             "port", &port))
-  {
-    GNUNET_free (unix_domain_socket);
-    return GNUNET_NO;
-  }
-
-  if (specific_peer->daemon->hostname != NULL)
-    GNUNET_asprintf (&to_match, "%s%s%llu", specific_peer->daemon->hostname,
-                     unix_domain_socket, port);
-  else
-    GNUNET_asprintf (&to_match, "%s%llu", unix_domain_socket, port);
-
-  while (pos != NULL)
-  {
-    if (0 == strcmp (to_match, pos->unique_string))
-    {
-      GNUNET_free (unix_domain_socket);
-      GNUNET_free (to_match);
-      return GNUNET_YES;
-    }
-    pos = pos->next;
-  }
-  pos = GNUNET_malloc (sizeof (struct DuplicateStats));
-  pos->unique_string = to_match;
-  pos->next = *stats_list;
-  *stats_list = pos;
-  GNUNET_free (unix_domain_socket);
-  return GNUNET_NO;
-}
-
-/**
- * Iterate over all (running) peers in the peer group, retrieve
- * all statistics from each.
- *
- * @param pg the peergroup to iterate statistics of
- * @param cont continuation to call once all stats have been retrieved
- * @param proc processing function for each statistic from each peer
- * @param cls closure to pass to proc
- *
- */
-void
-GNUNET_TESTING_get_statistics (struct GNUNET_TESTING_PeerGroup *pg,
-                               GNUNET_STATISTICS_Callback cont,
-                               GNUNET_TESTING_STATISTICS_Iterator proc,
-                               void *cls)
-{
-  struct StatsIterateContext *stats_context;
-  struct StatsCoreContext *core_ctx;
-  unsigned int i;
-  unsigned int total_count;
-  struct DuplicateStats *stats_list;
-  struct DuplicateStats *pos;
-
-  stats_list = NULL;
-
-  /* Allocate a single stats iteration context */
-  stats_context = GNUNET_malloc (sizeof (struct StatsIterateContext));
-  stats_context->cont = cont;
-  stats_context->proc = proc;
-  stats_context->cls = cls;
-  stats_context->pg = pg;
-  total_count = 0;
-
-  for (i = 0; i < pg->total; i++)
-  {
-    if ((pg->peers[i].daemon->running == GNUNET_YES) &&
-        (GNUNET_NO == stats_check_existing (pg, &pg->peers[i], &stats_list)))
-    {
-      /* Allocate one core context per core we need to connect to */
-      core_ctx = GNUNET_malloc (sizeof (struct StatsCoreContext));
-      core_ctx->daemon = pg->peers[i].daemon;
-      /* Set back pointer to topology iteration context */
-      core_ctx->iter_context = stats_context;
-      GNUNET_SCHEDULER_add_now (&schedule_get_statistics, core_ctx);
-      total_count++;
-    }
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Retrieving stats from %u total instances.\n", total_count);
-  if (0 != total_count)
-    stats_context->total = total_count;
-  else
-    GNUNET_free (stats_context);
-  if (stats_list != NULL)
-  {
-    pos = stats_list;
-    while (pos != NULL)
-    {
-      GNUNET_free (pos->unique_string);
-      stats_list = pos->next;
-      GNUNET_free (pos);
-      pos = stats_list->next;
-    }
-  }
-  return;
-}
-
-/**
- * Stop the connection process temporarily.
- *
- * @param pg the peer group to stop connecting
- */
-void
-GNUNET_TESTING_stop_connections (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  pg->stop_connects = GNUNET_YES;
-}
-
-/**
- * Resume the connection process temporarily.
- *
- * @param pg the peer group to resume connecting
- */
-void
-GNUNET_TESTING_resume_connections (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  pg->stop_connects = GNUNET_NO;
-}
-
-/**
- * There are many ways to connect peers that are supported by this function.
- * To connect peers in the same topology that was created via the
- * GNUNET_TESTING_create_topology, the topology variable must be set to
- * GNUNET_TESTING_TOPOLOGY_NONE.  If the topology variable is specified,
- * a new instance of that topology will be generated and attempted to be
- * connected.  This could result in some connections being impossible,
- * because some topologies are non-deterministic.
- *
- * @param pg the peer group struct representing the running peers
- * @param topology which topology to connect the peers in
- * @param options options for connecting the topology
- * @param option_modifier modifier for options that take a parameter
- * @param connect_timeout how long to wait before giving up on connecting
- *                        two peers
- * @param connect_attempts how many times to attempt to connect two peers
- *                         over the connect_timeout duration
- * @param notify_callback notification to be called once all connections completed
- * @param notify_cls closure for notification callback
- *
- * @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)
-{
-  switch (topology)
-  {
-  case GNUNET_TESTING_TOPOLOGY_CLIQUE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating clique CONNECT topology\n");
-    create_clique (pg, &add_connections, CONNECT, GNUNET_NO);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating small world (ring) CONNECT topology\n");
-    create_small_world_ring (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating small world (2d-torus) CONNECT topology\n");
-    create_small_world (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_RING:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring CONNECT topology\n");
-    create_ring (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating 2d torus CONNECT topology\n");
-    create_2d_torus (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating Erdos-Renyi CONNECT topology\n");
-    create_erdos_renyi (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_INTERNAT:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating InterNAT CONNECT topology\n");
-    create_nated_internet (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating Scale Free CONNECT topology\n");
-    create_scale_free (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_LINE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Creating straight line CONNECT topology\n");
-    create_line (pg, &add_connections, CONNECT);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_NONE:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating no CONNECT topology\n");
-    copy_allowed_topology (pg);
-    break;
-  default:
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Unknown topology specification, can't connect peers!\n"));
-    return GNUNET_SYSERR;
-  }
-
-  switch (options)
-  {
-  case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Connecting random subset (%'.2f percent) of possible peers\n",
-                100 * option_modifier);
-    choose_random_connections (pg, option_modifier);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Connecting a minimum of %u peers each (if possible)\n",
-                (unsigned int) option_modifier);
-    choose_minimum (pg, (unsigned int) option_modifier);
-    break;
-  case GNUNET_TESTING_TOPOLOGY_OPTION_DFS:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Using DFS to connect a minimum of %u peers each (if possible)\n",
-                (unsigned int) option_modifier);
-#if FIXME
-    perform_dfs (pg, (int) option_modifier);
-#endif
-    break;
-  case GNUNET_TESTING_TOPOLOGY_OPTION_ADD_CLOSEST:
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Finding additional %u closest peers each (if possible)\n",
-                (unsigned int) option_modifier);
-#if FIXME
-    add_closest (pg, (unsigned int) option_modifier, &add_connections, CONNECT);
-#endif
-    break;
-  case GNUNET_TESTING_TOPOLOGY_OPTION_NONE:
-    break;
-  case GNUNET_TESTING_TOPOLOGY_OPTION_ALL:
-    break;
-  default:
-    break;
-  }
-
-  return connect_topology (pg, connect_timeout, connect_attempts,
-                           notify_callback, notify_cls);
-}
-
-/**
- * Lookup and return the number of SSH connections to a host.
- *
- * @param hostname the hostname to lookup in the list
- * @param pg the peergroup that the host belongs to
- *
- * @return the number of current ssh connections to the host
- */
-static unsigned int
-count_outstanding_at_host (const char *hostname,
-                           struct GNUNET_TESTING_PeerGroup *pg)
-{
-  struct OutstandingSSH *pos;
-
-  pos = pg->ssh_head;
-  while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0))
-    pos = pos->next;
-  GNUNET_assert (pos != NULL);
-  return pos->outstanding;
-}
-
-/**
- * Increment the number of SSH connections to a host by one.
- *
- * @param hostname the hostname to lookup in the list
- * @param pg the peergroup that the host belongs to
- *
- */
-static void
-increment_outstanding_at_host (const char *hostname,
-                               struct GNUNET_TESTING_PeerGroup *pg)
-{
-  struct OutstandingSSH *pos;
-
-  pos = pg->ssh_head;
-  while ((NULL != pos) && (strcmp (pos->hostname, hostname) != 0))
-    pos = pos->next;
-  GNUNET_assert (NULL != pos);
-  pos->outstanding++;
-}
-
-/**
- * Decrement the number of SSH connections to a host by one.
- *
- * @param hostname the hostname to lookup in the list
- * @param pg the peergroup that the host belongs to
- *
- */
-static void
-decrement_outstanding_at_host (const char *hostname,
-                               struct GNUNET_TESTING_PeerGroup *pg)
-{
-  struct OutstandingSSH *pos;
-
-  pos = pg->ssh_head;
-  while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0))
-    pos = pos->next;
-  GNUNET_assert (pos != NULL);
-  pos->outstanding--;
-}
-
-/**
- * Callback that is called whenever a hostkey is generated
- * for a peer.  Call the real callback and decrement the
- * starting counter for the peergroup.
- *
- * @param cls closure
- * @param id identifier for the daemon, NULL on error
- * @param d handle for the daemon
- * @param emsg error message (NULL on success)
- */
-static void
-internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                           struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  struct InternalStartContext *internal_context = cls;
-
-  internal_context->peer->pg->starting--;
-  internal_context->peer->pg->started++;
-  if (internal_context->hostname != NULL)
-    decrement_outstanding_at_host (internal_context->hostname,
-                                   internal_context->peer->pg);
-  if (internal_context->hostkey_callback != NULL)
-    internal_context->hostkey_callback (internal_context->hostkey_cls, id, d,
-                                        emsg);
-  else if (internal_context->peer->pg->started ==
-           internal_context->peer->pg->total)
-  {
-    internal_context->peer->pg->started = 0;    /* Internal startup may use this counter! */
-    GNUNET_TESTING_daemons_continue_startup (internal_context->peer->pg);
-  }
-}
-
-/**
- * Callback that is called whenever a peer has finished starting.
- * Call the real callback and decrement the starting counter
- * for the peergroup.
- *
- * @param cls closure
- * @param id identifier for the daemon, NULL on error
- * @param cfg config
- * @param d handle for the daemon
- * @param emsg error message (NULL on success)
- */
-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)
-{
-  struct InternalStartContext *internal_context = cls;
-
-  internal_context->peer->pg->starting--;
-  if (internal_context->hostname != NULL)
-    decrement_outstanding_at_host (internal_context->hostname,
-                                   internal_context->peer->pg);
-  if (internal_context->start_cb != NULL)
-    internal_context->start_cb (internal_context->start_cb_cls, id, cfg, d,
-                                emsg);
-}
-
-
-/**
- * Calls GNUNET_TESTING_daemon_continue_startup to set the daemon's state
- * from HOSTKEY_CREATED to TOPOLOGY_SETUP. Makes sure not to saturate a host
- * with requests delaying them when needed.
- *
- * @param cls closure: internal context of the daemon.
- * @param tc TaskContext
- */
-static void
-internal_continue_startup (void *cls,
-                           const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct InternalStartContext *internal_context = cls;
-
-  internal_context->peer->startup_task = GNUNET_SCHEDULER_NO_TASK;
-
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-  {
-    return;
-  }
-
-  if ((internal_context->peer->pg->starting <
-       internal_context->peer->pg->max_concurrent_ssh) ||
-      ((internal_context->hostname != NULL) &&
-       (count_outstanding_at_host
-        (internal_context->hostname,
-         internal_context->peer->pg) <
-        internal_context->peer->pg->max_concurrent_ssh)))
-  {
-    if (internal_context->hostname != NULL)
-      increment_outstanding_at_host (internal_context->hostname,
-                                     internal_context->peer->pg);
-    internal_context->peer->pg->starting++;
-    GNUNET_TESTING_daemon_continue_startup (internal_context->peer->daemon);
-  }
-  else
-  {
-    internal_context->peer->startup_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                      (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                      &internal_continue_startup,
-                                      internal_context);
-  }
-}
-
-/**
- * Callback for informing us about a successful
- * or unsuccessful churn start call.
- *
- * @param cls a ChurnContext
- * @param id the peer identity of the started peer
- * @param cfg the handle to the configuration of the peer
- * @param d handle to the daemon for the peer
- * @param emsg NULL on success, non-NULL on failure
- *
- */
-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)
-{
-  struct ChurnRestartContext *startup_ctx = cls;
-  struct ChurnContext *churn_ctx = startup_ctx->churn_ctx;
-
-  unsigned int total_left;
-  char *error_message;
-
-  error_message = NULL;
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Churn stop callback failed with error `%s'\n", emsg);
-    churn_ctx->num_failed_start++;
-  }
-  else
-  {
-    churn_ctx->num_to_start--;
-  }
-
-  total_left =
-      (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) +
-      (churn_ctx->num_to_start - churn_ctx->num_failed_start);
-
-  if (total_left == 0)
-  {
-    if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
-      GNUNET_asprintf (&error_message,
-                       "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!",
-                       churn_ctx->num_failed_start, churn_ctx->num_failed_stop);
-    churn_ctx->cb (churn_ctx->cb_cls, error_message);
-    GNUNET_free_non_null (error_message);
-    GNUNET_free (churn_ctx);
-    GNUNET_free (startup_ctx);
-  }
-}
-
-static void
-schedule_churn_restart (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PeerRestartContext *peer_restart_ctx = cls;
-  struct ChurnRestartContext *startup_ctx = peer_restart_ctx->churn_restart_ctx;
-
-  if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh)
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_churn_restart, peer_restart_ctx);
-  else
-  {
-    if (startup_ctx->churn_ctx->service != NULL)
-      GNUNET_TESTING_daemon_start_stopped_service (peer_restart_ctx->daemon,
-                                                   startup_ctx->
-                                                   churn_ctx->service,
-                                                   startup_ctx->timeout,
-                                                   &churn_start_callback,
-                                                   startup_ctx);
-    else
-      GNUNET_TESTING_daemon_start_stopped (peer_restart_ctx->daemon,
-                                           startup_ctx->timeout,
-                                           &churn_start_callback, startup_ctx);
-    GNUNET_free (peer_restart_ctx);
-  }
-}
-
-/**
- * Callback for informing us about a successful
- * or unsuccessful churn start call.
- *
- * @param cls a struct ServiceStartContext *startup_ctx
- * @param id the peer identity of the started peer
- * @param cfg the handle to the configuration of the peer
- * @param d handle to the daemon for the peer
- * @param emsg NULL on success, non-NULL on failure
- *
- */
-void
-service_start_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                        const struct GNUNET_CONFIGURATION_Handle *cfg,
-                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  struct ServiceStartContext *startup_ctx = (struct ServiceStartContext *) cls;
-
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Service start failed with error `%s'\n", emsg);
-  }
-
-  startup_ctx->outstanding--;
-  startup_ctx->remaining--;
-
-  if (startup_ctx->remaining == 0)
-  {
-    startup_ctx->cb (startup_ctx->cb_cls, NULL);
-    GNUNET_free (startup_ctx->service);
-    GNUNET_free (startup_ctx);
-  }
-}
-
-static void
-schedule_service_start (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PeerServiceStartContext *peer_ctx = cls;
-  struct ServiceStartContext *startup_ctx = peer_ctx->start_ctx;
-
-  if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh)
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_service_start, peer_ctx);
-  else
-  {
-
-    GNUNET_TESTING_daemon_start_service (peer_ctx->daemon, startup_ctx->service,
-                                         startup_ctx->timeout,
-                                         &service_start_callback, startup_ctx);
-    GNUNET_free (peer_ctx);
-  }
-}
-
-
-static void
-internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct InternalStartContext *internal_context = cls;
-
-  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
-  {
-    return;
-  }
-
-  if ((internal_context->peer->pg->starting <
-       internal_context->peer->pg->max_concurrent_ssh) ||
-      ((internal_context->hostname != NULL) &&
-       (count_outstanding_at_host
-        (internal_context->hostname,
-         internal_context->peer->pg) <
-        internal_context->peer->pg->max_concurrent_ssh)))
-  {
-    if (internal_context->hostname != NULL)
-      increment_outstanding_at_host (internal_context->hostname,
-                                     internal_context->peer->pg);
-    internal_context->peer->pg->starting++;
-    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,
-                                     internal_context->hostkey,
-                                     &internal_hostkey_callback,
-                                     internal_context,
-                                     &internal_startup_callback,
-                                     internal_context);
-  }
-  else
-  {
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &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_destroy (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 (GNUNET_NO, NULL, NULL, "ssh", "ssh", arg,
-                               "peerStartHelper.pl", tempdir, NULL);
-  GNUNET_assert (helper->proc != NULL);
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "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
- * after successfully generating hostkeys for each peer.
- *
- * @param pg the peer group to continue starting
- *
- */
-void
-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++)
-    {
-      pg->peers[i].startup_task =
-          GNUNET_SCHEDULER_add_now (&internal_continue_startup,
-                                    &pg->peers[i].internal_context);
-    }
-  }
-#else
-  pg->starting = 0;
-  for (i = 0; i < pg->total; i++)
-  {
-    pg->peers[i].startup_task =
-        GNUNET_SCHEDULER_add_now (&internal_continue_startup,
-                                  &pg->peers[i].internal_context);
-  }
-#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
- * applications.  The port numbers (any option called "PORT") will be
- * adjusted to ensure that no two peers running on the same system
- * have the same port(s) in their respective configurations.
- *
- * @param cfg configuration template to use
- * @param total number of daemons to start
- * @param max_concurrent_connections for testing, how many peers can
- *                                   we connect to simultaneously
- * @param max_concurrent_ssh when starting with ssh, how many ssh
- *        connections will we allow at once (based on remote hosts allowed!)
- * @param timeout total time allowed for peers to start
- * @param hostkey_callback function to call on each peers hostkey generation
- *        if NULL, peers will be started by this call, if non-null,
- *        GNUNET_TESTING_daemons_continue_startup must be called after
- *        successful hostkey generation
- * @param hostkey_cls closure for hostkey callback
- * @param cb function to call on each daemon that was started
- * @param cb_cls closure for cb
- * @param connect_callback function to call each time two hosts are connected
- * @param connect_callback_cls closure for connect_callback
- * @param hostnames linked list of host structs to use to start peers on
- *                  (NULL to run on localhost only)
- *
- * @return NULL on error, otherwise handle to control peer group
- */
-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)
-{
-  struct GNUNET_TESTING_PeerGroup *pg;
-  const struct GNUNET_TESTING_Host *hostpos;
-  const char *hostname;
-  const char *username;
-  char *baseservicehome;
-  char *newservicehome;
-  char *tmpdir;
-  char *hostkeys_file;
-  char *arg;
-  char *ssh_port_str;
-  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;
-  uint16_t sshport;
-  uint32_t upnum;
-  uint32_t fdnum;
-  uint64_t fs;
-  uint64_t total_hostkeys;
-  struct GNUNET_OS_Process *proc;
-
-  username = NULL;
-  if (0 == total)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-
-  upnum = 0;
-  fdnum = 0;
-  pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup));
-  pg->cfg = cfg;
-  pg->notify_connection = connect_callback;
-  pg->notify_connection_cls = connect_callback_cls;
-  pg->total = total;
-  pg->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  pg->peers = GNUNET_malloc (total * sizeof (struct PeerData));
-  pg->max_outstanding_connections = max_concurrent_connections;
-  pg->max_concurrent_ssh = max_concurrent_ssh;
-  if (NULL != hostnames)
-  {
-    off = 0;
-    hostpos = hostnames;
-    while (hostpos != NULL)
-    {
-      hostpos = hostpos->next;
-      off++;
-    }
-    pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
-    off = 0;
-
-    hostpos = hostnames;
-    while (hostpos != NULL)
-    {
-      pg->hosts[off].minport = LOW_PORT;
-      pg->hosts[off].hostname = GNUNET_strdup (hostpos->hostname);
-      if (hostpos->username != NULL)
-        pg->hosts[off].username = GNUNET_strdup (hostpos->username);
-      pg->hosts[off].sshport = hostpos->port;
-      hostpos = hostpos->next;
-      off++;
-    }
-
-    if (off == 0)
-    {
-      pg->hosts = NULL;
-    }
-    hostcnt = off;
-    minport = 0;
-    pg->num_hosts = off;
-  }
-  else
-  {
-    hostcnt = 0;
-    minport = LOW_PORT;
-  }
-
-  /* Create the servicehome directory for each remote peer */
-  GNUNET_assert (GNUNET_OK ==
-                 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
-                                                        "SERVICEHOME",
-                                                        &baseservicehome));
-  for (i = 0; i < pg->num_hosts; i++)
-  {
-    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);
-    else
-      GNUNET_asprintf (&arg, "%s", pg->hosts[i].hostname);
-    if (pg->hosts[i].sshport != 0)
-    {
-      GNUNET_asprintf (&ssh_port_str, "%d", pg->hosts[i].sshport);
-      proc =
-       GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", "-P", ssh_port_str,
-                                   "-q",
-                                   arg, "mkdir -p", tmpdir, NULL);
-    }
-    else
-      proc =
-       GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", arg, "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 ", tmpdir);
-    GNUNET_free (tmpdir);
-    GNUNET_free (arg);
-    GNUNET_OS_process_wait (proc);
-    GNUNET_OS_process_destroy (proc);
-  }
-  GNUNET_free (baseservicehome);
-  baseservicehome = NULL;
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING", "HOSTKEYSFILE",
-                                             &hostkeys_file))
-  {
-    if (GNUNET_YES != GNUNET_DISK_file_test (hostkeys_file))
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _("Could not read hostkeys file!\n"));
-    else
-    {
-      /* Check hostkey file size, read entire thing into memory */
-      fd = GNUNET_DISK_file_open (hostkeys_file, GNUNET_DISK_OPEN_READ,
-                                  GNUNET_DISK_PERM_NONE);
-      if (NULL == fd)
-      {
-        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open",
-                                  hostkeys_file);
-        GNUNET_free (hostkeys_file);
-        for (i = 0; i < pg->num_hosts; i++)
-        {
-          GNUNET_free (pg->hosts[i].hostname);
-          GNUNET_free_non_null (pg->hosts[i].username);
-        }
-        GNUNET_free (pg->peers);
-        GNUNET_free (pg->hosts);
-        GNUNET_free (pg);
-        return NULL;
-      }
-
-      if (GNUNET_OK != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES))
-        fs = 0;
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Found file size %llu for hostkeys\n", fs);
-      if (0 != (fs % HOSTKEYFILESIZE))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                    "File size %llu seems incorrect for hostkeys...\n", fs);
-      }
-      else
-      {
-        total_hostkeys = fs / HOSTKEYFILESIZE;
-        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));
-      }
-      GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
-    }
-    GNUNET_free (hostkeys_file);
-  }
-
-  for (off = 0; off < total; off++)
-  {
-    if (hostcnt > 0)
-    {
-      hostname = pg->hosts[off % hostcnt].hostname;
-      username = pg->hosts[off % hostcnt].username;
-      sshport = pg->hosts[off % hostcnt].sshport;
-      pcfg =
-          GNUNET_TESTING_create_cfg (cfg, off, &pg->hosts[off % hostcnt].minport, &upnum,
-                       hostname, &fdnum);
-    }
-    else
-    {
-      hostname = NULL;
-      username = NULL;
-      sshport = 0;
-      pcfg = GNUNET_TESTING_create_cfg (cfg, off, &minport, &upnum, hostname, &fdnum);
-    }
-
-    if (NULL == pcfg)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Could not create configuration for peer number %u on `%s'!\n"),
-                  off, hostname == NULL ? "localhost" : hostname);
-      continue;
-    }
-
-    if (GNUNET_YES ==
-        GNUNET_CONFIGURATION_get_value_string (pcfg, "PATHS", "SERVICEHOME",
-                                               &baseservicehome))
-    {
-      if (hostname != NULL)
-        GNUNET_asprintf (&newservicehome, "%s/%s/%d/", baseservicehome,
-                         hostname, off);
-      else
-        GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off);
-      GNUNET_free (baseservicehome);
-      baseservicehome = NULL;
-    }
-    else
-    {
-      tmpdir = getenv ("TMPDIR");
-      tmpdir = tmpdir ? tmpdir : "/tmp";
-      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;
-    pg->peers[off].pg = pg;
-    pg->peers[off].internal_context.peer = &pg->peers[off];
-    pg->peers[off].internal_context.timeout = timeout;
-    pg->peers[off].internal_context.hostname = hostname;
-    pg->peers[off].internal_context.username = username;
-    pg->peers[off].internal_context.sshport = sshport;
-    if (pg->hostkey_data != NULL)
-      pg->peers[off].internal_context.hostkey =
-          &pg->hostkey_data[off * HOSTKEYFILESIZE];
-    pg->peers[off].internal_context.hostkey_callback = hostkey_callback;
-    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++)
-    {
-
-      if (hostcnt > 0)
-      {
-        hostname = pg->hosts[off % hostcnt].hostname;
-        username = pg->hosts[off % hostcnt].username;
-        sshport = pg->hosts[off % hostcnt].sshport;
-      }
-      else
-      {
-        hostname = NULL;
-        username = NULL;
-        sshport = 0;
-      }
-
-      if (GNUNET_YES ==
-          GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
-                                                 &baseservicehome))
-      {
-        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "baseservice home is %s\n",
-                    baseservicehome);
-        if (hostname != NULL)
-          GNUNET_asprintf (&newservicehome, "%s/%s/", baseservicehome,
-                           hostname);
-        else
-          GNUNET_asprintf (&newservicehome, "%s/", baseservicehome);
-        GNUNET_free (baseservicehome);
-        baseservicehome = NULL;
-      }
-      else
-      {
-        tmpdir = getenv ("TMPDIR");
-        tmpdir = tmpdir ? tmpdir : "/tmp";
-        if (hostname != NULL)
-          GNUNET_asprintf (&newservicehome, "%s/%s/%s/", tmpdir, hostname,
-                           "gnunet-testing-test-test");
-        else
-          GNUNET_asprintf (&newservicehome, "%s/%s/", tmpdir,
-                           "gnunet-testing-test-test", off);
-      }
-
-      if (NULL != username)
-        GNUNET_asprintf (&arg, "%s@%s:%s", username, pg->hosts[off].hostname,
-                         newservicehome);
-      else
-        GNUNET_asprintf (&arg, "%s:%s", pg->hosts[off].hostname,
-                         newservicehome);
-
-      /* FIXME: Doesn't support ssh_port option! */
-      proc =
-       GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "rsync", "rsync", "-r",
-                                   newservicehome, arg, NULL);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "copying directory with command rsync -r %s %s\n",
-                  newservicehome, arg);
-      GNUNET_free (newservicehome);
-      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_destroy (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);
-  }
-#endif
-  return pg;
-}
-
-/*
- * Get a daemon by number, so callers don't have to do nasty
- * offsetting operation.
- */
-struct GNUNET_TESTING_Daemon *
-GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg,
-                           unsigned int position)
-{
-  if (position < pg->total)
-    return pg->peers[position].daemon;
-  return NULL;
-}
-
-/*
- * Get a daemon by peer identity, so callers can
- * retrieve the daemon without knowing it's offset.
- *
- * @param pg the peer group to retrieve the daemon from
- * @param peer_id the peer identity of the daemon to retrieve
- *
- * @return the daemon on success, or NULL if no such peer identity is found
- */
-struct GNUNET_TESTING_Daemon *
-GNUNET_TESTING_daemon_get_by_id (struct GNUNET_TESTING_PeerGroup *pg,
-                                 const struct GNUNET_PeerIdentity *peer_id)
-{
-  unsigned int i;
-
-  for (i = 0; i < pg->total; i++)
-  {
-    if (0 ==
-        memcmp (&pg->peers[i].daemon->id, peer_id,
-                sizeof (struct GNUNET_PeerIdentity)))
-      return pg->peers[i].daemon;
-  }
-  return NULL;
-}
-
-/**
- * Prototype of a function that will be called when a
- * particular operation was completed the testing library.
- *
- * @param cls closure (a struct RestartContext)
- * @param id id of the peer that was restarted
- * @param cfg handle to the configuration of the peer
- * @param d handle to the daemon that was restarted
- * @param emsg NULL on success
- */
-static void
-restart_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                  const struct GNUNET_CONFIGURATION_Handle *cfg,
-                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  struct RestartContext *restart_context = cls;
-
-  if (emsg == NULL)
-  {
-    restart_context->peers_restarted++;
-  }
-  else
-  {
-    restart_context->peers_restart_failed++;
-  }
-
-  if (restart_context->peers_restarted == restart_context->peer_group->total)
-  {
-    restart_context->callback (restart_context->callback_cls, NULL);
-    GNUNET_free (restart_context);
-  }
-  else if (restart_context->peers_restart_failed +
-           restart_context->peers_restarted ==
-           restart_context->peer_group->total)
-  {
-    restart_context->callback (restart_context->callback_cls,
-                               "Failed to restart peers!");
-    GNUNET_free (restart_context);
-  }
-
-}
-
-/**
- * Callback for informing us about a successful
- * or unsuccessful churn stop call.
- *
- * @param cls a ChurnContext
- * @param emsg NULL on success, non-NULL on failure
- *
- */
-static void
-churn_stop_callback (void *cls, const char *emsg)
-{
-  struct ShutdownContext *shutdown_ctx = cls;
-  struct ChurnContext *churn_ctx = shutdown_ctx->cb_cls;
-  unsigned int total_left;
-  char *error_message;
-
-  error_message = NULL;
-  shutdown_ctx->outstanding--;
-
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Churn stop callback failed with error `%s'\n", emsg);
-    churn_ctx->num_failed_stop++;
-  }
-  else
-  {
-    churn_ctx->num_to_stop--;
-  }
-
-  total_left =
-      (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) +
-      (churn_ctx->num_to_start - churn_ctx->num_failed_start);
-
-  if (total_left == 0)
-  {
-    if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
-    {
-      GNUNET_asprintf (&error_message,
-                       "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!",
-                       churn_ctx->num_failed_start, churn_ctx->num_failed_stop);
-    }
-    churn_ctx->cb (churn_ctx->cb_cls, error_message);
-    GNUNET_free_non_null (error_message);
-    GNUNET_free (churn_ctx);
-    GNUNET_free (shutdown_ctx);
-  }
-}
-
-/**
- * Count the number of running peers.
- *
- * @param pg handle for the peer group
- *
- * @return the number of currently running peers in the peer group
- */
-unsigned int
-GNUNET_TESTING_daemons_running (struct GNUNET_TESTING_PeerGroup *pg)
-{
-  unsigned int i;
-  unsigned int running = 0;
-
-  for (i = 0; i < pg->total; i++)
-  {
-    if (pg->peers[i].daemon->running == GNUNET_YES)
-    {
-      GNUNET_assert (running != -1);
-      running++;
-    }
-  }
-  return running;
-}
-
-/**
- * Task to rate limit the number of outstanding peer shutdown
- * requests.  This is necessary for making sure we don't do
- * too many ssh connections at once, but is generally nicer
- * to any system as well (graduated task starts, as opposed
- * to calling gnunet-arm N times all at once).
- */
-static void
-schedule_churn_shutdown_task (void *cls,
-                              const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PeerShutdownContext *peer_shutdown_ctx = cls;
-  struct ShutdownContext *shutdown_ctx;
-  struct ChurnContext *churn_ctx;
-
-  GNUNET_assert (peer_shutdown_ctx != NULL);
-  shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
-  GNUNET_assert (shutdown_ctx != NULL);
-  churn_ctx = (struct ChurnContext *) shutdown_ctx->cb_cls;
-  if (shutdown_ctx->outstanding > churn_ctx->pg->max_concurrent_ssh)
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_churn_shutdown_task,
-                                  peer_shutdown_ctx);
-  else
-  {
-    shutdown_ctx->outstanding++;
-    if (churn_ctx->service != NULL)
-      GNUNET_TESTING_daemon_stop_service (peer_shutdown_ctx->daemon,
-                                          churn_ctx->service,
-                                          shutdown_ctx->timeout,
-                                          shutdown_ctx->cb, shutdown_ctx);
-    else
-      GNUNET_TESTING_daemon_stop (peer_shutdown_ctx->daemon,
-                                  shutdown_ctx->timeout, shutdown_ctx->cb,
-                                  shutdown_ctx, GNUNET_NO, GNUNET_YES);
-    GNUNET_free (peer_shutdown_ctx);
-  }
-}
-
-
-/**
- * Simulate churn by stopping some peers (and possibly
- * re-starting others if churn is called multiple times).  This
- * function can only be used to create leave-join churn (peers "never"
- * leave for good).  First "voff" random peers that are currently
- * online will be taken offline; then "von" random peers that are then
- * offline will be put back online.  No notifications will be
- * generated for any of these operations except for the callback upon
- * completion.
- *
- * @param pg handle for the peer group
- * @param service the service to churn off/on, NULL to churn peer
- * @param voff number of peers that should go offline
- * @param von number of peers that should come back online;
- *            must be zero on first call (since "testbed_start"
- *            always starts all of the peers)
- * @param timeout how long to wait for operations to finish before
- *        giving up
- * @param cb function to call at the end
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg,
-                              char *service, 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;
-  struct PeerShutdownContext *peer_shutdown_ctx;
-  struct PeerRestartContext *peer_restart_ctx;
-  struct ChurnRestartContext *churn_startup_ctx;
-
-  unsigned int running;
-  unsigned int stopped;
-  unsigned int total_running;
-  unsigned int total_stopped;
-  unsigned int i;
-  unsigned int *running_arr;
-  unsigned int *stopped_arr;
-  unsigned int *running_permute;
-  unsigned int *stopped_permute;
-  char *pos;
-
-  shutdown_ctx = NULL;
-  peer_shutdown_ctx = NULL;
-  peer_restart_ctx = NULL;
-  churn_startup_ctx = NULL;
-
-  running = 0;
-  stopped = 0;
-
-  if ((von == 0) && (voff == 0))        /* No peers at all? */
-  {
-    cb (cb_cls, NULL);
-    return;
-  }
-
-  for (i = 0; i < pg->total; i++)
-  {
-    if (service == NULL)
-    {
-      if (pg->peers[i].daemon->running == GNUNET_YES)
-      {
-        GNUNET_assert (running != -1);
-        running++;
-      }
-      else
-      {
-        GNUNET_assert (stopped != -1);
-        stopped++;
-      }
-    }
-    else
-    {
-      /* FIXME: make churned services a list! */
-      pos = pg->peers[i].daemon->churned_services;
-      /* FIXME: while (pos != NULL) */
-      if (pos != NULL)
-      {
-#if FIXME
-        if (0 == strcasecmp (pos, service))
-        {
-
-          break;
-        }
-#endif
-        GNUNET_assert (stopped != -1);
-        stopped++;
-        /* FIXME: pos = pos->next; */
-      }
-      if (pos == NULL)
-      {
-        GNUNET_assert (running != -1);
-        running++;
-      }
-    }
-  }
-
-  if (voff > running)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Trying to stop more peers (%d) than are currently running (%d)!\n",
-                voff, running);
-    cb (cb_cls, "Trying to stop more peers than are currently running!");
-    return;
-  }
-
-  if (von > stopped)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Trying to start more peers (%d) than are currently stopped (%d)!\n",
-                von, stopped);
-    cb (cb_cls, "Trying to start more peers than are currently stopped!");
-    return;
-  }
-
-  churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext));
-
-  if (service != NULL)
-    churn_ctx->service = GNUNET_strdup (service);
-  running_arr = NULL;
-  if (running > 0)
-    running_arr = GNUNET_malloc (running * sizeof (unsigned int));
-
-  stopped_arr = NULL;
-  if (stopped > 0)
-    stopped_arr = GNUNET_malloc (stopped * sizeof (unsigned int));
-
-  running_permute = NULL;
-  stopped_permute = NULL;
-
-  if (running > 0)
-    running_permute =
-        GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, running);
-  if (stopped > 0)
-    stopped_permute =
-        GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, stopped);
-
-  total_running = running;
-  total_stopped = stopped;
-  running = 0;
-  stopped = 0;
-
-  churn_ctx->num_to_start = von;
-  churn_ctx->num_to_stop = voff;
-  churn_ctx->cb = cb;
-  churn_ctx->cb_cls = cb_cls;
-  churn_ctx->pg = pg;
-
-  for (i = 0; i < pg->total; i++)
-  {
-    if (service == NULL)
-    {
-      if (pg->peers[i].daemon->running == GNUNET_YES)
-      {
-        GNUNET_assert ((running_arr != NULL) && (total_running > running));
-        running_arr[running] = i;
-        running++;
-      }
-      else
-      {
-        GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped));
-        stopped_arr[stopped] = i;
-        stopped++;
-      }
-    }
-    else
-    {
-      /* FIXME: make churned services a list! */
-      pos = pg->peers[i].daemon->churned_services;
-      /* FIXME: while (pos != NULL) */
-      if (pos != NULL)
-      {
-        GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped));
-        stopped_arr[stopped] = i;
-        stopped++;
-        /* FIXME: pos = pos->next; */
-      }
-      if (pos == NULL)
-      {
-        GNUNET_assert ((running_arr != NULL) && (total_running > running));
-        running_arr[running] = i;
-        running++;
-      }
-    }
-  }
-
-  GNUNET_assert (running >= voff);
-  if (voff > 0)
-  {
-    shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
-    shutdown_ctx->cb = &churn_stop_callback;
-    shutdown_ctx->cb_cls = churn_ctx;
-    shutdown_ctx->total_peers = voff;
-    shutdown_ctx->timeout = timeout;
-  }
-
-  for (i = 0; i < voff; i++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peer %d!\n",
-                running_arr[running_permute[i]]);
-    GNUNET_assert (running_arr != NULL);
-    peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext));
-    peer_shutdown_ctx->daemon =
-        pg->peers[running_arr[running_permute[i]]].daemon;
-    peer_shutdown_ctx->shutdown_ctx = shutdown_ctx;
-    GNUNET_SCHEDULER_add_now (&schedule_churn_shutdown_task, peer_shutdown_ctx);
-  }
-
-  GNUNET_assert (stopped >= von);
-  if (von > 0)
-  {
-    churn_startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext));
-    churn_startup_ctx->churn_ctx = churn_ctx;
-    churn_startup_ctx->timeout = timeout;
-    churn_startup_ctx->pg = pg;
-  }
-  for (i = 0; i < von; i++)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting up peer %d!\n",
-                stopped_arr[stopped_permute[i]]);
-    GNUNET_assert (stopped_arr != NULL);
-    peer_restart_ctx = GNUNET_malloc (sizeof (struct PeerRestartContext));
-    peer_restart_ctx->churn_restart_ctx = churn_startup_ctx;
-    peer_restart_ctx->daemon =
-        pg->peers[stopped_arr[stopped_permute[i]]].daemon;
-    GNUNET_SCHEDULER_add_now (&schedule_churn_restart, peer_restart_ctx);
-  }
-
-  GNUNET_free_non_null (running_arr);
-  GNUNET_free_non_null (stopped_arr);
-  GNUNET_free_non_null (running_permute);
-  GNUNET_free_non_null (stopped_permute);
-}
-
-/*
- * Start a given service for each of the peers in the peer group.
- *
- * @param pg handle for the peer group
- * @param service the service to start
- * @param timeout how long to wait for operations to finish before
- *        giving up
- * @param cb function to call once finished
- * @param cb_cls closure for cb
- *
- */
-void
-GNUNET_TESTING_daemons_start_service (struct GNUNET_TESTING_PeerGroup *pg,
-                                      char *service,
-                                      struct GNUNET_TIME_Relative timeout,
-                                      GNUNET_TESTING_NotifyCompletion cb,
-                                      void *cb_cls)
-{
-  struct ServiceStartContext *start_ctx;
-  struct PeerServiceStartContext *peer_start_ctx;
-  unsigned int i;
-
-  GNUNET_assert (service != NULL);
-
-  start_ctx = GNUNET_malloc (sizeof (struct ServiceStartContext));
-  start_ctx->pg = pg;
-  start_ctx->remaining = pg->total;
-  start_ctx->cb = cb;
-  start_ctx->cb_cls = cb_cls;
-  start_ctx->service = GNUNET_strdup (service);
-  start_ctx->timeout = timeout;
-
-  for (i = 0; i < pg->total; i++)
-  {
-    peer_start_ctx = GNUNET_malloc (sizeof (struct PeerServiceStartContext));
-    peer_start_ctx->start_ctx = start_ctx;
-    peer_start_ctx->daemon = pg->peers[i].daemon;
-    GNUNET_SCHEDULER_add_now (&schedule_service_start, peer_start_ctx);
-  }
-}
-
-/**
- * Restart all peers in the given group.
- *
- * @param pg the handle to the peer group
- * @param callback function to call on completion (or failure)
- * @param callback_cls closure for the callback function
- */
-void
-GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg,
-                                GNUNET_TESTING_NotifyCompletion callback,
-                                void *callback_cls)
-{
-  struct RestartContext *restart_context;
-  unsigned int off;
-
-  if (pg->total > 0)
-  {
-    restart_context = GNUNET_malloc (sizeof (struct RestartContext));
-    restart_context->peer_group = pg;
-    restart_context->peers_restarted = 0;
-    restart_context->callback = callback;
-    restart_context->callback_cls = callback_cls;
-
-    for (off = 0; off < pg->total; off++)
-    {
-      GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback,
-                                     restart_context);
-    }
-  }
-}
-
-
-/**
- * Start or stop an individual peer from the given group.
- *
- * @param pg handle to the peer group
- * @param offset which peer to start or stop
- * @param desired_status GNUNET_YES to have it running, GNUNET_NO to stop it
- * @param timeout how long to wait for shutdown
- * @param cb function to call at the end
- * @param cb_cls closure for cb
- */
-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)
-{
-  struct ShutdownContext *shutdown_ctx;
-  struct ChurnRestartContext *startup_ctx;
-  struct ChurnContext *churn_ctx;
-
-  if (GNUNET_NO == desired_status)
-  {
-    if (NULL != pg->peers[offset].daemon)
-    {
-      shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
-      churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext));
-      churn_ctx->num_to_start = 0;
-      churn_ctx->num_to_stop = 1;
-      churn_ctx->cb = cb;
-      churn_ctx->cb_cls = cb_cls;
-      shutdown_ctx->cb_cls = churn_ctx;
-      GNUNET_TESTING_daemon_stop (pg->peers[offset].daemon, timeout,
-                                  &churn_stop_callback, shutdown_ctx, GNUNET_NO,
-                                  GNUNET_YES);
-    }
-  }
-  else if (GNUNET_YES == desired_status)
-  {
-    if (NULL == pg->peers[offset].daemon)
-    {
-      startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext));
-      churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext));
-      churn_ctx->num_to_start = 1;
-      churn_ctx->num_to_stop = 0;
-      churn_ctx->cb = cb;
-      churn_ctx->cb_cls = cb_cls;
-      startup_ctx->churn_ctx = churn_ctx;
-      GNUNET_TESTING_daemon_start_stopped (pg->peers[offset].daemon, timeout,
-                                           &churn_start_callback, startup_ctx);
-    }
-  }
-  else
-    GNUNET_break (0);
-}
-
-
-/**
- * Callback for shutting down peers in a peer group.
- *
- * @param cls closure (struct ShutdownContext)
- * @param emsg NULL on success
- */
-static void
-internal_shutdown_callback (void *cls, const char *emsg)
-{
-  struct PeerShutdownContext *peer_shutdown_ctx = cls;
-  struct ShutdownContext *shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
-  unsigned int off;
-  int i;
-  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++;
-  }
-  else
-  {
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "internal_shutdown_callback",
-                     "Failed to stop a peer: %s\n", emsg);
-    shutdown_ctx->peers_failed++;
-  }
-
-  if ((shutdown_ctx->cb != NULL) &&
-      (shutdown_ctx->peers_down + shutdown_ctx->peers_failed ==
-       shutdown_ctx->total_peers))
-  {
-    if (shutdown_ctx->peers_failed > 0)
-      shutdown_ctx->cb (shutdown_ctx->cb_cls,
-                        "Not all peers successfully shut down!");
-    else
-      shutdown_ctx->cb (shutdown_ctx->cb_cls, NULL);
-
-    for (i = 0; i < shutdown_ctx->pg->total; i++)
-    {
-      if (shutdown_ctx->pg->peers[i].startup_task != GNUNET_SCHEDULER_NO_TASK)
-        GNUNET_SCHEDULER_cancel (shutdown_ctx->pg->peers[i].startup_task);
-    }
-    GNUNET_free (shutdown_ctx->pg->peers);
-    GNUNET_free_non_null (shutdown_ctx->pg->hostkey_data);
-    for (off = 0; off < shutdown_ctx->pg->num_hosts; off++)
-    {
-      GNUNET_free (shutdown_ctx->pg->hosts[off].hostname);
-      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);
-}
-
-
-/**
- * Task to rate limit the number of outstanding peer shutdown
- * requests.  This is necessary for making sure we don't do
- * too many ssh connections at once, but is generally nicer
- * to any system as well (graduated task starts, as opposed
- * to calling gnunet-arm N times all at once).
- */
-static void
-schedule_shutdown_task (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PeerShutdownContext *peer_shutdown_ctx = cls;
-  struct ShutdownContext *shutdown_ctx;
-  struct GNUNET_TESTING_Daemon *d;
-
-  GNUNET_assert (peer_shutdown_ctx != NULL);
-  d = peer_shutdown_ctx->daemon;
-  shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
-  GNUNET_assert (shutdown_ctx != NULL);
-
-  if ((shutdown_ctx->outstanding < shutdown_ctx->pg->max_concurrent_ssh) ||
-      ((d->hostname != NULL) &&
-       (count_outstanding_at_host
-        (d->hostname,
-         shutdown_ctx->pg) < shutdown_ctx->pg->max_concurrent_ssh)))
-  {
-    if (d->hostname != NULL)
-      increment_outstanding_at_host (d->hostname,
-                                     shutdown_ctx->pg);
-    shutdown_ctx->outstanding++;
-    GNUNET_TESTING_daemon_stop (d,
-                                shutdown_ctx->timeout,
-                                &internal_shutdown_callback, peer_shutdown_ctx,
-                                shutdown_ctx->delete_files, GNUNET_NO);
-  }
-  else
-    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
-                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
-                                  &schedule_shutdown_task, peer_shutdown_ctx);
-
-}
-
-/**
- * Read a testing hosts file based on a configuration.
- * Returns a DLL of hosts (caller must free!) on success
- * or NULL on failure.
- *
- * @param cfg a configuration with a testing section
- *
- * @return DLL of hosts on success, NULL on failure
- */
-struct GNUNET_TESTING_Host *
-GNUNET_TESTING_hosts_load (const struct GNUNET_CONFIGURATION_Handle *cfg)
-{
-  struct GNUNET_TESTING_Host *hosts;
-  struct GNUNET_TESTING_Host *temphost;
-  char *data;
-  char *buf;
-  char *hostfile;
-  struct stat frstat;
-  int count;
-  int ret;
-
-  /* Check for a hostfile containing user@host:port triples */
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile",
-                                             &hostfile))
-    return NULL;
-
-  hosts = NULL;
-  temphost = NULL;
-  data = NULL;
-  if (hostfile != NULL)
-  {
-    if (GNUNET_OK != GNUNET_DISK_file_test (hostfile))
-      GNUNET_DISK_fn_write (hostfile, NULL, 0,
-                            GNUNET_DISK_PERM_USER_READ |
-                            GNUNET_DISK_PERM_USER_WRITE);
-    if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Could not open file specified for host list, ending test!");
-      GNUNET_free (hostfile);
-      return NULL;
-    }
-
-    data = GNUNET_malloc_large (frstat.st_size);
-    GNUNET_assert (data != NULL);
-    if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size))
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  "Could not read file %s specified for host list, ending test!",
-                  hostfile);
-      GNUNET_free (hostfile);
-      GNUNET_free (data);
-      return NULL;
-    }
-
-    GNUNET_free_non_null (hostfile);
-
-    buf = data;
-    count = 0;
-    while (count < frstat.st_size - 1)
-    {
-      count++;
-      if (((data[count] == '\n')) && (buf != &data[count]))
-      {
-        data[count] = '\0';
-        temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host));
-        ret =
-            SSCANF (buf, "%a[a-zA-Z0-9_]@%a[a-zA-Z0-9.]:%hd",
-                    &temphost->username, &temphost->hostname, &temphost->port);
-        if (3 == ret)
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                      "Successfully read host %s, port %d and user %s from file\n",
-                      temphost->hostname, temphost->port, temphost->username);
-        }
-        else
-        {
-          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                      "Error reading line `%s' in hostfile\n", buf);
-          GNUNET_free (temphost);
-          buf = &data[count + 1];
-          continue;
-        }
-        temphost->next = hosts;
-        hosts = temphost;
-        buf = &data[count + 1];
-      }
-      else if ((data[count] == '\n') || (data[count] == '\0'))
-        buf = &data[count + 1];
-    }
-  }
-  GNUNET_free_non_null (data);
-
-  return hosts;
-}
-
-/**
- * Shutdown all peers started in the given group.
- *
- * @param pg handle to the peer group
- * @param timeout how long to wait for shutdown
- * @param cb callback to notify upon success or failure
- * @param cb_cls closure for cb
- */
-void
-GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg,
-                             struct GNUNET_TIME_Relative timeout,
-                             GNUNET_TESTING_NotifyCompletion cb, void *cb_cls)
-{
-  unsigned int off;
-  struct ShutdownContext *shutdown_ctx;
-  struct PeerShutdownContext *peer_shutdown_ctx;
-
-#if OLD
-  struct PeerConnection *conn_iter;
-  struct PeerConnection *temp_conn;
-#endif
-  struct ConnectContext *cc;
-
-  GNUNET_assert (pg->total > 0);
-  while (NULL != (cc = pg->cc_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, cc);
-    if (GNUNET_SCHEDULER_NO_TASK != cc->task)
-      GNUNET_SCHEDULER_cancel (cc->task);
-    if (NULL != cc->cc)
-      GNUNET_TESTING_daemons_connect_cancel (cc->cc);
-    GNUNET_free (cc);
-  }
-
-  shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
-  shutdown_ctx->delete_files =
-      GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "DELETE_FILES");
-  shutdown_ctx->cb = cb;
-  shutdown_ctx->cb_cls = cb_cls;
-  shutdown_ctx->total_peers = pg->total;
-  shutdown_ctx->timeout = timeout;
-  shutdown_ctx->pg = pg;
-
-  for (off = 0; off < pg->total; off++)
-  {
-    GNUNET_assert (NULL != pg->peers[off].daemon);
-    peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext));
-    peer_shutdown_ctx->daemon = pg->peers[off].daemon;
-    peer_shutdown_ctx->shutdown_ctx = shutdown_ctx;
-    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
-// FIXME Do DLL remove for all pg->peers[off].LIST
-    conn_iter = pg->peers[off].allowed_peers_head;
-    while (conn_iter != NULL)
-    {
-      temp_conn = conn_iter->next;
-      GNUNET_free (conn_iter);
-      conn_iter = temp_conn;
-    }
-    pg->peers[off].allowed_peers_head = NULL;
-
-    conn_iter = pg->peers[off].connect_peers_head;
-    while (conn_iter != NULL)
-    {
-      temp_conn = conn_iter->next;
-      GNUNET_free (conn_iter);
-      conn_iter = temp_conn;
-    }
-    pg->peers[off].connect_peers_head = NULL;
-
-    conn_iter = pg->peers[off].blacklisted_peers_head;
-    while (conn_iter != NULL)
-    {
-      temp_conn = conn_iter->next;
-      GNUNET_free (conn_iter);
-      conn_iter = temp_conn;
-    }
-    pg->peers[off].blacklisted_peers_head = NULL;
-
-    conn_iter = pg->peers[off].connect_peers_working_set_head;
-    while (conn_iter != NULL)
-    {
-      temp_conn = conn_iter->next;
-      GNUNET_free (conn_iter);
-      conn_iter = temp_conn;
-    }
-    pg->peers[off].connect_peers_working_set_head = NULL;
-#else
-    if (pg->peers[off].allowed_peers != NULL)
-      GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].allowed_peers);
-    if (pg->peers[off].connect_peers != NULL)
-      GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].connect_peers);
-    if (pg->peers[off].blacklisted_peers != NULL)
-      GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].blacklisted_peers);
-#endif
-  }
-}
-
-/* end of testing_group.c */
diff --git a/src/testing/testing_peergroup.c b/src/testing/testing_peergroup.c
deleted file mode 100644 (file)
index 87504ed..0000000
+++ /dev/null
@@ -1,1017 +0,0 @@
-/*
- This file is part of GNUnet
- (C) 2008-2011 Christian Grothoff (and other contributing authors)
-
- 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 3, or (at your
- option) any later version.
-
- GNUnet is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNUnet; see the file COPYING.  If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- */
-
-/**
- * @file testing/testing_peergroup.c
- * @brief API implementation for easy peer group creation
- * @author Nathan Evans
- * @author Christian Grothoff
- *
- */
-#include "platform.h"
-#include "gnunet_constants.h"
-#include "gnunet_arm_service.h"
-#include "gnunet_testing_lib.h"
-#include "gnunet_core_service.h"
-#include "gnunet_disk_lib.h"
-
-/** Globals **/
-#define DEFAULT_CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
-
-#define DEFAULT_CONNECT_ATTEMPTS 2
-
-/** Struct definitions **/
-
-struct PeerGroupStartupContext
-{
-  struct GNUNET_TESTING_PeerGroup *pg;
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
-  unsigned int total;
-  unsigned int peers_left;
-  unsigned long long max_concurrent_connections;
-
-  /**
-   * Maximum attemps to connect two daemons.
-   */
-  unsigned long long connect_attempts;
-
-  /**
-   * How long to spend trying to establish all the connections?
-   */
-  struct GNUNET_TIME_Relative connect_timeout;
-
-  unsigned long long max_concurrent_ssh;
-  struct GNUNET_TIME_Absolute timeout;
-  GNUNET_TESTING_NotifyConnection connect_cb;
-  GNUNET_TESTING_NotifyCompletion peergroup_cb;
-
-  /**
-   * Closure for all peergroup callbacks.
-   */
-  void *cls;
-
-  const struct GNUNET_TESTING_Host *hostnames;
-  
-  /**
-   * FIXME document
-   */
-  enum GNUNET_TESTING_Topology topology;
-
-  float topology_percentage;
-
-  float topology_probability;
-
-  /**
-   * FIXME document
-   */
-  enum GNUNET_TESTING_Topology restrict_topology;
-  
-  /**
-   * FIXME document
-   */
-  char *restrict_transports;
-  
-  /**
-   * Initial connections
-   */
-  enum GNUNET_TESTING_Topology connect_topology;
-  enum GNUNET_TESTING_TopologyOption connect_topology_option;
-  double connect_topology_option_modifier;
-  int verbose;
-
-  struct ProgressMeter *hostkey_meter;
-  struct ProgressMeter *peer_start_meter;
-  struct ProgressMeter *connect_meter;
-
-  /**
-   * Task used to kill the peergroup.
-   */
-  GNUNET_SCHEDULER_TaskIdentifier die_task;
-
-  char *fail_reason;
-
-  /**
-   * Variable used to store the number of connections we should wait for.
-   */
-  unsigned int expected_connections;
-
-  /**
-   * Time when the connecting peers was started.
-   */
-  struct GNUNET_TIME_Absolute connect_start_time;
-
-  /**
-   * The total number of connections that have been created so far.
-   */
-  unsigned int total_connections;
-
-  /**
-   * The total number of connections that have failed so far.
-   */
-  unsigned int failed_connections;
-
-  /**
-   * File handle to write out topology in dot format.
-   */
-  struct GNUNET_DISK_FileHandle *topology_output_file;
-};
-
-struct TopologyOutputContext
-{
-  struct GNUNET_DISK_FileHandle *file;
-  GNUNET_TESTING_NotifyCompletion notify_cb;
-  void *notify_cb_cls;
-};
-
-/**
- * Simple struct to keep track of progress, and print a
- * percentage meter for long running tasks.
- */
-struct ProgressMeter
-{
-  /**
-   * Total number of tasks to complete.
-   */
-  unsigned int total;
-
-  /**
-   * Print percentage done after modnum tasks.
-   */
-  unsigned int modnum;
-
-  /**
-   * Print a . each dotnum tasks.
-   */
-  unsigned int dotnum;
-
-  /**
-   * Total number completed thus far.
-   */
-  unsigned int completed;
-
-  /**
-   * Whether or not to print.
-   */
-  int print;
-
-  /**
-   * Startup string for progress meter.
-   */
-  char *startup_string;
-};
-
-
-/** Utility functions **/
-
-/**
- * Create a meter to keep track of the progress of some task.
- *
- * @param total the total number of items to complete
- * @param start_string a string to prefix the meter with (if printing)
- * @param print GNUNET_YES to print the meter, GNUNET_NO to count
- *              internally only
- *
- * @return the progress meter
- */
-static struct ProgressMeter *
-create_meter (unsigned int total, char *start_string, int print)
-{
-  struct ProgressMeter *ret;
-
-  ret = GNUNET_malloc (sizeof (struct ProgressMeter));
-  ret->print = print;
-  ret->total = total;
-  ret->modnum = (total / 4 == 0) ? 1 : (total / 4);
-  ret->dotnum = (total / 50) + 1;
-  if (start_string != NULL)
-    ret->startup_string = GNUNET_strdup (start_string);
-  else
-    ret->startup_string = GNUNET_strdup ("");
-
-  return ret;
-}
-
-/**
- * Update progress meter (increment by one).
- *
- * @param meter the meter to update and print info for
- *
- * @return GNUNET_YES if called the total requested,
- *         GNUNET_NO if more items expected
- */
-static int
-update_meter (struct ProgressMeter *meter)
-{
-  if (meter->print == GNUNET_YES)
-  {
-    if (meter->completed % meter->modnum == 0)
-    {
-      if (meter->completed == 0)
-      {
-        FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string);
-      }
-      else
-        FPRINTF (stdout, "%d%%",
-                 (int) (((float) meter->completed / meter->total) * 100));
-    }
-    else if (meter->completed % meter->dotnum == 0)
-      FPRINTF (stdout, "%s",  ".");
-
-    if (meter->completed + 1 == meter->total)
-      FPRINTF (stdout, "%d%%]\n", 100);
-    fflush (stdout);
-  }
-  meter->completed++;
-
-  if (meter->completed == meter->total)
-    return GNUNET_YES;
-  return GNUNET_NO;
-}
-
-/**
- * Reset progress meter.
- *
- * @param meter the meter to reset
- *
- * @return GNUNET_YES if meter reset,
- *         GNUNET_SYSERR on error
- */
-static int
-reset_meter (struct ProgressMeter *meter)
-{
-  if (meter == NULL)
-    return GNUNET_SYSERR;
-
-  meter->completed = 0;
-  return GNUNET_YES;
-}
-
-/**
- * Release resources for meter
- *
- * @param meter the meter to free
- */
-static void
-free_meter (struct ProgressMeter *meter)
-{
-  GNUNET_free_non_null (meter->startup_string);
-  GNUNET_free (meter);
-}
-
-
-/** Functions for creating, starting and connecting the peergroup **/
-
-/**
- * Check whether peers successfully shut down.
- */
-static void
-internal_shutdown_callback (void *cls, const char *emsg)
-{
-  struct PeerGroupStartupContext *pg_start_ctx = cls;
-
-  if (emsg != NULL)
-    pg_start_ctx->peergroup_cb (pg_start_ctx->cls, emsg);
-  else
-    pg_start_ctx->peergroup_cb (pg_start_ctx->cls, pg_start_ctx->fail_reason);
-}
-
-/**
- * Check if the get_handle is being used, if so stop the request.  Either
- * way, schedule the end_badly_cont function which actually shuts down the
- * test.
- */
-static void
-end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct PeerGroupStartupContext *pg_start_ctx = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Failing peer group startup with error: `%s'!\n",
-              pg_start_ctx->fail_reason);
-
-  GNUNET_TESTING_daemons_stop (pg_start_ctx->pg,
-                               GNUNET_TIME_absolute_get_remaining
-                               (pg_start_ctx->timeout),
-                               &internal_shutdown_callback, pg_start_ctx);
-
-  if (pg_start_ctx->hostkey_meter != NULL)
-  {
-    free_meter (pg_start_ctx->hostkey_meter);
-    pg_start_ctx->hostkey_meter = NULL;
-  }
-  if (pg_start_ctx->peer_start_meter != NULL)
-  {
-    free_meter (pg_start_ctx->peer_start_meter);
-    pg_start_ctx->peer_start_meter = NULL;
-  }
-  if (pg_start_ctx->connect_meter != NULL)
-  {
-    free_meter (pg_start_ctx->connect_meter);
-    pg_start_ctx->connect_meter = NULL;
-  }
-}
-
-/**
- * This function is called whenever a connection attempt is finished between two of
- * the started peers (started with GNUNET_TESTING_daemons_start).  The total
- * number of times this function is called should equal the number returned
- * from the GNUNET_TESTING_connect_topology call.
- *
- * The emsg variable is NULL on success (peers connected), and non-NULL on
- * failure (peers failed to connect).
- */
-static void
-internal_topology_callback (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)
-{
-  struct PeerGroupStartupContext *pg_start_ctx = cls;
-  char *temp_str;
-  char *second_str;
-  int temp;
-
-#if TIMING
-  unsigned long long duration;
-  unsigned long long total_duration;
-  unsigned int new_connections;
-  unsigned int new_failed_connections;
-  double conns_per_sec_recent;
-  double conns_per_sec_total;
-  double failed_conns_per_sec_recent;
-  double failed_conns_per_sec_total;
-#endif
-
-#if TIMING
-  if (GNUNET_TIME_absolute_get_difference
-      (connect_last_time,
-       GNUNET_TIME_absolute_get ()).rel_value >
-      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
-                                     CONN_UPDATE_DURATION).rel_value)
-  {
-    /* Get number of new connections */
-    new_connections = total_connections - previous_connections;
-
-    /* Get number of new FAILED connections */
-    new_failed_connections = failed_connections - previous_failed_connections;
-
-    /* Get duration in seconds */
-    duration =
-        GNUNET_TIME_absolute_get_difference (connect_last_time,
-                                             GNUNET_TIME_absolute_get
-                                             ()).rel_value / 1000;
-    total_duration =
-        GNUNET_TIME_absolute_get_difference (connect_start_time,
-                                             GNUNET_TIME_absolute_get
-                                             ()).rel_value / 1000;
-
-    failed_conns_per_sec_recent = (double) new_failed_connections / duration;
-    failed_conns_per_sec_total = (double) failed_connections / total_duration;
-    conns_per_sec_recent = (double) new_connections / duration;
-    conns_per_sec_total = (double) total_connections / total_duration;
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Recent: %.2f/s, Total: %.2f/s, Recent failed: %.2f/s, total failed %.2f/s\n",
-                conns_per_sec_recent, CONN_UPDATE_DURATION, conns_per_sec_total,
-                failed_conns_per_sec_recent, failed_conns_per_sec_total);
-    connect_last_time = GNUNET_TIME_absolute_get ();
-    previous_connections = total_connections;
-    previous_failed_connections = failed_connections;
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "have %u total_connections, %u failed\n", total_connections,
-                failed_connections);
-  }
-#endif
-
-
-  if (emsg == NULL)
-  {
-    pg_start_ctx->total_connections++;
-#if VERBOSE > 1
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "connected peer %s to peer %s, distance %u\n",
-                first_daemon->shortname, second_daemon->shortname, distance);
-#endif
-    if (pg_start_ctx->topology_output_file != NULL)
-    {
-      second_str = GNUNET_strdup (GNUNET_i2s (second));
-      temp =
-          GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n",
-                           GNUNET_i2s (first), second_str);
-      GNUNET_free (second_str);
-      if (temp > 0)
-        GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str,
-                                temp);
-      GNUNET_free (temp_str);
-    }
-  }
-  else
-  {
-    pg_start_ctx->failed_connections++;
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Failed to connect peer %s to peer %s with error :\n%s\n",
-                first_daemon->shortname, second_daemon->shortname, emsg);
-
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to connect peer %s to peer %s with error :\n%s\n",
-                first_daemon->shortname, second_daemon->shortname, emsg);
-#endif
-  }
-
-  GNUNET_assert (pg_start_ctx->connect_meter != NULL);
-  if (pg_start_ctx->connect_cb != NULL)
-    pg_start_ctx->connect_cb (pg_start_ctx->cls, first, second, distance,
-                              first_cfg, second_cfg, first_daemon,
-                              second_daemon, emsg);
-  if (GNUNET_YES != update_meter (pg_start_ctx->connect_meter))
-  {
-    /* No finished yet */
-    return;
-  }
-#if VERBOSE
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Created %d total connections, which is our target number!  Starting next phase of testing.\n",
-              pg_start_ctx->total_connections);
-#endif
-
-#if TIMING
-  total_duration =
-      GNUNET_TIME_absolute_get_difference (connect_start_time,
-                                            GNUNET_TIME_absolute_get
-                                            ()).rel_value / 1000;
-  failed_conns_per_sec_total = (double) failed_connections / total_duration;
-  conns_per_sec_total = (double) total_connections / total_duration;
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Overall connection info --- Total: %u, Total Failed %u/s\n",
-              total_connections, failed_connections);
-  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-              "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n",
-              conns_per_sec_total, failed_conns_per_sec_total);
-#endif
-
-  GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
-  GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
-
-  /* Call final callback, signifying that the peer group has been started and connected */
-  if (pg_start_ctx->peergroup_cb != NULL)
-    pg_start_ctx->peergroup_cb (pg_start_ctx->cls, NULL);
-
-  if (pg_start_ctx->topology_output_file != NULL)
-  {
-    temp = GNUNET_asprintf (&temp_str, "}\n");
-    if (temp > 0)
-      GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str,
-                              temp);
-    GNUNET_free (temp_str);
-    GNUNET_DISK_file_close (pg_start_ctx->topology_output_file);
-  }
-  GNUNET_free_non_null (pg_start_ctx->fail_reason);
-  if (NULL != pg_start_ctx->hostkey_meter)
-    free_meter(pg_start_ctx->hostkey_meter);
-  if (NULL != pg_start_ctx->peer_start_meter)
-    free_meter(pg_start_ctx->peer_start_meter);
-  if (NULL != pg_start_ctx->connect_meter)
-    free_meter(pg_start_ctx->connect_meter);
-  GNUNET_free (pg_start_ctx);
-}
-
-
-/**
- * Callback called for each started daemon.
- *
- * @param cls Clause (PG Context).
- * @param id PeerIdentidy of started daemon.
- * @param cfg Configuration used by the daemon.
- * @param d Handle for the daemon.
- * @param emsg Error message, NULL on success.
- */
-static void
-internal_peers_started_callback (void *cls,
-                                 const struct GNUNET_PeerIdentity *id,
-                                 const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                 struct GNUNET_TESTING_Daemon *d,
-                                 const char *emsg)
-{
-  struct PeerGroupStartupContext *pg_start_ctx = cls;
-
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Failed to start daemon with error: `%s'\n", emsg);
-    return;
-  }
-  GNUNET_assert (id != NULL);
-
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
-              (pg_start_ctx->total - pg_start_ctx->peers_left) + 1,
-              pg_start_ctx->total);
-#endif
-
-  pg_start_ctx->peers_left--;
-
-  if (NULL == pg_start_ctx->peer_start_meter)
-  {
-    /* Cancelled Ctrl-C or error */
-    return;
-  }
-  if (GNUNET_YES == update_meter (pg_start_ctx->peer_start_meter))
-  {
-#if VERBOSE
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "All %d daemons started, now connecting peers!\n",
-                pg_start_ctx->total);
-#endif
-    GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
-    GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
-
-    pg_start_ctx->expected_connections = UINT_MAX;
-    // FIXME: why whould peers_left be != 0?? Or pg NULL?
-    if ((pg_start_ctx->pg != NULL) && (pg_start_ctx->peers_left == 0))
-    {
-      pg_start_ctx->connect_start_time = GNUNET_TIME_absolute_get ();
-      pg_start_ctx->expected_connections =
-          GNUNET_TESTING_connect_topology (pg_start_ctx->pg,
-                                           pg_start_ctx->connect_topology,
-                                           pg_start_ctx->connect_topology_option,
-                                           pg_start_ctx->connect_topology_option_modifier,
-                                           pg_start_ctx->connect_timeout,
-                                           pg_start_ctx->connect_attempts, NULL,
-                                           NULL);
-
-      pg_start_ctx->connect_meter =
-          create_meter (pg_start_ctx->expected_connections, "Peer connection ",
-                        pg_start_ctx->verbose);
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
-                  pg_start_ctx->expected_connections);
-    }
-
-    if (pg_start_ctx->expected_connections == 0)
-    {
-      GNUNET_free_non_null (pg_start_ctx->fail_reason);
-      pg_start_ctx->fail_reason =
-          GNUNET_strdup ("from connect topology (bad return)");
-      pg_start_ctx->die_task =
-          GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx);
-      return;
-    }
-
-    GNUNET_free_non_null (pg_start_ctx->fail_reason);
-    pg_start_ctx->fail_reason =
-        GNUNET_strdup ("from connect topology (timeout)");
-    pg_start_ctx->die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                      (pg_start_ctx->timeout), &end_badly,
-                                      pg_start_ctx);
-  }
-}
-
-/**
- * Callback indicating that the hostkey was created for a peer.
- *
- * @param cls NULL
- * @param id the peer identity
- * @param d the daemon handle (pretty useless at this point, remove?)
- * @param emsg non-null on failure
- */
-static void
-internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
-                           struct GNUNET_TESTING_Daemon *d, const char *emsg)
-{
-  struct PeerGroupStartupContext *pg_start_ctx = cls;
-  unsigned int create_expected_connections;
-
-  if (emsg != NULL)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Hostkey callback received error: %s\n", emsg);
-  }
-
-#if VERBOSE > 1
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Hostkey (%d/%d) created for peer `%s'\n",
-              pg_start_ctx->total - pg_start_ctx->peers_left + 1,
-              pg_start_ctx->total, GNUNET_i2s (id));
-#endif
-
-  pg_start_ctx->peers_left--;
-  if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter))
-  {
-    GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
-    GNUNET_free_non_null (pg_start_ctx->fail_reason);
-    /* Set up task in case topology creation doesn't finish
-     * within a reasonable amount of time */
-    pg_start_ctx->fail_reason = GNUNET_strdup ("from create_topology");
-    pg_start_ctx->die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                      (pg_start_ctx->timeout), &end_badly,
-                                      pg_start_ctx);
-    pg_start_ctx->peers_left = pg_start_ctx->total;     /* Reset counter */
-    create_expected_connections =
-        GNUNET_TESTING_create_topology (pg_start_ctx->pg,
-                                        pg_start_ctx->topology,
-                                        pg_start_ctx->restrict_topology,
-                                        pg_start_ctx->restrict_transports);
-    if (create_expected_connections > 0)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                  "Topology set up, have %u expected connections, now starting peers!\n",
-                  create_expected_connections);
-      GNUNET_TESTING_daemons_continue_startup (pg_start_ctx->pg);
-    }
-    else
-    {
-      GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
-      GNUNET_free_non_null (pg_start_ctx->fail_reason);
-      pg_start_ctx->fail_reason =
-          GNUNET_strdup ("from create topology (bad return)");
-      pg_start_ctx->die_task =
-          GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx);
-      return;
-    }
-
-    GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
-    GNUNET_free_non_null (pg_start_ctx->fail_reason);
-    pg_start_ctx->fail_reason =
-        GNUNET_strdup ("from continue startup (timeout)");
-    pg_start_ctx->die_task =
-        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                      (pg_start_ctx->timeout), &end_badly,
-                                      pg_start_ctx);
-  }
-}
-
-
-/**
- * Prototype of a callback function indicating that two peers
- * are currently connected.
- *
- * @param cls closure
- * @param first peer id for first daemon
- * @param second peer id for the second daemon
- * @param emsg error message (NULL on success)
- */
-void
-write_topology_cb (void *cls, const struct GNUNET_PeerIdentity *first,
-                   const struct GNUNET_PeerIdentity *second, const char *emsg)
-{
-  struct TopologyOutputContext *topo_ctx;
-  int temp;
-  char *temp_str;
-  char *temp_pid2;
-
-  topo_ctx = (struct TopologyOutputContext *) cls;
-  GNUNET_assert (topo_ctx->file != NULL);
-  if ((emsg == NULL) && (first != NULL) && (second != NULL))
-  {
-    GNUNET_assert (first != NULL);
-    GNUNET_assert (second != NULL);
-    temp_pid2 = GNUNET_strdup (GNUNET_i2s (second));
-    temp =
-        GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n", GNUNET_i2s (first),
-                         temp_pid2);
-    GNUNET_free (temp_pid2);
-    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
-  }
-  else if ((emsg == NULL) && (first == NULL) && (second == NULL))
-  {
-    temp = GNUNET_asprintf (&temp_str, "}\n");
-    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
-    GNUNET_DISK_file_close (topo_ctx->file);
-    topo_ctx->notify_cb (topo_ctx->notify_cb_cls, NULL);
-    GNUNET_free (topo_ctx);
-  }
-  else
-  {
-    temp = GNUNET_asprintf (&temp_str, "}\n");
-    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
-    GNUNET_DISK_file_close (topo_ctx->file);
-    topo_ctx->notify_cb (topo_ctx->notify_cb_cls, emsg);
-    GNUNET_free (topo_ctx);
-  }
-}
-
-/**
- * Print current topology to a graphviz readable file.
- *
- * @param pg a currently running peergroup to print to file
- * @param output_filename the file to write the topology to
- * @param notify_cb callback to call upon completion or failure
- * @param notify_cb_cls closure for notify_cb
- *
- */
-void
-GNUNET_TESTING_peergroup_topology_to_file (struct GNUNET_TESTING_PeerGroup *pg,
-                                           const char *output_filename,
-                                           GNUNET_TESTING_NotifyCompletion
-                                           notify_cb, void *notify_cb_cls)
-{
-  struct TopologyOutputContext *topo_ctx;
-  int temp;
-  char *temp_str;
-
-  topo_ctx = GNUNET_malloc (sizeof (struct TopologyOutputContext));
-
-  topo_ctx->notify_cb = notify_cb;
-  topo_ctx->notify_cb_cls = notify_cb_cls;
-  topo_ctx->file =
-      GNUNET_DISK_file_open (output_filename,
-                             GNUNET_DISK_OPEN_READWRITE |
-                             GNUNET_DISK_OPEN_CREATE,
-                             GNUNET_DISK_PERM_USER_READ |
-                             GNUNET_DISK_PERM_USER_WRITE);
-  if (topo_ctx->file == NULL)
-  {
-    notify_cb (notify_cb_cls, "Failed to open output file!");
-    GNUNET_free (topo_ctx);
-    return;
-  }
-
-  temp = GNUNET_asprintf (&temp_str, "strict graph G {\n");
-  if (temp > 0)
-    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
-  GNUNET_free_non_null (temp_str);
-  GNUNET_TESTING_get_topology (pg, &write_topology_cb, topo_ctx);
-}
-
-/**
- * Start a peer group with a given number of peers.  Notify
- * on completion of peer startup and connection based on given
- * topological constraints.  Optionally notify on each
- * established connection.
- *
- * @param cfg configuration template to use
- * @param total number of daemons to start
- * @param timeout total time allowed for peers to start
- * @param connect_cb function to call each time two daemons are connected
- * @param peergroup_cb function to call once all peers are up and connected
- * @param peergroup_cls closure for peergroup callbacks
- * @param hostnames linked list of host structs to use to start peers on
- *                  (NULL to run on localhost only)
- *
- * @return NULL on error, otherwise handle to control peer group
- */
-struct GNUNET_TESTING_PeerGroup *
-GNUNET_TESTING_peergroup_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
-                                unsigned int total,
-                                struct GNUNET_TIME_Relative timeout,
-                                GNUNET_TESTING_NotifyConnection connect_cb,
-                                GNUNET_TESTING_NotifyCompletion peergroup_cb,
-                                void *peergroup_cls,
-                                const struct GNUNET_TESTING_Host *hostnames)
-{
-  struct PeerGroupStartupContext *pg_start_ctx;
-  char *temp_str;
-  int temp;
-  struct GNUNET_TIME_Relative rtimeout;
-
-  GNUNET_assert (total > 0);
-  GNUNET_assert (cfg != NULL);
-
-  pg_start_ctx = GNUNET_malloc (sizeof (struct PeerGroupStartupContext));
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
-                                             &pg_start_ctx->connect_attempts))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "connect_attempts");
-    GNUNET_free (pg_start_ctx);
-    return NULL;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT",
-                                           &pg_start_ctx->connect_timeout))
-  {
-    pg_start_ctx->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
-                                             "max_outstanding_connections",
-                                             &pg_start_ctx->max_concurrent_connections))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "max_outstanding_connections");
-    GNUNET_free (pg_start_ctx);
-    return NULL;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
-                                             "max_concurrent_ssh",
-                                             &pg_start_ctx->max_concurrent_ssh))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "max_concurrent_ssh");
-    GNUNET_free (pg_start_ctx);
-    return NULL;
-  }
-
-  if (GNUNET_SYSERR ==
-      (pg_start_ctx->verbose =
-       GNUNET_CONFIGURATION_get_value_yesno (cfg, "testing",
-                                             "use_progressbars")))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "use_progressbars");
-    GNUNET_free (pg_start_ctx);
-    return NULL;
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "PEERGROUP_TIMEOUT",
-                                           &rtimeout))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
-                "testing", "PEERGROUP_TIMEOUT");
-    GNUNET_free (pg_start_ctx);
-    return NULL;
-  }
-  pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute (rtimeout);
-
-
-  /* Read topology related options from the configuration file */
-  temp_str = NULL;
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology",
-                                              &temp_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_get (&pg_start_ctx->topology, temp_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid topology `%s' given for section %s option %s\n",
-                temp_str, "TESTING", "TOPOLOGY");
-    pg_start_ctx->topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;    /* Defaults to NONE, so set better default here */
-  }
-  GNUNET_free_non_null (temp_str);
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "topology_output_file", &temp_str))
-  {
-    pg_start_ctx->topology_output_file =
-        GNUNET_DISK_file_open (temp_str,
-                               GNUNET_DISK_OPEN_READWRITE |
-                               GNUNET_DISK_OPEN_CREATE,
-                               GNUNET_DISK_PERM_USER_READ |
-                               GNUNET_DISK_PERM_USER_WRITE);
-    if (pg_start_ctx->topology_output_file != NULL)
-    {
-      GNUNET_free (temp_str);
-      temp = GNUNET_asprintf (&temp_str, "strict graph G {\n");
-      if (temp > 0)
-        GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str,
-                                temp);
-    }
-    GNUNET_free (temp_str);
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "percentage",
-                                             &temp_str))
-    pg_start_ctx->topology_percentage = 0.5;
-  else
-  {
-    pg_start_ctx->topology_percentage = atof (temp_str);
-    GNUNET_free (temp_str);
-  }
-
-  if (GNUNET_OK !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "probability",
-                                             &temp_str))
-    pg_start_ctx->topology_probability = 0.5;
-  else
-  {
-    pg_start_ctx->topology_probability = atof (temp_str);
-    GNUNET_free (temp_str);
-  }
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "connect_topology", &temp_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_get (&pg_start_ctx->connect_topology, temp_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid connect topology `%s' given for section %s option %s\n",
-                temp_str, "TESTING", "CONNECT_TOPOLOGY");
-  }
-  GNUNET_free_non_null (temp_str);
-
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "connect_topology_option",
-                                              &temp_str)) &&
-      (GNUNET_NO ==
-       GNUNET_TESTING_topology_option_get
-       (&pg_start_ctx->connect_topology_option, temp_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid connect topology option `%s' given for section %s option %s\n",
-                temp_str, "TESTING", "CONNECT_TOPOLOGY_OPTION");
-    pg_start_ctx->connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */
-  }
-  GNUNET_free_non_null (temp_str);
-
-  if (GNUNET_YES ==
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "connect_topology_option_modifier",
-                                             &temp_str))
-  {
-    if (SSCANF
-        (temp_str, "%lf", &pg_start_ctx->connect_topology_option_modifier) != 1)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                  _
-                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
-                  temp_str, "connect_topology_option_modifier", "TESTING");
-      GNUNET_free (temp_str);
-      GNUNET_free (pg_start_ctx);
-      return NULL;
-    }
-    GNUNET_free (temp_str);
-  }
-
-  if (GNUNET_YES !=
-      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                             "blacklist_transports",
-                                             &pg_start_ctx->restrict_transports))
-    pg_start_ctx->restrict_transports = NULL;
-
-  pg_start_ctx->restrict_topology = GNUNET_TESTING_TOPOLOGY_NONE;
-  if ((GNUNET_YES ==
-       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
-                                              "blacklist_topology", &temp_str))
-      && (GNUNET_NO ==
-          GNUNET_TESTING_topology_get (&pg_start_ctx->restrict_topology,
-                                       temp_str)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                "Invalid topology `%s' given for section %s option %s\n",
-                temp_str, "TESTING", "BLACKLIST_TOPOLOGY");
-  }
-
-  GNUNET_free_non_null (temp_str);
-
-  pg_start_ctx->cfg = cfg;
-  pg_start_ctx->total = total;
-  pg_start_ctx->peers_left = total;
-  pg_start_ctx->connect_cb = connect_cb;
-  pg_start_ctx->peergroup_cb = peergroup_cb;
-  pg_start_ctx->cls = peergroup_cls;
-  pg_start_ctx->hostnames = hostnames;
-  pg_start_ctx->hostkey_meter =
-      create_meter (pg_start_ctx->peers_left, "Hostkeys created ",
-                    pg_start_ctx->verbose);
-  pg_start_ctx->peer_start_meter =
-      create_meter (pg_start_ctx->peers_left, "Peers started ",
-                    pg_start_ctx->verbose);
-  /* Make compilers happy */
-  reset_meter (pg_start_ctx->peer_start_meter);
-  pg_start_ctx->fail_reason =
-      GNUNET_strdup
-      ("didn't generate all hostkeys within allowed startup time!");
-  pg_start_ctx->die_task =
-      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
-                                    (pg_start_ctx->timeout), &end_badly,
-                                    pg_start_ctx);
-
-  pg_start_ctx->pg =
-      GNUNET_TESTING_daemons_start (pg_start_ctx->cfg, pg_start_ctx->peers_left,
-                                    pg_start_ctx->max_concurrent_connections,
-                                    pg_start_ctx->max_concurrent_ssh,
-                                    GNUNET_TIME_absolute_get_remaining
-                                    (pg_start_ctx->timeout),
-                                    &internal_hostkey_callback, pg_start_ctx,
-                                    &internal_peers_started_callback,
-                                    pg_start_ctx, &internal_topology_callback,
-                                    pg_start_ctx, pg_start_ctx->hostnames);
-
-  return pg_start_ctx->pg;
-}
-
-/* end of testing_peergroup.c */
diff --git a/src/testing_old/Makefile.am b/src/testing_old/Makefile.am
new file mode 100644 (file)
index 0000000..2984831
--- /dev/null
@@ -0,0 +1,283 @@
+INCLUDES = -I$(top_srcdir)/src/include
+
+if MINGW
+  WINFLAGS = -Wl,--no-undefined -Wl,--export-all-symbols
+endif
+
+if USE_COVERAGE
+  AM_CFLAGS = --coverage -O0
+  XLIB = -lgcov
+endif
+
+pkgcfgdir= $(pkgdatadir)/config.d/
+
+dist_pkgcfg_DATA = \
+  testing_old.conf
+
+if HAVE_EXPENSIVE_TESTS
+  EXPENSIVE_TESTS = \
+   test_testing_topology_stability \
+   test_testing_topology_clique_random \
+   test_testing_topology_clique_minimum \
+   test_testing_topology_clique_dfs \
+   test_testing_topology_churn \
+   test_testing_topology_line \
+   test_testing_topology_blacklist \
+   test_testing_group_remote \
+   test_testing_topology_ring \
+   test_testing_topology_2d_torus \
+   test_testing_topology_small_world_ring \
+   test_testing_topology_small_world_torus \
+   test_testing_topology_erdos_renyi \
+   test_testing_topology_internat \
+   test_testing_topology_scale_free
+endif
+
+lib_LTLIBRARIES = \
+  libgnunettestingold.la 
+
+libgnunettestingold_la_SOURCES = \
+  helper.c \
+  testing.c  \
+  testing_group.c \
+  testing_peergroup.c
+libgnunettestingold_la_LIBADD = $(XLIB) \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/statistics/libgnunetstatistics.la \
+ $(top_builddir)/src/transport/libgnunettransport.la \
+ $(top_builddir)/src/hello/libgnunethello.la \
+ -lm \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(LTLIBINTL)
+libgnunettestingold_la_LDFLAGS = \
+ $(GN_LIB_LDFLAGS) \
+ -version-info 0:1:0
+
+
+bin_PROGRAMS = \
+ gnunet-testing
+
+check_PROGRAMS = \
+ test_testing \
+ test_testing_connect \
+ test_testing_reconnect \
+ test_testing_group \
+ test_testing_peergroup \
+ test_testing_topology_stability \
+ test_testing_topology_clique \
+ test_testing_topology_clique_random \
+ test_testing_topology_clique_minimum \
+ test_testing_topology_clique_dfs \
+ test_testing_topology_churn \
+ test_testing_topology_line \
+ test_testing_topology_blacklist \
+ test_testing_group_remote \
+ test_testing_2dtorus \
+ test_testing_topology_ring \
+ test_testing_topology_2d_torus \
+ test_testing_topology_small_world_ring \
+ test_testing_topology_small_world_torus \
+ test_testing_topology_erdos_renyi \
+ test_testing_topology_internat \
+ test_testing_topology_none \
+ test_testing_topology_scale_free 
+
+if ENABLE_TEST_RUN 
+TESTS = \
+ test_testing \
+ test_testing_connect \
+ test_testing_reconnect \
+ test_testing_group \
+ test_testing_peergroup \
+ test_testing_new_portreservation \
+ test_testing_new_peerstartup \
+ test_testing_new_servicestartup
+endif
+
+gnunet_testing_SOURCES = \
+ gnunet-testing.c         
+gnunet_testing_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la \
+ $(GN_LIBINTL)
+gnunet_testing_DEPENDENCIES = \
+ libgnunettestingold.la
+
+
+test_testing_SOURCES = \
+ test_testing.c
+test_testing_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_connect_SOURCES = \
+ test_testing_connect.c
+test_testing_connect_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_reconnect_SOURCES = \
+ test_testing_reconnect.c
+test_testing_reconnect_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_group_SOURCES = \
+ test_testing_group.c
+test_testing_group_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_peergroup_SOURCES = \
+ test_testing_peergroup.c
+test_testing_peergroup_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la 
+
+test_testing_topology_clique_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_clique_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_stability_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_stability_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_blacklist_SOURCES = \
+ test_testing_topology_blacklist.c
+test_testing_topology_blacklist_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la 
+
+test_testing_topology_churn_SOURCES = \
+ test_testing_topology_churn.c
+test_testing_topology_churn_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la 
+
+test_testing_topology_clique_random_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_clique_random_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_topology_clique_minimum_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_clique_minimum_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_clique_dfs_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_clique_dfs_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_topology_line_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_line_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+
+test_testing_group_remote_SOURCES = \
+ test_testing_group_remote.c
+test_testing_group_remote_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_2dtorus_SOURCES = \
+  test_testing_2dtorus.c
+test_testing_2dtorus_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/util/libgnunetutil.la 
+
+test_testing_topology_ring_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_ring_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la  
+
+test_testing_topology_2d_torus_SOURCES = \
+  test_testing_topology.c
+test_testing_topology_2d_torus_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la 
+
+test_testing_topology_small_world_ring_SOURCES = \
+  test_testing_topology.c
+test_testing_topology_small_world_ring_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_small_world_torus_SOURCES = \
+  test_testing_topology.c
+test_testing_topology_small_world_torus_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_internat_SOURCES = \
+  test_testing_topology.c
+test_testing_topology_internat_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_erdos_renyi_SOURCES = \
+  test_testing_topology.c
+test_testing_topology_erdos_renyi_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_scale_free_SOURCES = \
+  test_testing_topology.c
+test_testing_topology_scale_free_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+test_testing_topology_none_SOURCES = \
+ test_testing_topology.c
+test_testing_topology_none_LDADD = \
+ $(top_builddir)/src/testing_old/libgnunettestingold.la \
+ $(top_builddir)/src/core/libgnunetcore.la \
+ $(top_builddir)/src/util/libgnunetutil.la
+
+
+EXTRA_DIST = \
+ test_testing_defaults.conf \
+ test_testing_data.conf \
+ test_testing_connect_peer1.conf \
+ test_testing_connect_peer2.conf \
+ test_testing_2dtorus.conf \
+ test_testing_data_topology_clique.conf \
+ test_testing_data_topology_clique_random.conf \
+ test_testing_data_topology_clique_minimum.conf \
+ test_testing_data_topology_clique_dfs.conf \
+ test_testing_data_topology_ring.conf \
+ test_testing_data_topology_2d_torus.conf \
+ test_testing_data_topology_small_world_ring.conf \
+ test_testing_data_topology_small_world_torus.conf \
+ test_testing_data_topology_erdos_renyi.conf \
+ test_testing_data_topology_internat.conf \
+ test_testing_data_topology_scale_free.conf \
+ test_testing_data_topology_blacklist.conf \
+ test_testing_data_topology_churn.conf \
+ test_testing_data_topology_none.conf \
+ test_testing_data_remote.conf \
+ test_testing_data_topology_stability.conf \
+ test_testing_peergroup_data.conf
diff --git a/src/testing_old/gnunet-testing-remote-peer-start.pl b/src/testing_old/gnunet-testing-remote-peer-start.pl
new file mode 100755 (executable)
index 0000000..e4f72e9
--- /dev/null
@@ -0,0 +1,92 @@
+# 
+#  This file is part of GNUnet
+#  (C) 2008, 2009 Christian Grothoff (and other contributing authors)
+# 
+#  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 3, or (at your
+#  option) any later version.
+# 
+#  GNUnet is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+# 
+#  You should have received a copy of the GNU General Public License
+#  along with GNUnet; see the file COPYING.  If not, write to the
+#  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+#  Boston, MA 02111-1307, USA.
+# 
+# 
+# 
+#  @file contrib/peerStartHelper.pl
+#  @brief Helper process for starting gnunet-testing peers.
+#  @author Nathan Evans
+#
+# Finds configuration files (or any files) of the format
+# /path/*/gnunet-testing-config* and runs gnunet-arm with
+# each as the given configuration.
+#
+# usage: peerStartHelper.pl /path/to/testing_dir/
+#!/usr/bin/perl
+use strict;
+
+my $max_outstanding = 300;
+
+$ARGV[0] || die "No directory provided for peer information, exiting!\n";
+
+my $directory = $ARGV[0];
+my @config_files = `find $directory -iname gnunet-testing-config*`;
+my @child_arr = {};
+my $count = 0;
+my $outstanding = 0;
+foreach my $file (@config_files)
+{
+  chomp($file);
+  #print "Starting GNUnet peer with config file $file\n";
+  my $pid = fork();
+  if ($pid == -1) 
+  {
+   die;
+  } 
+  elsif ($pid == 0) 
+  {
+    exec "gnunet-arm -q -c $file -s"  or die;
+  }
+
+  if ($pid != 0)
+  {
+    push @child_arr, $pid;
+    $count++;
+    $outstanding++;
+    if ($outstanding > $max_outstanding)
+    {
+      for (my $i = 0; $i < $max_outstanding / 5; $i++)
+      {
+       #print "Too many outstanding peers, waiting!\n";
+       waitpid($child_arr[0], 0);
+       shift(@child_arr);
+       $outstanding--;
+      }
+    }
+  }
+}
+
+print "All $count peers started (waiting for them to finish!\n";
+
+while ($outstanding > 0)
+{
+  waitpid($child_arr[0], 0);
+  shift(@child_arr);
+  $outstanding--;
+  if ($outstanding % 50 == 0)
+  {
+    print "All $count peers started (waiting for $outstanding to finish!\n";
+  }
+}
+
+while (wait() != -1) {sleep 1}
+
+print "All $count peers started!\n";
+
+
diff --git a/src/testing_old/gnunet-testing.c b/src/testing_old/gnunet-testing.c
new file mode 100644 (file)
index 0000000..bdbb5e8
--- /dev/null
@@ -0,0 +1,291 @@
+/*
+     This file is part of GNUnet.
+     (C) 2001, 2002, 2004, 2005, 2006, 2007, 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+
+/**
+ * @file testing/gnunet-testing.c
+ * @brief tool to use testing functionality from cmd line
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_getopt_lib.h"
+#include "gnunet_program_lib.h"
+#include "gnunet_testing_lib.h"
+
+#define HOSTKEYFILESIZE 914
+
+/**
+ * Final status code.
+ */
+static int ret;
+
+static unsigned int create_hostkey;
+
+static unsigned int create_cfg;
+
+static int create_no;
+
+static char * create_cfg_template;
+
+static char * create_hostkey_file;
+
+static int
+create_unique_cfgs (const char * template, const unsigned int no)
+{
+  int fail = GNUNET_NO;
+
+  uint16_t port = 20000;
+  uint32_t upnum = 1;
+  uint32_t fdnum = 1;
+
+  if (GNUNET_NO == GNUNET_DISK_file_test(template))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Configuration template `%s': file not found\n", create_cfg_template);
+    return 1;
+  }
+
+  int cur = 0;
+  char * cur_file;
+  char *service_home = NULL;
+  char *cur_service_home = NULL;
+
+  struct GNUNET_CONFIGURATION_Handle *cfg_new = NULL;
+  struct GNUNET_CONFIGURATION_Handle *cfg_tmpl = GNUNET_CONFIGURATION_create();
+
+  /* load template */
+  if ((create_cfg_template != NULL) && (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl, create_cfg_template)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not load template `%s'\n", create_cfg_template);
+    GNUNET_CONFIGURATION_destroy(cfg_tmpl);
+
+    return 1;
+  }
+  /* load defaults */
+  else if (GNUNET_OK != GNUNET_CONFIGURATION_load(cfg_tmpl,  NULL))
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+
+  if (GNUNET_SYSERR == GNUNET_CONFIGURATION_get_value_string(cfg_tmpl, "PATHS", "SERVICEHOME", &service_home))
+  {
+    GNUNET_asprintf(&service_home, "%s", "/tmp/testing");
+  }
+  else
+  {
+    int s = strlen (service_home);
+    if (service_home[s-1] == DIR_SEPARATOR)
+      service_home[s-1] = '\0';
+  }
+
+  while (cur < no)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating configuration no. %u \n", cur);
+    if (create_cfg_template != NULL)
+      GNUNET_asprintf (&cur_file,"%04u-%s",cur, create_cfg_template);
+    else
+      GNUNET_asprintf (&cur_file,"%04u%s",cur, ".conf");
+
+
+    GNUNET_asprintf (&cur_service_home, "%s-%04u%c",service_home, cur, DIR_SEPARATOR);
+    GNUNET_CONFIGURATION_set_value_string (cfg_tmpl,"PATHS","SERVICEHOME", cur_service_home);
+    GNUNET_CONFIGURATION_set_value_string (cfg_tmpl,"PATHS","DEFAULTCONFIG", cur_file);
+    GNUNET_free (cur_service_home);
+
+    cfg_new = GNUNET_TESTING_create_cfg(cfg_tmpl, cur, &port, &upnum, NULL, &fdnum);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing configuration no. %u to file `%s' \n", cur, cur_file);
+    if (GNUNET_OK != GNUNET_CONFIGURATION_write(cfg_new, cur_file))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to write configuration no. %u \n", cur);
+      fail = GNUNET_YES;
+    }
+
+    GNUNET_CONFIGURATION_destroy (cfg_new);
+    GNUNET_free (cur_file);
+    if (fail == GNUNET_YES)
+      break;
+    cur ++;
+  }
+
+  GNUNET_CONFIGURATION_destroy(cfg_tmpl);
+  GNUNET_free (service_home);
+  if (fail == GNUNET_NO)
+    return 0;
+  else
+    return 1;
+}
+
+static int
+create_hostkeys (const unsigned int no)
+{
+  struct GNUNET_DISK_FileHandle *fd;
+  int cur = 0;
+  uint64_t fs;
+  uint64_t total_hostkeys;
+  char *hostkey_data;
+  char *hostkey_src_file;
+  char *hostkey_dest_file;
+
+  /* prepare hostkeys */
+  if (create_hostkey_file == NULL)
+    hostkey_src_file = "../../contrib/testing_hostkeys.dat";
+  else
+  {
+    hostkey_src_file = create_hostkey_file;
+  }
+
+  if (GNUNET_YES != GNUNET_DISK_file_test (hostkey_src_file))
+  {
+    if (create_hostkey_file == NULL)
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Could not read hostkeys file, specify hostkey file with -H!\n"));
+    else
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Specified hostkey file `%s' not found!\n"), create_hostkey_file);
+    return 1;
+  }
+  else
+  {
+    /* Check hostkey file size, read entire thing into memory */
+    fd = GNUNET_DISK_file_open (hostkey_src_file, GNUNET_DISK_OPEN_READ,
+                                GNUNET_DISK_PERM_NONE);
+    if (NULL == fd)
+    {
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", hostkey_src_file);
+      return 1;
+    }
+
+    if (GNUNET_OK != GNUNET_DISK_file_size (hostkey_src_file, &fs, GNUNET_YES, GNUNET_YES))
+      fs = 0;
+
+    if (0 != (fs % HOSTKEYFILESIZE))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "File size %llu seems incorrect for hostkeys...\n", fs);
+    }
+    else
+    {
+      total_hostkeys = fs / HOSTKEYFILESIZE;
+      hostkey_data = GNUNET_malloc_large (fs);
+      GNUNET_assert (fs == GNUNET_DISK_file_read (fd, hostkey_data, fs));
+      GNUNET_log  (GNUNET_ERROR_TYPE_DEBUG,
+                       "Read %llu hostkeys from file\n", total_hostkeys);
+    }
+    GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
+  }
+
+  while (cur < no)
+  {
+    GNUNET_asprintf (&hostkey_dest_file, "%04u-hostkey",cur);
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_DISK_directory_create_for_file (hostkey_dest_file));
+    fd = GNUNET_DISK_file_open (hostkey_dest_file,
+                                GNUNET_DISK_OPEN_READWRITE |
+                                GNUNET_DISK_OPEN_CREATE,
+                                GNUNET_DISK_PERM_USER_READ |
+                                GNUNET_DISK_PERM_USER_WRITE);
+    GNUNET_assert (fd != NULL);
+    GNUNET_assert (HOSTKEYFILESIZE ==
+                   GNUNET_DISK_file_write (fd, &hostkey_data[cur * HOSTKEYFILESIZE], HOSTKEYFILESIZE));
+    GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "transport-testing",
+                     "Wrote hostkey to file: `%s' \n", hostkey_dest_file);
+    GNUNET_free (hostkey_dest_file);
+    cur ++;
+  }
+
+  GNUNET_free (hostkey_data);
+
+  return 0;
+}
+
+/**
+ * Main function that will be run by the scheduler.
+ *
+ * @param cls closure
+ * @param args remaining command-line arguments
+ * @param cfgfile name of the configuration file used (for saving, can be NULL!)
+ * @param cfg configuration
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  /* main code here */
+  if (create_cfg == GNUNET_YES)
+  {
+    if (create_no > 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u configuration files based on template `%s'\n", create_no, create_cfg_template);
+      ret = create_unique_cfgs (create_cfg_template, create_no);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
+      ret = 1;
+    }
+  }
+
+  if (create_hostkey == GNUNET_YES)
+  {
+    if  (create_no > 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating %u hostkeys \n", create_no);
+      ret = create_hostkeys (create_no);
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Missing arguments! \n");
+      ret = 1;
+    }
+  }
+
+  GNUNET_free_non_null (create_cfg_template);
+}
+
+
+/**
+ * The main function.
+ *
+ * @param argc number of arguments from the command line
+ * @param argv command line arguments
+ * @return 0 ok, 1 on error
+ */
+int
+main (int argc, char *const *argv)
+{
+  static const struct GNUNET_GETOPT_CommandLineOption options[] = {
+    {'C', "cfg", NULL, gettext_noop ("create unique configuration files"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &create_cfg},
+     {'k', "key", NULL, gettext_noop ("create hostkey files from pre-computed hostkey list"),
+     GNUNET_NO, &GNUNET_GETOPT_set_one, &create_hostkey},
+     {'H', "hostkeys", NULL, gettext_noop ("host key file"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &create_hostkey_file},
+    {'n', "number", NULL, gettext_noop ("number of unique configuration files or hostkeys to create"),
+     GNUNET_YES, &GNUNET_GETOPT_set_uint, &create_no},
+    {'t', "template", NULL, gettext_noop ("configuration template"),
+     GNUNET_YES, &GNUNET_GETOPT_set_string, &create_cfg_template},
+    GNUNET_GETOPT_OPTION_END
+  };
+  return (GNUNET_OK ==
+          GNUNET_PROGRAM_run (argc, argv, "gnunet-testing",
+                              gettext_noop ("Command line tool to access the testing library"), options, &run,
+                              NULL)) ? ret : 1;
+}
+
+/* end of gnunet-testing.c */
diff --git a/src/testing_old/helper.c b/src/testing_old/helper.c
new file mode 100644 (file)
index 0000000..ebb37eb
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+      This file is part of GNUnet
+      (C) 2012 Christian Grothoff (and other contributing authors)
+
+      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 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+      Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file testing/helper.c
+ * @brief helper functions for testing
+ * @author Christian Grothoff
+ *
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+
+
+
+/**
+ * Obtain the peer identity of the peer with the given configuration
+ * handle.  This function reads the private key of the peer, obtains
+ * the public key and hashes it.
+ *
+ * @param cfg configuration of the peer
+ * @param pid where to store the peer identity
+ * @return GNUNET_OK on success, GNUNET_SYSERR on failure
+ */
+int
+GNUNET_TESTING_get_peer_identity (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                 struct GNUNET_PeerIdentity *pid)
+{
+  char *keyfile;
+  struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (cfg, "GNUNETD", "HOSTKEY",
+                                               &keyfile))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _
+                ("Peer is lacking HOSTKEY configuration setting.\n"));
+    return GNUNET_SYSERR;
+  }
+  my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
+  GNUNET_free (keyfile);
+  if (my_private_key == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not access hostkey.\n"));
+    return GNUNET_SYSERR;
+  }
+  GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
+  GNUNET_CRYPTO_rsa_key_free (my_private_key);
+  GNUNET_CRYPTO_hash (&my_public_key, sizeof (my_public_key),
+                      &pid->hashPubKey);
+  return GNUNET_OK;
+}
+
+
+/* end of helper.c */
diff --git a/src/testing_old/test_testing.c b/src/testing_old/test_testing.c
new file mode 100644 (file)
index 0000000..3e2cd65
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing.c
+ * @brief testcase for testing.c
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_YES
+
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+static int ok;
+
+static void
+end_cb (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
+    ok = 1;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon terminated, will now exit.\n");
+#endif
+    ok = 0;
+  }
+}
+
+
+
+void
+do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_Daemon *d = cls;
+
+  GNUNET_TESTING_daemon_stop (d, TIMEOUT, &end_cb, NULL, GNUNET_YES, GNUNET_NO);
+}
+
+
+static void
+my_cb (void *cls, const struct GNUNET_PeerIdentity *id,
+       const struct GNUNET_CONFIGURATION_Handle *cfg,
+       struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  GNUNET_assert (id != NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Daemon `%s' started, will now stop it.\n", GNUNET_i2s (id));
+#endif
+  GNUNET_SCHEDULER_add_now (&do_shutdown, d);
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_TESTING_Daemon *d;
+
+  ok = 1;
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
+#endif
+  d = GNUNET_TESTING_daemon_start (cfg, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
+                                   NULL, NULL, &my_cb, NULL);
+  GNUNET_assert (d != NULL);
+}
+
+static int
+check ()
+{
+  char *const argv[] = { "test-testing",
+    "-c",
+    "test_testing_data.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                      "test-testing", "nohelp", options, &run, &ok);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test-testing",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+
+  return ret;
+}
+
+/* end of test_testing.c */
diff --git a/src/testing_old/test_testing_2dtorus.c b/src/testing_old/test_testing_2dtorus.c
new file mode 100644 (file)
index 0000000..00a66d6
--- /dev/null
@@ -0,0 +1,372 @@
+/*
+     This file is part of GNUnet.
+     (C) 2011 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_2dtorus.c
+ *
+ * @brief Test for creating a 2dtorus.
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_YES
+#define REMOVE_DIR GNUNET_YES
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1500)
+
+/**
+ * Time to wait for stuff that should be rather fast
+ */
+#define SHORT_TIME GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+
+/**
+ * How many events have happened
+ */
+static int ok;
+
+/**
+ * Be verbose
+ */
+static int verbose;
+
+/**
+ * Total number of peers in the test.
+ */
+static unsigned long long num_peers;
+
+/**
+ * Global configuration file
+ */
+static struct GNUNET_CONFIGURATION_Handle *testing_cfg;
+
+/**
+ * Total number of currently running peers.
+ */
+static unsigned long long peers_running;
+
+/**
+ * Total number of successful connections in the whole network.
+ */
+static unsigned int total_connections;
+
+/**
+ * Total number of counted topo connections
+ */
+static unsigned int topo_connections;
+
+/**
+ * Total number of failed connections in the whole network.
+ */
+static unsigned int failed_connections;
+
+/**
+ * The currently running peer group.
+ */
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/**
+ * Task called to disconnect peers
+ */
+static GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+/**
+ * Task called to shutdown test.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier shutdown_handle;
+
+
+/**
+ * Check whether peers successfully shut down.
+ */
+static void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Shutdown of peers failed!\n");
+#endif
+    ok--;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "test: All peers successfully shut down!\n");
+#endif
+  }
+}
+
+
+static void
+shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Ending test.\n");
+#endif
+
+  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+  GNUNET_CONFIGURATION_destroy (testing_cfg);
+}
+
+
+static void
+disconnect_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: disconnecting peers\n");
+
+  if (GNUNET_SCHEDULER_NO_TASK != shutdown_handle)
+  {
+    GNUNET_SCHEDULER_cancel (shutdown_handle);
+    shutdown_handle = GNUNET_SCHEDULER_add_now (&shutdown_task, NULL);
+  }
+}
+
+
+/**
+ * Prototype of a callback function indicating that two peers
+ * are currently connected.
+ *
+ * @param cls closure
+ * @param first peer id for first daemon
+ * @param second peer id for the second daemon
+ * @param distance distance between the connected peers
+ * @param emsg error message (NULL on success)
+ */
+void
+topo_cb (void *cls, const struct GNUNET_PeerIdentity *first,
+         const struct GNUNET_PeerIdentity *second, const char *emsg)
+{
+  topo_connections++;
+  if (NULL != emsg)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: Error by topo %u: %s\n",
+                topo_connections, emsg);
+  }
+  else
+  {
+    if (first == NULL || second == NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u NULL\n",
+                  topo_connections);
+      if (disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+      {
+        GNUNET_SCHEDULER_cancel (disconnect_task);
+        GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
+      }
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Connection %u ok\n",
+                topo_connections);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   %s\n", GNUNET_i2s (first));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   %s\n", GNUNET_i2s (second));
+  }
+}
+
+
+/**
+ * peergroup_ready: start test when all peers are connected
+ * @param cls closure
+ * @param emsg error message
+ */
+static void
+peergroup_ready (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "test: Peergroup callback called with error, aborting test!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Error from testing: `%s'\n",
+                emsg);
+    ok--;
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    return;
+  }
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "************************************************************\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "test: Peer Group started successfully!\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Have %u connections\n",
+              total_connections);
+#endif
+
+  peers_running = GNUNET_TESTING_daemons_running (pg);
+  if (0 < failed_connections)
+  {
+    ok = GNUNET_SYSERR;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "test: %u connections have FAILED!\n",
+                failed_connections);
+    disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_peers, NULL);
+
+  }
+  else
+  {
+    GNUNET_TESTING_get_topology (pg, &topo_cb, NULL);
+    disconnect_task =
+        GNUNET_SCHEDULER_add_delayed (SHORT_TIME, &disconnect_peers, NULL);
+    ok = GNUNET_OK;
+  }
+
+}
+
+
+/**
+ * Function that will be called whenever two daemons are connected by
+ * the testing library.
+ *
+ * @param cls closure
+ * @param first peer id for first daemon
+ * @param second peer id for the second daemon
+ * @param distance distance between the connected peers
+ * @param first_cfg config for the first daemon
+ * @param second_cfg config for the second daemon
+ * @param first_daemon handle for the first daemon
+ * @param second_daemon handle for the second daemon
+ * @param emsg error message (NULL on success)
+ */
+static void
+connect_cb (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)
+{
+  if (emsg == NULL)
+  {
+    total_connections++;
+  }
+  else
+  {
+    failed_connections++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "test: Problem with new connection (%s)\n", emsg);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   (%s)\n", GNUNET_i2s (first));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test:   (%s)\n", GNUNET_i2s (second));
+  }
+
+}
+
+
+/**
+ * run: load configuration options and schedule test to run (start peergroup)
+ * @param cls closure
+ * @param args argv
+ * @param cfgfile configuration file name (can be NULL)
+ * @param cfg configuration handle
+ */
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_TESTING_Host *hosts;
+
+  ok = GNUNET_NO;
+  total_connections = 0;
+  failed_connections = 0;
+  testing_cfg = GNUNET_CONFIGURATION_dup (cfg);
+
+  GNUNET_log_setup ("test_testing_2dtorus",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Starting daemons.\n");
+  GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
+                                         "use_progressbars", "YES");
+#endif
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (testing_cfg, "testing",
+                                             "num_peers", &num_peers))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Option TESTING:NUM_PEERS is required!\n");
+    return;
+  }
+
+  hosts = GNUNET_TESTING_hosts_load (testing_cfg);
+
+  pg = GNUNET_TESTING_peergroup_start (testing_cfg, num_peers, TIMEOUT,
+                                       &connect_cb, &peergroup_ready, NULL,
+                                       hosts);
+  GNUNET_assert (pg != NULL);
+  shutdown_handle =
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
+                                    &shutdown_task, NULL);
+}
+
+
+/**
+ * test_testing_2dtorus command line options
+ */
+static struct GNUNET_GETOPT_CommandLineOption options[] = {
+  {'V', "verbose", NULL,
+   gettext_noop ("be verbose (print progress information)"),
+   0, &GNUNET_GETOPT_set_one, &verbose},
+  GNUNET_GETOPT_OPTION_END
+};
+
+
+/**
+ * Main: start test
+ */
+int
+main (int argc, char *argv[])
+{
+  char *const argv2[] = {
+    argv[0],
+    "-c",
+    "test_testing_2dtorus.conf",
+#if VERBOSE
+    "-L",
+    "DEBUG",
+#endif
+    NULL
+  };
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: Start\n");
+
+
+  GNUNET_PROGRAM_run ((sizeof (argv2) / sizeof (char *)) - 1, argv2,
+                      "test_testing_2dtorus",
+                      gettext_noop ("Test testing 2d torus."), options, &run,
+                      NULL);
+#if REMOVE_DIR
+  GNUNET_DISK_directory_remove ("/tmp/test_testing_2dtorus");
+#endif
+  if (GNUNET_OK != ok)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "test: FAILED!\n");
+    return 1;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "test: success\n");
+  return 0;
+}
+
+/* end of test_testing_2dtorus.c */
diff --git a/src/testing_old/test_testing_2dtorus.conf b/src/testing_old/test_testing_2dtorus.conf
new file mode 100644 (file)
index 0000000..d69969f
--- /dev/null
@@ -0,0 +1,81 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+SERVICEHOME = /tmp/test_testing_2dtorus/
+DEFAULTCONFIG = test_testing_2dtorus.conf
+
+[arm]
+PORT = 10010
+DEFAULTSERVICES = core
+#DEBUG = YES
+
+[statistics]
+AUTOSTART = YES
+PORT = 10000
+
+[dht]
+DEBUG = NO
+AUTOSTART = YES
+ACCEPT_FROM6 = ::1;
+ACCEPT_FROM = 127.0.0.1;
+HOSTNAME = localhost
+PORT = 10001
+
+[nse]
+WORKBITS = 0
+
+[dns]
+AUTOSTART = NO
+PORT = 10011
+
+[transport]
+PORT = 10002
+AUTOSTART = YES
+PLUGINS = tcp
+
+[nat]
+DISABLEV6 = YES 
+BINDTO = 127.0.0.1
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+
+[ats]
+WAN_QUOTA_IN = 1 GB
+WAN_QUOTA_OUT = 1 GB
+
+[core]
+AUTOSTART = YES
+PORT = 10003
+
+[peerinfo]
+AUTOSTART = YES
+PORT = 10004
+
+[testing_old]
+NUM_PEERS = 16
+WEAKRANDOM = YES
+TOPOLOGY = 2D_TORUS
+CONNECT_TOPOLOGY = 2D_TORUS
+#TOPOLOGY_FILE = small.dat
+CONNECT_TOPOLOGY = 2D_TORUS
+#CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM
+#CONNECT_TOPOLOGY_OPTION_MODIFIER = 25
+#PERCENTAGE = 3
+#PROBABILITY = .1
+F2F = NO
+CONNECT_TIMEOUT = 600 s
+CONNECT_ATTEMPTS = 2
+DEBUG = YES
+HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
+MAX_CONCURRENT_SSH = 10
+USE_PROGRESSBARS = YES
+PEERGROUP_TIMEOUT = 2400 s
+TOPOLOGY_OUTPUT_FILE = testing_topo_initial
+MAX_OUTSTANDING_CONNECTIONS = 75
+#SINGLE_PEERINFO_PER_HOST = YES
+#NUM_PEERINFO_PER_HOST = 10
+#SINGLE_STATISTICS_PER_HOST = YES
+#NUM_STATISTICS_PER_HOST = 10
+DELETE_FILES = YES
diff --git a/src/testing_old/test_testing_connect.c b/src/testing_old/test_testing_connect.c
new file mode 100644 (file)
index 0000000..c69c203
--- /dev/null
@@ -0,0 +1,197 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_connect.c
+ * @brief testcase for functions to connect two peers in testing.c
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_NO
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+#define CONNECT_ATTEMPTS 3
+
+static int ok;
+
+static struct GNUNET_TESTING_Daemon *d1;
+
+static struct GNUNET_TESTING_Daemon *d2;
+
+static struct GNUNET_CONFIGURATION_Handle *c1;
+
+static struct GNUNET_CONFIGURATION_Handle *c2;
+
+static struct GNUNET_TESTING_ConnectContext *cc;
+
+static void
+end2_cb (void *cls, const char *emsg)
+{
+
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
+    ok = 1;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Both daemons terminated, will now exit.\n");
+#endif
+    ok = 0;
+  }
+}
+
+static void
+end1_cb (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n",
+                emsg);
+    ok = 1;
+  }
+  else
+  {
+    ok = 0;
+  }
+
+  GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL, GNUNET_YES,
+                              GNUNET_NO);
+  d2 = NULL;
+}
+
+static void
+finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL, GNUNET_YES,
+                              GNUNET_NO);
+  d1 = NULL;
+}
+
+static void
+my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first,
+                     const struct GNUNET_PeerIdentity *second,
+                     unsigned int 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)
+{
+  cc = NULL;
+  GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+}
+
+
+static void
+my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id,
+        const struct GNUNET_CONFIGURATION_Handle *cfg,
+        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  GNUNET_assert (id != NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
+              GNUNET_i2s (id));
+#endif
+  cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS,
+                                       GNUNET_YES, &my_connect_complete, NULL);
+}
+
+
+static void
+my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id,
+        const struct GNUNET_CONFIGURATION_Handle *cfg,
+        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  GNUNET_assert (id != NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
+              GNUNET_i2s (id));
+#endif
+  d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
+                                    NULL, NULL, &my_cb2, NULL);
+  GNUNET_assert (d2 != NULL);
+
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  ok = 1;
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
+#endif
+  c1 = GNUNET_CONFIGURATION_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (c1,
+                                            "test_testing_connect_peer1.conf"));
+  c2 = GNUNET_CONFIGURATION_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (c2,
+                                            "test_testing_connect_peer2.conf"));
+  d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
+                                    NULL, NULL, &my_cb1, NULL);
+  GNUNET_assert (d1 != NULL);
+}
+
+static int
+check ()
+{
+  char *const argv[] = { "test-testing",
+    "-c",
+    "test_testing_data.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                      "test-testing-connect", "nohelp", options, &run, &ok);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test-testing-connect",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+  return ret;
+}
+
+/* end of test_testing_connect.c */
diff --git a/src/testing_old/test_testing_connect_peer1.conf b/src/testing_old/test_testing_connect_peer1.conf
new file mode 100644 (file)
index 0000000..cccda5e
--- /dev/null
@@ -0,0 +1,37 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+SERVICEHOME = /tmp/test-gnunet-testing-connect-peer1/
+DEFAULTCONFIG = test_testing_connect_peer1.conf
+
+[transport-tcp]
+PORT = 12568
+
+[arm]
+PORT = 12566
+DEFAULTSERVICES = core
+UNIXPATH = /tmp/gnunet-p1-service-arm.sock
+
+[statistics]
+PORT = 12567
+UNIXPATH = /tmp/gnunet-p1-service-statistics.sock
+
+[resolver]
+PORT = 12564
+UNIXPATH = /tmp/gnunet-p1-service-resolver.sock
+
+[peerinfo]
+PORT = 12569
+UNIXPATH = /tmp/gnunet-p1-service-peerinfo.sock
+
+[transport]
+PORT = 12565
+UNIXPATH = /tmp/gnunet-p1-service-transport.sock
+
+[core]
+PORT = 12570
+UNIXPATH = /tmp/gnunet-p1-service-core.sock
+
+[ats]
+PORT = 12571
+UNIXPATH = /tmp/gnunet-p1-service-ats.sock
+
diff --git a/src/testing_old/test_testing_connect_peer2.conf b/src/testing_old/test_testing_connect_peer2.conf
new file mode 100644 (file)
index 0000000..08ec551
--- /dev/null
@@ -0,0 +1,37 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+SERVICEHOME = /tmp/test-gnunet-testing-connect-peer2/
+DEFAULTCONFIG = test_testing_connect_peer2.conf
+
+[transport-tcp]
+PORT = 22568
+
+[arm]
+PORT = 22566
+DEFAULTSERVICES = core
+UNIXPATH = /tmp/gnunet-p2-service-arm.sock
+
+[statistics]
+PORT = 22567
+UNIXPATH = /tmp/gnunet-p2-service-statistics.sock
+
+[resolver]
+PORT = 22564
+UNIXPATH = /tmp/gnunet-p2-service-resolver.sock
+
+[peerinfo]
+PORT = 22569
+UNIXPATH = /tmp/gnunet-p2-service-peerinfo.sock
+
+[transport]
+PORT = 22565
+UNIXPATH = /tmp/gnunet-p2-service-transport.sock
+
+[core]
+PORT = 22570
+UNIXPATH = /tmp/gnunet-p2-service-core.sock
+
+[ats]
+PORT = 22571
+UNIXPATH = /tmp/gnunet-p2-service-ats.sock
+
diff --git a/src/testing_old/test_testing_data.conf b/src/testing_old/test_testing_data.conf
new file mode 100644 (file)
index 0000000..c46cb0d
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data.conf
+
+[arm]
+DEFAULTSERVICES = core
+
diff --git a/src/testing_old/test_testing_data_remote.conf b/src/testing_old/test_testing_data_remote.conf
new file mode 100644 (file)
index 0000000..477baad
--- /dev/null
@@ -0,0 +1,12 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_remote.conf
+
+[TESTING_old]
+CONTROL_HOST = 127.0.0.1
+HOSTFILE = remote_hosts.txt
+MAX_OUTSTANDING_SSH = 5
+
+[statistics]
+AUTOSTART = NO
+
diff --git a/src/testing_old/test_testing_data_topology_2d_torus.conf b/src/testing_old/test_testing_data_topology_2d_torus.conf
new file mode 100644 (file)
index 0000000..62fff69
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_2d_torus.conf
+
+[TESTING_old]
+NUM_PEERS = 13
+TOPOLOGY = 2D_TORUS
diff --git a/src/testing_old/test_testing_data_topology_blacklist.conf b/src/testing_old/test_testing_data_topology_blacklist.conf
new file mode 100644 (file)
index 0000000..28e6130
--- /dev/null
@@ -0,0 +1,13 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_blacklist.conf
+
+[TESTING_old]
+NUM_PEERS = 4
+TOPOLOGY = CLIQUE
+BLACKLIST_TOPOLOGY = RING
+BLACKLIST_TRANSPORTS = tcp udp http
+
+[transport-udp]
+PORT = 2568
+
diff --git a/src/testing_old/test_testing_data_topology_churn.conf b/src/testing_old/test_testing_data_topology_churn.conf
new file mode 100644 (file)
index 0000000..ae46bf0
--- /dev/null
@@ -0,0 +1,10 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_churn.conf
+
+[TESTING_old]
+NUM_PEERS = 12
+
+[arm]
+DEFAULTSERVICES = peerinfo transport core
+
diff --git a/src/testing_old/test_testing_data_topology_clique.conf b/src/testing_old/test_testing_data_topology_clique.conf
new file mode 100644 (file)
index 0000000..c71a4b6
--- /dev/null
@@ -0,0 +1,10 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+CONNECT_TIMEOUT = 180 s
+CONNECT_ATTEMPTS = 14
+NUM_PEERS = 4
+TOPOLOGY = CLIQUE
+SETTLE_TIME = 0
diff --git a/src/testing_old/test_testing_data_topology_clique_dfs.conf b/src/testing_old/test_testing_data_topology_clique_dfs.conf
new file mode 100644 (file)
index 0000000..349c398
--- /dev/null
@@ -0,0 +1,13 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+NUM_PEERS = 7
+TOPOLOGY = CLIQUE
+CONNECT_TOPOLOGY_OPTION = CONNECT_DFS
+CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0
+
+[arm]
+DEFAULTSERVICES = peerinfo transport core
+
diff --git a/src/testing_old/test_testing_data_topology_clique_minimum.conf b/src/testing_old/test_testing_data_topology_clique_minimum.conf
new file mode 100644 (file)
index 0000000..8d8206d
--- /dev/null
@@ -0,0 +1,10 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+NUM_PEERS = 20
+TOPOLOGY = CLIQUE
+CONNECT_TOPOLOGY_OPTION = CONNECT_MINIMUM
+CONNECT_TOPOLOGY_OPTION_MODIFIER = 2.0
+
diff --git a/src/testing_old/test_testing_data_topology_clique_random.conf b/src/testing_old/test_testing_data_topology_clique_random.conf
new file mode 100644 (file)
index 0000000..d761752
--- /dev/null
@@ -0,0 +1,16 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+NUM_PEERS = 20
+TOPOLOGY = CLIQUE
+CONNECT_TOPOLOGY_OPTION = CONNECT_RANDOM_SUBSET
+CONNECT_TOPOLOGY_OPTION_MODIFIER = .15
+
+[statistics]
+AUTOSTART = NO
+
+[resolver]
+AUTOSTART = NO
+
diff --git a/src/testing_old/test_testing_data_topology_erdos_renyi.conf b/src/testing_old/test_testing_data_topology_erdos_renyi.conf
new file mode 100644 (file)
index 0000000..ece17e5
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+TOPOLOGY = ERDOS_RENYI
+
diff --git a/src/testing_old/test_testing_data_topology_internat.conf b/src/testing_old/test_testing_data_topology_internat.conf
new file mode 100644 (file)
index 0000000..14475ce
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+TOPOLOGY = INTERNAT
+
diff --git a/src/testing_old/test_testing_data_topology_none.conf b/src/testing_old/test_testing_data_topology_none.conf
new file mode 100644 (file)
index 0000000..38e6586
--- /dev/null
@@ -0,0 +1,37 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+NUM_PEERS = 1000
+TOPOLOGY = NONE
+F2F = NO
+BLACKLIST_TOPOLOGY = NONE
+CONNECT_TOPOLOGY = RING
+
+[arm]
+PORT = 0
+
+[statistics]
+AUTOSTART = NO
+PORT = 0
+
+[resolver]
+AUTOSTART = NO
+PORT = 0
+
+[peerinfo]
+PORT = 0
+
+[transport]
+PORT = 0
+
+[core]
+PORT = 0
+
+[topology]
+PORT = 0
+
+[hostlist]
+PORT = 0
+
diff --git a/src/testing_old/test_testing_data_topology_ring.conf b/src/testing_old/test_testing_data_topology_ring.conf
new file mode 100644 (file)
index 0000000..5320ae0
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+TOPOLOGY = RING
+
diff --git a/src/testing_old/test_testing_data_topology_scale_free.conf b/src/testing_old/test_testing_data_topology_scale_free.conf
new file mode 100644 (file)
index 0000000..ae72335
--- /dev/null
@@ -0,0 +1,11 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_scale_free.conf
+
+[TESTING_old]
+NUM_PEERS = 50
+TOPOLOGY = SCALE_FREE
+
+[arm]
+DEFAULTSERVICES = peerinfo transport core
+
diff --git a/src/testing_old/test_testing_data_topology_small_world_ring.conf b/src/testing_old/test_testing_data_topology_small_world_ring.conf
new file mode 100644 (file)
index 0000000..10e398f
--- /dev/null
@@ -0,0 +1,8 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+NUM_PEERS = 25
+TOPOLOGY = SMALL_WORLD_RING
+
diff --git a/src/testing_old/test_testing_data_topology_small_world_torus.conf b/src/testing_old/test_testing_data_topology_small_world_torus.conf
new file mode 100644 (file)
index 0000000..d5a58b7
--- /dev/null
@@ -0,0 +1,7 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+TOPOLOGY = SMALL_WORLD
+
diff --git a/src/testing_old/test_testing_data_topology_stability.conf b/src/testing_old/test_testing_data_topology_stability.conf
new file mode 100644 (file)
index 0000000..389c0aa
--- /dev/null
@@ -0,0 +1,9 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_data_topology_clique.conf
+
+[TESTING_old]
+SETTLE_TIME = 600 s
+NUM_PEERS = 2
+TOPOLOGY = CLIQUE
+
diff --git a/src/testing_old/test_testing_defaults.conf b/src/testing_old/test_testing_defaults.conf
new file mode 100644 (file)
index 0000000..a89064f
--- /dev/null
@@ -0,0 +1,78 @@
+[PATHS]
+SERVICEHOME = /tmp/test-gnunet-testing/
+DEFAULTCONFIG = test_testing_defaults.conf
+
+[resolver]
+PORT = 2564
+
+[transport]
+PORT = 2565
+PLUGINS = tcp
+
+[arm]
+PORT = 2566
+DEFAULTSERVICES = 
+
+[statistics]
+PORT = 2567
+
+[transport-tcp]
+PORT = 2568
+BINDTO = 127.0.0.1
+
+[peerinfo]
+PORT = 2569
+
+[core]
+PORT = 2570
+
+[testing_old]
+NUM_PEERS = 5
+WEAKRANDOM = YES
+F2F = YES
+HOSTKEYSFILE = ../../contrib/testing_hostkeys.dat
+
+[dht]
+AUTOSTART = NO
+
+[nat]
+DISABLEV6 = YES
+ENABLE_UPNP = NO
+BEHIND_NAT = NO
+ALLOW_NAT = NO
+INTERNAL_ADDRESS = 127.0.0.1
+EXTERNAL_ADDRESS = 127.0.0.1
+USE_LOCALADDR = NO
+
+[dns]
+AUTOSTART = NO
+
+[nse]
+AUTOSTART = NO
+
+[mesh]
+AUTOSTART = NO
+
+[datastore]
+AUTOSTART = NO
+
+[fs]
+AUTOSTART = NO
+
+[dv]
+AUTOSTART = NO
+
+[chat]
+AUTOSTART = NO
+
+[vpn]
+AUTOSTART = NO
+
+[gns]
+AUTOSTART = NO
+
+[namestore]
+AUTOSTART = NO
+
+[lockmanager]
+AUTOSTART = NO
diff --git a/src/testing_old/test_testing_group.c b/src/testing_old/test_testing_group.c
new file mode 100644 (file)
index 0000000..f5df45b
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_group.c
+ * @brief testcase for functions to connect peers in testing.c
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_NO
+
+#define NUM_PEERS 4
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+static int ok;
+
+static int peers_left;
+
+static int failed_peers;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
+#endif
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+#endif
+  }
+}
+
+
+static void
+my_cb (void *cls, const struct GNUNET_PeerIdentity *id,
+       const struct GNUNET_CONFIGURATION_Handle *cfg,
+       struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (id == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Start callback called with error (too long starting peers), aborting test!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
+    failed_peers++;
+    if (failed_peers == peers_left)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Too many peers failed, ending test!\n");
+      ok = 1;
+      GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    }
+    return;
+  }
+
+  peers_left--;
+  if (peers_left == 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All peers started successfully, ending test!\n");
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    ok = 0;
+  }
+  else if (failed_peers == peers_left)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Too many peers failed, ending test!\n");
+    ok = 1;
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+  }
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  ok = 1;
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
+#endif
+  peers_left = NUM_PEERS;
+  pg = GNUNET_TESTING_daemons_start (cfg, peers_left,   /* Total number of peers */
+                                     peers_left,        /* Number of outstanding connections */
+                                     peers_left,        /* Number of parallel ssh connections, or peers being started at once */
+                                     TIMEOUT, NULL, NULL, &my_cb, NULL, NULL,
+                                     NULL, NULL);
+  GNUNET_assert (pg != NULL);
+}
+
+static int
+check ()
+{
+  char *const argv[] = { "test-testing",
+    "-c",
+    "test_testing_data.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                      "test-testing-group", "nohelp", options, &run, &ok);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test-testing-group",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+  /**
+   * Still need to remove the base testing directory here,
+   * because group starts will create subdirectories under this
+   * main dir.  However, we no longer need to sleep, as the
+   * shutdown sequence won't return until everything is cleaned
+   * up.
+   */
+  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
+  return ret;
+}
+
+/* end of test_testing_group.c */
diff --git a/src/testing_old/test_testing_group_remote.c b/src/testing_old/test_testing_group_remote.c
new file mode 100644 (file)
index 0000000..b06655c
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_group_remote.c
+ * @brief testcase for testing remote and local starting and connecting
+ *        of hosts from the testing library.  The test_testing_data_remote.conf
+ *        file should be modified if this testcase is intended to be used.
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_YES
+
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+#define DEFAULT_NUM_PEERS 8;
+
+static int ok;
+
+static int peers_left;
+
+static int peers_failed;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+static unsigned long long num_peers;
+
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Shutdown of peers failed (error %s)!\n", emsg);
+#endif
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+#endif
+  }
+}
+
+
+static void
+my_cb (void *cls, const struct GNUNET_PeerIdentity *id,
+       const struct GNUNET_CONFIGURATION_Handle *cfg,
+       struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    peers_failed++;
+  }
+
+  peers_left--;
+  if (peers_left == 0)
+  {
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    ok = 0;
+  }
+  else if (peers_failed == peers_left)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Too many peers failed, ending test!\n");
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+  }
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_TESTING_Host *hosts;
+  struct GNUNET_TESTING_Host *hostpos;
+  struct GNUNET_TESTING_Host *temphost;
+  char *hostfile;
+  struct stat frstat;
+  char *buf;
+  char *data;
+  int count;
+  int ret;
+
+  ok = 1;
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
+#endif
+
+  if (GNUNET_SYSERR ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+                                             &num_peers))
+    num_peers = DEFAULT_NUM_PEERS;
+
+  GNUNET_assert (num_peers > 0 && num_peers < (unsigned long long) -1);
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "hostfile",
+                                             &hostfile))
+    hostfile = NULL;
+
+  hosts = NULL;
+  data = NULL;
+  if (hostfile != NULL)
+  {
+    if (GNUNET_OK != GNUNET_DISK_file_test (hostfile))
+      GNUNET_DISK_fn_write (hostfile, NULL, 0,
+                            GNUNET_DISK_PERM_USER_READ |
+                            GNUNET_DISK_PERM_USER_WRITE);
+    if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not open file specified for host list, ending test!");
+      ok = 1119;
+      GNUNET_free (hostfile);
+      return;
+    }
+
+    data = GNUNET_malloc_large (frstat.st_size);
+    GNUNET_assert (data != NULL);
+    if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not read file %s specified for host list, ending test!",
+                  hostfile);
+      GNUNET_free (hostfile);
+      GNUNET_free (data);
+      return;
+    }
+
+    GNUNET_free_non_null (hostfile);
+
+    buf = data;
+    count = 0;
+    while (count < frstat.st_size)
+    {
+      count++;
+      if (count >= frstat.st_size)
+        break;
+
+      /* if (((data[count] == '\n') || (data[count] == '\0')) && (buf != &data[count])) */
+      if (((data[count] == '\n')) && (buf != &data[count]))
+      {
+        data[count] = '\0';
+        temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host));
+        ret =
+            SSCANF (buf, "%a[a-zA-Z0-9]@%a[a-zA-Z0-9.]:%hd",
+                    &temphost->username, &temphost->hostname, &temphost->port);
+        if (3 == ret)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Successfully read host %s, port %d and user %s from file\n",
+                      temphost->hostname, temphost->port, temphost->username);
+        }
+        else
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Error reading line `%s' in hostfile\n", buf);
+          GNUNET_free (temphost);
+          buf = &data[count + 1];
+          continue;
+        }
+        /* temphost->hostname = buf; */
+        temphost->next = hosts;
+        hosts = temphost;
+        buf = &data[count + 1];
+      }
+      else if ((data[count] == '\n') || (data[count] == '\0'))
+        buf = &data[count + 1];
+    }
+  }
+
+  peers_left = num_peers;
+  pg = GNUNET_TESTING_daemons_start (cfg, peers_left,   /* Total number of peers */
+                                     peers_left,        /* Number of outstanding connections */
+                                     peers_left,        /* Number of parallel ssh connections, or peers being started at once */
+                                     TIMEOUT, NULL, NULL, &my_cb, NULL, NULL,
+                                     NULL, hosts);
+  hostpos = hosts;
+  while (hostpos != NULL)
+  {
+    temphost = hostpos->next;
+    GNUNET_free (hostpos->hostname);
+    GNUNET_free (hostpos->username);
+    GNUNET_free (hostpos);
+    hostpos = temphost;
+  }
+  GNUNET_free_non_null (data);
+  GNUNET_assert (pg != NULL);
+
+}
+
+static int
+check ()
+{
+  char *const argv[] = { "test-testing",
+    "-c",
+    "test_testing_data_remote.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                      "test-testing-group", "nohelp", options, &run, &ok);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test-testing-group",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+  /**
+   * Still need to remove the base testing directory here,
+   * because group starts will create subdirectories under this
+   * main dir.  However, we no longer need to sleep, as the
+   * shutdown sequence won't return until everything is cleaned
+   * up.
+   */
+  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
+  return ret;
+}
+
+/* end of test_testing_group.c */
diff --git a/src/testing_old/test_testing_large_topology.c b/src/testing_old/test_testing_large_topology.c
new file mode 100644 (file)
index 0000000..cd80db1
--- /dev/null
@@ -0,0 +1,1197 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_topology.c
+ * @brief base testcase for testing all the topologies provided
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_os_lib.h"
+
+#define VERBOSE GNUNET_YES
+
+#define DELAY_FOR_LOGGING GNUNET_NO
+
+#define SECONDS_PER_PEER_START 120
+
+#define DEFAULT_NUM_PEERS 4
+
+#define MAX_OUTSTANDING_CONNECTIONS 100
+
+static float fail_percentage = 0.05;
+
+static int ok;
+
+struct GNUNET_TIME_Relative connect_timeout;
+
+static unsigned long long connect_attempts;
+
+static unsigned long long num_peers;
+
+static unsigned int topology_connections;
+
+static unsigned int total_connections;
+
+static unsigned int failed_connections;
+
+static unsigned int total_server_connections;
+
+static unsigned int total_messages_received;
+
+static unsigned int expected_messages;
+
+static unsigned int expected_connections;
+
+static unsigned long long peers_left;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+const struct GNUNET_CONFIGURATION_Handle *main_cfg;
+
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+static char *dotOutFileName;
+
+static struct GNUNET_TIME_Relative settle_time;
+
+static FILE *dotOutFile;
+
+static char *topology_string;
+
+static char *blacklist_transports;
+
+static int transmit_ready_scheduled;
+
+static int transmit_ready_failed;
+
+static int transmit_ready_called;
+
+struct GNUNET_TIME_Relative test_timeout;
+
+struct GNUNET_TIME_Relative timeout;
+
+static unsigned int modnum;
+
+static unsigned int dotnum;
+
+static enum GNUNET_TESTING_Topology topology;
+
+static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE;  /* Don't do any blacklisting */
+
+static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
+
+static enum GNUNET_TESTING_TopologyOption connect_topology_option =
+    GNUNET_TESTING_TOPOLOGY_OPTION_ALL;
+
+static double connect_topology_option_modifier = 0.0;
+
+static char *test_directory;
+
+#define MTYPE 12345
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct GNUNET_TestMessage
+{
+  /**
+   * Header of the message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this message.
+   */
+  uint32_t uid;
+};
+GNUNET_NETWORK_STRUCT_END
+
+struct TestMessageContext
+{
+  /* This is a linked list */
+  struct TestMessageContext *next;
+
+  /* Handle to the sending peer core */
+  struct GNUNET_CORE_Handle *peer1handle;
+
+  /* Handle to the receiving peer core */
+  struct GNUNET_CORE_Handle *peer2handle;
+
+  /* Handle to the sending peer daemon */
+  struct GNUNET_TESTING_Daemon *peer1;
+
+  /* Handle to the receiving peer daemon */
+  struct GNUNET_TESTING_Daemon *peer2;
+
+  /* Identifier for this message, so we don't disconnect other peers! */
+  uint32_t uid;
+
+  /* Has peer1 been notified already of a connection to peer2? */
+  int peer1notified;
+
+  /* Has the core of peer2 been connected already? */
+  int peer2connected;
+
+  /* Task for disconnecting cores, allow task to be cancelled on shutdown */
+  GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+};
+
+static struct TestMessageContext *test_messages;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
+#endif
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+#endif
+  }
+}
+
+#if DELAY_FOR_LOGGING
+static void
+gather_log_data ()
+{
+  char *peer_number;
+  char *connect_number;
+  struct GNUNET_OS_Process *mem_process;
+
+  GNUNET_asprintf (&peer_number, "%llu", num_peers);
+  GNUNET_asprintf (&connect_number, "%llu", expected_connections);
+  mem_process =
+      GNUNET_OS_start_process (NULL, NULL, "./memsize.pl", "memsize.pl",
+                               "totals.txt", peer_number, connect_number, NULL);
+  GNUNET_OS_process_wait (mem_process);
+  GNUNET_OS_process_destroy (mem_process);
+  mem_process = NULL;
+}
+
+#endif
+
+static void
+finish_testing ()
+{
+  GNUNET_assert (pg != NULL);
+  struct TestMessageContext *pos;
+  struct TestMessageContext *free_pos;
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Called finish testing, stopping daemons.\n");
+#endif
+
+  pos = test_messages;
+  while (pos != NULL)
+  {
+    if (pos->peer1handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer1handle);
+      pos->peer1handle = NULL;
+    }
+    if (pos->peer2handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer2handle);
+      pos->peer2handle = NULL;
+    }
+    free_pos = pos;
+    pos = pos->next;
+    if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (free_pos->disconnect_task);
+    }
+    GNUNET_free (free_pos);
+  }
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
+              transmit_ready_scheduled, transmit_ready_failed,
+              transmit_ready_called);
+#endif
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
+#endif
+  GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL);
+
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "}");
+    FCLOSE (dotOutFile);
+  }
+
+  ok = 0;
+}
+
+
+static void
+disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct TestMessageContext *pos = cls;
+
+  /* Disconnect from the respective cores */
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n",
+              GNUNET_i2s (&pos->peer1->id));
+#endif
+  if (pos->peer1handle != NULL)
+    GNUNET_CORE_disconnect (pos->peer1handle);
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n",
+              GNUNET_i2s (&pos->peer2->id));
+#endif
+  if (pos->peer2handle != NULL)
+    GNUNET_CORE_disconnect (pos->peer2handle);
+  /* Set handles to NULL so test case can be ended properly */
+  pos->peer1handle = NULL;
+  pos->peer2handle = NULL;
+  pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  /* Decrement total connections so new can be established */
+  total_server_connections -= 2;
+}
+
+
+static void
+topology_cb (void *cls, const struct GNUNET_PeerIdentity *first,
+             const struct GNUNET_PeerIdentity *second, const char *emsg)
+{
+  FILE *outfile = cls;
+
+  if (first != NULL)
+  {
+    if (outfile != NULL)
+    {
+      FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first));
+      FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second));
+    }
+    topology_connections++;
+  }
+  else
+  {
+    FPRINTF (stderr,
+             "Finished iterating over topology, %d total connections!\n",
+             topology_connections);
+    if (outfile != NULL)
+    {
+      FPRINTF (outfile, "%s",  "}\n");
+      FCLOSE (outfile);
+      GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+    }
+  }
+}
+
+static int
+process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer,
+               const struct GNUNET_MessageHeader *message,
+               const struct GNUNET_ATS_Information *atsi)
+{
+  char *dotOutFileNameFinished;
+  FILE *dotOutFileFinished;
+  struct TestMessageContext *pos = cls;
+  struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message;
+
+  if (pos->uid != ntohl (msg->uid))
+    return GNUNET_OK;
+
+#if VERBOSE
+  if ((total_messages_received) % modnum == 0)
+  {
+    if (total_messages_received == 0)
+      FPRINTF (stdout, "%s",  "0%%");
+    else
+      FPRINTF (stdout, "%d%%",
+               (int) (((float) total_messages_received / expected_messages) *
+                      100));
+
+  }
+  else if (total_messages_received % dotnum == 0)
+  {
+    FPRINTF (stdout, "%s",  ".");
+  }
+  fflush (stdout);
+#endif
+
+  total_messages_received++;
+
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received message from `%4s', type %d.\n", GNUNET_i2s (peer),
+              ntohs (message->type));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Total messages received %d, expected %d.\n",
+              total_messages_received, expected_messages);
+#endif
+
+  if (total_messages_received == expected_messages)
+  {
+#if VERBOSE
+    FPRINTF (stdout, "%s",  "100%%]\n");
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology");
+    dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w");
+    GNUNET_free (dotOutFileNameFinished);
+    if (dotOutFileFinished != NULL)
+    {
+      FPRINTF (dotOutFileFinished, "%s",  "strict graph G {\n");
+    }
+    topology_connections = 0;
+    GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished);
+    //GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+  }
+  else
+  {
+    pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos);
+  }
+
+  return GNUNET_OK;
+}
+
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char *msg = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "End badly was called (%s)... stopping daemons.\n", msg);
+  struct TestMessageContext *pos;
+  struct TestMessageContext *free_pos;
+
+  pos = test_messages;
+  while (pos != NULL)
+  {
+    if (pos->peer1handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer1handle);
+      pos->peer1handle = NULL;
+    }
+    if (pos->peer2handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer2handle);
+      pos->peer2handle = NULL;
+    }
+    free_pos = pos;
+    pos = pos->next;
+    GNUNET_free (free_pos);
+  }
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
+              transmit_ready_scheduled, transmit_ready_failed,
+              transmit_ready_called);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Total messages received %d, expected %d.\n",
+              total_messages_received, expected_messages);
+#endif
+
+  if (pg != NULL)
+  {
+    GNUNET_TESTING_daemons_stop (pg, timeout, &shutdown_callback, NULL);
+    ok = 7331;                  /* Opposite of leet */
+  }
+  else
+    ok = 401;                   /* Never got peers started */
+
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "}");
+    FCLOSE (dotOutFile);
+  }
+}
+
+static size_t
+transmit_ready (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_TestMessage *m;
+  struct TestMessageContext *pos = cls;
+
+  GNUNET_assert (buf != NULL);
+  m = (struct GNUNET_TestMessage *) buf;
+  m->header.type = htons (MTYPE);
+  m->header.size = htons (sizeof (struct GNUNET_TestMessage));
+  m->uid = htonl (pos->uid);
+  transmit_ready_called++;
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n",
+              GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled,
+              transmit_ready_called);
+#endif
+  return sizeof (struct GNUNET_TestMessage);
+}
+
+
+static struct GNUNET_CORE_MessageHandler no_handlers[] = {
+  {NULL, 0, 0}
+};
+
+static struct GNUNET_CORE_MessageHandler handlers[] = {
+  {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)},
+  {NULL, 0, 0}
+};
+
+static void
+init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server,
+                   const struct GNUNET_PeerIdentity *my_identity)
+{
+  struct TestMessageContext *pos = cls;
+
+  total_server_connections++;
+
+  pos->peer2connected = GNUNET_YES;
+  if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */
+  {
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
+                GNUNET_i2s (my_identity),
+                GNUNET_h2s (&pos->peer1->id.hashPubKey));
+#endif
+    if (NULL ==
+        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout,
+                                           &pos->peer2->id,
+                                           sizeof (struct GNUNET_TestMessage),
+                                           &transmit_ready, pos))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
+                  GNUNET_i2s (&pos->peer2->id));
+      transmit_ready_failed++;
+    }
+    else
+    {
+      transmit_ready_scheduled++;
+    }
+  }
+}
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ * @param atsi performance data for the connection
+ */
+static void
+connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_ATS_Information *atsi)
+{
+  struct TestMessageContext *pos = cls;
+
+  if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity)))
+  {
+    pos->peer1notified = GNUNET_YES;
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Peer `%s' notified of connection to peer `%s'\n",
+                GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey));
+#endif
+  }
+  else
+    return;
+
+  if (pos->peer2connected == GNUNET_YES)        /* Already connected and notified of connection, send message! */
+  {
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
+                GNUNET_i2s (&pos->peer2->id),
+                GNUNET_h2s (&pos->peer1->id.hashPubKey));
+#endif
+    if (NULL ==
+        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, 0, timeout,
+                                           &pos->peer2->id,
+                                           sizeof (struct GNUNET_TestMessage),
+                                           &transmit_ready, pos))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
+                  GNUNET_i2s (&pos->peer2->id));
+      transmit_ready_failed++;
+    }
+    else
+    {
+      transmit_ready_scheduled++;
+    }
+  }
+}
+
+static void
+init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server,
+                   const struct GNUNET_PeerIdentity *my_identity)
+{
+  struct TestMessageContext *pos = cls;
+
+  total_server_connections++;
+
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Core connection to `%4s' established, setting up handles\n",
+              GNUNET_i2s (my_identity));
+#endif
+
+  /*
+   * Connect to the receiving peer
+   */
+  pos->peer2handle =
+      GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL,
+                           NULL, NULL, NULL, GNUNET_YES, NULL, GNUNET_YES,
+                           handlers);
+
+}
+
+
+static void
+send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct TestMessageContext *pos = cls;
+
+  if ((pos == test_messages) && (settle_time.rel_value > 0))
+  {
+    topology_connections = 0;
+    GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
+  }
+  if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL))
+    return;
+
+  if (die_task == GNUNET_SCHEDULER_NO_TASK)
+  {
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
+                                      "from send test messages (timeout)");
+  }
+
+  if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS)
+  {
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 1),
+                                  &send_test_messages, pos);
+    return;                     /* Otherwise we'll double schedule messages here! */
+  }
+
+  /*
+   * Connect to the sending peer
+   */
+  pos->peer1handle =
+      GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1,
+                           &connect_notify_peers, NULL, NULL, NULL, GNUNET_NO,
+                           NULL, GNUNET_NO, no_handlers);
+
+  GNUNET_assert (pos->peer1handle != NULL);
+
+  if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS)
+  {
+    GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 1),
+                                  &send_test_messages, pos->next);
+  }
+}
+
+
+void
+topology_callback (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)
+{
+  struct TestMessageContext *temp_context;
+
+  if (emsg == NULL)
+  {
+#if VERBOSE
+    if ((total_connections) % modnum == 0)
+    {
+      if (total_connections == 0)
+        FPRINTF (stdout, "%s",  "0%%");
+      else
+        FPRINTF (stdout, "%d%%",
+                 (int) (((float) total_connections / expected_connections) *
+                        100));
+
+    }
+    else if (total_connections % dotnum == 0)
+    {
+      FPRINTF (stdout, "%s",  ".");
+    }
+    fflush (stdout);
+#endif
+    total_connections++;
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n",
+                first_daemon->shortname, second_daemon->shortname);
+#endif
+    temp_context = GNUNET_malloc (sizeof (struct TestMessageContext));
+    temp_context->peer1 = first_daemon;
+    temp_context->peer2 = second_daemon;
+    temp_context->next = test_messages;
+    temp_context->uid = total_connections;
+    temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+    test_messages = temp_context;
+
+    expected_messages++;
+    if (dotOutFile != NULL)
+      FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname,
+               second_daemon->shortname);
+  }
+#if VERBOSE
+  else
+  {
+    failed_connections++;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to connect peer %s to peer %s with error :\n%s\n",
+                first_daemon->shortname, second_daemon->shortname, emsg);
+  }
+#endif
+
+  if (total_connections == expected_connections)
+  {
+#if VERBOSE
+    FPRINTF (stdout, "%s",  "100%%]\n");
+#endif
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Created %d total connections, which is our target number!  Calling send messages.\n",
+                total_connections);
+#endif
+    modnum = expected_messages / 4;
+    dotnum = (expected_messages / 50) + 1;
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task = GNUNET_SCHEDULER_NO_TASK;
+#if DELAY_FOR_LOGGING
+    FPRINTF (stdout, "%s",  "Sending test messages in 10 seconds.\n");
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 10),
+                                  &send_test_messages, test_messages);
+    gather_log_data ();
+#else
+    if (settle_time.rel_value > 0)
+    {
+      GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
+    }
+    GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages,
+                                  test_messages);
+#endif
+#if VERBOSE
+    FPRINTF (stdout, "%s",  "Test message progress: [");
+#endif
+
+  }
+  else if (total_connections + failed_connections == expected_connections)
+  {
+    if (failed_connections <
+        (unsigned int) (fail_percentage * total_connections))
+    {
+      GNUNET_SCHEDULER_cancel (die_task);
+      die_task = GNUNET_SCHEDULER_NO_TASK;
+      GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages);
+    }
+    else
+    {
+      GNUNET_SCHEDULER_cancel (die_task);
+      die_task =
+          GNUNET_SCHEDULER_add_now (&end_badly,
+                                    "from topology_callback (too many failed connections)");
+    }
+  }
+  else
+  {
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Have %d total connections, %d failed connections, Want %d (at least %d)\n",
+                total_connections, failed_connections, expected_connections,
+                expected_connections -
+                (unsigned int) (fail_percentage * expected_connections));
+#endif
+  }
+}
+
+static void
+topology_creation_finished (void *cls, const char *emsg)
+{
+#if VERBOSE
+  if (emsg == NULL)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All topology connections created successfully!\n");
+#endif
+}
+
+static void
+connect_topology ()
+{
+  expected_connections = -1;
+  if ((pg != NULL) && (peers_left == 0))
+  {
+    expected_connections =
+        GNUNET_TESTING_connect_topology (pg, connection_topology,
+                                         connect_topology_option,
+                                         connect_topology_option_modifier,
+                                         connect_timeout, connect_attempts,
+                                         &topology_creation_finished, NULL);
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
+                expected_connections);
+#endif
+  }
+
+  GNUNET_SCHEDULER_cancel (die_task);
+  if (expected_connections == GNUNET_SYSERR)
+  {
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from connect topology (bad return)");
+  }
+
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
+                                    "from connect topology (timeout)");
+  modnum = expected_connections / 4;
+  dotnum = (expected_connections / 50) + 1;
+#if VERBOSE
+  FPRINTF (stdout, "%s",  "Peer connection progress: [");
+#endif
+}
+
+static void
+create_topology ()
+{
+  peers_left = num_peers;       /* Reset counter */
+  if (GNUNET_TESTING_create_topology
+      (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Topology set up, now starting peers!\n");
+    FPRINTF (stdout, "%s",  "Daemon start progress [");
+#endif
+    GNUNET_TESTING_daemons_continue_startup (pg);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from create topology (bad return)");
+  }
+  GNUNET_SCHEDULER_cancel (die_task);
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
+                                    "from continue startup (timeout)");
+}
+
+
+static void
+peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                        const struct GNUNET_CONFIGURATION_Handle *cfg,
+                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to start daemon with error: `%s'\n", emsg);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
+              (num_peers - peers_left) + 1, num_peers);
+#endif
+#if VERBOSE
+  if ((num_peers - peers_left) % modnum == 0)
+  {
+    if (num_peers - peers_left == 0)
+      FPRINTF (stdout, "%s",  "0%%");
+    else
+      FPRINTF (stdout, "%d%%",
+               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
+
+  }
+  else if ((num_peers - peers_left) % dotnum == 0)
+  {
+    FPRINTF (stdout, "%s",  ".");
+  }
+  fflush (stdout);
+#endif
+  peers_left--;
+  if (peers_left == 0)
+  {
+#if VERBOSE
+    FPRINTF (stdout, "%s",  "100%%]\n");
+#endif
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d daemons started, now connecting peers!\n", num_peers);
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (timeout, &end_badly,
+                                      "from peers_started_callback");
+#if DELAY_FOR_LOGGING
+    FPRINTF (stdout, "%s",  "Connecting topology in 10 seconds\n");
+    gather_log_data ();
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 10),
+                                  &connect_topology, NULL);
+#else
+    connect_topology ();
+#endif
+    ok = 0;
+  }
+}
+
+/**
+ * Callback indicating that the hostkey was created for a peer.
+ *
+ * @param cls NULL
+ * @param id the peer identity
+ * @param d the daemon handle (pretty useless at this point, remove?)
+ * @param emsg non-null on failure
+ */
+void
+hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Hostkey callback received error: %s\n", emsg);
+  }
+
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left,
+              num_peers, GNUNET_i2s (id));
+#endif
+
+#if VERBOSE
+  if ((num_peers - peers_left) % modnum == 0)
+  {
+    if (num_peers - peers_left == 0)
+      FPRINTF (stdout, "%s",  "0%%");
+    else
+      FPRINTF (stdout, "%d%%",
+               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
+
+  }
+  else if ((num_peers - peers_left) % dotnum == 0)
+  {
+    FPRINTF (stdout, "%s",  ".");
+  }
+  fflush (stdout);
+#endif
+  peers_left--;
+  if (peers_left == 0)
+  {
+#if VERBOSE
+    FPRINTF (stdout, "%s",  "100%%]\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d hostkeys created, now creating topology!\n", num_peers);
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (test_timeout, &end_badly,
+                                      "from create_topology");
+    GNUNET_SCHEDULER_add_now (&create_topology, NULL);
+    ok = 0;
+  }
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *topology_str;
+  char *connect_topology_str;
+  char *blacklist_topology_str;
+  char *connect_topology_option_str;
+  char *connect_topology_option_modifier_string;
+  unsigned long long temp_settle;
+
+  ok = 1;
+
+  dotOutFile = FOPEN (dotOutFileName, "w");
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "strict graph G {\n");
+  }
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting daemons based on config file %s\n", cfgfile);
+#endif
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+                                             &test_directory))
+  {
+    ok = 404;
+    return;
+  }
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology",
+                                              &topology_str)) &&
+      (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid topology `%s' given for section %s option %s\n",
+                topology_str, "TESTING", "TOPOLOGY");
+    topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;  /* Defaults to NONE, so set better default here */
+  }
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                              "connect_topology",
+                                              &connect_topology_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_get (&connection_topology,
+                                    connect_topology_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid connect topology `%s' given for section %s option %s\n",
+                connect_topology_str, "TESTING", "CONNECT_TOPOLOGY");
+  }
+  GNUNET_free_non_null (connect_topology_str);
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                              "connect_topology_option",
+                                              &connect_topology_option_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_option_get (&connect_topology_option,
+                                           connect_topology_option_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid connect topology option `%s' given for section %s option %s\n",
+                connect_topology_option_str, "TESTING",
+                "CONNECT_TOPOLOGY_OPTION");
+    connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL;       /* Defaults to NONE, set to ALL */
+  }
+  GNUNET_free_non_null (connect_topology_option_str);
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                             "connect_topology_option_modifier",
+                                             &connect_topology_option_modifier_string))
+  {
+    if (SSCANF
+        (connect_topology_option_modifier_string, "%lf",
+         &connect_topology_option_modifier) != 1)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  connect_topology_option_modifier_string,
+                  "connect_topology_option_modifier", "TESTING");
+    }
+    GNUNET_free (connect_topology_option_modifier_string);
+  }
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                             "blacklist_transports",
+                                             &blacklist_transports))
+    blacklist_transports = NULL;
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                              "blacklist_topology",
+                                              &blacklist_topology_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_get (&blacklist_topology,
+                                    blacklist_topology_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid topology `%s' given for section %s option %s\n",
+                topology_str, "TESTING", "BLACKLIST_TOPOLOGY");
+  }
+  GNUNET_free_non_null (topology_str);
+  GNUNET_free_non_null (blacklist_topology_str);
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME",
+                                           &settle_time))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "SETTLE_TIME");
+    return;
+  }
+  if (GNUNET_SYSERR ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+                                             &num_peers))
+    num_peers = DEFAULT_NUM_PEERS;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "CONNECT_TIMEOUT",
+                                             &connect_timeout))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "CONNECT_TIMEOUT");
+    return;
+  }
+
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
+                                             &connect_attempts))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "connect_attempts");
+    return;
+  }
+
+  main_cfg = cfg;
+
+  peers_left = num_peers;
+
+  /**
+   * How long until we fail the whole testcase?
+   */
+  test_timeout =
+      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply
+                                     (GNUNET_TIME_UNIT_SECONDS,
+                                      SECONDS_PER_PEER_START), num_peers * 2);
+
+  /**
+   * How long until we give up on starting the peers?
+   */
+  timeout =
+      GNUNET_TIME_relative_multiply (GNUNET_TIME_relative_multiply
+                                     (GNUNET_TIME_UNIT_SECONDS,
+                                      SECONDS_PER_PEER_START), num_peers);
+
+  modnum = num_peers / 4;
+  dotnum = (num_peers / 50) + 1;
+#if VERBOSE
+  FPRINTF (stdout, "%s",  "Hostkey generation progress: [");
+#endif
+  /* Set up a task to end testing if peer start fails */
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (timeout, &end_badly,
+                                    "didn't generate all hostkeys within a reasonable amount of time!!!");
+
+  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
+  pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left / 2,
+                                     peers_left, timeout, &hostkey_callback,
+                                     NULL, &peers_started_callback, NULL,
+                                     &topology_callback, NULL, NULL);
+
+}
+
+static int
+check ()
+{
+  char *binary_name;
+  char *config_file_name;
+
+  GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string);
+  GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf",
+                   topology_string);
+  int ret;
+
+  char *const argv[] = { binary_name,
+    "-c",
+    config_file_name,
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  ret =
+      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                          binary_name, "nohelp", options, &run, &ok);
+  if (ret != GNUNET_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "`test-testing-topology-%s': Failed with error code %d\n",
+                topology_string, ret);
+  }
+  GNUNET_free (binary_name);
+  GNUNET_free (config_file_name);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+  char *binary_start_pos;
+  char *our_binary_name;
+
+  binary_start_pos = rindex (argv[0], '/');
+  GNUNET_assert (binary_start_pos != NULL);
+  topology_string = strstr (binary_start_pos, "_topology");
+  GNUNET_assert (topology_string != NULL);
+  topology_string++;
+  topology_string = strstr (topology_string, "_");
+  GNUNET_assert (topology_string != NULL);
+  topology_string++;
+
+  GNUNET_asprintf (&our_binary_name, "test-testing-large-topology_%s",
+                   topology_string);
+  GNUNET_asprintf (&dotOutFileName, "large_topology_%s.dot", topology_string);
+
+  GNUNET_log_setup (our_binary_name,
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+
+  /**
+   * Need to remove base directory, subdirectories taken care
+   * of by the testing framework.
+   */
+  if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to remove testing directory %s\n", test_directory);
+  }
+  GNUNET_free (our_binary_name);
+  return ret;
+}
+
+/* end of test_testing_topology.c */
diff --git a/src/testing_old/test_testing_peergroup.c b/src/testing_old/test_testing_peergroup.c
new file mode 100644 (file)
index 0000000..061a0ca
--- /dev/null
@@ -0,0 +1,157 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_peergroup.c
+ * @brief testcase for functions to connect peers in testing_peergroup.c
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_NO
+
+#define NUM_PEERS 4
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+static int ok;
+
+static int peers_left;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
+#endif
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+#endif
+    ok = 0;
+  }
+}
+
+
+static void
+my_cb (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Peergroup callback called with error, aborting test!\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Error from testing: `%s'\n");
+    ok = 1;
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    return;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Peer Group started successfully, ending test!\n");
+  /**
+   * If something is to actually be DONE with the testcase, it should
+   * be put in here.  Usually there will be a struct declared (or global
+   * variables can be used) to keep track of the state, statistics,
+   * handles to peers, etc.  The example here is the opaque "TestCaseData"
+   * struct that could be passed into a function "additional_code_for_testing"
+   * which can be used to perform actions on the peers in the peergroup.
+   * Also, the GNUNET_TESTING_daemons_stop call would need to be removed,
+   * and only called once all of the testing is complete.
+   */
+
+  /**
+   * struct TestcaseData *state_closure;
+   * GNUNET_SCHEDULER_add_now(&additional_code_for_testing, state_closure);
+   */
+
+  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_CONFIGURATION_Handle *testing_cfg;
+
+  ok = 1;
+  testing_cfg = GNUNET_CONFIGURATION_create ();
+  GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (testing_cfg, cfgfile));
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemons.\n");
+  GNUNET_CONFIGURATION_set_value_string (testing_cfg, "testing",
+                                         "use_progressbars", "YES");
+#endif
+  peers_left = NUM_PEERS;
+  pg = GNUNET_TESTING_peergroup_start (testing_cfg, peers_left, TIMEOUT, NULL,
+                                       &my_cb, NULL, NULL);
+  GNUNET_assert (pg != NULL);
+}
+
+static int
+check ()
+{
+  char *const argv[] = { "test-testing-peergroup",
+    "-c",
+    "test_testing_peergroup_data.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                      "test-testing-peergroup", "nohelp", options, &run, &ok);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test-testing-peergroup",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+  GNUNET_DISK_directory_remove ("/tmp/test-gnunet-testing");
+  return ret;
+}
+
+/* end of test_testing_peergroup.c */
diff --git a/src/testing_old/test_testing_peergroup_data.conf b/src/testing_old/test_testing_peergroup_data.conf
new file mode 100644 (file)
index 0000000..880cebf
--- /dev/null
@@ -0,0 +1,22 @@
+@INLINE@ test_testing_defaults.conf
+[PATHS]
+DEFAULTCONFIG = test_testing_peergroup_data.conf
+
+[TESTING_old]
+CONNECT_ATTEMPTS = 2
+MAX_OUTSTANDING_CONNECTIONS = 20
+MAX_CONCURRENT_SSH = 1
+PEERGROUP_TIMEOUT = 300 s
+TOPOLOGY = CLIQUE
+PERCENTAGE = 0.5
+PROBABILITY = 0.5
+CONNECT_TOPOLOGY = CLIQUE
+CONNECT_TOPOLOGY_OPTION = CONNECT_NONE
+CONNECT_TOPOLOGY_OPTION_MODIFIER = 0.0
+BLACKLIST_TOPOLOGY = NONE
+BLACKLIST_TRANSPORTS = tcp udp
+USE_PROGRESSBARS = NO
+
+[arm]
+DEFAULTSERVICES = core
+
diff --git a/src/testing_old/test_testing_reconnect.c b/src/testing_old/test_testing_reconnect.c
new file mode 100644 (file)
index 0000000..bcee386
--- /dev/null
@@ -0,0 +1,249 @@
+/*
+     This file is part of GNUnet.
+     (C) 2010 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_reconnect.c
+ * @brief testcase for functions to connect two peers in testing.c
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+
+#define VERBOSE GNUNET_YES
+
+/**
+ * How long until we give up on connecting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+#define CONNECT_ATTEMPTS 3
+
+static int ok;
+
+static struct GNUNET_TESTING_Daemon *d1;
+
+static struct GNUNET_TESTING_Daemon *d2;
+
+static struct GNUNET_CONFIGURATION_Handle *c1;
+
+static struct GNUNET_CONFIGURATION_Handle *c2;
+
+static struct GNUNET_TESTING_ConnectContext *cc;
+
+/**
+ * How many start-connect-stop iterations should we do?
+ */
+#define NUM_PHASES 2
+
+static int phase;
+
+/**
+ * Run the next phase of starting daemons, connecting them and
+ * stopping them again.
+ */
+static void
+run_phase (void);
+
+static void
+end2_cb (void *cls, const char *emsg)
+{
+
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Ending with error: %s\n", emsg);
+    ok = 1;
+  }
+  else
+  {
+    if (phase < NUM_PHASES)
+    {
+      FPRINTF (stderr, "%s",  ".");
+      run_phase ();
+      return;
+    }
+    FPRINTF (stderr, "%s",  ".\n");
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Both daemons terminated, will now exit.\n");
+#endif
+    ok = 0;
+  }
+}
+
+static void
+end1_cb (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Stopping daemon 1 gave: %s\n",
+                emsg);
+    ok = 1;
+  }
+  else
+  {
+    ok = 0;
+  }
+  if (d2 != NULL)
+  {
+    GNUNET_TESTING_daemon_stop (d2, TIMEOUT, &end2_cb, NULL,
+                                (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO,
+                                GNUNET_NO);
+    d2 = NULL;
+  }
+}
+
+static void
+finish_testing (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_TESTING_daemon_stop (d1, TIMEOUT, &end1_cb, NULL,
+                              (phase == NUM_PHASES) ? GNUNET_YES : GNUNET_NO,
+                              GNUNET_NO);
+  d1 = NULL;
+}
+
+
+static void
+my_connect_complete (void *cls, const struct GNUNET_PeerIdentity *first,
+                     const struct GNUNET_PeerIdentity *second,
+                     unsigned int 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)
+{
+  cc = NULL;
+#if VERBOSE
+  FPRINTF (stderr, "Peer %s ", GNUNET_i2s (first));
+  FPRINTF (stderr, "connected to %s\n", GNUNET_i2s (second));
+#endif
+  GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+}
+
+
+
+
+static void
+my_cb2 (void *cls, const struct GNUNET_PeerIdentity *id,
+        const struct GNUNET_CONFIGURATION_Handle *cfg,
+        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 2 gave: %s\n",
+                emsg);
+    GNUNET_assert (0);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
+              GNUNET_i2s (id));
+#endif
+  cc = GNUNET_TESTING_daemons_connect (d1, d2, TIMEOUT, CONNECT_ATTEMPTS,
+                                       GNUNET_YES, &my_connect_complete, NULL);
+}
+
+
+static void
+my_cb1 (void *cls, const struct GNUNET_PeerIdentity *id,
+        const struct GNUNET_CONFIGURATION_Handle *cfg,
+        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Starting daemon 1 gave: %s\n",
+                emsg);
+    GNUNET_assert (0);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Daemon `%s' started.\n",
+              GNUNET_i2s (id));
+#endif
+  d2 = GNUNET_TESTING_daemon_start (c2, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
+                                    NULL, NULL, &my_cb2, NULL);
+  GNUNET_assert (d2 != NULL);
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  ok = 1;
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting daemon.\n");
+#endif
+  c1 = GNUNET_CONFIGURATION_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (c1,
+                                            "test_testing_connect_peer1.conf"));
+  c2 = GNUNET_CONFIGURATION_create ();
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_load (c2,
+                                            "test_testing_connect_peer2.conf"));
+  run_phase ();
+}
+
+static void
+run_phase ()
+{
+  phase++;
+  d1 = GNUNET_TESTING_daemon_start (c1, TIMEOUT, GNUNET_NO, NULL, NULL, 0, NULL,
+                                    NULL, NULL, &my_cb1, NULL);
+  GNUNET_assert (d1 != NULL);
+}
+
+static int
+check ()
+{
+  char *const argv[] = { "test-testing-reconnect",
+    "-c",
+    "test_testing_data.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                      "test-testing-reconnect", "nohelp", options, &run, &ok);
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test-testing-reconnect",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+  return ret;
+}
+
+/* end of test_testing_reconnect.c */
diff --git a/src/testing_old/test_testing_topology.c b/src/testing_old/test_testing_topology.c
new file mode 100644 (file)
index 0000000..94cbc0d
--- /dev/null
@@ -0,0 +1,1220 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_topology.c
+ * @brief base testcase for testing all the topologies provided
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_os_lib.h"
+
+
+#define PROGRESS_BARS GNUNET_YES
+
+#define DELAY_FOR_LOGGING GNUNET_NO
+
+/**
+ * How long until we fail the whole testcase?
+ */
+#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 240)
+
+/**
+ * How long until we give up on starting the peers?
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 500)
+
+#define SECONDS_PER_PEER_START 120
+
+#define DEFAULT_NUM_PEERS 4
+
+#define MAX_OUTSTANDING_CONNECTIONS 100
+
+static float fail_percentage = 0.05;
+
+static int ok;
+
+static unsigned long long num_peers;
+
+struct GNUNET_TIME_Relative connect_timeout;
+
+static unsigned long long connect_attempts;
+
+static unsigned int topology_connections;
+
+static unsigned int total_connections;
+
+static unsigned int failed_connections;
+
+static unsigned int total_server_connections;
+
+static unsigned int total_messages_received;
+
+static unsigned int expected_messages;
+
+static unsigned int expected_connections;
+
+static unsigned long long peers_left;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+const struct GNUNET_CONFIGURATION_Handle *main_cfg;
+
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+static char *dotOutFileName;
+
+static struct GNUNET_TIME_Relative settle_time;
+
+static FILE *dotOutFile;
+
+static char *topology_string;
+
+static char *blacklist_transports;
+
+static int transmit_ready_scheduled;
+
+static int transmit_ready_failed;
+
+static int transmit_ready_called;
+
+static unsigned int modnum;
+
+static unsigned int dotnum;
+
+static enum GNUNET_TESTING_Topology topology;
+
+static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_NONE;  /* Don't do any blacklisting */
+
+static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
+
+static enum GNUNET_TESTING_TopologyOption connect_topology_option =
+    GNUNET_TESTING_TOPOLOGY_OPTION_ALL;
+
+static double connect_topology_option_modifier = 0.0;
+
+static char *test_directory;
+
+#define MTYPE 12345
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct GNUNET_TestMessage
+{
+  /**
+   * Header of the message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this message.
+   */
+  uint32_t uid;
+};
+GNUNET_NETWORK_STRUCT_END
+
+struct TestMessageContext
+{
+  /* This is a linked list */
+  struct TestMessageContext *next;
+
+  /* Handle to the sending peer core */
+  struct GNUNET_CORE_Handle *peer1handle;
+
+  /* Handle to the receiving peer core */
+  struct GNUNET_CORE_Handle *peer2handle;
+
+  /* Handle to the sending peer daemon */
+  struct GNUNET_TESTING_Daemon *peer1;
+
+  /* Handle to the receiving peer daemon */
+  struct GNUNET_TESTING_Daemon *peer2;
+
+  /* Identifier for this message, so we don't disconnect other peers! */
+  uint32_t uid;
+
+  /* Has peer1 been notified already of a connection to peer2? */
+  int peer1notified;
+
+  /* Has the core of peer2 been connected already? */
+  int peer2connected;
+
+  /* Task for disconnecting cores, allow task to be cancelled on shutdown */
+  GNUNET_SCHEDULER_TaskIdentifier disconnect_task;
+
+};
+
+static struct TestMessageContext *test_messages;
+
+/**
+ * Check whether peers successfully shut down.
+ */
+static void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Shutdown of peers failed: %s!\n",
+               emsg);
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+  }
+}
+
+
+#if DELAY_FOR_LOGGING
+static void
+gather_log_data ()
+{
+  char *peer_number;
+  char *connect_number;
+  struct GNUNET_OS_Process *mem_process;
+
+  GNUNET_asprintf (&peer_number, "%llu", num_peers);
+  GNUNET_asprintf (&connect_number, "%llu", expected_connections);
+  mem_process =
+      GNUNET_OS_start_process (NULL, NULL, "./memsize.pl", "memsize.pl",
+                               "totals.txt", peer_number, connect_number, NULL);
+  GNUNET_OS_process_wait (mem_process);
+  GNUNET_OS_process_destroy (mem_process);
+  mem_process = NULL;
+}
+#endif
+
+
+static void
+finish_testing ()
+{
+  GNUNET_assert (pg != NULL);
+  struct TestMessageContext *pos;
+  struct TestMessageContext *free_pos;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Called finish testing, stopping daemons.\n");
+  pos = test_messages;
+  while (pos != NULL)
+  {
+    if (pos->peer1handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer1handle);
+      pos->peer1handle = NULL;
+    }
+    if (pos->peer2handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer2handle);
+      pos->peer2handle = NULL;
+    }
+    free_pos = pos;
+    pos = pos->next;
+    if (free_pos->disconnect_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (free_pos->disconnect_task);
+    }
+    GNUNET_free (free_pos);
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
+              transmit_ready_scheduled, transmit_ready_failed,
+              transmit_ready_called);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
+  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "}");
+    FCLOSE (dotOutFile);
+  }
+  ok = 0;
+}
+
+
+static void
+disconnect_cores (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct TestMessageContext *pos = cls;
+
+  /* Disconnect from the respective cores */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 1 `%4s'\n",
+              GNUNET_i2s (&pos->peer1->id));
+  if (pos->peer1handle != NULL)
+  {
+    GNUNET_CORE_disconnect (pos->peer1handle);
+    pos->peer1handle = NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Disconnecting from peer 2 `%4s'\n",
+              GNUNET_i2s (&pos->peer2->id));
+  if (pos->peer2handle != NULL)
+  {
+    GNUNET_CORE_disconnect (pos->peer2handle);
+    pos->peer2handle = NULL;
+  }
+  pos->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+  /* Decrement total connections so new can be established */
+  total_server_connections -= 2;
+}
+
+#if DO_STATS
+static void
+stats_finished (void *cls, int result)
+{
+  GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+}
+
+/**
+ * Callback function to process statistic values.
+ *
+ * @param cls closure
+ * @param peer the peer the statistics belong to
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
+ * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
+ */
+static int
+stats_print (void *cls, const struct GNUNET_PeerIdentity *peer,
+             const char *subsystem, const char *name, uint64_t value,
+             int is_persistent)
+{
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s:%s:%s -- %llu\n", GNUNET_i2s (peer),
+              subsystem, name, value);
+  return GNUNET_OK;
+}
+#endif
+
+
+static void
+topology_cb (void *cls, const struct GNUNET_PeerIdentity *first,
+             const struct GNUNET_PeerIdentity *second, const char *emsg)
+{
+  FILE *outfile = cls;
+
+  if (first != NULL)
+  {
+    if (outfile != NULL)
+    {
+      FPRINTF (outfile, "\t\"%s\" -- ", GNUNET_i2s (first));
+      FPRINTF (outfile, "\"%s\";\n", GNUNET_i2s (second));
+    }
+    topology_connections++;
+  }
+  else
+  {
+    FPRINTF (stderr,
+             "Finished iterating over topology, %d total connections!\n",
+             topology_connections);
+    if (outfile != NULL)
+    {
+      FPRINTF (outfile, "%s",  "}\n");
+      FCLOSE (outfile);
+#if DO_STATS
+      GNUNET_TESTING_get_statistics (pg, &stats_finished, &stats_print, NULL);
+#endif
+      GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+    }
+  }
+}
+
+
+static int
+process_mtype (void *cls, const struct GNUNET_PeerIdentity *peer,
+               const struct GNUNET_MessageHeader *message,
+               const struct GNUNET_ATS_Information *atsi,
+               unsigned int atsi_count)
+{
+  char *dotOutFileNameFinished;
+  FILE *dotOutFileFinished;
+  struct TestMessageContext *pos = cls;
+  struct GNUNET_TestMessage *msg = (struct GNUNET_TestMessage *) message;
+
+  if (pos->uid != ntohl (msg->uid))
+    return GNUNET_OK;
+
+#if PROGRESS_BARS
+  if ((total_messages_received) % modnum == 0)
+  {
+    if (total_messages_received == 0)
+      FPRINTF (stdout, "%s",  "0%%");
+    else
+      FPRINTF (stdout, "%d%%",
+               (int) (((float) total_messages_received / expected_messages) *
+                      100));
+
+  }
+  else if (total_messages_received % dotnum == 0)
+  {
+    FPRINTF (stdout, "%s",  ".");
+  }
+  fflush (stdout);
+#endif
+
+  total_messages_received++;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received message from `%4s', type %d.\n", GNUNET_i2s (peer),
+              ntohs (message->type));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Total messages received %d, expected %d.\n",
+              total_messages_received, expected_messages);
+
+  if (total_messages_received == expected_messages)
+  {
+#if PROGRESS_BARS
+    FPRINTF (stdout, "%s",  "100%%]\n");
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    GNUNET_asprintf (&dotOutFileNameFinished, "%s.dot", "final_topology");
+    dotOutFileFinished = FOPEN (dotOutFileNameFinished, "w");
+    GNUNET_free (dotOutFileNameFinished);
+    if (dotOutFileFinished != NULL)
+    {
+      FPRINTF (dotOutFileFinished, "%s",  "strict graph G {\n");
+    }
+    topology_connections = 0;
+    GNUNET_TESTING_get_topology (pg, &topology_cb, dotOutFileFinished);
+    //GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+  }
+  else
+  {
+    pos->disconnect_task = GNUNET_SCHEDULER_add_now (&disconnect_cores, pos);
+  }
+
+  return GNUNET_OK;
+}
+
+
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char *msg = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+              "Ending with error: %s\n", msg);
+  struct TestMessageContext *pos;
+  struct TestMessageContext *free_pos;
+
+  pos = test_messages;
+  while (pos != NULL)
+  {
+    if (pos->peer1handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer1handle);
+      pos->peer1handle = NULL;
+    }
+    if (pos->peer2handle != NULL)
+    {
+      GNUNET_CORE_disconnect (pos->peer2handle);
+      pos->peer2handle = NULL;
+    }
+    free_pos = pos;
+    pos = pos->next;
+    GNUNET_free (free_pos);
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Transmit_ready's scheduled %d, failed %d, transmit_ready's called %d\n",
+              transmit_ready_scheduled, transmit_ready_failed,
+              transmit_ready_called);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Total messages received %d, expected %d.\n",
+              total_messages_received, expected_messages);
+
+  if (pg != NULL)
+  {
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    ok = 7331;                  /* Opposite of leet */
+  }
+  else
+    ok = 401;                   /* Never got peers started */
+
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "}");
+    FCLOSE (dotOutFile);
+  }
+}
+
+
+static size_t
+transmit_ready (void *cls, size_t size, void *buf)
+{
+  struct GNUNET_TestMessage *m;
+  struct TestMessageContext *pos = cls;
+
+  GNUNET_assert (buf != NULL);
+  m = (struct GNUNET_TestMessage *) buf;
+  m->header.type = htons (MTYPE);
+  m->header.size = htons (sizeof (struct GNUNET_TestMessage));
+  m->uid = htonl (pos->uid);
+  transmit_ready_called++;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "transmit ready for peer %s\ntransmit_ready's scheduled %d, transmit_ready's called %d\n",
+              GNUNET_i2s (&pos->peer1->id), transmit_ready_scheduled,
+              transmit_ready_called);
+  return sizeof (struct GNUNET_TestMessage);
+}
+
+
+static struct GNUNET_CORE_MessageHandler no_handlers[] = {
+  {NULL, 0, 0}
+};
+
+
+static struct GNUNET_CORE_MessageHandler handlers[] = {
+  {&process_mtype, MTYPE, sizeof (struct GNUNET_TestMessage)},
+  {NULL, 0, 0}
+};
+
+
+static void
+init_notify_peer2 (void *cls, struct GNUNET_CORE_Handle *server,
+                   const struct GNUNET_PeerIdentity *my_identity)
+{
+  struct TestMessageContext *pos = cls;
+
+  total_server_connections++;
+
+  pos->peer2connected = GNUNET_YES;
+  if (pos->peer1notified == GNUNET_YES) /* Peer 1 has been notified of connection to peer 2 */
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
+                GNUNET_i2s (my_identity),
+                GNUNET_h2s (&pos->peer1->id.hashPubKey));
+    if (NULL ==
+        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0,
+                                           TIMEOUT, &pos->peer2->id,
+                                           sizeof (struct GNUNET_TestMessage),
+                                           &transmit_ready, pos))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
+                  GNUNET_i2s (&pos->peer2->id));
+      transmit_ready_failed++;
+    }
+    else
+    {
+      transmit_ready_scheduled++;
+    }
+  }
+}
+
+
+/**
+ * Method called whenever a given peer connects.
+ *
+ * @param cls closure
+ * @param peer peer identity this notification is about
+ * @param atsi performance data for the connection
+ * @param atsi_count number of records in 'atsi'
+ */
+static void
+connect_notify_peers (void *cls, const struct GNUNET_PeerIdentity *peer,
+                      const struct GNUNET_ATS_Information *atsi,
+                      unsigned int atsi_count)
+{
+  struct TestMessageContext *pos = cls;
+
+  if (0 == memcmp (peer, &pos->peer2->id, sizeof (struct GNUNET_PeerIdentity)))
+  {
+    pos->peer1notified = GNUNET_YES;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Peer `%s' notified of connection to peer `%s'\n",
+                GNUNET_i2s (&pos->peer1->id), GNUNET_h2s (&peer->hashPubKey));
+  }
+  else
+    return;
+
+  if (pos->peer2connected == GNUNET_YES)        /* Already connected and notified of connection, send message! */
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Scheduling message send to peer `%s' from peer `%s' (init_notify_peer2)\n",
+                GNUNET_i2s (&pos->peer2->id),
+                GNUNET_h2s (&pos->peer1->id.hashPubKey));
+    if (NULL ==
+        GNUNET_CORE_notify_transmit_ready (pos->peer1handle, GNUNET_YES, 0,
+                                           TIMEOUT, &pos->peer2->id,
+                                           sizeof (struct GNUNET_TestMessage),
+                                           &transmit_ready, pos))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "RECEIVED NULL when asking core (1) for transmission to peer `%4s'\n",
+                  GNUNET_i2s (&pos->peer2->id));
+      transmit_ready_failed++;
+    }
+    else
+    {
+      transmit_ready_scheduled++;
+    }
+  }
+}
+
+
+static void
+init_notify_peer1 (void *cls, struct GNUNET_CORE_Handle *server,
+                   const struct GNUNET_PeerIdentity *my_identity)
+{
+  struct TestMessageContext *pos = cls;
+
+  total_server_connections++;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Core connection to `%4s' established, setting up handles\n",
+              GNUNET_i2s (my_identity));
+  /*
+   * Connect to the receiving peer
+   */
+  pos->peer2handle =
+      GNUNET_CORE_connect (pos->peer2->cfg, pos, &init_notify_peer2, NULL,
+                           NULL, NULL, GNUNET_YES, NULL, GNUNET_YES, handlers);
+
+}
+
+
+static void
+send_test_messages (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct TestMessageContext *pos = cls;
+
+  if ((pos == test_messages) && (settle_time.rel_value > 0))
+  {
+    topology_connections = 0;
+    GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
+  }
+  if (((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0) || (cls == NULL))
+    return;
+
+  if (die_task == GNUNET_SCHEDULER_NO_TASK)
+  {
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly,
+                                      "from send test messages (timeout)");
+  }
+
+  if (total_server_connections >= MAX_OUTSTANDING_CONNECTIONS)
+  {
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 1),
+                                  &send_test_messages, pos);
+    return;                     /* Otherwise we'll double schedule messages here! */
+  }
+
+  /*
+   * Connect to the sending peer
+   */
+  pos->peer1handle =
+      GNUNET_CORE_connect (pos->peer1->cfg, pos, &init_notify_peer1,
+                           &connect_notify_peers, NULL, NULL, GNUNET_NO, NULL,
+                           GNUNET_NO, no_handlers);
+
+  GNUNET_assert (pos->peer1handle != NULL);
+
+  if (total_server_connections < MAX_OUTSTANDING_CONNECTIONS)
+  {
+    GNUNET_SCHEDULER_add_now (&send_test_messages, pos->next);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 1),
+                                  &send_test_messages, pos->next);
+  }
+}
+
+
+static void
+topology_callback (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)
+{
+  struct TestMessageContext *temp_context;
+
+  if (emsg == NULL)
+  {
+#if PROGRESS_BARS
+    if ((total_connections) % modnum == 0)
+    {
+      if (total_connections == 0)
+        FPRINTF (stdout, "%s",  "0%%");
+      else
+        FPRINTF (stdout, "%d%%",
+                 (int) (((float) total_connections / expected_connections) *
+                        100));
+
+    }
+    else if (total_connections % dotnum == 0)
+    {
+      FPRINTF (stdout, "%s",  ".");
+    }
+    fflush (stdout);
+#endif
+    total_connections++;
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "connected peer %s to peer %s\n",
+                first_daemon->shortname, second_daemon->shortname);
+    temp_context = GNUNET_malloc (sizeof (struct TestMessageContext));
+    temp_context->peer1 = first_daemon;
+    temp_context->peer2 = second_daemon;
+    temp_context->next = test_messages;
+    temp_context->uid = total_connections;
+    temp_context->disconnect_task = GNUNET_SCHEDULER_NO_TASK;
+    test_messages = temp_context;
+
+    expected_messages++;
+    if (dotOutFile != NULL)
+      FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname,
+               second_daemon->shortname);
+  }
+  else
+  {
+    failed_connections++;
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Failed to connect peer %s to peer %s with error :\n%s\n",
+                first_daemon->shortname, second_daemon->shortname, emsg);
+  }
+
+  if (total_connections == expected_connections)
+  {
+#if PROGRESS_BARS
+    FPRINTF (stdout, "%s",  "100%%]\n");
+#endif
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Created %d total connections, which is our target number!  Calling send messages.\n",
+                total_connections);
+    modnum = expected_messages / 4;
+    dotnum = (expected_messages / 50) + 1;
+    if (modnum == 0)
+      modnum = 1;
+    if (dotnum == 0)
+      dotnum = 1;
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task = GNUNET_SCHEDULER_NO_TASK;
+#if DELAY_FOR_LOGGING
+    FPRINTF (stdout, "%s",  "Sending test messages in 10 seconds.\n");
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 10),
+                                  &send_test_messages, test_messages);
+    gather_log_data ();
+#else
+    if (settle_time.rel_value > 0)
+    {
+      GNUNET_TESTING_get_topology (pg, &topology_cb, NULL);
+    }
+    GNUNET_SCHEDULER_add_delayed (settle_time, &send_test_messages,
+                                  test_messages);
+#endif
+#if PROGRESS_BARS
+    FPRINTF (stdout, "%s",  "Test message progress: [");
+#endif
+
+  }
+  else if (total_connections + failed_connections == expected_connections)
+  {
+    if (failed_connections <
+        (unsigned int) (fail_percentage * total_connections))
+    {
+      GNUNET_SCHEDULER_cancel (die_task);
+      die_task = GNUNET_SCHEDULER_NO_TASK;
+      GNUNET_SCHEDULER_add_now (&send_test_messages, test_messages);
+    }
+    else
+    {
+      GNUNET_SCHEDULER_cancel (die_task);
+      die_task =
+          GNUNET_SCHEDULER_add_now (&end_badly,
+                                    "from topology_callback (too many failed connections)");
+    }
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Have %d total connections, %d failed connections, Want %d (at least %d)\n",
+                total_connections, failed_connections, expected_connections,
+                expected_connections -
+                (unsigned int) (fail_percentage * expected_connections));
+  }
+}
+
+
+static void
+topology_creation_finished (void *cls, const char *emsg)
+{
+  if (emsg == NULL)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All topology connections created successfully!\n");
+}
+
+
+static void
+connect_topology ()
+{
+  expected_connections = -1;
+  if ((pg != NULL) && (peers_left == 0))
+  {
+    expected_connections =
+        GNUNET_TESTING_connect_topology (pg, connection_topology,
+                                         connect_topology_option,
+                                         connect_topology_option_modifier,
+                                         connect_timeout, connect_attempts,
+                                         &topology_creation_finished, NULL);
+#if PROGRESS_BARS
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
+                expected_connections);
+#endif
+  }
+
+  GNUNET_SCHEDULER_cancel (die_task);
+  if (expected_connections < 1)
+  {
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from connect topology (bad return)");
+    return;
+  }
+
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_SECONDS,
+                                     SECONDS_PER_PEER_START * num_peers),
+                                    &end_badly,
+                                    "from connect topology (timeout)");
+  modnum = expected_connections / 4;
+  dotnum = (expected_connections / 50) + 1;
+  if (modnum == 0)
+    modnum = 1;
+  if (dotnum == 0)
+    dotnum = 1;
+#if PROGRESS_BARS
+  FPRINTF (stdout, "%s",  "Peer connection progress: [");
+#endif
+}
+
+static void
+create_topology ()
+{
+  peers_left = num_peers;       /* Reset counter */
+  if (GNUNET_TESTING_create_topology
+      (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
+  {
+#if PROGRESS_BARS
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Topology set up, now starting peers!\n");
+    FPRINTF (stdout, "%s",  "Daemon start progress [");
+#endif
+    GNUNET_TESTING_daemons_continue_startup (pg);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from create topology (bad return)");
+  }
+  GNUNET_SCHEDULER_cancel (die_task);
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_SECONDS,
+                                     SECONDS_PER_PEER_START * num_peers),
+                                    &end_badly,
+                                    "from continue startup (timeout)");
+}
+
+
+static void
+peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                        const struct GNUNET_CONFIGURATION_Handle *cfg,
+                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to start daemon with error: `%s'\n", emsg);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
+              (num_peers - peers_left) + 1, num_peers);
+#if PROGRESS_BARS
+  if ((num_peers - peers_left) % modnum == 0)
+  {
+    if (num_peers - peers_left == 0)
+      FPRINTF (stdout, "%s",  "0%%");
+    else
+      FPRINTF (stdout, "%d%%",
+               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
+
+  }
+  else if ((num_peers - peers_left) % dotnum == 0)
+  {
+    FPRINTF (stdout, "%s",  ".");
+  }
+  fflush (stdout);
+#endif
+  peers_left--;
+  if (peers_left == 0)
+  {
+#if PROGRESS_BARS
+    FPRINTF (stdout, "%s",  "100%%]\n");
+#endif
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d daemons started, now connecting peers!\n", num_peers);
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_TIME_UNIT_MINUTES, 8), &end_badly,
+                                      "from peers_started_callback");
+#if DELAY_FOR_LOGGING
+    FPRINTF (stdout, "%s",  "Connecting topology in 10 seconds\n");
+    gather_log_data ();
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_SECONDS, 10),
+                                  &connect_topology, NULL);
+#else
+    connect_topology ();
+#endif
+    ok = 0;
+  }
+}
+
+/**
+ * Callback indicating that the hostkey was created for a peer.
+ *
+ * @param cls NULL
+ * @param id the peer identity
+ * @param d the daemon handle (pretty useless at this point, remove?)
+ * @param emsg non-null on failure
+ */
+void
+hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Hostkey callback received error: %s\n", emsg);
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Hostkey (%d/%d) created for peer `%s'\n", num_peers - peers_left,
+              num_peers, GNUNET_i2s (id));
+#if PROGRESS_BARS
+  if ((num_peers - peers_left) % modnum == 0)
+  {
+    if (num_peers - peers_left == 0)
+      FPRINTF (stdout, "%s",  "0%%");
+    else
+      FPRINTF (stdout, "%d%%",
+               (int) (((float) (num_peers - peers_left) / num_peers) * 100));
+
+  }
+  else if ((num_peers - peers_left) % dotnum == 0)
+  {
+    FPRINTF (stdout, "%s",  ".");
+  }
+  fflush (stdout);
+#endif
+  peers_left--;
+  if (peers_left == 0)
+  {
+#if PROGRESS_BARS
+    FPRINTF (stdout, "%s",  "100%%]\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d hostkeys created, now creating topology!\n", num_peers);
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly,
+                                      "from create_topology");
+    GNUNET_SCHEDULER_add_now (&create_topology, NULL);
+    ok = 0;
+  }
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  char *topology_str;
+  char *connect_topology_str;
+  char *blacklist_topology_str;
+  char *connect_topology_option_str;
+  char *connect_topology_option_modifier_string;
+  unsigned long long max_outstanding_connections;
+
+  ok = 1;
+
+  dotOutFile = FOPEN (dotOutFileName, "w");
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "strict graph G {\n");
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting daemons based on config file %s\n", cfgfile);
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+                                             &test_directory))
+  {
+    ok = 404;
+    return;
+  }
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "topology",
+                                              &topology_str)) &&
+      (GNUNET_NO == GNUNET_TESTING_topology_get (&topology, topology_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid topology `%s' given for section %s option %s\n",
+                topology_str, "TESTING", "TOPOLOGY");
+    topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;  /* Defaults to NONE, so set better default here */
+  }
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                              "connect_topology",
+                                              &connect_topology_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_get (&connection_topology,
+                                    connect_topology_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid connect topology `%s' given for section %s option %s\n",
+                connect_topology_str, "TESTING", "CONNECT_TOPOLOGY");
+  }
+  GNUNET_free_non_null (connect_topology_str);
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                              "connect_topology_option",
+                                              &connect_topology_option_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_option_get (&connect_topology_option,
+                                           connect_topology_option_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid connect topology option `%s' given for section %s option %s\n",
+                connect_topology_option_str, "TESTING",
+                "CONNECT_TOPOLOGY_OPTION");
+    connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL;       /* Defaults to NONE, set to ALL */
+  }
+  GNUNET_free_non_null (connect_topology_option_str);
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                             "connect_topology_option_modifier",
+                                             &connect_topology_option_modifier_string))
+  {
+    if (SSCANF
+        (connect_topology_option_modifier_string, "%lf",
+         &connect_topology_option_modifier) != 1)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  connect_topology_option_modifier_string,
+                  "connect_topology_option_modifier", "TESTING");
+    }
+    GNUNET_free (connect_topology_option_modifier_string);
+  }
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                             "blacklist_transports",
+                                             &blacklist_transports))
+    blacklist_transports = NULL;
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                              "blacklist_topology",
+                                              &blacklist_topology_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_get (&blacklist_topology,
+                                    blacklist_topology_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid topology `%s' given for section %s option %s\n",
+                topology_str, "TESTING", "BLACKLIST_TOPOLOGY");
+  }
+  GNUNET_free_non_null (topology_str);
+  GNUNET_free_non_null (blacklist_topology_str);
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "SETTLE_TIME",
+                                           &settle_time))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "SETTLE_TIME");
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT",
+                                           &connect_timeout))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "CONNECT_TIMEOUT");
+    return;
+  }
+
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
+                                             &connect_attempts))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "connect_attempts");
+    return;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
+                                             "max_outstanding_connections",
+                                             &max_outstanding_connections))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "max_outstanding_connections");
+    return;
+  }
+
+  if (GNUNET_SYSERR ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+                                             &num_peers))
+    num_peers = DEFAULT_NUM_PEERS;
+
+  main_cfg = cfg;
+
+  peers_left = num_peers;
+  modnum = num_peers / 4;
+  dotnum = (num_peers / 50) + 1;
+  if (modnum == 0)
+    modnum = 1;
+  if (dotnum == 0)
+    dotnum = 1;
+#if PROGRESS_BARS
+  FPRINTF (stdout, "%s",  "Hostkey generation progress: [");
+#endif
+  /* Set up a task to end testing if peer start fails */
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_SECONDS,
+                                     SECONDS_PER_PEER_START * num_peers),
+                                    &end_badly,
+                                    "didn't generate all hostkeys within a reasonable amount of time!!!");
+
+  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
+  pg = GNUNET_TESTING_daemons_start (cfg, peers_left,
+                                     max_outstanding_connections, peers_left,
+                                     GNUNET_TIME_relative_multiply
+                                     (GNUNET_TIME_UNIT_SECONDS,
+                                      SECONDS_PER_PEER_START * num_peers),
+                                     &hostkey_callback, NULL,
+                                     &peers_started_callback, NULL,
+                                     &topology_callback, NULL, NULL);
+
+}
+
+
+static int
+check ()
+{
+  char *binary_name;
+  char *config_file_name;
+
+  GNUNET_asprintf (&binary_name, "test-testing-topology-%s", topology_string);
+  GNUNET_asprintf (&config_file_name, "test_testing_data_topology_%s.conf",
+                   topology_string);
+  int ret;
+
+  char *const argv[] = { binary_name,
+    "-c",
+    config_file_name,
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  ret =
+      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                          binary_name, "nohelp", options, &run, &ok);
+  if (ret != GNUNET_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "`test-testing-topology-%s': Failed with error code %d\n",
+                topology_string, ret);
+  }
+  GNUNET_free (binary_name);
+  GNUNET_free (config_file_name);
+  return ok;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+  char *binary_start_pos;
+  char *our_binary_name;
+  char *dotexe;
+
+  binary_start_pos = strchr (argv[0], '/');
+  GNUNET_assert (binary_start_pos != NULL);
+  topology_string = strstr (binary_start_pos, "_topology");
+  GNUNET_assert (topology_string != NULL);
+  topology_string++;
+  topology_string = strstr (topology_string, "_");
+  GNUNET_assert (topology_string != NULL);
+  topology_string++;
+  topology_string = GNUNET_strdup (topology_string);
+  if (NULL != (dotexe = strstr (topology_string, ".exe")))
+    dotexe[0] = '\0';
+  GNUNET_asprintf (&our_binary_name, "test-testing-topology_%s",
+                   topology_string);
+  GNUNET_asprintf (&dotOutFileName, "topology_%s.dot", topology_string);
+
+  GNUNET_log_setup (our_binary_name,
+                    "WARNING",
+                    NULL);
+  ret = check ();
+  GNUNET_free (topology_string);
+
+  /**
+   * Need to remove base directory, subdirectories taken care
+   * of by the testing framework.
+   */
+  if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to remove testing directory %s\n", test_directory);
+  }
+  GNUNET_free (our_binary_name);
+  return ret;
+}
+
+/* end of test_testing_topology.c */
diff --git a/src/testing_old/test_testing_topology_blacklist.c b/src/testing_old/test_testing_topology_blacklist.c
new file mode 100644 (file)
index 0000000..c90f48d
--- /dev/null
@@ -0,0 +1,595 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_topology_blacklist.c
+ * @brief base testcase for testing transport level blacklisting
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+
+#define VERBOSE GNUNET_NO
+
+/**
+ * How long until we fail the whole testcase?
+ */
+#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
+
+/**
+ * How long until we give up on starting the peers? (Must be longer than the connect timeout!)
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+#define DEFAULT_NUM_PEERS 4
+
+#define MAX_OUTSTANDING_CONNECTIONS 300
+
+static int ok;
+
+struct GNUNET_TIME_Relative connect_timeout;
+
+static unsigned long long connect_attempts;
+
+static unsigned long long num_peers;
+
+static unsigned int total_connections;
+
+static unsigned int failed_connections;
+
+static unsigned int expected_connections;
+
+static unsigned int expected_failed_connections;
+
+static unsigned long long peers_left;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+const struct GNUNET_CONFIGURATION_Handle *main_cfg;
+
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+static char *dotOutFileName;
+
+static FILE *dotOutFile;
+
+static char *blacklist_transports;
+
+static enum GNUNET_TESTING_Topology topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;  /* Overlay should allow all connections */
+
+static enum GNUNET_TESTING_Topology blacklist_topology = GNUNET_TESTING_TOPOLOGY_RING;  /* Blacklist underlay into a ring */
+
+static enum GNUNET_TESTING_Topology connection_topology = GNUNET_TESTING_TOPOLOGY_NONE; /* NONE actually means connect all allowed peers */
+
+static enum GNUNET_TESTING_TopologyOption connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Try to connect all possible OVERLAY connections */
+
+static double connect_topology_option_modifier = 0.0;
+
+static char *test_directory;
+
+#define MTYPE 12345
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct GNUNET_TestMessage
+{
+  /**
+   * Header of the message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this message.
+   */
+  uint32_t uid;
+};
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
+#endif
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+#endif
+  }
+}
+
+static void
+finish_testing ()
+{
+  GNUNET_assert (pg != NULL);
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Called finish testing, stopping daemons.\n");
+#endif
+  sleep (1);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
+#endif
+  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n");
+#endif
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "}");
+    FCLOSE (dotOutFile);
+  }
+
+  ok = 0;
+}
+
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char *msg = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "End badly was called (%s)... stopping daemons.\n", msg);
+
+  if (pg != NULL)
+  {
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    ok = 7331;                  /* Opposite of leet */
+  }
+  else
+    ok = 401;                   /* Never got peers started */
+
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "}");
+    FCLOSE (dotOutFile);
+  }
+}
+
+
+
+void
+topology_callback (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)
+{
+  if (emsg == NULL)
+  {
+    total_connections++;
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s\n",
+                first_daemon->shortname, second_daemon->shortname);
+#endif
+    if (dotOutFile != NULL)
+      FPRINTF (dotOutFile, "\tn%s -- n%s;\n", first_daemon->shortname,
+               second_daemon->shortname);
+  }
+
+  else
+  {
+    failed_connections++;
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to connect peer %s to peer %s with error :\n%s\n",
+                first_daemon->shortname, second_daemon->shortname, emsg);
+#endif
+  }
+
+
+  if (total_connections == expected_connections)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Created %d total connections, which is our target number (that's bad)!\n",
+                total_connections);
+#endif
+
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task = GNUNET_SCHEDULER_NO_TASK;
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from topology_callback (too many successful connections)");
+  }
+  else if (total_connections + failed_connections == expected_connections)
+  {
+    if ((failed_connections == expected_failed_connections) &&
+        (total_connections ==
+         expected_connections - expected_failed_connections))
+    {
+      GNUNET_SCHEDULER_cancel (die_task);
+      die_task = GNUNET_SCHEDULER_NO_TASK;
+      die_task = GNUNET_SCHEDULER_add_now (&finish_testing, NULL);
+    }
+    else
+    {
+      GNUNET_SCHEDULER_cancel (die_task);
+      die_task =
+          GNUNET_SCHEDULER_add_now (&end_badly,
+                                    "from topology_callback (wrong number of failed connections)");
+    }
+  }
+  else
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Have %d total connections, %d failed connections, Want %d (failed) and %d (successful)\n",
+                total_connections, failed_connections,
+                expected_failed_connections,
+                expected_connections - expected_failed_connections);
+#endif
+  }
+}
+
+static void
+connect_topology ()
+{
+  expected_connections = -1;
+  if ((pg != NULL) && (peers_left == 0))
+  {
+    expected_connections =
+        GNUNET_TESTING_connect_topology (pg, connection_topology,
+                                         connect_topology_option,
+                                         connect_topology_option_modifier,
+                                         connect_timeout, connect_attempts,
+                                         NULL, NULL);
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
+                expected_connections);
+#endif
+  }
+
+  GNUNET_SCHEDULER_cancel (die_task);
+  if (expected_connections == GNUNET_SYSERR)
+  {
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from connect topology (bad return)");
+  }
+
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly,
+                                    "from connect topology (timeout)");
+}
+
+static void
+create_topology ()
+{
+  peers_left = num_peers;       /* Reset counter */
+  if (GNUNET_TESTING_create_topology
+      (pg, topology, blacklist_topology, blacklist_transports) != GNUNET_SYSERR)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Topology set up, now starting peers!\n");
+#endif
+    GNUNET_TESTING_daemons_continue_startup (pg);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task =
+        GNUNET_SCHEDULER_add_now (&end_badly,
+                                  "from create topology (bad return)");
+  }
+  GNUNET_SCHEDULER_cancel (die_task);
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (TEST_TIMEOUT, &end_badly,
+                                    "from continue startup (timeout)");
+}
+
+
+static void
+peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                        const struct GNUNET_CONFIGURATION_Handle *cfg,
+                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to start daemon with error: `%s'\n", emsg);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
+              (num_peers - peers_left) + 1, num_peers);
+#endif
+  peers_left--;
+  if (peers_left == 0)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d daemons started, now creating topology!\n", num_peers);
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
+                                      "from peers_started_callback");
+    connect_topology ();
+    ok = 0;
+  }
+}
+
+/**
+ * Callback indicating that the hostkey was created for a peer.
+ *
+ * @param cls NULL
+ * @param id the peer identity
+ * @param d the daemon handle (pretty useless at this point, remove?)
+ * @param emsg non-null on failure
+ */
+void
+hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Hostkey callback received error: %s\n", emsg);
+  }
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Hostkey created for peer `%s'\n",
+              GNUNET_i2s (id));
+#endif
+  peers_left--;
+  if (peers_left == 0)
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d hostkeys created, now creating topology!\n", num_peers);
+#endif
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
+                                      "from hostkey_callback");
+    GNUNET_SCHEDULER_add_now (&create_topology, NULL);
+    ok = 0;
+  }
+}
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  unsigned long long topology_num;
+  unsigned long long connect_topology_num;
+  unsigned long long blacklist_topology_num;
+  unsigned long long connect_topology_option_num;
+  char *connect_topology_option_modifier_string;
+
+  ok = 1;
+
+  dotOutFile = FOPEN (dotOutFileName, "w");
+  if (dotOutFile != NULL)
+  {
+    FPRINTF (dotOutFile, "%s",  "strict graph G {\n");
+  }
+
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting daemons based on config file %s\n", cfgfile);
+#endif
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+                                             &test_directory))
+  {
+    ok = 404;
+    if (dotOutFile != NULL)
+    {
+      FCLOSE (dotOutFile);
+    }
+    return;
+  }
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "topology",
+                                             &topology_num))
+    topology = topology_num;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_topology",
+                                             &connect_topology_num))
+    connection_topology = connect_topology_num;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
+                                             "connect_topology_option",
+                                             &connect_topology_option_num))
+    connect_topology_option = connect_topology_option_num;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                             "connect_topology_option_modifier",
+                                             &connect_topology_option_modifier_string))
+  {
+    if (SSCANF
+        (connect_topology_option_modifier_string, "%lf",
+         &connect_topology_option_modifier) != 1)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  connect_topology_option_modifier_string,
+                  "connect_topology_option_modifier", "TESTING");
+      GNUNET_free (connect_topology_option_modifier_string);
+      ok = 707;
+      if (dotOutFile != NULL)
+      {
+        FCLOSE (dotOutFile);
+      }
+      return;
+    }
+    GNUNET_free (connect_topology_option_modifier_string);
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
+                                             "blacklist_transports",
+                                             &blacklist_transports))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "No transports specified for blacklisting in blacklist testcase (this shouldn't happen!)\n");
+    ok = 808;
+    if (dotOutFile != NULL)
+    {
+      FCLOSE (dotOutFile);
+    }
+    return;
+  }
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
+                                             "blacklist_topology",
+                                             &blacklist_topology_num))
+    blacklist_topology = blacklist_topology_num;
+
+  if (GNUNET_SYSERR ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+                                             &num_peers))
+    num_peers = DEFAULT_NUM_PEERS;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg, "testing", "CONNECT_TIMEOUT",
+                                           &connect_timeout))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "CONNECT_TIMEOUT");
+    return;
+  }
+
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "connect_attempts",
+                                             &connect_attempts))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing", "connect_attempts");
+    return;
+  }
+
+  main_cfg = cfg;
+
+  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
+  peers_left = num_peers;
+
+  /* For this specific test we only really want a CLIQUE topology as the
+   * overlay allowed topology, and a RING topology as the underlying connection
+   * allowed topology.  So we will expect only num_peers * 2 connections to
+   * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail.
+   */
+  expected_connections = num_peers * (num_peers - 1);
+  expected_failed_connections = expected_connections - (num_peers * 2);
+
+
+  /* Set up a task to end testing if peer start fails */
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
+                                    "didn't start all daemons in reasonable amount of time!!!");
+
+  pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left,
+                                     TIMEOUT, &hostkey_callback, NULL,
+                                     &peers_started_callback, NULL,
+                                     &topology_callback, NULL, NULL);
+
+}
+
+static int
+check ()
+{
+  int ret;
+
+  char *const argv[] = { "test-testing-topology-blacklist",
+    "-c",
+    "test_testing_data_topology_blacklist.conf",
+#if VERBOSE
+    "-L", "DEBUG",
+#endif
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  ret =
+      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                          "test-testing-topology-blacklist", "nohelp", options,
+                          &run, &ok);
+  if (ret != GNUNET_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "`test-testing-topology-blacklist': Failed with error code %d\n",
+                ret);
+  }
+
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test_testing_topology_blacklist",
+#if VERBOSE
+                    "DEBUG",
+#else
+                    "WARNING",
+#endif
+                    NULL);
+  ret = check ();
+
+  /**
+   * Need to remove base directory, subdirectories taken care
+   * of by the testing framework.
+   */
+  if (test_directory != NULL)
+  {
+    if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to remove testing directory %s\n", test_directory);
+    }
+  }
+
+  return ret;
+}
+
+/* end of test_testing_topology_blacklist.c */
diff --git a/src/testing_old/test_testing_topology_churn.c b/src/testing_old/test_testing_topology_churn.c
new file mode 100644 (file)
index 0000000..9c0bbf2
--- /dev/null
@@ -0,0 +1,322 @@
+/*
+     This file is part of GNUnet.
+     (C) 2009 Christian Grothoff (and other contributing authors)
+
+     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 3, or (at your
+     option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     General Public License for more details.
+
+     You should have received a copy of the GNU General Public License
+     along with GNUnet; see the file COPYING.  If not, write to the
+     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+     Boston, MA 02111-1307, USA.
+*/
+/**
+ * @file testing/test_testing_topology_churn.c
+ * @brief base testcase for testing simple churn functionality
+ */
+#include "platform.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+
+
+/**
+ * How long until we fail the whole testcase?
+ */
+#define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 600)
+
+/**
+ * How long until we give up on starting the peers? (Must be longer than the connect timeout!)
+ */
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 300)
+
+#define DEFAULT_NUM_PEERS 4
+
+static int ok;
+
+static unsigned long long num_peers;
+
+static unsigned int expected_connections;
+
+static unsigned int expected_failed_connections;
+
+static unsigned long long peers_left;
+
+static struct GNUNET_TESTING_PeerGroup *pg;
+
+const struct GNUNET_CONFIGURATION_Handle *main_cfg;
+
+GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+static char *test_directory;
+
+#define MTYPE 12345
+
+GNUNET_NETWORK_STRUCT_BEGIN
+
+struct GNUNET_TestMessage
+{
+  /**
+   * Header of the message
+   */
+  struct GNUNET_MessageHeader header;
+
+  /**
+   * Unique identifier for this message.
+   */
+  uint32_t uid;
+};
+GNUNET_NETWORK_STRUCT_END
+
+/**
+ * Check whether peers successfully shut down.
+ */
+void
+shutdown_callback (void *cls, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
+    if (ok == 0)
+      ok = 666;
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully shut down!\n");
+  }
+}
+
+static void
+finish_testing ()
+{
+  GNUNET_assert (pg != NULL);
+
+  if (die_task != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel (die_task);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Called finish testing, stopping daemons.\n");
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling daemons_stop\n");
+  GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "daemons_stop finished\n");
+  ok = 0;
+}
+
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  char *msg = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "End badly was called (%s)... stopping daemons.\n", msg);
+
+  if (pg != NULL)
+  {
+    GNUNET_TESTING_daemons_stop (pg, TIMEOUT, &shutdown_callback, NULL);
+    ok = 7331;                  /* Opposite of leet */
+  }
+  else
+    ok = 401;                   /* Never got peers started */
+
+}
+
+struct ChurnTestContext
+{
+  GNUNET_SCHEDULER_Task next_task;
+
+};
+
+static struct ChurnTestContext churn_ctx;
+
+/**
+ * Churn callback, report on success or failure of churn operation.
+ *
+ * @param cls closure
+ * @param emsg NULL on success
+ */
+void
+churn_callback (void *cls, const char *emsg)
+{
+  if (emsg == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Successfully churned peers!\n",
+                emsg);
+    GNUNET_SCHEDULER_add_now (churn_ctx.next_task, NULL);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to churn peers with error `%s'\n", emsg);
+    GNUNET_SCHEDULER_cancel (die_task);
+    die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
+  }
+}
+
+
+static void
+churn_peers_both ()
+{
+  churn_ctx.next_task = &finish_testing;
+  GNUNET_TESTING_daemons_churn (pg, NULL, 1, 1, TIMEOUT, &churn_callback, NULL);
+}
+
+static void
+churn_peers_off_again ()
+{
+  churn_ctx.next_task = &churn_peers_both;
+  GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL);
+}
+
+static void
+churn_peers_on ()
+{
+  churn_ctx.next_task = &churn_peers_off_again;
+  GNUNET_TESTING_daemons_churn (pg, NULL, 0, 2, TIMEOUT, &churn_callback, NULL);
+}
+
+static void
+churn_peers_off ()
+{
+  churn_ctx.next_task = &churn_peers_on;
+  GNUNET_TESTING_daemons_churn (pg, NULL, 2, 0, TIMEOUT, &churn_callback, NULL);
+}
+
+static void
+peers_started_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                        const struct GNUNET_CONFIGURATION_Handle *cfg,
+                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to start daemon with error: `%s'\n", emsg);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
+              (num_peers - peers_left) + 1, num_peers);
+  peers_left--;
+  if (peers_left == 0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d daemons started, now testing churn!\n", num_peers);
+    GNUNET_SCHEDULER_cancel (die_task);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
+                                      "from peers_started_callback");
+    churn_peers_off ();
+    ok = 0;
+  }
+}
+
+
+static void
+run (void *cls, char *const *args, const char *cfgfile,
+     const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  ok = 1;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Starting daemons based on config file %s\n", cfgfile);
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "paths", "servicehome",
+                                             &test_directory))
+  {
+    ok = 404;
+    return;
+  }
+
+  if (GNUNET_SYSERR ==
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing", "num_peers",
+                                             &num_peers))
+    num_peers = DEFAULT_NUM_PEERS;
+
+  main_cfg = cfg;
+
+  peers_left = num_peers;
+  GNUNET_assert (num_peers > 0 && num_peers < (unsigned int) -1);
+
+  /* For this specific test we only really want a CLIQUE topology as the
+   * overlay allowed topology, and a RING topology as the underlying connection
+   * allowed topology.  So we will expect only num_peers * 2 connections to
+   * work, and (num_peers * (num_peers - 1)) - (num_peers * 2) to fail.
+   */
+  expected_connections = num_peers * (num_peers - 1);
+  expected_failed_connections = expected_connections - (num_peers * 2);
+
+
+  /* Set up a task to end testing if peer start fails */
+  die_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                    (GNUNET_TIME_UNIT_MINUTES, 5), &end_badly,
+                                    "didn't start all daemons in reasonable amount of time!!!");
+
+  pg = GNUNET_TESTING_daemons_start (cfg, peers_left, peers_left, peers_left,
+                                     TIMEOUT, NULL, NULL,
+                                     &peers_started_callback, NULL, NULL, NULL,
+                                     NULL);
+
+}
+
+static int
+check ()
+{
+  int ret;
+
+  char *const argv[] = { "test-testing-topology-churn",
+    "-c",
+    "test_testing_data_topology_churn.conf",
+    NULL
+  };
+  struct GNUNET_GETOPT_CommandLineOption options[] = {
+    GNUNET_GETOPT_OPTION_END
+  };
+  ret =
+      GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1, argv,
+                          "test-testing-topology-churn", "nohelp", options,
+                          &run, &ok);
+  if (ret != GNUNET_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "`test-testing-topology-churn': Failed with error code %d\n",
+                ret);
+  }
+
+  return ok;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int ret;
+
+  GNUNET_log_setup ("test_testing_topology_churn",
+                    "WARNING",
+                    NULL);
+  ret = check ();
+
+  /**
+   * Need to remove base directory, subdirectories taken care
+   * of by the testing framework.
+   */
+  if (test_directory != NULL)
+  {
+    if (GNUNET_DISK_directory_remove (test_directory) != GNUNET_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Failed to remove testing directory %s\n", test_directory);
+    }
+  }
+
+  return ret;
+}
+
+/* end of test_testing_topology_churn.c */
diff --git a/src/testing_old/testing.c b/src/testing_old/testing.c
new file mode 100644 (file)
index 0000000..5456d56
--- /dev/null
@@ -0,0 +1,2204 @@
+/*
+      This file is part of GNUnet
+      (C) 2008, 2009 Christian Grothoff (and other contributing authors)
+
+      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 3, or (at your
+      option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      General Public License for more details.
+
+      You should have received a copy of the GNU General Public License
+      along with GNUnet; see the file COPYING.  If not, write to the
+      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+      Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file testing/testing.c
+ * @brief convenience API for writing testcases for GNUnet
+ *        Many testcases need to start and stop gnunetd,
+ *        and this library is supposed to make that easier
+ *        for TESTCASES.  Normal programs should always
+ *        use functions from gnunet_{util,arm}_lib.h.  This API is
+ *        ONLY for writing testcases!
+ * @author Christian Grothoff
+ *
+ */
+#include "platform.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_core_service.h"
+#include "gnunet_constants.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_hello_lib.h"
+
+/**
+ * Hack to deal with initial HELLO's being often devoid of addresses.
+ * This hack causes 'process_hello' to ignore HELLOs without addresses.
+ * The correct implementation would continue with 'process_hello' until
+ * the connection could be established...
+ */
+#define EMPTY_HACK GNUNET_YES
+
+/**
+ * How long do we wait after starting gnunet-service-arm
+ * for the core service to be alive?
+ */
+#define ARM_START_WAIT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 120)
+
+/**
+ * How many times are we willing to try to wait for "scp" or
+ * "gnunet-service-arm" to complete (waitpid) before giving up?
+ */
+#define MAX_EXEC_WAIT_RUNS 250
+
+static struct GNUNET_CORE_MessageHandler no_handlers[] = { {NULL, 0, 0} };
+
+#if EMPTY_HACK
+static int
+test_address (void *cls, const struct GNUNET_HELLO_Address *address,
+              struct GNUNET_TIME_Absolute expiration)
+{
+  int *empty = cls;
+
+  *empty = GNUNET_NO;
+  return GNUNET_OK;
+}
+#endif
+
+/**
+ * Receive the HELLO from one peer, give it to the other
+ * and ask them to connect.
+ *
+ * @param cls Closure (daemon whose hello is this).
+ * @param message HELLO message of peer
+ */
+static void
+process_hello (void *cls, const struct GNUNET_MessageHeader *message)
+{
+  struct GNUNET_TESTING_Daemon *daemon = cls;
+  int msize;
+
+#if EMPTY_HACK
+  int empty;
+
+  empty = GNUNET_YES;
+  GNUNET_assert (message != NULL);
+  GNUNET_HELLO_iterate_addresses ((const struct GNUNET_HELLO_Message *) message,
+                                  GNUNET_NO, &test_address, &empty);
+  if (GNUNET_YES == empty)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Skipping empty HELLO address of peer %s\n",
+                GNUNET_i2s (&daemon->id));
+    return;
+  }
+#endif
+  GNUNET_assert (daemon->phase == SP_GET_HELLO ||
+                 daemon->phase == SP_START_DONE);
+  daemon->cb = NULL;            // FIXME: why??? (see fsm:SP_START_CORE, notify_daemon_started)
+  if (daemon->task != GNUNET_SCHEDULER_NO_TASK) /* Assertion here instead? */
+    GNUNET_SCHEDULER_cancel (daemon->task);
+
+  if (daemon->server != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Received `%s' from transport service of `%4s', disconnecting core!\n",
+                "HELLO", GNUNET_i2s (&daemon->id));
+    GNUNET_CORE_disconnect (daemon->server);
+    daemon->server = NULL;
+  }
+
+  msize = ntohs (message->size);
+  if (msize < 1)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "HELLO message of peer %s is of size 0\n",
+                GNUNET_i2s (&daemon->id));
+    return;
+  }
+  if (daemon->ghh != NULL)
+  {
+    GNUNET_TRANSPORT_get_hello_cancel (daemon->ghh);
+    daemon->ghh = NULL;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Received `%s' from transport service of `%4s'\n", "HELLO",
+              GNUNET_i2s (&daemon->id));
+  GNUNET_free_non_null (daemon->hello);
+  daemon->hello = GNUNET_malloc (msize);
+  memcpy (daemon->hello, message, msize);
+
+  if (daemon->th != NULL)
+  {
+    GNUNET_TRANSPORT_disconnect (daemon->th);
+    daemon->th = NULL;
+  }
+  daemon->phase = SP_START_DONE;
+}
+
+
+/**
+ * Notify of a peer being up and running.  Scheduled as a task
+ * so that variables which may need to be set are set before
+ * the connect callback can set up new operations.
+ * FIXME: what variables?????? where from????
+ *
+ * @param cls the testing daemon
+ * @param tc task scheduler context
+ */
+static void
+notify_daemon_started (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_Daemon *d = cls;
+  GNUNET_TESTING_NotifyDaemonRunning cb;
+
+  cb = d->cb;
+  d->cb = NULL;
+  if (NULL != cb)
+    cb (d->cb_cls, &d->id, d->cfg, d, NULL);
+}
+
+
+/**
+ * Finite-state machine for starting GNUnet.
+ *
+ * @param cls our "struct GNUNET_TESTING_Daemon"
+ * @param tc unused
+ */
+static void
+start_fsm (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_Daemon *d = cls;
+  GNUNET_TESTING_NotifyDaemonRunning cb;
+  enum GNUNET_OS_ProcessStatusType type;
+  unsigned long code;
+  char *dst;
+  int bytes_read;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer %s FSM is in phase %u.\n",
+              GNUNET_i2s (&d->id), d->phase);
+  d->task = GNUNET_SCHEDULER_NO_TASK;
+  switch (d->phase)
+  {
+  case SP_COPYING:
+    /* confirm copying complete */
+    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code))
+    {
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
+      {
+        cb = d->cb;
+        d->cb = NULL;
+        if (NULL != cb)
+          cb (d->cb_cls, NULL, d->cfg, d,
+              _
+              ("`scp' does not seem to terminate (timeout copying config).\n"));
+        return;
+      }
+      /* wait some more */
+      d->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        d);
+      return;
+    }
+    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+    {
+      cb = d->cb;
+      d->cb = NULL;
+      if (NULL != cb)
+        cb (d->cb_cls, NULL, d->cfg, d, _("`scp' did not complete cleanly.\n"));
+      return;
+    }
+    GNUNET_OS_process_destroy (d->proc_arm_copying);
+    d->proc_arm_copying = NULL;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Successfully copied configuration file.\n");
+    d->phase = SP_COPIED;
+    /* fall-through */
+  case SP_COPIED:
+    /* Start create hostkey process if we don't already know the peer identity! */
+    if (GNUNET_NO == d->have_hostkey)
+    {
+      GNUNET_assert (NULL == d->proc_arm_peerinfo);
+      d->pipe_stdout = GNUNET_DISK_pipe (GNUNET_NO, GNUNET_NO, GNUNET_NO, GNUNET_YES);
+      if (d->pipe_stdout == NULL)
+      {
+        cb = d->cb;
+        d->cb = NULL;
+        if (NULL != cb)
+          cb (d->cb_cls, NULL, d->cfg, d,
+              (NULL ==
+               d->hostname) ?
+              _("Failed to create pipe for `gnunet-peerinfo' process.\n") :
+              _("Failed to create pipe for `ssh' process.\n"));
+        return;
+      }
+      if (NULL == d->hostname)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Starting `%s', with command `%s %s %s %s'.\n",
+                    "gnunet-peerinfo", "gnunet-peerinfo", "-c", d->cfgfile,
+                    "-sq");
+        d->proc_arm_peerinfo =
+           GNUNET_OS_start_process (GNUNET_YES, NULL, d->pipe_stdout, "gnunet-peerinfo",
+                                     "gnunet-peerinfo", "-c", d->cfgfile, "-sq",
+                                     NULL);
+        GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
+      }
+      else
+      {
+        if (d->username != NULL)
+          GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
+        else
+          dst = GNUNET_strdup (d->hostname);
+
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "Starting `%s', with command `%s %s %s %s %s %s'.\n",
+                    "gnunet-peerinfo", "ssh", dst, "gnunet-peerinfo", "-c",
+                    d->cfgfile, "-sq");
+        if (d->ssh_port_str == NULL)
+        {
+          d->proc_arm_peerinfo = GNUNET_OS_start_process (GNUNET_NO, NULL, d->pipe_stdout, "ssh", "ssh",
+                                             "-q",
+                                             dst, "gnunet-peerinfo", "-c",
+                                             d->cfgfile, "-sq", NULL);
+        }
+        else
+        {
+          d->proc_arm_peerinfo =
+             GNUNET_OS_start_process (GNUNET_NO, NULL, d->pipe_stdout, "ssh", "ssh", "-p",
+                                       d->ssh_port_str,
+                                       "-q",
+                                       dst, "gnunet-peerinfo", "-c", d->cfgfile,
+                                       "-sq", NULL);
+        }
+        GNUNET_DISK_pipe_close_end (d->pipe_stdout, GNUNET_DISK_PIPE_END_WRITE);
+        GNUNET_free (dst);
+      }
+      if (NULL == d->proc_arm_peerinfo)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _("Could not start `%s' process to create hostkey.\n"),
+                    (NULL == d->hostname) ? "gnunet-peerinfo" : "ssh");
+        cb = d->cb;
+        d->cb = NULL;
+        if (NULL != cb)
+          cb (d->cb_cls, NULL, d->cfg, d,
+              (NULL ==
+               d->hostname) ? _("Failed to start `gnunet-peerinfo' process.\n")
+              : _("Failed to start `ssh' process.\n"));
+        GNUNET_DISK_pipe_close (d->pipe_stdout);
+        return;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Started `%s', waiting for hostkey.\n", "gnunet-peerinfo");
+      d->phase = SP_HOSTKEY_CREATE;
+      d->task =
+          GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
+                                          (d->max_timeout),
+                                          GNUNET_DISK_pipe_handle
+                                          (d->pipe_stdout,
+                                           GNUNET_DISK_PIPE_END_READ),
+                                          &start_fsm, d);
+    }
+    else                        /* Already have a hostkey! */
+    {
+      if (d->hostkey_callback != NULL)
+      {
+        d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL);
+        d->hostkey_callback = NULL;
+        d->phase = SP_HOSTKEY_CREATED;
+      }
+      else
+        d->phase = SP_TOPOLOGY_SETUP;
+
+      /* wait some more */
+      d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
+    }
+    break;
+  case SP_HOSTKEY_CREATE:
+    bytes_read =
+        GNUNET_DISK_file_read (GNUNET_DISK_pipe_handle
+                               (d->pipe_stdout, GNUNET_DISK_PIPE_END_READ),
+                               &d->hostkeybuf[d->hostkeybufpos],
+                               sizeof (d->hostkeybuf) - d->hostkeybufpos);
+    if (bytes_read > 0)
+      d->hostkeybufpos += bytes_read;
+
+    if ((d->hostkeybufpos < 104) && (bytes_read > 0))
+    {
+      /* keep reading */
+      d->task =
+          GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_absolute_get_remaining
+                                          (d->max_timeout),
+                                          GNUNET_DISK_pipe_handle
+                                          (d->pipe_stdout,
+                                           GNUNET_DISK_PIPE_END_READ),
+                                          &start_fsm, d);
+      return;
+    }
+    d->hostkeybuf[103] = '\0';
+
+    if ((bytes_read < 0) ||
+        (GNUNET_OK !=
+         GNUNET_CRYPTO_hash_from_string (d->hostkeybuf, &d->id.hashPubKey)))
+    {
+      /* error */
+      if (bytes_read < 0)
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    _("Error reading from gnunet-peerinfo: %s\n"),
+                    STRERROR (errno));
+      else
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    _("Malformed output from gnunet-peerinfo!\n"));
+      cb = d->cb;
+      d->cb = NULL;
+      GNUNET_DISK_pipe_close (d->pipe_stdout);
+      d->pipe_stdout = NULL;
+      (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL);      
+      GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo));
+      GNUNET_OS_process_destroy (d->proc_arm_peerinfo);
+      d->proc_arm_peerinfo = NULL;
+      if (NULL != cb)
+        cb (d->cb_cls, NULL, d->cfg, d, _("Failed to get hostkey!\n"));
+      return;
+    }
+    d->shortname = GNUNET_strdup (GNUNET_i2s (&d->id));
+    GNUNET_DISK_pipe_close (d->pipe_stdout);
+    d->pipe_stdout = NULL;
+    (void) GNUNET_OS_process_kill (d->proc_arm_peerinfo, SIGKILL);
+    GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (d->proc_arm_peerinfo));
+    GNUNET_OS_process_destroy (d->proc_arm_peerinfo);
+    d->proc_arm_peerinfo = NULL;
+    d->have_hostkey = GNUNET_YES;
+    if (d->hostkey_callback != NULL)
+    {
+      d->hostkey_callback (d->hostkey_cls, &d->id, d, NULL);
+      d->hostkey_callback = NULL;
+      d->phase = SP_HOSTKEY_CREATED;
+    }
+    else
+    {
+      d->phase = SP_TOPOLOGY_SETUP;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully got hostkey!\n");
+    /* Fall through */
+  case SP_HOSTKEY_CREATED:
+    /* wait for topology finished */
+    if ((GNUNET_YES == d->dead) ||
+        (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0))
+    {
+      cb = d->cb;
+      d->cb = NULL;
+      if (NULL != cb)
+        cb (d->cb_cls, NULL, d->cfg, d,
+            _("`Failed while waiting for topology setup!\n"));
+      return;
+    }
+
+    d->task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                      d);
+    break;
+  case SP_TOPOLOGY_SETUP:      /* Indicates topology setup has completed! */
+    /* start GNUnet on remote host */
+    if (NULL == d->hostname)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Starting `%s', with command `%s %s %s %s'.\n",
+                  "gnunet-arm", "gnunet-arm", "-c", d->cfgfile, 
+                  "-s");
+      d->proc_arm_start =
+         GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm", "-c",
+                                   d->cfgfile,
+                                   "-s", "-q", "-T",
+                                   GNUNET_TIME_relative_to_string
+                                   (GNUNET_TIME_absolute_get_remaining
+                                    (d->max_timeout)), NULL);
+    }
+    else
+    {
+      if (d->username != NULL)
+        GNUNET_asprintf (&dst, "%s@%s", d->username, d->hostname);
+      else
+        dst = GNUNET_strdup (d->hostname);
+
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Starting `%s', with command `%s %s %s %s %s %s %s'.\n",
+                  "gnunet-arm", "ssh", dst, "gnunet-arm", "-c", d->cfgfile,
+                  "-s", "-q");
+      if (d->ssh_port_str == NULL)
+      {
+        d->proc_arm_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
+                                           "-q",
+                                           dst, "gnunet-arm",
+                                           "-c", d->cfgfile, "-s", "-q", "-T",
+                                           GNUNET_TIME_relative_to_string
+                                           (GNUNET_TIME_absolute_get_remaining
+                                            (d->max_timeout)), NULL);
+      }
+      else
+      {
+
+        d->proc_arm_start =
+           GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", "-p",
+                                     d->ssh_port_str,
+                                     "-q",
+                                     dst, "gnunet-arm",
+                                     "-c", d->cfgfile, "-s", "-q", "-T",
+                                     GNUNET_TIME_relative_to_string
+                                     (GNUNET_TIME_absolute_get_remaining
+                                      (d->max_timeout)), NULL);
+      }
+      GNUNET_free (dst);
+    }
+    if (NULL == d->proc_arm_start)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("Could not start `%s' process to start GNUnet.\n"),
+                  (NULL == d->hostname) ? "gnunet-arm" : "ssh");
+      cb = d->cb;
+      d->cb = NULL;
+      if (NULL != cb)
+        cb (d->cb_cls, NULL, d->cfg, d,
+            (NULL ==
+             d->hostname) ? _("Failed to start `gnunet-arm' process.\n") :
+            _("Failed to start `ssh' process.\n"));
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Started `%s', waiting for `%s' to be up.\n", "gnunet-arm",
+                "gnunet-service-core");
+    d->phase = SP_START_ARMING;
+    d->task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                      d);
+        // FIXME: busy wait?
+    break;
+  case SP_START_ARMING:
+    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_start, &type, &code))
+    {
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
+      {
+        cb = d->cb;
+        d->cb = NULL;
+        if (NULL != cb)
+          cb (d->cb_cls, NULL, d->cfg, d,
+              (NULL ==
+               d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") :
+              _("`ssh' does not seem to terminate.\n"));
+        if (d->cfg != NULL)
+        {
+          GNUNET_CONFIGURATION_destroy (d->cfg);
+          d->cfg = NULL;
+        }
+        if (d->cfgfile != NULL)
+        {
+          GNUNET_free (d->cfgfile);
+          d->cfgfile = NULL;
+        }
+        GNUNET_free_non_null (d->hostname);
+        GNUNET_free_non_null (d->username);
+        GNUNET_OS_process_destroy (d->proc_arm_start);
+       d->proc_arm_start = NULL;
+       d->username = NULL;
+        d->hostname = NULL;     // Quick hack to avoid crashing (testing need to be
+        d->cfg = NULL;          // overhauled anyway, and the error managing is
+       // GNUNET_free (d); // FIXME (could this leak)
+        // pretty broken anyway.
+        return;
+      }
+      /* wait some more */
+      d->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        d);
+          // FIXME: busy wait?
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Successfully started `%s'.\n",
+                "gnunet-arm");
+    GNUNET_OS_process_destroy (d->proc_arm_start);
+    d->proc_arm_start = NULL;
+    d->phase = SP_START_CORE;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Calling CORE_connect\n");
+    /* Fall through */
+  case SP_START_CORE:
+    if (d->server != NULL)
+      GNUNET_CORE_disconnect (d->server);
+
+    d->th = GNUNET_TRANSPORT_connect (d->cfg, &d->id, d, NULL, NULL, NULL);
+    if (d->th == NULL)
+    {
+      if (GNUNET_YES == d->dead)
+        GNUNET_TESTING_daemon_stop (d,
+                                    GNUNET_TIME_absolute_get_remaining
+                                    (d->max_timeout), d->dead_cb,
+                                    d->dead_cb_cls, GNUNET_YES, GNUNET_NO);
+      else if (NULL != d->cb)
+        d->cb (d->cb_cls, &d->id, d->cfg, d,
+               _("Failed to connect to transport service!\n"));
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Connected to transport service `%s', getting HELLO\n",
+                GNUNET_i2s (&d->id));
+    d->ghh = GNUNET_TRANSPORT_get_hello (d->th, &process_hello, d);
+    /* FIXME: store task ID somewhere! */
+    GNUNET_SCHEDULER_add_now (&notify_daemon_started, d);
+    /*cb = d->cb;
+     * d->cb = NULL;
+     * if (NULL != cb)
+     * cb (d->cb_cls, &d->id, d->cfg, d, NULL); */
+    d->running = GNUNET_YES;
+    d->phase = SP_GET_HELLO;
+    break;
+  case SP_GET_HELLO:
+    if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
+    {
+      if (d->server != NULL)
+        GNUNET_CORE_disconnect (d->server);
+      if (d->th != NULL)
+        GNUNET_TRANSPORT_disconnect (d->th);
+      cb = d->cb;
+      d->cb = NULL;
+      if (NULL != cb)
+        cb (d->cb_cls, NULL, d->cfg, d, _("Unable to get HELLO for peer!\n"));
+      GNUNET_CONFIGURATION_destroy (d->cfg);
+      GNUNET_free (d->cfgfile);
+      GNUNET_free_non_null (d->hostname);
+      GNUNET_free_non_null (d->username);
+      GNUNET_free (d);
+      return;
+    }
+    if (d->hello != NULL)
+      return;
+    GNUNET_assert (d->task == GNUNET_SCHEDULER_NO_TASK);
+    d->task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_CONSTANTS_SERVICE_RETRY, 2),
+                                      &start_fsm, d);
+    break;
+  case SP_START_DONE:
+    GNUNET_break (0);
+    break;
+  case SP_SERVICE_START:
+    /* confirm gnunet-arm exited */
+    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_start, &type, &code))
+    {
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
+      {
+        cb = d->cb;
+        d->cb = NULL;
+        if (NULL != cb)
+          cb (d->cb_cls, NULL, d->cfg, d,
+              (NULL ==
+               d->hostname) ? _("`gnunet-arm' does not seem to terminate.\n") :
+              _("`ssh' does not seem to terminate.\n"));
+        return;
+      }
+      /* wait some more */
+      d->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        d);
+      return;
+    }
+#if EXTRA_CHECKS
+    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+    {
+      cb = d->cb;
+      d->cb = NULL;
+      if (NULL != cb)
+        cb (d->cb_cls, NULL, d->cfg, d,
+            (NULL ==
+             d->hostname) ?
+            _
+            ("`gnunet-arm' terminated with non-zero exit status (or timed out)!\n")
+            : _("`ssh' does not seem to terminate.\n"));
+      return;
+    }
+#endif
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service startup complete!\n");
+    cb = d->cb;
+    d->cb = NULL;
+    d->phase = SP_START_DONE;
+    if (NULL != cb)
+      cb (d->cb_cls, &d->id, d->cfg, d, NULL);
+    GNUNET_OS_process_destroy (d->proc_arm_srv_start);
+    d->proc_arm_srv_start = NULL;
+    break;
+  case SP_SERVICE_SHUTDOWN_START:
+    /* confirm copying complete */
+    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_srv_stop, &type, &code))
+    {
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
+      {
+        if (NULL != d->dead_cb)
+          d->dead_cb (d->dead_cb_cls,
+                      _
+                      ("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
+        return;
+      }
+      /* wait some more */
+      d->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        d);
+      return;
+    }
+#if EXTRA_CHECKS
+    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+    {
+      if (NULL != d->dead_cb)
+        d->dead_cb (d->dead_cb_cls,
+                    _
+                    ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n"));
+      return;
+    }
+#endif
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Service shutdown complete.\n");
+    if (NULL != d->dead_cb)
+      d->dead_cb (d->dead_cb_cls, NULL);
+    break;
+  case SP_SHUTDOWN_START:
+    /* confirm copying complete !??? */
+    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_stop, &type, &code))
+    {
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)
+      {
+        if (NULL != d->dead_cb)
+          d->dead_cb (d->dead_cb_cls,
+                      _
+                      ("either `gnunet-arm' or `ssh' does not seem to terminate.\n"));
+        if (d->th != NULL)
+        {
+          GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
+          d->ghh = NULL;
+          GNUNET_TRANSPORT_disconnect (d->th);
+          d->th = NULL;
+        }
+        if (d->cfg != NULL)
+        {
+          GNUNET_CONFIGURATION_destroy (d->cfg);
+          d->cfg = NULL;
+        }
+        if (d->cfgfile != NULL)
+        {
+          GNUNET_free (d->cfgfile);
+          d->cfgfile = NULL;
+        }
+        GNUNET_free_non_null (d->hello);
+        GNUNET_free_non_null (d->hostname);
+        GNUNET_free_non_null (d->username);
+        GNUNET_free_non_null (d->shortname);
+        GNUNET_OS_process_destroy (d->proc_arm_stop);
+        d->proc_arm_stop = NULL;
+        GNUNET_free (d);
+        return;
+      }
+      /* wait some more */
+      d->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        d);
+      return;
+    }
+    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+    {
+      if (NULL != d->dead_cb)
+        d->dead_cb (d->dead_cb_cls,
+                    _
+                    ("shutdown (either `gnunet-arm' or `ssh') did not complete cleanly.\n"));
+      if (d->th != NULL)
+      {
+        GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
+        d->ghh = NULL;
+        GNUNET_TRANSPORT_disconnect (d->th);
+        d->th = NULL;
+      }
+      if (d->server != NULL)
+      {
+        GNUNET_CORE_disconnect (d->server);
+        d->server = NULL;
+      }
+      GNUNET_CONFIGURATION_destroy (d->cfg);
+      d->cfg = NULL;
+      GNUNET_free (d->cfgfile);
+      GNUNET_free_non_null (d->hello);
+      GNUNET_free_non_null (d->hostname);
+      GNUNET_free_non_null (d->username);
+      GNUNET_free_non_null (d->shortname);
+      GNUNET_OS_process_destroy (d->proc_arm_stop);
+      d->proc_arm_stop = NULL;
+      GNUNET_free (d);
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Peer shutdown complete.\n");
+    if (d->server != NULL)
+    {
+      GNUNET_CORE_disconnect (d->server);
+      d->server = NULL;
+    }
+
+    if (d->th != NULL)
+    {
+      GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
+      d->ghh = NULL;
+      GNUNET_TRANSPORT_disconnect (d->th);
+      d->th = NULL;
+    }
+
+    if (NULL != d->dead_cb)
+      d->dead_cb (d->dead_cb_cls, NULL);
+
+    /* state clean up and notifications */
+    if (d->churn == GNUNET_NO)
+    {
+      GNUNET_CONFIGURATION_destroy (d->cfg);
+      d->cfg = NULL;
+      GNUNET_free (d->cfgfile);
+      GNUNET_free_non_null (d->hostname);
+      GNUNET_free_non_null (d->username);
+    }
+
+    GNUNET_free_non_null (d->hello);
+    d->hello = NULL;
+    GNUNET_free_non_null (d->shortname);
+    GNUNET_OS_process_destroy (d->proc_arm_stop);
+    d->proc_arm_stop = NULL;
+    d->shortname = NULL;
+    if (d->churn == GNUNET_NO)
+      GNUNET_free (d);
+
+    break;
+  case SP_CONFIG_UPDATE:
+    /* confirm copying complete */
+    if (GNUNET_OK != GNUNET_OS_process_status (d->proc_arm_copying, &type, &code))
+    {
+      if (GNUNET_TIME_absolute_get_remaining (d->max_timeout).rel_value == 0)   /* FIXME: config update should take timeout parameter! */
+      {
+        cb = d->cb;
+        d->cb = NULL;
+        if (NULL != cb)
+          cb (d->cb_cls, NULL, d->cfg, d,
+              _("`scp' does not seem to terminate.\n"));
+        return;
+      }
+      /* wait some more */
+      d->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        d);
+      return;
+    }
+    if ((type != GNUNET_OS_PROCESS_EXITED) || (code != 0))
+    {
+      if (NULL != d->update_cb)
+        d->update_cb (d->update_cb_cls, _("`scp' did not complete cleanly.\n"));
+      return;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Successfully copied configuration file.\n");
+    if (NULL != d->update_cb)
+      d->update_cb (d->update_cb_cls, NULL);
+    d->phase = SP_START_DONE;
+    break;
+  }
+}
+
+/**
+ * Continues GNUnet daemon startup when user wanted to be notified
+ * once a hostkey was generated (for creating friends files, blacklists,
+ * etc.).
+ *
+ * @param daemon the daemon to finish starting
+ */
+void
+GNUNET_TESTING_daemon_continue_startup (struct GNUNET_TESTING_Daemon *daemon)
+{
+  GNUNET_assert (daemon->phase == SP_HOSTKEY_CREATED);
+  daemon->phase = SP_TOPOLOGY_SETUP;
+}
+
+/**
+ * Check whether the given daemon is running.
+ *
+ * @param daemon the daemon to check
+ *
+ * @return GNUNET_YES if the daemon is up, GNUNET_NO if the
+ *         daemon is down, GNUNET_SYSERR on error.
+ */
+int
+GNUNET_TESTING_test_daemon_running (struct GNUNET_TESTING_Daemon *daemon)
+{
+  if (daemon == NULL)
+    return GNUNET_SYSERR;
+
+  if (daemon->running == GNUNET_YES)
+    return GNUNET_YES;
+  return GNUNET_NO;
+}
+
+
+/**
+ * Starts a GNUnet daemon service which has been previously stopped.
+ *
+ * @param d the daemon for which the service should be started
+ * @param service the name of the service to start
+ * @param timeout how long to wait for process for shutdown to complete
+ * @param cb function called once the service starts
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemon_start_stopped_service (struct GNUNET_TESTING_Daemon *d,
+                                             char *service,
+                                             struct GNUNET_TIME_Relative
+                                             timeout,
+                                             GNUNET_TESTING_NotifyDaemonRunning
+                                             cb, void *cb_cls)
+{
+  char *arg;
+
+  d->cb = cb;
+  d->cb_cls = cb_cls;
+
+  GNUNET_assert (d->running == GNUNET_YES);
+
+  if (d->phase == SP_CONFIG_UPDATE)
+  {
+    GNUNET_SCHEDULER_cancel (d->task);
+    d->phase = SP_START_DONE;
+  }
+
+  if (d->churned_services == NULL)
+  {
+    d->cb (d->cb_cls, &d->id, d->cfg, d,
+           "No service has been churned off yet!!");
+    return;
+  }
+  d->phase = SP_SERVICE_START;
+  GNUNET_free (d->churned_services);
+  d->churned_services = NULL;
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  /* Check if this is a local or remote process */
+  if (NULL != d->hostname)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with config `%s' on host `%s'.\n",
+                d->cfgfile, d->hostname);
+    if (d->username != NULL)
+      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
+    else
+      arg = GNUNET_strdup (d->hostname);
+
+    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
+                                       "-q",
+                                       arg, "gnunet-arm",
+                                       "-c", d->cfgfile, "-i", service, "-q",
+                                       "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q\n",
+                arg, "gnunet-arm", d->cfgfile, service);
+    GNUNET_free (arg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile);
+    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
+                                       "-c", d->cfgfile, "-i", service, "-q",
+                                       "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       NULL);
+  }
+
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
+}
+
+/**
+ * Starts a GNUnet daemon's service.
+ *
+ * @param d the daemon for which the service should be started
+ * @param service the name of the service to start
+ * @param timeout how long to wait for process for startup
+ * @param cb function called once gnunet-arm returns
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemon_start_service (struct GNUNET_TESTING_Daemon *d,
+                                     const char *service,
+                                     struct GNUNET_TIME_Relative timeout,
+                                     GNUNET_TESTING_NotifyDaemonRunning cb,
+                                     void *cb_cls)
+{
+  char *arg;
+
+  d->cb = cb;
+  d->cb_cls = cb_cls;
+
+  GNUNET_assert (service != NULL);
+  GNUNET_assert (d->running == GNUNET_YES);
+  GNUNET_assert (d->phase == SP_START_DONE);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              _("Starting service %s for peer `%4s'\n"), service,
+              GNUNET_i2s (&d->id));
+  d->phase = SP_SERVICE_START;
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  /* Check if this is a local or remote process */
+  if (NULL != d->hostname)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with config `%s' on host `%s'.\n",
+                d->cfgfile, d->hostname);
+    if (d->username != NULL)
+      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
+    else
+      arg = GNUNET_strdup (d->hostname);
+
+    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
+                                       "-q",
+                                       arg, "gnunet-arm",
+                                       "-c", d->cfgfile, "-i", service, "-q",
+                                       "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with command ssh %s gnunet-arm -c %s -i %s -q -T %s\n",
+                arg, "gnunet-arm", d->cfgfile, service,
+                GNUNET_TIME_relative_to_string (timeout));
+    GNUNET_free (arg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with config `%s' locally.\n", d->cfgfile);
+    d->proc_arm_srv_start = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
+                                       "-c", d->cfgfile, "-i", service, "-q",
+                                       "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Starting gnunet-arm with command %s -c %s -i %s -q -T %s\n",
+                "gnunet-arm", d->cfgfile, service,
+                GNUNET_TIME_relative_to_string (timeout));
+  }
+
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
+}
+
+/**
+ * Start a peer that has previously been stopped using the daemon_stop
+ * call (and files weren't deleted and the allow restart flag)
+ *
+ * @param daemon the daemon to start (has been previously stopped)
+ * @param timeout how long to wait for restart
+ * @param cb the callback for notification when the peer is running
+ * @param cb_cls closure for the callback
+ */
+void
+GNUNET_TESTING_daemon_start_stopped (struct GNUNET_TESTING_Daemon *daemon,
+                                     struct GNUNET_TIME_Relative timeout,
+                                     GNUNET_TESTING_NotifyDaemonRunning cb,
+                                     void *cb_cls)
+{
+  if (daemon->running == GNUNET_YES)
+  {
+    cb (cb_cls, &daemon->id, daemon->cfg, daemon,
+        "Daemon already running, can't restart!");
+    return;
+  }
+
+  daemon->cb = cb;
+  daemon->cb_cls = cb_cls;
+  daemon->phase = SP_TOPOLOGY_SETUP;
+  daemon->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  /* FIXME: why add_continuation? */
+  GNUNET_SCHEDULER_add_continuation (&start_fsm, daemon,
+                                     GNUNET_SCHEDULER_REASON_PREREQ_DONE);
+}
+
+/**
+ * Starts a GNUnet daemon.  GNUnet must be installed on the target
+ * system and available in the PATH.  The machine must furthermore be
+ * reachable via "ssh" (unless the hostname is "NULL") without the
+ * need to enter a password.
+ *
+ * @param cfg configuration to use
+ * @param timeout how long to wait starting up peers
+ * @param pretend GNUNET_YES to set up files but not start peer GNUNET_NO
+ *                to really start the peer (default)
+ * @param hostname name of the machine where to run GNUnet
+ *        (use NULL for localhost).
+ * @param ssh_username ssh username to use when connecting to hostname
+ * @param sshport port to pass to ssh process when connecting to hostname
+ * @param hostkey pointer to a hostkey to be written to disk (instead of being generated)
+ * @param hostkey_callback function to call once the hostkey has been
+ *        generated for this peer, but it hasn't yet been started
+ *        (NULL to start immediately, otherwise waits on GNUNET_TESTING_daemon_continue_start)
+ * @param hostkey_cls closure for hostkey callback
+ * @param cb function to call once peer is up, or failed to start
+ * @param cb_cls closure for cb
+ * @return handle to the daemon (actual start will be completed asynchronously)
+ */
+struct GNUNET_TESTING_Daemon *
+GNUNET_TESTING_daemon_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                             struct GNUNET_TIME_Relative timeout, int pretend,
+                             const char *hostname, const char *ssh_username,
+                             uint16_t sshport, const char *hostkey,
+                             GNUNET_TESTING_NotifyHostkeyCreated
+                             hostkey_callback, void *hostkey_cls,
+                             GNUNET_TESTING_NotifyDaemonRunning cb,
+                             void *cb_cls)
+{
+  struct GNUNET_TESTING_Daemon *ret;
+  char *arg;
+  char *username;
+  char *servicehome;
+  char *baseservicehome;
+  char *slash;
+  char *hostkeyfile;
+  char *temp_file_name;
+  struct GNUNET_DISK_FileHandle *fn;
+  struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded public_key;
+  struct GNUNET_CRYPTO_RsaPrivateKey *private_key;
+
+  ret = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Daemon));
+  ret->hostname = (hostname == NULL) ? NULL : GNUNET_strdup (hostname);
+  if (sshport != 0)
+  {
+    GNUNET_asprintf (&ret->ssh_port_str, "%d", sshport);
+  }
+  else
+    ret->ssh_port_str = NULL;
+
+  /* Find service home and base service home directories, create it if it doesn't exist */
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
+                                                        "SERVICEHOME",
+                                                        &servicehome));
+
+  GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_create (servicehome));
+  GNUNET_asprintf (&temp_file_name, "%s/gnunet-testing-config", servicehome);
+  ret->cfgfile = GNUNET_DISK_mktemp (temp_file_name);
+  GNUNET_free (temp_file_name);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Setting up peer with configuration file `%s'.\n", ret->cfgfile);
+  if (NULL == ret->cfgfile)
+  {
+    GNUNET_free_non_null (ret->ssh_port_str);
+    GNUNET_free_non_null (ret->hostname);
+    GNUNET_free (ret);
+    return NULL;
+  }
+  ret->hostkey_callback = hostkey_callback;
+  ret->hostkey_cls = hostkey_cls;
+  ret->cb = cb;
+  ret->cb_cls = cb_cls;
+  ret->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  ret->cfg = GNUNET_CONFIGURATION_dup (cfg);
+  GNUNET_CONFIGURATION_set_value_string (ret->cfg, "PATHS", "DEFAULTCONFIG",
+                                         ret->cfgfile);
+
+  if (hostkey != NULL)          /* Get the peer identity from the hostkey */
+  {
+    private_key = GNUNET_CRYPTO_rsa_decode_key (hostkey, HOSTKEYFILESIZE);
+    GNUNET_assert (private_key != NULL);
+    GNUNET_CRYPTO_rsa_key_get_public (private_key, &public_key);
+    GNUNET_CRYPTO_hash (&public_key,
+                        sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded),
+                        &ret->id.hashPubKey);
+    ret->shortname = GNUNET_strdup (GNUNET_i2s (&ret->id));
+    ret->have_hostkey = GNUNET_YES;
+    GNUNET_CRYPTO_rsa_key_free (private_key);
+  }
+
+  /* Write hostkey to file, if we were given one */
+  hostkeyfile = NULL;
+  if (hostkey != NULL)
+  {
+    GNUNET_asprintf (&hostkeyfile, "%s/.hostkey", servicehome);
+    fn = GNUNET_DISK_file_open (hostkeyfile,
+                                GNUNET_DISK_OPEN_READWRITE |
+                                GNUNET_DISK_OPEN_CREATE,
+                                GNUNET_DISK_PERM_USER_READ |
+                                GNUNET_DISK_PERM_USER_WRITE);
+    GNUNET_assert (fn != NULL);
+    GNUNET_assert (HOSTKEYFILESIZE ==
+                   GNUNET_DISK_file_write (fn, hostkey, HOSTKEYFILESIZE));
+    GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fn));
+  }
+
+  /* write configuration to temporary file */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_write (ret->cfg, ret->cfgfile))
+  {
+    if (0 != UNLINK (ret->cfgfile))
+      GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
+                                ret->cfgfile);
+    GNUNET_CONFIGURATION_destroy (ret->cfg);
+    GNUNET_free_non_null (ret->hostname);
+    GNUNET_free (ret->cfgfile);
+    GNUNET_free (ret);
+    return NULL;
+  }
+  if (ssh_username != NULL)
+    username = GNUNET_strdup (ssh_username);
+  if ((ssh_username == NULL) &&
+      (GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING_OLD", "USERNAME",
+                                              &username)))
+  {
+    if (NULL != getenv ("USER"))
+      username = GNUNET_strdup (getenv ("USER"));
+    else
+      username = NULL;
+  }
+  ret->username = username;
+
+  if (GNUNET_NO == pretend)     /* Copy files, enter finite state machine */
+  {
+    /* copy directory to remote host */
+    if (NULL != hostname)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Copying configuration directory to host `%s'.\n", hostname);
+      baseservicehome = GNUNET_strdup (servicehome);
+      /* Remove trailing /'s */
+      while (baseservicehome[strlen (baseservicehome) - 1] == '/')
+        baseservicehome[strlen (baseservicehome) - 1] = '\0';
+      /* Find next directory /, jump one ahead */
+      slash = strrchr (baseservicehome, '/');
+      if (slash != NULL)
+        *(++slash) = '\0';
+
+      ret->phase = SP_COPYING;
+      if (NULL != username)
+        GNUNET_asprintf (&arg, "%s@%s:%s", username, hostname, baseservicehome);
+      else
+        GNUNET_asprintf (&arg, "%s:%s", hostname, baseservicehome);
+      GNUNET_free (baseservicehome);
+      if (ret->ssh_port_str == NULL)
+      {
+        ret->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", "-r",
+                                             "-q",
+                                             servicehome, arg, NULL);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                    "copying directory with command scp -r %s %s\n",
+                    servicehome, arg);
+      }
+      else
+      {
+        ret->proc_arm_copying =
+           GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp", "-r", "-P",
+                                     ret->ssh_port_str,
+                                     "-q",
+                                     servicehome, arg, NULL);
+      }
+      GNUNET_free (arg);
+      if (NULL == ret->proc_arm_copying)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _
+                    ("Could not start `%s' process to copy configuration directory.\n"),
+                    "scp");
+        if (0 != UNLINK (ret->cfgfile))
+          GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
+                                    ret->cfgfile);
+        GNUNET_CONFIGURATION_destroy (ret->cfg);
+        GNUNET_free_non_null (ret->hostname);
+        GNUNET_free_non_null (ret->username);
+        GNUNET_free (ret->cfgfile);
+        GNUNET_free (ret);
+        if ((hostkey != NULL) && (0 != UNLINK (hostkeyfile)))
+          GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink",
+                                    hostkeyfile);
+        GNUNET_free_non_null (hostkeyfile);
+        GNUNET_assert (GNUNET_OK == GNUNET_DISK_directory_remove (servicehome));
+        GNUNET_free (servicehome);
+        return NULL;
+      }
+
+      ret->task =
+          GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm,
+                                        ret);
+      GNUNET_free_non_null (hostkeyfile);
+      GNUNET_free (servicehome);
+      return ret;
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "No need to copy configuration file since we are running locally.\n");
+    ret->phase = SP_COPIED;
+    /* FIXME: why add_cont? */
+    GNUNET_SCHEDULER_add_continuation (&start_fsm, ret,
+                                       GNUNET_SCHEDULER_REASON_PREREQ_DONE);
+  }
+  GNUNET_free_non_null (hostkeyfile);
+  GNUNET_free (servicehome);
+  return ret;
+}
+
+
+/**
+ * Restart (stop and start) a GNUnet daemon.
+ *
+ * @param d the daemon that should be restarted
+ * @param cb function called once the daemon is (re)started
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemon_restart (struct GNUNET_TESTING_Daemon *d,
+                               GNUNET_TESTING_NotifyDaemonRunning cb,
+                               void *cb_cls)
+{
+  char *arg;
+  char *del_arg;
+
+  del_arg = NULL;
+  if (NULL != d->cb)
+  {
+    d->dead = GNUNET_YES;
+    return;
+  }
+
+  d->cb = cb;
+  d->cb_cls = cb_cls;
+
+  if (d->phase == SP_CONFIG_UPDATE)
+  {
+    GNUNET_SCHEDULER_cancel (d->task);
+    d->phase = SP_START_DONE;
+  }
+  if (d->server != NULL)
+  {
+    GNUNET_CORE_disconnect (d->server);
+    d->server = NULL;
+  }
+
+  if (d->th != NULL)
+  {
+    GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
+    d->ghh = NULL;
+    GNUNET_TRANSPORT_disconnect (d->th);
+    d->th = NULL;
+  }
+  /* state clean up and notifications */
+  GNUNET_free_non_null (d->hello);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
+              GNUNET_i2s (&d->id));
+  d->phase = SP_START_ARMING;
+
+  /* Check if this is a local or remote process */
+  if (NULL != d->hostname)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with config `%s' on host `%s'.\n",
+                d->cfgfile, d->hostname);
+    if (d->username != NULL)
+      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
+    else
+      arg = GNUNET_strdup (d->hostname);
+
+    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
+                                       "-q",
+                                       arg, "gnunet-arm",
+                                       "-c", d->cfgfile, "-e", "-r", NULL);
+    /* Use -r to restart arm and all services */
+
+    GNUNET_free (arg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
+    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
+                                       "-c", d->cfgfile, "-e", "-r", NULL);
+  }
+
+  GNUNET_free_non_null (del_arg);
+  d->task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
+
+}
+
+
+/**
+ * Stops a GNUnet daemon.
+ *
+ * @param d the daemon that should be stopped
+ * @param service the name of the service to stop
+ * @param timeout how long to wait for process for shutdown to complete
+ * @param cb function called once the daemon was stopped
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemon_stop_service (struct GNUNET_TESTING_Daemon *d,
+                                    const char *service,
+                                    struct GNUNET_TIME_Relative timeout,
+                                    GNUNET_TESTING_NotifyCompletion cb,
+                                    void *cb_cls)
+{
+  char *arg;
+
+  d->dead_cb = cb;
+  d->dead_cb_cls = cb_cls;
+
+  GNUNET_assert (d->running == GNUNET_YES);
+
+  if (d->phase == SP_CONFIG_UPDATE)
+  {
+    GNUNET_SCHEDULER_cancel (d->task);
+    d->phase = SP_START_DONE;
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Terminating peer `%4s'\n"),
+              GNUNET_i2s (&d->id));
+  if (d->churned_services != NULL)
+  {
+    d->dead_cb (d->dead_cb_cls, "A service has already been turned off!!");
+    return;
+  }
+  d->phase = SP_SERVICE_SHUTDOWN_START;
+  d->churned_services = GNUNET_strdup (service);
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  /* Check if this is a local or remote process */
+  if (NULL != d->hostname)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with config `%s' on host `%s'.\n",
+                d->cfgfile, d->hostname);
+    if (d->username != NULL)
+      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
+    else
+      arg = GNUNET_strdup (d->hostname);
+    
+    d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
+                                       "-q",
+                                       arg, "gnunet-arm",
+                                       "-c", d->cfgfile, "-k", service, "-q",
+                                       "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -k %s -q\n",
+                arg, "gnunet-arm", d->cfgfile, service);
+    GNUNET_free (arg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
+    d->proc_arm_srv_stop = GNUNET_OS_start_process (GNUNET_YES, NULL, NULL, "gnunet-arm", "gnunet-arm",
+                                       "-c", d->cfgfile, "-k", service, "-q",
+                                       "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       NULL);
+  }
+
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
+}
+
+
+/**
+ * Forcefully terminate a process and clean up the child.
+ *
+ * @param proc handle to process to kill
+ */
+static void
+kill_and_close_process (struct GNUNET_OS_Process *proc)
+{
+  (void) GNUNET_OS_process_kill (proc, SIGKILL); 
+  GNUNET_break (GNUNET_OK == GNUNET_OS_process_wait (proc));
+  GNUNET_OS_process_destroy (proc);
+}
+
+
+/**
+ * Stops a GNUnet daemon.
+ *
+ * @param d the daemon that should be stopped
+ * @param timeout how long to wait for process for shutdown to complete
+ * @param cb function called once the daemon was stopped
+ * @param cb_cls closure for cb
+ * @param delete_files GNUNET_YES to remove files, GNUNET_NO
+ *        to leave them
+ * @param allow_restart GNUNET_YES to restart peer later (using this API)
+ *        GNUNET_NO to kill off and clean up for good
+ */
+void
+GNUNET_TESTING_daemon_stop (struct GNUNET_TESTING_Daemon *d,
+                            struct GNUNET_TIME_Relative timeout,
+                            GNUNET_TESTING_NotifyCompletion cb, void *cb_cls,
+                            int delete_files, int allow_restart)
+{
+  char *arg;
+  char *del_arg;
+
+  d->dead_cb = cb;
+  d->dead_cb_cls = cb_cls;
+
+  if (NULL != d->cb)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Setting d->dead on peer `%4s'\n"),
+                GNUNET_i2s (&d->id));
+    d->dead = GNUNET_YES;
+    return;
+  }
+  if (NULL != d->proc_arm_start)
+  {
+    kill_and_close_process (d->proc_arm_start);
+    d->proc_arm_start = NULL;
+  }
+  if (NULL != d->proc_arm_srv_start)
+  {
+    kill_and_close_process (d->proc_arm_srv_start);
+    d->proc_arm_srv_start = NULL;
+  }
+  if (NULL != d->proc_arm_srv_stop)
+  {
+    kill_and_close_process (d->proc_arm_srv_stop);
+    d->proc_arm_srv_stop = NULL;
+  }
+  if (NULL != d->proc_arm_copying)
+  {
+    kill_and_close_process (d->proc_arm_copying);
+    d->proc_arm_copying = NULL;
+  }
+  if (NULL != d->proc_arm_peerinfo)
+  {
+    kill_and_close_process (d->proc_arm_peerinfo);
+    d->proc_arm_peerinfo = NULL;
+  }
+  if ((d->running == GNUNET_NO) && (d->churn == GNUNET_YES))
+  {
+    /* Peer has already been stopped in churn context!
+     * Free what was left from churning! */
+    GNUNET_assert (d->cfg != NULL);
+    GNUNET_CONFIGURATION_destroy (d->cfg);
+    if (delete_files == GNUNET_YES)
+    {
+      if (0 != UNLINK (d->cfgfile))
+      {
+        GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "unlink");
+      }
+    }
+    GNUNET_free (d->cfgfile);
+    GNUNET_free_non_null (d->hostname);
+    GNUNET_free_non_null (d->username);
+    if (NULL != d->dead_cb)
+      d->dead_cb (d->dead_cb_cls, NULL);
+    /* FIXME: this should be an assert and the test below
+       should not be required, but testing is broken... */
+    GNUNET_break (NULL == d->proc_arm_stop);
+    if (NULL == d->proc_arm_stop) 
+    GNUNET_free (d);
+    return;
+  }
+
+  del_arg = NULL;
+  if (delete_files == GNUNET_YES)
+  {
+    GNUNET_asprintf (&del_arg, "-d");
+  }
+
+  if (d->phase == SP_CONFIG_UPDATE)
+  {
+    GNUNET_SCHEDULER_cancel (d->task);
+    d->phase = SP_START_DONE;
+  }
+  /** Move this call to scheduled shutdown as fix for CORE_connect calling daemon_stop?
+  if (d->server != NULL)
+    {
+      GNUNET_CORE_disconnect (d->server);
+      d->server = NULL;
+    }
+    */
+  /* shutdown ARM process (will terminate others) */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Terminating peer `%4s'\n" ,
+              GNUNET_i2s (&d->id));
+  d->phase = SP_SHUTDOWN_START;
+  d->running = GNUNET_NO;
+  if (allow_restart == GNUNET_YES)
+    d->churn = GNUNET_YES;
+  if (d->th != NULL)
+  {
+    GNUNET_TRANSPORT_get_hello_cancel (d->ghh);
+    d->ghh = NULL;
+    GNUNET_TRANSPORT_disconnect (d->th);
+    d->th = NULL;
+  }
+  /* Check if this is a local or remote process */
+
+
+  if (NULL != d->hostname)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with config `%s' on host `%s'.\n",
+                d->cfgfile, d->hostname);
+    if (d->username != NULL)
+      GNUNET_asprintf (&arg, "%s@%s", d->username, d->hostname);
+    else
+      arg = GNUNET_strdup (d->hostname);
+
+    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh",
+                                       "-q",
+                                       arg, "gnunet-arm",
+                                       "-c", d->cfgfile, "-e", "-q", "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       del_arg, NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with command ssh %s gnunet-arm -c %s -e -q %s\n",
+                arg, "gnunet-arm", d->cfgfile, del_arg);
+    /* Use -e to end arm, and -d to remove temp files */
+    GNUNET_free (arg);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Stopping gnunet-arm with config `%s' locally.\n", d->cfgfile);
+    d->proc_arm_stop = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "gnunet-arm", "gnunet-arm",
+                                       "-c", d->cfgfile, "-e", "-q", "-T",
+                                       GNUNET_TIME_relative_to_string (timeout),
+                                       del_arg, NULL);
+    GNUNET_assert (NULL != d->proc_arm_stop);
+  }
+
+  GNUNET_free_non_null (del_arg);
+  d->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  if (GNUNET_SCHEDULER_NO_TASK != d->task)
+    GNUNET_SCHEDULER_cancel(d->task);
+  d->task = GNUNET_SCHEDULER_add_now (&start_fsm, d);
+}
+
+
+/**
+ * Changes the configuration of a GNUnet daemon.
+ *
+ * @param d the daemon that should be modified
+ * @param cfg the new configuration for the daemon
+ * @param cb function called once the configuration was changed
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemon_reconfigure (struct GNUNET_TESTING_Daemon *d,
+                                   struct GNUNET_CONFIGURATION_Handle *cfg,
+                                   GNUNET_TESTING_NotifyCompletion cb,
+                                   void *cb_cls)
+{
+  char *arg;
+
+  if (d->phase != SP_START_DONE)
+  {
+    if (NULL != cb)
+      cb (cb_cls,
+          _
+          ("Peer not yet running, can not change configuration at this point."));
+    return;
+  }
+
+  /* 1) write configuration to temporary file */
+  if (GNUNET_OK != GNUNET_CONFIGURATION_write (cfg, d->cfgfile))
+  {
+    if (NULL != cb)
+      cb (cb_cls, _("Failed to write new configuration to disk."));
+    return;
+  }
+
+  /* 2) copy file to remote host (if necessary) */
+  if (NULL == d->hostname)
+  {
+    /* signal success */
+    if (NULL != cb)
+      cb (cb_cls, NULL);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Copying updated configuration file to remote host `%s'.\n",
+              d->hostname);
+  d->phase = SP_CONFIG_UPDATE;
+  if (NULL != d->username)
+    GNUNET_asprintf (&arg, "%s@%s:%s", d->username, d->hostname, d->cfgfile);
+  else
+    GNUNET_asprintf (&arg, "%s:%s", d->hostname, d->cfgfile);
+  d->proc_arm_copying = GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "scp", "scp",
+                                     "-q",
+                                     d->cfgfile, arg, NULL);
+  GNUNET_free (arg);
+  if (NULL == d->proc_arm_copying)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Could not start `%s' process to copy configuration file.\n"),
+                "scp");
+    if (NULL != cb)
+      cb (cb_cls, _("Failed to copy new configuration to remote machine."));
+    d->phase = SP_START_DONE;
+    return;
+  }
+  d->update_cb = cb;
+  d->update_cb_cls = cb_cls;
+  d->task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_CONSTANTS_EXEC_WAIT, &start_fsm, d);
+}
+
+
+/**
+ * Data kept for each pair of peers that we try
+ * to connect.
+ */
+struct GNUNET_TESTING_ConnectContext
+{
+  /**
+   * Testing handle to the first daemon.
+   */
+  struct GNUNET_TESTING_Daemon *d1;
+
+  /**
+   * Handle to core of first daemon (to check connect)
+   */
+  struct GNUNET_CORE_Handle *d1core;
+
+  /**
+   * Have we actually connected to the core of the first daemon yet?
+   */
+  int d1core_ready;
+
+  /**
+   * Testing handle to the second daemon.
+   */
+  struct GNUNET_TESTING_Daemon *d2;
+
+  /**
+   * Transport handle to the first daemon (to offer the HELLO of the second daemon to).
+   */
+  struct GNUNET_TRANSPORT_Handle *d1th;
+
+  /**
+   * Function to call once we are done (or have timed out).
+   */
+  GNUNET_TESTING_NotifyConnection cb;
+
+  /**
+   * Closure for "nb".
+   */
+  void *cb_cls;
+
+  /**
+   * The relative timeout from whence this connect attempt was
+   * started.  Allows for reconnect attempts.
+   */
+  struct GNUNET_TIME_Relative relative_timeout;
+
+  /**
+   * Maximum number of connect attempts, will retry connection
+   * this number of times on failures.
+   */
+  unsigned int connect_attempts;
+
+  /**
+   * Hello timeout task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier hello_send_task;
+
+  /**
+   * Connect timeout task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+
+  /**
+   * When should this operation be complete (or we must trigger
+   * a timeout).
+   */
+  struct GNUNET_TIME_Relative timeout_hello;
+
+  /**
+   * Was the connection attempt successful?
+   */
+  int connected;
+
+  /**
+   * When connecting, do we need to send the HELLO?
+   */
+  int send_hello;
+
+  /**
+   * The distance between the two connected peers
+   */
+  uint32_t distance;
+};
+
+
+/** Forward declaration **/
+static void
+reattempt_daemons_connect (void *cls,
+                           const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+
+/**
+ * Notify callback about success or failure of the attempt
+ * to connect the two peers
+ *
+ * @param cls our "struct GNUNET_TESTING_ConnectContext" (freed)
+ * @param tc reason tells us if we succeeded or failed
+ */
+static void
+notify_connect_result (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_ConnectContext *ctx = cls;
+
+  ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (ctx->hello_send_task);
+    ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  if (ctx->d1th != NULL)
+    GNUNET_TRANSPORT_disconnect (ctx->d1th);
+  ctx->d1th = NULL;
+  if (ctx->d1core != NULL)
+    GNUNET_CORE_disconnect (ctx->d1core);
+  ctx->d1core = NULL;
+
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+  {
+    GNUNET_free (ctx);
+    return;
+  }
+
+  if (ctx->connected == GNUNET_YES)
+  {
+    if (ctx->cb != NULL)
+    {
+      ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, ctx->distance,
+               ctx->d1->cfg, ctx->d2->cfg, ctx->d1, ctx->d2, NULL);
+    }
+  }
+  else if (ctx->connect_attempts > 0)
+  {
+    ctx->d1core_ready = GNUNET_NO;
+    ctx->timeout_task =
+        GNUNET_SCHEDULER_add_now (&reattempt_daemons_connect, ctx);
+    return;
+  }
+  else
+  {
+    if (ctx->cb != NULL)
+    {
+      ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+               ctx->d2->cfg, ctx->d1, ctx->d2, _("Peers failed to connect"));
+    }
+  }
+  GNUNET_free (ctx);
+}
+
+
+/**
+ * Success, connection is up.  Signal client our success.
+ *
+ * @param cls our "struct GNUNET_TESTING_ConnectContext"
+ * @param peer identity of the peer that has connected
+ * @param atsi performance information
+ * @param atsi_count number of records in 'atsi'
+ *
+ */
+static void
+connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
+                const struct GNUNET_ATS_Information *atsi,
+                unsigned int atsi_count)
+{
+  struct GNUNET_TESTING_ConnectContext *ctx = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n",
+              ctx->d1->shortname, GNUNET_i2s (peer));
+  if (0 != memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity)))
+    return;
+  ctx->connected = GNUNET_YES;
+  ctx->distance = 0;            /* FIXME: distance */
+  if (ctx->hello_send_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (ctx->hello_send_task);
+    ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  GNUNET_SCHEDULER_cancel (ctx->timeout_task);
+  ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
+}
+
+
+static void
+send_hello (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_ConnectContext *ctx = cls;
+  struct GNUNET_MessageHeader *hello;
+
+  ctx->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    return;
+  if ((ctx->d1core_ready == GNUNET_YES) && (ctx->d2->hello != NULL) &&
+      (NULL != GNUNET_HELLO_get_header (ctx->d2->hello)) &&
+      (ctx->d1->phase == SP_START_DONE) && (ctx->d2->phase == SP_START_DONE))
+  {
+    hello = GNUNET_HELLO_get_header (ctx->d2->hello);
+    GNUNET_assert (hello != NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Offering hello of %s to %s\n",
+                ctx->d2->shortname, ctx->d1->shortname);
+    GNUNET_TRANSPORT_offer_hello (ctx->d1th, hello, NULL, NULL);
+    GNUNET_assert (ctx->d1core != NULL);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending connect request to TRANSPORT of %s for peer %s\n",
+                GNUNET_i2s (&ctx->d1->id),
+                GNUNET_h2s (&ctx->d2->id.hashPubKey));
+    GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id);
+    ctx->timeout_hello =
+        GNUNET_TIME_relative_add (ctx->timeout_hello,
+                                  GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 500));
+  }
+  ctx->hello_send_task =
+      GNUNET_SCHEDULER_add_delayed (ctx->timeout_hello, &send_hello, ctx);
+}
+
+/**
+ * Notify of a successful connection to the core service.
+ *
+ * @param cls a ConnectContext
+ * @param server handle to the core service
+ * @param my_identity the peer identity of this peer
+ */
+void
+core_init_notify (void *cls, struct GNUNET_CORE_Handle *server,
+                  const struct GNUNET_PeerIdentity *my_identity)
+{
+  struct GNUNET_TESTING_ConnectContext *connect_ctx = cls;
+
+  connect_ctx->d1core_ready = GNUNET_YES;
+
+  if (connect_ctx->send_hello == GNUNET_NO)
+  {
+    GNUNET_TRANSPORT_try_connect (connect_ctx->d1th, &connect_ctx->d2->id);
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Sending connect request to TRANSPORT of %s for peer %s\n",
+                connect_ctx->d1->shortname, connect_ctx->d2->shortname);
+  }
+}
+
+
+/**
+ * Try to connect again some peers that failed in an earlier attempt. This will
+ * be tried as many times as connection_attempts in the configuration file.
+ *
+ * @param cls Closure (connection context between the two peers).
+ * @param tc TaskContext.
+ */
+static void
+reattempt_daemons_connect (void *cls,
+                           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_TESTING_ConnectContext *ctx = cls;
+
+  ctx->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "re-attempting connect of peer %s to peer %s\n",
+              ctx->d1->shortname, ctx->d2->shortname);
+  ctx->connect_attempts--;
+  GNUNET_assert (ctx->d1core == NULL);
+  ctx->d1core_ready = GNUNET_NO;
+  ctx->d1core =
+      GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify,
+                           &connect_notify, NULL, NULL, GNUNET_NO, NULL,
+                           GNUNET_NO, no_handlers);
+  if (ctx->d1core == NULL)
+  {
+    if (NULL != ctx->cb)
+      ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+               ctx->d2->cfg, ctx->d1, ctx->d2,
+               _("Failed to connect to core service of first peer!\n"));
+    GNUNET_free (ctx);
+    return;
+  }
+
+  /* Don't know reason for initial connect failure, update the HELLO for the second peer */
+  if (NULL != ctx->d2->hello)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "updating %s's HELLO\n",
+                ctx->d2->shortname);
+    GNUNET_free (ctx->d2->hello);
+    ctx->d2->hello = NULL;
+    if (NULL != ctx->d2->th)
+    {
+      GNUNET_TRANSPORT_get_hello_cancel (ctx->d2->ghh);
+      ctx->d2->ghh = NULL;
+      GNUNET_TRANSPORT_disconnect (ctx->d2->th);
+    }
+    ctx->d2->th =
+        GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
+                                  NULL);
+    GNUNET_assert (ctx->d2->th != NULL);
+    ctx->d2->ghh =
+        GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "didn't have %s's HELLO\n",
+                ctx->d2->shortname);
+  }
+
+  if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "didn't have %s's HELLO, trying to get it now\n",
+                ctx->d2->shortname);
+    ctx->d2->th =
+        GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
+                                  NULL);
+    if (NULL == ctx->d2->th)
+    {
+      GNUNET_CORE_disconnect (ctx->d1core);
+      GNUNET_free (ctx);
+      if (NULL != ctx->cb)
+        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+                 ctx->d2->cfg, ctx->d1, ctx->d2,
+                 _("Failed to connect to transport service!\n"));
+      return;
+    }
+    ctx->d2->ghh =
+        GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
+  }
+  else
+  {
+    if (NULL == ctx->d2->hello)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "didn't have %s's HELLO but th wasn't NULL, not trying!!\n",
+                  ctx->d2->shortname);
+    }
+  }
+
+  if (ctx->send_hello == GNUNET_YES)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending %s's HELLO to %s\n",
+                ctx->d1->shortname, ctx->d2->shortname);
+    ctx->d1th =
+        GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL,
+                                  NULL, NULL);
+    if (ctx->d1th == NULL)
+    {
+      GNUNET_CORE_disconnect (ctx->d1core);
+      GNUNET_free (ctx);
+      if (NULL != ctx->cb)
+        ctx->cb (ctx->cb_cls, &ctx->d1->id, &ctx->d2->id, 0, ctx->d1->cfg,
+                 ctx->d2->cfg, ctx->d1, ctx->d2,
+                 _("Failed to connect to transport service!\n"));
+      return;
+    }
+    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task);
+    ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Trying to reconnect %s to %s\n",
+                ctx->d1->shortname, ctx->d2->shortname);
+    GNUNET_TRANSPORT_try_connect (ctx->d1th, &ctx->d2->id);
+  }
+  ctx->timeout_task =
+      GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
+                                    &notify_connect_result, ctx);
+}
+
+/**
+ * Iterator for currently known peers, to ensure
+ * that we don't try to send duplicate connect
+ * requests to core.
+ *
+ * @param cls our "struct GNUNET_TESTING_ConnectContext"
+ * @param peer identity of the peer that has connected,
+ *        NULL when iteration has finished
+ * @param atsi performance information
+ * @param atsi_count number of records in 'atsi'
+ *
+ */
+static void
+core_initial_iteration (void *cls, const struct GNUNET_PeerIdentity *peer,
+                        const struct GNUNET_ATS_Information *atsi,
+                        unsigned int atsi_count)
+{
+  struct GNUNET_TESTING_ConnectContext *ctx = cls;
+
+  if ((peer != NULL) &&
+      (0 == memcmp (&ctx->d2->id, peer, sizeof (struct GNUNET_PeerIdentity))))
+  {
+    ctx->connected = GNUNET_YES;
+    ctx->distance = 0;          /* FIXME: distance */
+    return;
+  }
+  if (peer != NULL)
+    return;                     /* ignore other peers */
+  /* peer == NULL: End of iteration over peers */
+
+  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->timeout_task);
+  if (ctx->connected == GNUNET_YES)
+  {
+    ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
+    return;
+  }
+
+  /* Peer not already connected, need to schedule connect request! */
+  if (ctx->d1core == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Peers are NOT connected, connecting to core!\n");
+    ctx->d1core =
+        GNUNET_CORE_connect (ctx->d1->cfg, ctx, &core_init_notify,
+                             &connect_notify, NULL, NULL, GNUNET_NO, NULL,
+                             GNUNET_NO, no_handlers);
+  }
+
+  if (ctx->d1core == NULL)
+  {
+    ctx->timeout_task = GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
+    return;
+  }
+
+  if ((NULL == ctx->d2->hello) && (ctx->d2->th == NULL))        /* Do not yet have the second peer's hello, set up a task to get it */
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Don't have d2's HELLO, trying to get it!\n");
+    ctx->d2->th =
+        GNUNET_TRANSPORT_connect (ctx->d2->cfg, &ctx->d2->id, NULL, NULL, NULL,
+                                  NULL);
+    if (ctx->d2->th == NULL)
+    {
+      GNUNET_CORE_disconnect (ctx->d1core);
+      ctx->d1core = NULL;
+      ctx->timeout_task =
+          GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
+      return;
+    }
+    ctx->d2->ghh =
+        GNUNET_TRANSPORT_get_hello (ctx->d2->th, &process_hello, ctx->d2);
+  }
+
+  if (ctx->send_hello == GNUNET_YES)
+  {
+    ctx->d1th =
+        GNUNET_TRANSPORT_connect (ctx->d1->cfg, &ctx->d1->id, ctx->d1, NULL,
+                                  NULL, NULL);
+    if (ctx->d1th == NULL)
+    {
+      GNUNET_CORE_disconnect (ctx->d1core);
+      ctx->d1core = NULL;
+      ctx->timeout_task =
+          GNUNET_SCHEDULER_add_now (&notify_connect_result, ctx);
+      return;
+    }
+    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == ctx->hello_send_task);
+    ctx->hello_send_task = GNUNET_SCHEDULER_add_now (&send_hello, ctx);
+  }
+
+  ctx->timeout_task =
+      GNUNET_SCHEDULER_add_delayed (ctx->relative_timeout,
+                                    &notify_connect_result, ctx);
+
+}
+
+
+/**
+ * Establish a connection between two GNUnet daemons.  The daemons
+ * must both be running and not be stopped until either the
+ * 'cb' callback is called OR the connection request has been
+ * explicitly cancelled.
+ *
+ * @param d1 handle for the first daemon
+ * @param d2 handle for the second daemon
+ * @param timeout how long is the connection attempt
+ *        allowed to take?
+ * @param max_connect_attempts how many times should we try to reconnect
+ *        (within timeout)
+ * @param send_hello GNUNET_YES to send the HELLO, GNUNET_NO to assume
+ *                   the HELLO has already been exchanged
+ * @param cb function to call at the end
+ * @param cb_cls closure for cb
+ * @return handle to cancel the request
+ */
+struct GNUNET_TESTING_ConnectContext *
+GNUNET_TESTING_daemons_connect (struct GNUNET_TESTING_Daemon *d1,
+                                struct GNUNET_TESTING_Daemon *d2,
+                                struct GNUNET_TIME_Relative timeout,
+                                unsigned int max_connect_attempts,
+                                int send_hello,
+                                GNUNET_TESTING_NotifyConnection cb,
+                                void *cb_cls)
+{
+  struct GNUNET_TESTING_ConnectContext *ctx;
+
+  if ((d1->running == GNUNET_NO) || (d2->running == GNUNET_NO))
+  {
+    if (NULL != cb)
+      cb (cb_cls, &d1->id, &d2->id, 0, d1->cfg, d2->cfg, d1, d2,
+          _("Peers are not fully running yet, can not connect!\n"));
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peers are not up!\n");
+    return NULL;
+  }
+
+  ctx = GNUNET_malloc (sizeof (struct GNUNET_TESTING_ConnectContext));
+  ctx->d1 = d1;
+  ctx->d2 = d2;
+  ctx->timeout_hello =
+      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 500);
+  ctx->relative_timeout =
+      GNUNET_TIME_relative_divide (timeout, max_connect_attempts);
+  ctx->cb = cb;
+  ctx->cb_cls = cb_cls;
+  ctx->connect_attempts = max_connect_attempts;
+  ctx->connected = GNUNET_NO;
+  ctx->send_hello = send_hello;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Asked to connect peer %s to peer %s\n",
+              d1->shortname, d2->shortname);
+  /* Core is up! Iterate over all _known_ peers first to check if we are already connected to the peer! */
+  GNUNET_assert (NULL !=
+                 GNUNET_CORE_is_peer_connected (ctx->d1->cfg, &ctx->d2->id,
+                                                &core_initial_iteration, ctx));
+  return ctx;
+}
+
+
+/**
+ * Cancel an attempt to connect two daemons.
+ *
+ * @param cc connect context
+ */
+void
+GNUNET_TESTING_daemons_connect_cancel (struct GNUNET_TESTING_ConnectContext *cc)
+{
+  if (GNUNET_SCHEDULER_NO_TASK != cc->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (cc->timeout_task);
+    cc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (GNUNET_SCHEDULER_NO_TASK != cc->hello_send_task)
+  {
+    GNUNET_SCHEDULER_cancel (cc->hello_send_task);
+    cc->hello_send_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (NULL != cc->d1core)
+  {
+    GNUNET_CORE_disconnect (cc->d1core);
+    cc->d1core = NULL;
+  }
+  if (NULL != cc->d1th)
+  {
+    GNUNET_TRANSPORT_disconnect (cc->d1th);
+    cc->d1th = NULL;
+  }
+  GNUNET_free (cc);
+}
+
+
+/* end of testing.c */
diff --git a/src/testing_old/testing.conf b/src/testing_old/testing.conf
new file mode 100644 (file)
index 0000000..7e25f8c
--- /dev/null
@@ -0,0 +1,11 @@
+[TESTING]
+# How long before failing a connection?
+CONNECT_TIMEOUT = 30 s
+# How many connect attempts should we make?
+CONNECT_ATTEMPTS = 3
+# How many connections can happen simultaneously?
+MAX_OUTSTANDING_CONNECTIONS = 50
+
+# Should we clean up the files on peer group shutdown?
+DELETE_FILES = YES
+
diff --git a/src/testing_old/testing_group.c b/src/testing_old/testing_group.c
new file mode 100644 (file)
index 0000000..3ba7c5c
--- /dev/null
@@ -0,0 +1,7038 @@
+/*
+ This file is part of GNUnet
+ (C) 2008, 2009 Christian Grothoff (and other contributing authors)
+
+ 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 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file testing/testing_group.c
+ * @brief convenience API for writing testcases for GNUnet
+ * @author Nathan Evans
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+
+#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
+ * enough to not conflict with client-ports (typically starting around
+ * 32k).
+ */
+#define LOW_PORT 12000
+
+/**
+ * Highest port used for GNUnet testing.  Should be low enough to not
+ * conflict with the port range for "local" ports (client apps; see
+ * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
+ */
+#define HIGH_PORT 56000
+
+/* Maximum time to delay connect attempt */
+#define MAX_CONNECT_DELAY 300
+
+/**
+ * Which list of peers do we need to modify?
+ */
+enum PeerLists
+{
+  /** Modify allowed peers */
+  ALLOWED,
+
+  /** Modify connect peers */
+  CONNECT,
+
+  /** Modify blacklist peers */
+  BLACKLIST,
+
+  /** Modify workingset peers */
+  WORKING_SET
+};
+
+/**
+ * Prototype of a function called whenever two peers would be connected
+ * in a certain topology.
+ */
+typedef unsigned int (*GNUNET_TESTING_ConnectionProcessor) (struct
+                                                            GNUNET_TESTING_PeerGroup
+                                                            * pg,
+                                                            unsigned int first,
+                                                            unsigned int second,
+                                                            enum PeerLists list,
+                                                            unsigned int check);
+
+/**
+ * Context for handling churning a peer group
+ */
+struct ChurnContext
+{
+  /**
+   * The peergroup we are dealing with.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * Name of the service to churn on/off, NULL
+   * to churn entire peer.
+   */
+  char *service;
+
+  /**
+   * Callback used to notify of churning finished
+   */
+  GNUNET_TESTING_NotifyCompletion cb;
+
+  /**
+   * Closure for callback
+   */
+  void *cb_cls;
+
+  /**
+   * Number of peers that still need to be started
+   */
+  unsigned int num_to_start;
+
+  /**
+   * Number of peers that still need to be stopped
+   */
+  unsigned int num_to_stop;
+
+  /**
+   * Number of peers that failed to start
+   */
+  unsigned int num_failed_start;
+
+  /**
+   * Number of peers that failed to stop
+   */
+  unsigned int num_failed_stop;
+};
+
+struct RestartContext
+{
+  /**
+   * The group of peers being restarted
+   */
+  struct GNUNET_TESTING_PeerGroup *peer_group;
+
+  /**
+   * How many peers have been restarted thus far
+   */
+  unsigned int peers_restarted;
+
+  /**
+   * How many peers got an error when restarting
+   */
+  unsigned int peers_restart_failed;
+
+  /**
+   * The function to call once all peers have been restarted
+   */
+  GNUNET_TESTING_NotifyCompletion callback;
+
+  /**
+   * Closure for callback function
+   */
+  void *callback_cls;
+
+};
+
+struct SendHelloContext
+{
+  /**
+   * Global handle to the peer group.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * The data about this specific peer.
+   */
+  struct PeerData *peer;
+
+  /**
+   * The next HELLO that needs sent to this peer.
+   */
+  struct PeerConnection *peer_pos;
+
+  /**
+   * Are we connected to CORE yet?
+   */
+  unsigned int core_ready;
+
+  /**
+   * How many attempts should we make for failed connections?
+   */
+  unsigned int connect_attempts;
+
+  /**
+   * Task for scheduling core connect requests to be sent.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier core_connect_task;
+};
+
+struct ShutdownContext
+{
+  struct GNUNET_TESTING_PeerGroup *pg;
+  /**
+   * Total peers to wait for
+   */
+  unsigned int total_peers;
+
+  /**
+   * Number of peers successfully shut down
+   */
+  unsigned int peers_down;
+
+  /**
+   * Number of peers failed to shut down
+   */
+  unsigned int peers_failed;
+
+  /**
+   * Number of peers we have started shutting
+   * down.  If too many, wait on them.
+   */
+  unsigned int outstanding;
+
+  /**
+   * Timeout for shutdown.
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * Callback to call when all peers either
+   * shutdown or failed to shutdown
+   */
+  GNUNET_TESTING_NotifyCompletion cb;
+
+  /**
+   * Closure for cb
+   */
+  void *cb_cls;
+
+  /**
+   * Should we delete all of the files from the peers?
+   */
+  int delete_files;
+};
+
+/**
+ * Individual shutdown context for a particular peer.
+ */
+struct PeerShutdownContext
+{
+  /**
+   * Pointer to the high level shutdown context.
+   */
+  struct ShutdownContext *shutdown_ctx;
+
+  /**
+   * The daemon handle for the peer to shut down.
+   */
+  struct GNUNET_TESTING_Daemon *daemon;
+};
+
+/**
+ * Individual shutdown context for a particular peer.
+ */
+struct PeerRestartContext
+{
+  /**
+   * Pointer to the high level restart context.
+   */
+  struct ChurnRestartContext *churn_restart_ctx;
+
+  /**
+   * The daemon handle for the peer to shut down.
+   */
+  struct GNUNET_TESTING_Daemon *daemon;
+};
+
+struct ServiceStartContext
+{
+  struct GNUNET_TESTING_PeerGroup *pg;
+  unsigned int remaining;
+  GNUNET_TESTING_NotifyCompletion cb;
+  unsigned int outstanding;
+  char *service;
+  struct GNUNET_TIME_Relative timeout;
+  void *cb_cls;
+};
+
+/**
+ * Individual shutdown context for a particular peer.
+ */
+struct PeerServiceStartContext
+{
+  /**
+   * Pointer to the high level start context.
+   */
+  struct ServiceStartContext *start_ctx;
+
+  /**
+   * The daemon handle for the peer to start the service on.
+   */
+  struct GNUNET_TESTING_Daemon *daemon;
+};
+
+struct CreateTopologyContext
+{
+
+  /**
+   * Function to call with number of connections
+   */
+  GNUNET_TESTING_NotifyConnections cont;
+
+  /**
+   * Closure for connection notification
+   */
+  void *cls;
+};
+
+enum States
+{
+  /** Waiting to read number of peers */
+  NUM_PEERS,
+
+  /** Should find next peer index */
+  PEER_INDEX,
+
+  /** Should find colon */
+  COLON,
+
+  /** Should read other peer index, space, or endline */
+  OTHER_PEER_INDEX
+};
+
+#if OLD
+struct PeerConnection
+{
+  /**
+   * Doubly Linked list
+   */
+  struct PeerConnection *prev;
+
+  /*
+   * Doubly Linked list
+   */
+  struct PeerConnection *next;
+
+  /*
+   * Index of daemon in pg->peers
+   */
+  uint32_t index;
+
+};
+#endif
+
+struct InternalStartContext
+{
+  /**
+   * Pointer to peerdata
+   */
+  struct PeerData *peer;
+
+  /**
+   * Timeout for peer startup
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * Client callback for hostkey notification
+   */
+  GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback;
+
+  /**
+   * Closure for hostkey_callback
+   */
+  void *hostkey_cls;
+
+  /**
+   * Client callback for peer start notification
+   */
+  GNUNET_TESTING_NotifyDaemonRunning start_cb;
+
+  /**
+   * Closure for cb
+   */
+  void *start_cb_cls;
+
+  /**
+   * Hostname, where to start the peer
+   */
+  const char *hostname;
+
+  /**
+   * Username to use when connecting to the
+   * host via ssh.
+   */
+  const char *username;
+
+  /**
+   * Pointer to starting memory location of a hostkey
+   */
+  const char *hostkey;
+
+  /**
+   * Port to use for ssh.
+   */
+  uint16_t sshport;
+
+};
+
+struct ChurnRestartContext
+{
+  /**
+   * PeerGroup that we are working with.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * Number of restarts currently in flight.
+   */
+  unsigned int outstanding;
+
+  /**
+   * Handle to the underlying churn context.
+   */
+  struct ChurnContext *churn_ctx;
+
+  /**
+   * How long to allow the operation to take.
+   */
+  struct GNUNET_TIME_Relative timeout;
+};
+
+struct OutstandingSSH
+{
+  struct OutstandingSSH *next;
+
+  struct OutstandingSSH *prev;
+
+  /**
+   * Number of current ssh connections.
+   */
+  uint32_t outstanding;
+
+  /**
+   * The hostname of this peer.
+   */
+  const char *hostname;
+};
+
+/**
+ * Data we keep per peer.
+ */
+struct PeerData
+{
+  /**
+   * (Initial) configuration of the host.
+   * (initial because clients could change
+   *  it and we would not know about those
+   *  updates).
+   */
+  struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  /**
+   * Handle for controlling the daemon.
+   */
+  struct GNUNET_TESTING_Daemon *daemon;
+
+  /**
+   * The peergroup this peer belongs to.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+#if OLD
+  /**
+   * Linked list of allowed peer connections.
+   */
+  struct PeerConnection *allowed_peers_head;
+
+  /**
+   * Linked list of allowed peer connections.
+   */
+  struct PeerConnection *allowed_peers_tail;
+
+  /**
+   * Linked list of blacklisted peer connections.
+   */
+  struct PeerConnection *blacklisted_peers_head;
+
+  /**
+   * Linked list of blacklisted peer connections.
+   */
+  struct PeerConnection *blacklisted_peers_tail;
+
+  /**
+   * Linked list of connect peer connections.
+   */
+  struct PeerConnection *connect_peers_head;
+
+  /**
+   * Linked list of connect peer connections.
+   */
+  struct PeerConnection *connect_peers_tail;
+
+  /**
+   * Linked list of connect peer connections.
+   */
+  struct PeerConnection *connect_peers_working_set_head;
+
+  /**
+   * Linked list of connect peer connections.
+   */
+  struct PeerConnection *connect_peers_working_set_tail;
+
+#else
+  /**
+   * Hash map of allowed peer connections (F2F created topology)
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *allowed_peers;
+
+  /**
+   * Hash map of blacklisted peers
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers;
+
+  /**
+   * Hash map of peer connections
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *connect_peers;
+
+  /**
+   * Temporary hash map of peer connections
+   */
+  struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set;
+#endif
+
+  /**
+   * Temporary variable for topology creation, should be reset before
+   * creating any topology so the count is valid once finished.
+   */
+  int num_connections;
+
+  /**
+   * Context to keep track of peers being started, to
+   * stagger hostkey generation and peer startup.
+   */
+  struct InternalStartContext internal_context;
+
+  /**
+   * Task ID for the queued internal_continue_startup task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier startup_task;
+
+};
+
+/**
+ * Linked list of per-host data.
+ */
+struct HostData
+{
+  /**
+   * Name of the host.
+   */
+  char *hostname;
+
+  /**
+   * SSH username to use when connecting to this host.
+   */
+  char *username;
+
+  /**
+   * SSH port to use when connecting to this host.
+   */
+  uint16_t sshport;
+
+  /**
+   * Lowest port that we have not yet used
+   * for GNUnet.
+   */
+  uint16_t minport;
+};
+
+struct TopologyIterateContext
+{
+  /**
+   * The peergroup we are working with.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * Callback for notifying of two connected peers.
+   */
+  GNUNET_TESTING_NotifyTopology topology_cb;
+
+  /**
+   * Closure for topology_cb
+   */
+  void *cls;
+
+  /**
+   * Number of peers currently connected to.
+   */
+  unsigned int connected;
+
+  /**
+   * Number of peers we have finished iterating.
+   */
+  unsigned int completed;
+
+  /**
+   * Number of peers total.
+   */
+  unsigned int total;
+};
+
+struct StatsIterateContext
+{
+  /**
+   * The peergroup that we are dealing with.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * Continuation to call once all stats information has been retrieved.
+   */
+  GNUNET_STATISTICS_Callback cont;
+
+  /**
+   * Proc function to call on each value received.
+   */
+  GNUNET_TESTING_STATISTICS_Iterator proc;
+
+  /**
+   * Closure for topology_cb
+   */
+  void *cls;
+
+  /**
+   * Number of peers currently connected to.
+   */
+  unsigned int connected;
+
+  /**
+   * Number of peers we have finished iterating.
+   */
+  unsigned int completed;
+
+  /**
+   * Number of peers total.
+   */
+  unsigned int total;
+};
+
+struct CoreContext
+{
+  void *iter_context;
+  struct GNUNET_TESTING_Daemon *daemon;
+};
+
+struct StatsCoreContext
+{
+  void *iter_context;
+  struct GNUNET_TESTING_Daemon *daemon;
+  /**
+   * Handle to the statistics service.
+   */
+  struct GNUNET_STATISTICS_Handle *stats_handle;
+
+  /**
+   * Handle for getting statistics.
+   */
+  struct GNUNET_STATISTICS_GetHandle *stats_get_handle;
+};
+
+struct ConnectTopologyContext
+{
+  /**
+   * How many connections are left to create.
+   */
+  unsigned int remaining_connections;
+
+  /**
+   * Handle to group of peers.
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * How long to try this connection before timing out.
+   */
+  struct GNUNET_TIME_Relative connect_timeout;
+
+  /**
+   * How many times to retry connecting the two peers.
+   */
+  unsigned int connect_attempts;
+
+  /**
+   * Temp value set for each iteration.
+   */
+  //struct PeerData *first;
+
+  /**
+   * Notification that all peers are connected.
+   */
+  GNUNET_TESTING_NotifyCompletion notify_connections_done;
+
+  /**
+   * Closure for notify.
+   */
+  void *notify_cls;
+};
+
+struct ConnectContext;
+
+/**
+ * Handle to a group of GNUnet peers.
+ */
+struct GNUNET_TESTING_PeerGroup
+{
+  /**
+   * Configuration template.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+  struct ConnectContext *cc_head;
+
+  struct ConnectContext *cc_tail;
+
+  /**
+   * Function to call on each started daemon.
+   */
+  //GNUNET_TESTING_NotifyDaemonRunning cb;
+
+  /**
+   * Closure for cb.
+   */
+  //void *cb_cls;
+
+  /*
+   * Function to call on each topology connection created
+   */
+  GNUNET_TESTING_NotifyConnection notify_connection;
+
+  /*
+   * Callback for notify_connection
+   */
+  void *notify_connection_cls;
+
+  /**
+   * Array of information about hosts.
+   */
+  struct HostData *hosts;
+
+  /**
+   * Number of hosts (size of HostData)
+   */
+  unsigned int num_hosts;
+
+  /**
+   * Array of "total" peers.
+   */
+  struct PeerData *peers;
+
+  /**
+   * Number of peers in this group.
+   */
+  unsigned int total;
+
+  /**
+   * At what time should we fail the peer startup process?
+   */
+  struct GNUNET_TIME_Absolute max_timeout;
+
+  /**
+   * How many peers are being started right now?
+   */
+  unsigned int starting;
+
+  /**
+   * How many peers have already been started?
+   */
+  unsigned int started;
+
+  /**
+   * Number of possible connections to peers
+   * at a time.
+   */
+  unsigned int max_outstanding_connections;
+
+  /**
+   * Number of ssh connections to peers (max).
+   */
+  unsigned int max_concurrent_ssh;
+
+  /**
+   * Number of connects we are waiting on, allows us to rate limit
+   * connect attempts.
+   */
+  unsigned int outstanding_connects;
+
+  /**
+   * Number of HELLOs we have yet to send.
+   */
+  unsigned int remaining_hellos;
+
+  /**
+   * How many connects have already been scheduled?
+   */
+  unsigned int total_connects_scheduled;
+
+  /**
+   * Hostkeys loaded from a file.
+   */
+  char *hostkey_data;
+
+  /**
+   * Head of DLL to keep track of the number of outstanding
+   * ssh connections per peer.
+   */
+  struct OutstandingSSH *ssh_head;
+
+  /**
+   * Tail of DLL to keep track of the number of outstanding
+   * ssh connections per peer.
+   */
+  struct OutstandingSSH *ssh_tail;
+
+  /**
+   * Stop scheduling peers connecting.
+   */
+  unsigned int stop_connects;
+
+  /**
+   * Connection context for peer group.
+   */
+  struct ConnectTopologyContext ct_ctx;
+};
+
+struct UpdateContext
+{
+  /**
+   * The altered configuration.
+   */
+  struct GNUNET_CONFIGURATION_Handle *ret;
+
+  /**
+   * The original configuration to alter.
+   */
+  const struct GNUNET_CONFIGURATION_Handle *orig;
+
+  /**
+   * The hostname that this peer will run on.
+   */
+  const char *hostname;
+
+  /**
+   * The next possible port to assign.
+   */
+  unsigned int nport;
+
+  /**
+   * Unique number for unix domain sockets.
+   */
+  unsigned int upnum;
+
+  /**
+   * Unique number for this peer/host to offset
+   * things that are grouped by host.
+   */
+  unsigned int fdnum;
+};
+
+struct ConnectContext
+{
+
+  struct ConnectContext *next;
+
+  struct ConnectContext *prev;
+
+  /**
+   * Index of peer to connect second to.
+   */
+  uint32_t first_index;
+
+  /**
+   * Index of peer to connect first to.
+   */
+  uint32_t second_index;
+
+  /**
+   * Task associated with the attempt to connect.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier task;
+
+  /**
+   * Context in 'testing.c', to cancel connection attempt.
+   */
+  struct GNUNET_TESTING_ConnectContext *cc;
+
+  /**
+   * Higher level topology connection context.
+   */
+  struct ConnectTopologyContext *ct_ctx;
+
+  /**
+   * Whether this connection has been accounted for in the schedule_connect call.
+   */
+  int counted;
+};
+
+struct UnblacklistContext
+{
+  /**
+   * The peergroup
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * uid of the first peer
+   */
+  uint32_t first_uid;
+};
+
+struct RandomContext
+{
+  /**
+   * The peergroup
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * uid of the first peer
+   */
+  uint32_t first_uid;
+
+  /**
+   * Peer data for first peer.
+   */
+  struct PeerData *first;
+
+  /**
+   * Random percentage to use
+   */
+  double percentage;
+};
+
+struct MinimumContext
+{
+  /**
+   * The peergroup
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * uid of the first peer
+   */
+  uint32_t first_uid;
+
+  /**
+   * Peer data for first peer.
+   */
+  struct PeerData *first;
+
+  /**
+   * Number of conns per peer
+   */
+  unsigned int num_to_add;
+
+  /**
+   * Permuted array of all possible connections.  Only add the Nth
+   * peer if it's in the Nth position.
+   */
+  unsigned int *pg_array;
+
+  /**
+   * What number is the current element we are iterating over?
+   */
+  unsigned int current;
+};
+
+struct DFSContext
+{
+  /**
+   * The peergroup
+   */
+  struct GNUNET_TESTING_PeerGroup *pg;
+
+  /**
+   * uid of the first peer
+   */
+  uint32_t first_uid;
+
+  /**
+   * uid of the second peer
+   */
+  uint32_t second_uid;
+
+  /**
+   * Peer data for first peer.
+   */
+  struct PeerData *first;
+
+  /**
+   * Which peer has been chosen as the one to add?
+   */
+  unsigned int chosen;
+
+  /**
+   * What number is the current element we are iterating over?
+   */
+  unsigned int current;
+};
+
+/**
+ * Simple struct to keep track of progress, and print a
+ * nice little percentage meter for long running tasks.
+ */
+struct ProgressMeter
+{
+  unsigned int total;
+
+  unsigned int modnum;
+
+  unsigned int dotnum;
+
+  unsigned int completed;
+
+  int print;
+
+  char *startup_string;
+};
+
+#if !OLD
+/**
+ * Convert unique ID to hash code.
+ *
+ * @param uid unique ID to convert
+ * @param hash set to uid (extended with zeros)
+ */
+static void
+hash_from_uid (uint32_t uid, GNUNET_HashCode * hash)
+{
+  memset (hash, 0, sizeof (GNUNET_HashCode));
+  *((uint32_t *) hash) = uid;
+}
+
+/**
+ * Convert hash code to unique ID.
+ *
+ * @param uid unique ID to convert
+ * @param hash set to uid (extended with zeros)
+ */
+static void
+uid_from_hash (const GNUNET_HashCode * hash, uint32_t * uid)
+{
+  memcpy (uid, hash, sizeof (uint32_t));
+}
+#endif
+
+#if USE_SEND_HELLOS
+static struct GNUNET_CORE_MessageHandler no_handlers[] = {
+  {NULL, 0, 0}
+};
+#endif
+
+/**
+ * Create a meter to keep track of the progress of some task.
+ *
+ * @param total the total number of items to complete
+ * @param start_string a string to prefix the meter with (if printing)
+ * @param print GNUNET_YES to print the meter, GNUNET_NO to count
+ *              internally only
+ *
+ * @return the progress meter
+ */
+static struct ProgressMeter *
+create_meter (unsigned int total, char *start_string, int print)
+{
+  struct ProgressMeter *ret;
+
+  ret = GNUNET_malloc (sizeof (struct ProgressMeter));
+  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);
+  else
+    ret->startup_string = GNUNET_strdup ("");
+
+  return ret;
+}
+
+/**
+ * Update progress meter (increment by one).
+ *
+ * @param meter the meter to update and print info for
+ *
+ * @return GNUNET_YES if called the total requested,
+ *         GNUNET_NO if more items expected
+ */
+static int
+update_meter (struct ProgressMeter *meter)
+{
+  if (meter->print == GNUNET_YES)
+  {
+    if (meter->completed % meter->modnum == 0)
+    {
+      if (meter->completed == 0)
+      {
+        FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string);
+      }
+      else
+        FPRINTF (stdout, "%d%%",
+                 (int) (((float) meter->completed / meter->total) * 100));
+    }
+    else if (meter->completed % meter->dotnum == 0)
+      FPRINTF (stdout, "%s",  ".");
+
+    if (meter->completed + 1 == meter->total)
+      FPRINTF (stdout, "%d%%]\n", 100);
+    fflush (stdout);
+  }
+  meter->completed++;
+
+  if (meter->completed == meter->total)
+    return GNUNET_YES;
+  if (meter->completed > meter->total)
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Progress meter overflow!!\n");
+  return GNUNET_NO;
+}
+
+/**
+ * Reset progress meter.
+ *
+ * @param meter the meter to reset
+ *
+ * @return GNUNET_YES if meter reset,
+ *         GNUNET_SYSERR on error
+ */
+static int
+reset_meter (struct ProgressMeter *meter)
+{
+  if (meter == NULL)
+    return GNUNET_SYSERR;
+
+  meter->completed = 0;
+  return GNUNET_YES;
+}
+
+/**
+ * Release resources for meter
+ *
+ * @param meter the meter to free
+ */
+static void
+free_meter (struct ProgressMeter *meter)
+{
+  GNUNET_free_non_null (meter->startup_string);
+  GNUNET_free (meter);
+}
+
+/**
+ * Get a topology from a string input.
+ *
+ * @param topology where to write the retrieved topology
+ * @param topology_string The string to attempt to
+ *        get a configuration value from
+ * @return GNUNET_YES if topology string matched a
+ *         known topology, GNUNET_NO if not
+ */
+int
+GNUNET_TESTING_topology_get (enum GNUNET_TESTING_Topology *topology,
+                             const char *topology_string)
+{
+  /**
+   * Strings representing topologies in enum
+   */
+  static const char *topology_strings[] = {
+    /**
+     * A clique (everyone connected to everyone else).
+     */
+    "CLIQUE",
+
+    /**
+     * Small-world network (2d torus plus random links).
+     */
+    "SMALL_WORLD",
+
+    /**
+     * Small-world network (ring plus random links).
+     */
+    "SMALL_WORLD_RING",
+
+    /**
+     * Ring topology.
+     */
+    "RING",
+
+    /**
+     * 2-d torus.
+     */
+    "2D_TORUS",
+
+    /**
+     * Random graph.
+     */
+    "ERDOS_RENYI",
+
+    /**
+     * Certain percentage of peers are unable to communicate directly
+     * replicating NAT conditions
+     */
+    "INTERNAT",
+
+    /**
+     * Scale free topology.
+     */
+    "SCALE_FREE",
+
+    /**
+     * Straight line topology.
+     */
+    "LINE",
+
+    /**
+     * All peers are disconnected.
+     */
+    "NONE",
+
+    /**
+     * Read the topology from a file.
+     */
+    "FROM_FILE",
+
+    NULL
+  };
+
+  int curr = 0;
+
+  if (topology_string == NULL)
+    return GNUNET_NO;
+  while (topology_strings[curr] != NULL)
+  {
+    if (strcasecmp (topology_strings[curr], topology_string) == 0)
+    {
+      *topology = curr;
+      return GNUNET_YES;
+    }
+    curr++;
+  }
+  *topology = GNUNET_TESTING_TOPOLOGY_NONE;
+  return GNUNET_NO;
+}
+
+/**
+ * Get connect topology option from string input.
+ *
+ * @param topology_option where to write the retrieved topology
+ * @param topology_string The string to attempt to
+ *        get a configuration value from
+ * @return GNUNET_YES if string matched a known
+ *         topology option, GNUNET_NO if not
+ */
+int
+GNUNET_TESTING_topology_option_get (enum GNUNET_TESTING_TopologyOption
+                                    *topology_option,
+                                    const char *topology_string)
+{
+  /**
+   * Options for connecting a topology as strings.
+   */
+  static const char *topology_option_strings[] = {
+    /**
+     * Try to connect all peers specified in the topology.
+     */
+    "CONNECT_ALL",
+
+    /**
+     * Choose a random subset of connections to create.
+     */
+    "CONNECT_RANDOM_SUBSET",
+
+    /**
+     * Create at least X connections for each peer.
+     */
+    "CONNECT_MINIMUM",
+
+    /**
+     * Using a depth first search, create one connection
+     * per peer.  If any are missed (graph disconnected)
+     * start over at those peers until all have at least one
+     * connection.
+     */
+    "CONNECT_DFS",
+
+    /**
+     * Find the N closest peers to each allowed peer in the
+     * topology and make sure a connection to those peers
+     * exists in the connect topology.
+     */
+    "CONNECT_CLOSEST",
+
+    /**
+     * No options specified.
+     */
+    "CONNECT_NONE",
+
+    NULL
+  };
+  int curr = 0;
+
+  if (topology_string == NULL)
+    return GNUNET_NO;
+  while (NULL != topology_option_strings[curr])
+  {
+    if (strcasecmp (topology_option_strings[curr], topology_string) == 0)
+    {
+      *topology_option = curr;
+      return GNUNET_YES;
+    }
+    curr++;
+  }
+  *topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_NONE;
+  return GNUNET_NO;
+}
+
+/**
+ * Function to iterate over options.  Copies
+ * the options to the target configuration,
+ * updating PORT values as needed.
+ *
+ * @param cls closure
+ * @param section name of the section
+ * @param option name of the option
+ * @param value value of the option
+ */
+static void
+update_config (void *cls, const char *section, const char *option,
+               const char *value)
+{
+  struct UpdateContext *ctx = cls;
+  unsigned int ival;
+  char cval[12];
+  char uval[128];
+  char *single_variable;
+  char *per_host_variable;
+  unsigned long long num_per_host;
+
+  GNUNET_asprintf (&single_variable, "single_%s_per_host", section);
+  GNUNET_asprintf (&per_host_variable, "num_%s_per_host", section);
+
+  if ((0 == strcmp (option, "PORT")) && (1 == SSCANF (value, "%u", &ival)))
+  {
+    if ((ival != 0) &&
+        (GNUNET_YES !=
+         GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing_old",
+                                               single_variable)))
+    {
+      GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
+      value = cval;
+    }
+    else if ((ival != 0) &&
+             (GNUNET_YES ==
+              GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing_old",
+                                                    single_variable)) &&
+             GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing_old",
+                                                    per_host_variable,
+                                                    &num_per_host))
+    {
+      GNUNET_snprintf (cval, sizeof (cval), "%u",
+                       ival + ctx->fdnum % num_per_host);
+      value = cval;
+    }
+
+    /* FIXME: REMOVE FOREVER HACK HACK HACK */
+    if (0 == strcasecmp (section, "transport-tcp"))
+      GNUNET_CONFIGURATION_set_value_string (ctx->ret, section,
+                                             "ADVERTISED_PORT", value);
+  }
+
+  if (0 == strcmp (option, "UNIXPATH"))
+  {
+    if (GNUNET_YES !=
+        GNUNET_CONFIGURATION_get_value_yesno (ctx->orig, "testing_old",
+                                              single_variable))
+    {
+      GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section,
+                       ctx->upnum++);
+      value = uval;
+    }
+    else if ((GNUNET_YES ==
+              GNUNET_CONFIGURATION_get_value_number (ctx->orig, "testing_old",
+                                                     per_host_variable,
+                                                     &num_per_host)) &&
+             (num_per_host > 0))
+
+    {
+      GNUNET_snprintf (uval, sizeof (uval), "/tmp/test-service-%s-%u", section,
+                       ctx->fdnum % num_per_host);
+      value = uval;
+    }
+  }
+
+  if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL))
+  {
+    value = ctx->hostname;
+  }
+  GNUNET_free (single_variable);
+  GNUNET_free (per_host_variable);
+  GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value);
+}
+
+/**
+ * Create a new configuration using the given configuration
+ * as a template; however, each PORT in the existing cfg
+ * must be renumbered by incrementing "*port".  If we run
+ * out of "*port" numbers, return NULL.
+ *
+ * @param cfg template configuration
+ * @param off the current peer offset
+ * @param port port numbers to use, update to reflect
+ *             port numbers that were used
+ * @param upnum number to make unix domain socket names unique
+ * @param hostname hostname of the controlling host, to allow control connections from
+ * @param fdnum number used to offset the unix domain socket for grouped processes
+ *              (such as statistics or peerinfo, which can be shared among others)
+ *
+ * @return new configuration, NULL on error
+ */
+struct GNUNET_CONFIGURATION_Handle *
+GNUNET_TESTING_create_cfg (const struct GNUNET_CONFIGURATION_Handle *cfg, uint32_t off,
+             uint16_t * port, uint32_t * upnum, const char *hostname,
+             uint32_t * fdnum)
+{
+  struct UpdateContext uc;
+  uint16_t orig;
+  char *control_host;
+  char *allowed_hosts;
+  unsigned long long skew_variance;
+  unsigned long long skew_offset;
+  long long actual_offset;
+
+  orig = *port;
+  uc.nport = *port;
+  uc.upnum = *upnum;
+  uc.fdnum = *fdnum;
+  uc.ret = GNUNET_CONFIGURATION_create ();
+  uc.hostname = hostname;
+  uc.orig = cfg;
+
+  GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
+  if (uc.nport >= HIGH_PORT)
+  {
+    *port = orig;
+    GNUNET_CONFIGURATION_destroy (uc.ret);
+    return NULL;
+  }
+
+  if ((GNUNET_OK ==
+       GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "skew_variance",
+                                              &skew_variance)) &&
+      (skew_variance > 0))
+  {
+    skew_offset =
+        GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  skew_variance + 1);
+    actual_offset =
+        skew_offset - GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                                skew_variance + 1);
+    /* Min is -skew_variance, Max is skew_variance */
+    skew_offset = skew_variance + actual_offset;        /* Normal distribution around 0 */
+    GNUNET_CONFIGURATION_set_value_number (uc.ret, "testing_old", "skew_offset",
+                                           skew_offset);
+  }
+
+  if (GNUNET_CONFIGURATION_get_value_string
+      (cfg, "testing_old", "control_host", &control_host) == GNUNET_OK)
+  {
+    if (hostname != NULL)
+      GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1; %s;", control_host,
+                       hostname);
+    else
+      GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", control_host);
+
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "ACCEPT_FROM",
+                                           allowed_hosts);
+
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "ACCEPT_FROM",
+                                           allowed_hosts);
+
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "ACCEPT_FROM",
+                                           allowed_hosts);
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "ACCEPT_FROM",
+                                           allowed_hosts);
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "ACCEPT_FROM",
+                                           allowed_hosts);
+
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "core", "UNIXPATH", "");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport", "UNIXPATH", "");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "dht", "UNIXPATH", "");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "statistics", "UNIXPATH",
+                                           "");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nse", "UNIXPATH", "");
+
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat",
+                                           "USE_LOCALADDR", "YES");
+    GNUNET_free_non_null (control_host);
+    GNUNET_free (allowed_hosts);
+  }
+
+  /* arm needs to know to allow connections from the host on which it is running,
+   * otherwise gnunet-arm is unable to connect to it in some instances */
+  if (hostname != NULL)
+  {
+    GNUNET_asprintf (&allowed_hosts, "%s; 127.0.0.1;", hostname);
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO", hostname);
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS",
+                                           hostname);
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS",
+                                           hostname);
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "disablev6", "BINDTO",
+                                           "YES");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-tcp",
+                                           "USE_LOCALADDR", "YES");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "transport-udp",
+                                           "USE_LOCALADDR", "YES");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "arm", "ACCEPT_FROM",
+                                           allowed_hosts);
+    GNUNET_free (allowed_hosts);
+  }
+  else
+  {
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat",
+                                           "USE_LOCALADDR", "YES");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "BINDTO",
+                                           "127.0.0.1");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "INTERNAL_ADDRESS",
+                                           "127.0.0.1");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "EXTERNAL_ADDRESS",
+                                           "127.0.0.1");
+    GNUNET_CONFIGURATION_set_value_string (uc.ret, "nat", "disablev6",
+                                           "YES");
+  }
+
+  *port = (uint16_t) uc.nport;
+  *upnum = uc.upnum;
+  uc.fdnum++;
+  *fdnum = uc.fdnum;
+  return uc.ret;
+}
+
+/*
+ * Remove entries from the peer connection list
+ *
+ * @param pg the peer group we are working with
+ * @param first index of the first peer
+ * @param second index of the second peer
+ * @param list the peer list to use
+ * @param check UNUSED
+ *
+ * @return the number of connections added (can be 0, 1 or 2)
+ *
+ */
+static unsigned int
+remove_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
+                    unsigned int second, enum PeerLists list,
+                    unsigned int check)
+{
+  int removed;
+
+#if OLD
+  struct PeerConnection **first_list;
+  struct PeerConnection **second_list;
+  struct PeerConnection *first_iter;
+  struct PeerConnection *second_iter;
+  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
+
+  removed = 0;
+#if OLD
+  switch (list)
+  {
+  case ALLOWED:
+    first_list = &pg->peers[first].allowed_peers_head;
+    second_list = &pg->peers[second].allowed_peers_head;
+    first_tail = &pg->peers[first].allowed_peers_tail;
+    second_tail = &pg->peers[second].allowed_peers_tail;
+    break;
+  case CONNECT:
+    first_list = &pg->peers[first].connect_peers_head;
+    second_list = &pg->peers[second].connect_peers_head;
+    first_tail = &pg->peers[first].connect_peers_tail;
+    second_tail = &pg->peers[second].connect_peers_tail;
+    break;
+  case BLACKLIST:
+    first_list = &pg->peers[first].blacklisted_peers_head;
+    second_list = &pg->peers[second].blacklisted_peers_head;
+    first_tail = &pg->peers[first].blacklisted_peers_tail;
+    second_tail = &pg->peers[second].blacklisted_peers_tail;
+    break;
+  case WORKING_SET:
+    first_list = &pg->peers[first].connect_peers_working_set_head;
+    second_list = &pg->peers[second].connect_peers_working_set_head;
+    first_tail = &pg->peers[first].connect_peers_working_set_tail;
+    second_tail = &pg->peers[second].connect_peers_working_set_tail;
+    break;
+  default:
+    GNUNET_break (0);
+    return 0;
+  }
+
+  first_iter = *first_list;
+  while (first_iter != NULL)
+  {
+    if (first_iter->index == second)
+    {
+      GNUNET_CONTAINER_DLL_remove (*first_list, *first_tail, first_iter);
+      GNUNET_free (first_iter);
+      removed++;
+      break;
+    }
+    first_iter = first_iter->next;
+  }
+
+  second_iter = *second_list;
+  while (second_iter != NULL)
+  {
+    if (second_iter->index == first)
+    {
+      GNUNET_CONTAINER_DLL_remove (*second_list, *second_tail, second_iter);
+      GNUNET_free (second_iter);
+      removed++;
+      break;
+    }
+    second_iter = second_iter->next;
+  }
+#else
+  if (GNUNET_YES ==
+      GNUNET_CONTAINER_multihashmap_contains (pg->
+                                              peers[first].blacklisted_peers,
+                                              &hash_second))
+  {
+    GNUNET_CONTAINER_multihashmap_remove_all (pg->
+                                              peers[first].blacklisted_peers,
+                                              &hash_second);
+  }
+
+  if (GNUNET_YES ==
+      GNUNET_CONTAINER_multihashmap_contains (pg->
+                                              peers[second].blacklisted_peers,
+                                              &hash_first))
+  {
+    GNUNET_CONTAINER_multihashmap_remove_all (pg->
+                                              peers[second].blacklisted_peers,
+                                              &hash_first);
+  }
+#endif
+
+  return removed;
+}
+
+/**
+ * Add entries to the some list
+ *
+ * @param pg the peer group we are working with
+ * @param first index of the first peer
+ * @param second index of the second peer
+ * @param list the list type that we should modify
+ * @param check GNUNET_YES to check lists before adding
+ *              GNUNET_NO to force add
+ *
+ * @return the number of connections added (can be 0, 1 or 2)
+ *
+ */
+static unsigned int
+add_connections (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first,
+                 unsigned int second, enum PeerLists list, unsigned int check)
+{
+  int added;
+  int add_first;
+  int add_second;
+
+  struct PeerConnection **first_list;
+  struct PeerConnection **second_list;
+  struct PeerConnection *first_iter;
+  struct PeerConnection *second_iter;
+  struct PeerConnection *new_first;
+  struct PeerConnection *new_second;
+  struct PeerConnection **first_tail;
+  struct PeerConnection **second_tail;
+
+  switch (list)
+  {
+  case ALLOWED:
+    first_list = &pg->peers[first].allowed_peers_head;
+    second_list = &pg->peers[second].allowed_peers_head;
+    first_tail = &pg->peers[first].allowed_peers_tail;
+    second_tail = &pg->peers[second].allowed_peers_tail;
+    break;
+  case CONNECT:
+    first_list = &pg->peers[first].connect_peers_head;
+    second_list = &pg->peers[second].connect_peers_head;
+    first_tail = &pg->peers[first].connect_peers_tail;
+    second_tail = &pg->peers[second].connect_peers_tail;
+    break;
+  case BLACKLIST:
+    first_list = &pg->peers[first].blacklisted_peers_head;
+    second_list = &pg->peers[second].blacklisted_peers_head;
+    first_tail = &pg->peers[first].blacklisted_peers_tail;
+    second_tail = &pg->peers[second].blacklisted_peers_tail;
+    break;
+  case WORKING_SET:
+    first_list = &pg->peers[first].connect_peers_working_set_head;
+    second_list = &pg->peers[second].connect_peers_working_set_head;
+    first_tail = &pg->peers[first].connect_peers_working_set_tail;
+    second_tail = &pg->peers[second].connect_peers_working_set_tail;
+    break;
+  default:
+    GNUNET_break (0);
+    return 0;
+  }
+
+  add_first = GNUNET_YES;
+  add_second = GNUNET_YES;
+
+  if (check == GNUNET_YES)
+  {
+    first_iter = *first_list;
+    while (first_iter != NULL)
+    {
+      if (first_iter->index == second)
+      {
+        add_first = GNUNET_NO;
+        break;
+      }
+      first_iter = first_iter->next;
+    }
+
+    second_iter = *second_list;
+    while (second_iter != NULL)
+    {
+      if (second_iter->index == first)
+      {
+        add_second = GNUNET_NO;
+        break;
+      }
+      second_iter = second_iter->next;
+    }
+  }
+
+  added = 0;
+  if (add_first)
+  {
+    new_first = GNUNET_malloc (sizeof (struct PeerConnection));
+    new_first->index = second;
+    GNUNET_CONTAINER_DLL_insert (*first_list, *first_tail, new_first);
+    pg->peers[first].num_connections++;
+    added++;
+  }
+
+  if (add_second)
+  {
+    new_second = GNUNET_malloc (sizeof (struct PeerConnection));
+    new_second->index = first;
+    GNUNET_CONTAINER_DLL_insert (*second_list, *second_tail, new_second);
+    pg->peers[second].num_connections++;
+    added++;
+  }
+
+  return added;
+}
+
+/**
+ * Scale free network construction as described in:
+ *
+ * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
+ *
+ * Start with a network of "one" peer, then progressively add
+ * peers up to the total number.  At each step, iterate over
+ * all possible peers and connect new peer based on number of
+ * existing connections of the target peer.
+ *
+ * @param pg the peer group we are dealing with
+ * @param proc the connection processor to use
+ * @param list the peer list to use
+ *
+ * @return the number of connections created
+ */
+static unsigned int
+create_scale_free (struct GNUNET_TESTING_PeerGroup *pg,
+                   GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+{
+
+  unsigned int total_connections;
+  unsigned int outer_count;
+  unsigned int i;
+  unsigned int previous_total_connections;
+  double random;
+  double probability;
+
+  GNUNET_assert (pg->total > 1);
+
+  /* Add a connection between the first two nodes */
+  total_connections = proc (pg, 0, 1, list, GNUNET_YES);
+
+  for (outer_count = 1; outer_count < pg->total; outer_count++)
+  {
+    previous_total_connections = total_connections;
+    for (i = 0; i < outer_count; i++)
+    {
+      probability =
+          pg->peers[i].num_connections / (double) previous_total_connections;
+      random =
+          ((double)
+           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                     UINT64_MAX)) / ((double) UINT64_MAX);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Considering connecting peer %d to peer %d\n", outer_count,
+                  i);
+      if (random < probability)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
+                    outer_count, i);
+        total_connections += proc (pg, outer_count, i, list, GNUNET_YES);
+      }
+    }
+  }
+
+  return total_connections;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.  Creates a small world topology
+ * according to the rewired ring construction.  The basic
+ * behavior is that a ring topology is created, but with some
+ * probability instead of connecting a peer to the next
+ * neighbor in the ring a connection will be created to a peer
+ * selected uniformly at random.   We use the TESTING
+ * PERCENTAGE option to specify what number of
+ * connections each peer should have.  Default is 2,
+ * which makes the ring, any given number is multiplied by
+ * the log of the network size; i.e. a PERCENTAGE of 2 makes
+ * each peer have on average 2logn connections.  The additional
+ * connections are made at increasing distance around the ring
+ * from the original peer, or to random peers based on the re-
+ * wiring probability. The TESTING
+ * PROBABILITY option is used as the probability that a given
+ * connection is rewired.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_small_world_ring (struct GNUNET_TESTING_PeerGroup *pg,
+                         GNUNET_TESTING_ConnectionProcessor proc,
+                         enum PeerLists list)
+{
+  unsigned int i, j;
+  int nodeToConnect;
+  unsigned int natLog;
+  unsigned int randomPeer;
+  double random, logNModifier, probability;
+  unsigned int smallWorldConnections;
+  int connsPerPeer;
+  char *p_string;
+  int max;
+  int min;
+  unsigned int useAnd;
+  int connect_attempts;
+
+  logNModifier = 0.5;           /* FIXME: default value? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &logNModifier) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "LOGNMODIFIER", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+  probability = 0.5;            /* FIXME: default percentage? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PROBABILITY",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &probability) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "PERCENTAGE", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+  natLog = log (pg->total);
+  connsPerPeer = ceil (natLog * logNModifier);
+
+  if (connsPerPeer % 2 == 1)
+    connsPerPeer += 1;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Target is %d connections per peer.",
+              connsPerPeer);
+
+  smallWorldConnections = 0;
+  connect_attempts = 0;
+  for (i = 0; i < pg->total; i++)
+  {
+    useAnd = 0;
+    max = i + connsPerPeer / 2;
+    min = i - connsPerPeer / 2;
+
+    if (max > pg->total - 1)
+    {
+      max = max - pg->total;
+      useAnd = 1;
+    }
+
+    if (min < 0)
+    {
+      min = pg->total - 1 + min;
+      useAnd = 1;
+    }
+
+    for (j = 0; j < connsPerPeer / 2; j++)
+    {
+      random =
+          ((double)
+           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                     UINT64_MAX) / ((double) UINT64_MAX));
+      if (random < probability)
+      {
+        /* Connect to uniformly selected random peer */
+        randomPeer =
+            GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
+        while ((((randomPeer < max) && (randomPeer > min)) && (useAnd == 0)) ||
+               (((randomPeer > min) || (randomPeer < max)) && (useAnd == 1)))
+        {
+          randomPeer =
+              GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
+        }
+        smallWorldConnections += proc (pg, i, randomPeer, list, GNUNET_YES);
+      }
+      else
+      {
+        nodeToConnect = i + j + 1;
+        if (nodeToConnect > pg->total - 1)
+        {
+          nodeToConnect = nodeToConnect - pg->total;
+        }
+        connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
+      }
+    }
+
+  }
+
+  connect_attempts += smallWorldConnections;
+
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg,
+                       GNUNET_TESTING_ConnectionProcessor proc,
+                       enum PeerLists list)
+{
+  unsigned int outer_count, inner_count;
+  unsigned int cutoff;
+  int connect_attempts;
+  double nat_percentage;
+  char *p_string;
+
+  nat_percentage = 0.6;         /* FIXME: default percentage? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &nat_percentage) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "PERCENTAGE", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+
+  cutoff = (unsigned int) (nat_percentage * pg->total);
+  connect_attempts = 0;
+  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
+  {
+    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
+    {
+      if ((outer_count > cutoff) || (inner_count > cutoff))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
+                    outer_count, inner_count);
+        connect_attempts +=
+            proc (pg, outer_count, inner_count, list, GNUNET_YES);
+      }
+    }
+  }
+  return connect_attempts;
+}
+
+#if TOPOLOGY_HACK
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_nated_internet_copy (struct GNUNET_TESTING_PeerGroup *pg,
+                            GNUNET_TESTING_ConnectionProcessor proc,
+                            enum PeerLists list)
+{
+  unsigned int outer_count, inner_count;
+  unsigned int cutoff;
+  int connect_attempts;
+  double nat_percentage;
+  char *p_string;
+  unsigned int count;
+  struct ProgressMeter *conn_meter;
+
+  nat_percentage = 0.6;         /* FIXME: default percentage? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &nat_percentage) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "PERCENTAGE", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+
+  cutoff = (unsigned int) (nat_percentage * pg->total);
+  count = 0;
+  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
+  {
+    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
+    {
+      if ((outer_count > cutoff) || (inner_count > cutoff))
+      {
+        count++;
+      }
+    }
+  }
+  conn_meter = create_meter (count, "NAT COPY", GNUNET_YES);
+  connect_attempts = 0;
+  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
+  {
+    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
+    {
+      if ((outer_count > cutoff) || (inner_count > cutoff))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
+                    outer_count, inner_count);
+        connect_attempts +=
+            proc (pg, outer_count, inner_count, list, GNUNET_YES);
+        add_connections (pg, outer_count, inner_count, ALLOWED, GNUNET_NO);
+        update_meter (conn_meter);
+      }
+    }
+  }
+  free_meter (conn_meter);
+
+  return connect_attempts;
+}
+#endif
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_small_world (struct GNUNET_TESTING_PeerGroup *pg,
+                    GNUNET_TESTING_ConnectionProcessor proc,
+                    enum PeerLists list)
+{
+  unsigned int i, j, k;
+  unsigned int square;
+  unsigned int rows;
+  unsigned int cols;
+  unsigned int toggle = 1;
+  unsigned int nodeToConnect;
+  unsigned int natLog;
+  unsigned int node1Row;
+  unsigned int node1Col;
+  unsigned int node2Row;
+  unsigned int node2Col;
+  unsigned int distance;
+  double probability, random, percentage;
+  unsigned int smallWorldConnections;
+  unsigned int small_world_it;
+  char *p_string;
+  int connect_attempts;
+
+  square = floor (sqrt (pg->total));
+  rows = square;
+  cols = square;
+
+  percentage = 0.5;             /* FIXME: default percentage? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PERCENTAGE",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &percentage) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "PERCENTAGE", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+  if (percentage < 0.0)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _
+                ("Invalid value `%s' for option `%s' in section `%s': got %f, needed value greater than 0\n"),
+                "PERCENTAGE", "TESTING_OLD", percentage);
+    percentage = 0.5;
+  }
+  probability = 0.5;            /* FIXME: default percentage? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PROBABILITY",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &probability) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "PROBABILITY", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+  if (square * square != pg->total)
+  {
+    while (rows * cols < pg->total)
+    {
+      if (toggle % 2 == 0)
+        rows++;
+      else
+        cols++;
+
+      toggle++;
+    }
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting nodes in 2d torus topology: %u rows %u columns\n",
+              rows, cols);
+  connect_attempts = 0;
+  /* Rows and columns are all sorted out, now iterate over all nodes and connect each
+   * to the node to its right and above.  Once this is over, we'll have our torus!
+   * Special case for the last node (if the rows and columns are not equal), connect
+   * to the first in the row to maintain topology.
+   */
+  for (i = 0; i < pg->total; i++)
+  {
+    /* First connect to the node to the right */
+    if (((i + 1) % cols != 0) && (i + 1 != pg->total))
+      nodeToConnect = i + 1;
+    else if (i + 1 == pg->total)
+      nodeToConnect = rows * cols - cols;
+    else
+      nodeToConnect = i - cols + 1;
+
+    connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
+
+    if (i < cols)
+    {
+      nodeToConnect = (rows * cols) - cols + i;
+      if (nodeToConnect >= pg->total)
+        nodeToConnect -= cols;
+    }
+    else
+      nodeToConnect = i - cols;
+
+    if (nodeToConnect < pg->total)
+      connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
+  }
+  natLog = log (pg->total);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "natural log of %d is %d, will run %d iterations\n", pg->total,
+              natLog, (int) (natLog * percentage));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Total connections added thus far: %u!\n", connect_attempts);
+  smallWorldConnections = 0;
+  small_world_it = (unsigned int) (natLog * percentage);
+  if (small_world_it < 1)
+    small_world_it = 1;
+  GNUNET_assert (small_world_it > 0 && small_world_it < (unsigned int) -1);
+  for (i = 0; i < small_world_it; i++)
+  {
+    for (j = 0; j < pg->total; j++)
+    {
+      /* Determine the row and column of node at position j on the 2d torus */
+      node1Row = j / cols;
+      node1Col = j - (node1Row * cols);
+      for (k = 0; k < pg->total; k++)
+      {
+        /* Determine the row and column of node at position k on the 2d torus */
+        node2Row = k / cols;
+        node2Col = k - (node2Row * cols);
+        /* Simple Cartesian distance */
+        distance = abs (node1Row - node2Row) + abs (node1Col - node2Col);
+        if (distance > 1)
+        {
+          /* Calculate probability as 1 over the square of the distance */
+          probability = 1.0 / (distance * distance);
+          /* Choose a random value between 0 and 1 */
+          random =
+              ((double)
+               GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                         UINT64_MAX)) / ((double) UINT64_MAX);
+          /* If random < probability, then connect the two nodes */
+          if (random < probability)
+            smallWorldConnections += proc (pg, j, k, list, GNUNET_YES);
+
+        }
+      }
+    }
+  }
+  connect_attempts += smallWorldConnections;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Total connections added for small world: %d!\n",
+              smallWorldConnections);
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg,
+                    GNUNET_TESTING_ConnectionProcessor proc,
+                    enum PeerLists list)
+{
+  double temp_rand;
+  unsigned int outer_count;
+  unsigned int inner_count;
+  int connect_attempts;
+  double probability;
+  char *p_string;
+
+  probability = 0.5;            /* FIXME: default percentage? */
+  if (GNUNET_OK ==
+      GNUNET_CONFIGURATION_get_value_string (pg->cfg, "TESTING_OLD", "PROBABILITY",
+                                             &p_string))
+  {
+    if (SSCANF (p_string, "%lf", &probability) != 1)
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  p_string, "PROBABILITY", "TESTING_OLD");
+    GNUNET_free (p_string);
+  }
+  connect_attempts = 0;
+  for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
+  {
+    for (inner_count = outer_count + 1; inner_count < pg->total; inner_count++)
+    {
+      temp_rand =
+          ((double)
+           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                     UINT64_MAX)) / ((double) UINT64_MAX);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "rand is %f probability is %f\n",
+                  temp_rand, probability);
+      if (temp_rand < probability)
+      {
+        connect_attempts +=
+            proc (pg, outer_count, inner_count, list, GNUNET_YES);
+      }
+    }
+  }
+
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.  This particular function creates
+ * the connections for a 2d-torus, plus additional "closest"
+ * connections per peer.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg,
+                 GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+{
+  unsigned int i;
+  unsigned int square;
+  unsigned int rows;
+  unsigned int cols;
+  unsigned int toggle = 1;
+  unsigned int nodeToConnect;
+  int connect_attempts;
+
+  connect_attempts = 0;
+
+  square = floor (sqrt (pg->total));
+  rows = square;
+  cols = square;
+
+  if (square * square != pg->total)
+  {
+    while (rows * cols < pg->total)
+    {
+      if (toggle % 2 == 0)
+        rows++;
+      else
+        cols++;
+
+      toggle++;
+    }
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting nodes in 2d torus topology: %u rows %u columns\n",
+              rows, cols);
+  /* Rows and columns are all sorted out, now iterate over all nodes and connect each
+   * to the node to its right and above.  Once this is over, we'll have our torus!
+   * Special case for the last node (if the rows and columns are not equal), connect
+   * to the first in the row to maintain topology.
+   */
+  for (i = 0; i < pg->total; i++)
+  {
+    /* First connect to the node to the right */
+    if (((i + 1) % cols != 0) && (i + 1 != pg->total))
+      nodeToConnect = i + 1;
+    else if (i + 1 == pg->total)
+      nodeToConnect = rows * cols - cols;
+    else
+      nodeToConnect = i - cols + 1;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i,
+                nodeToConnect);
+    connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
+
+    /* Second connect to the node immediately above */
+    if (i < cols)
+    {
+      nodeToConnect = (rows * cols) - cols + i;
+      if (nodeToConnect >= pg->total)
+        nodeToConnect -= cols;
+    }
+    else
+      nodeToConnect = i - cols;
+
+    if (nodeToConnect < pg->total)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n", i,
+                  nodeToConnect);
+      connect_attempts += proc (pg, i, nodeToConnect, list, GNUNET_YES);
+    }
+
+  }
+
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ * @param check does the connection processor need to check before
+ *              performing an action on the list?
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_clique (struct GNUNET_TESTING_PeerGroup *pg,
+               GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list,
+               unsigned int check)
+{
+  unsigned int outer_count;
+  unsigned int inner_count;
+  int connect_attempts;
+  struct ProgressMeter *conn_meter;
+
+  connect_attempts = 0;
+
+  conn_meter =
+      create_meter ((((pg->total * pg->total) + pg->total) / 2) - 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++)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
+                  outer_count, inner_count);
+      connect_attempts += proc (pg, outer_count, inner_count, list, check);
+      update_meter (conn_meter);
+    }
+  }
+  reset_meter (conn_meter);
+  free_meter (conn_meter);
+  return connect_attempts;
+}
+
+#if !OLD
+/**
+ * Iterator over hash map entries.
+ *
+ * @param cls closure the peer group
+ * @param key the key stored in the hashmap is the
+ *            index of the peer to connect to
+ * @param value value in the hash map, handle to the peer daemon
+ * @return GNUNET_YES if we should continue to
+ *         iterate,
+ *         GNUNET_NO if not.
+ */
+static int
+unblacklist_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct UnblacklistContext *un_ctx = cls;
+  uint32_t second_pos;
+
+  uid_from_hash (key, &second_pos);
+
+  unblacklist_connections (un_ctx->pg, un_ctx->first_uid, second_pos);
+
+  return GNUNET_YES;
+}
+#endif
+
+#if !OLD
+/**
+ * Create a blacklist topology based on the allowed topology
+ * which disallows any connections not in the allowed topology
+ * at the transport level.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to allow
+ *        up connections between two peers
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+copy_allowed (struct GNUNET_TESTING_PeerGroup *pg,
+              GNUNET_TESTING_ConnectionProcessor proc)
+{
+  unsigned int count;
+  unsigned int total;
+  struct PeerConnection *iter;
+
+#if !OLD
+  struct UnblacklistContext un_ctx;
+
+  un_ctx.pg = pg;
+#endif
+  total = 0;
+  for (count = 0; count < pg->total - 1; count++)
+  {
+#if OLD
+    iter = pg->peers[count].allowed_peers_head;
+    while (iter != NULL)
+    {
+      remove_connections (pg, count, iter->index, BLACKLIST, GNUNET_YES);
+      //unblacklist_connections(pg, count, iter->index);
+      iter = iter->next;
+    }
+#else
+    un_ctx.first_uid = count;
+    total +=
+        GNUNET_CONTAINER_multihashmap_iterate (pg->peers[count].allowed_peers,
+                                               &unblacklist_iterator, &un_ctx);
+#endif
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unblacklisted %u peers\n", total);
+  return total;
+}
+#endif
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list which list should be modified
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_line (struct GNUNET_TESTING_PeerGroup *pg,
+             GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+{
+  unsigned int count;
+  unsigned int connect_attempts;
+
+  connect_attempts = 0;
+  /* Connect each peer to the next highest numbered peer */
+  for (count = 0; count < pg->total - 1; count++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
+                count, count + 1);
+    connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES);
+  }
+
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param filename the file to read topology information from
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_from_file (struct GNUNET_TESTING_PeerGroup *pg, char *filename,
+                  GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+{
+  int connect_attempts;
+  unsigned int first_peer_index;
+  unsigned int second_peer_index;
+  struct stat frstat;
+  int count;
+  char *data;
+  const char *buf;
+  unsigned int total_peers;
+  enum States curr_state;
+
+  connect_attempts = 0;
+  if (GNUNET_OK != GNUNET_DISK_file_test (filename))
+    GNUNET_DISK_fn_write (filename, NULL, 0, GNUNET_DISK_PERM_USER_READ);
+
+  if ((0 != STAT (filename, &frstat)) || (frstat.st_size == 0))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not open file `%s' specified for topology!", filename);
+    return connect_attempts;
+  }
+
+  data = GNUNET_malloc_large (frstat.st_size);
+  GNUNET_assert (data != NULL);
+  if (frstat.st_size != GNUNET_DISK_fn_read (filename, data, frstat.st_size))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Could not read file %s specified for host list, ending test!",
+                filename);
+    GNUNET_free (data);
+    return connect_attempts;
+  }
+
+  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;
+  while (count < frstat.st_size - 1)
+  {
+    if ((buf[count] == '\n') || (buf[count] == ' '))
+    {
+      count++;
+      continue;
+    }
+
+    switch (curr_state)
+    {
+    case NUM_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");
+        GNUNET_free (data);
+        return connect_attempts;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Found %u total peers in topology\n",
+                  total_peers);
+      GNUNET_assert (total_peers == pg->total);
+      curr_state = PEER_INDEX;
+      while ((buf[count] != '\n') && (count < frstat.st_size - 1))
+        count++;
+      count++;
+      break;
+    case 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");
+        GNUNET_free (data);
+        return connect_attempts;
+      }
+      while ((buf[count] != ':') && (count < frstat.st_size - 1))
+        count++;
+      count++;
+      curr_state = OTHER_PEER_INDEX;
+      break;
+    case COLON:
+      if (1 == sscanf (&buf[count], ":"))
+        curr_state = OTHER_PEER_INDEX;
+      count++;
+      break;
+    case OTHER_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");
+        GNUNET_free (data);
+        return connect_attempts;
+      }
+      /* 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);
+      while ((buf[count] != '\n') && (buf[count] != ',') &&
+             (count < frstat.st_size - 1))
+        count++;
+      if (buf[count] == '\n')
+      {
+        curr_state = PEER_INDEX;
+      }
+      else if (buf[count] != ',')
+      {
+        curr_state = OTHER_PEER_INDEX;
+      }
+      count++;
+      break;
+    default:
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Found bad data in topology file while in state %d!\n",
+                  curr_state);
+      GNUNET_break (0);
+      GNUNET_free (data);
+      return connect_attempts;
+    }
+  }
+  GNUNET_free (data);
+  return connect_attempts;
+}
+
+/**
+ * Create a topology given a peer group (set of running peers)
+ * and a connection processor.
+ *
+ * @param pg the peergroup to create the topology on
+ * @param proc the connection processor to call to actually set
+ *        up connections between two peers
+ * @param list the peer list to use
+ *
+ * @return the number of connections that were set up
+ *
+ */
+static unsigned int
+create_ring (struct GNUNET_TESTING_PeerGroup *pg,
+             GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+{
+  unsigned int count;
+  int connect_attempts;
+
+  connect_attempts = 0;
+
+  /* Connect each peer to the next highest numbered peer */
+  for (count = 0; count < pg->total - 1; count++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting peer %d to peer %d\n",
+                count, count + 1);
+    connect_attempts += proc (pg, count, count + 1, list, GNUNET_YES);
+  }
+
+  /* Connect the last peer to the first peer */
+  connect_attempts += proc (pg, pg->total - 1, 0, list, GNUNET_YES);
+
+  return connect_attempts;
+}
+
+#if !OLD
+/**
+ * Iterator for writing friends of a peer to a file.
+ *
+ * @param cls closure, an open writable file handle
+ * @param key the key the daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that needs to be written.
+ *
+ * @return GNUNET_YES to continue iteration
+ *
+ * TODO: Could replace friend_file_iterator and blacklist_file_iterator
+ *       with a single file_iterator that takes a closure which contains
+ *       the prefix to write before the peer.  Then this could be used
+ *       for blacklisting multiple transports and writing the friend
+ *       file.  I'm sure *someone* will complain loudly about other
+ *       things that negate these functions even existing so no point in
+ *       "fixing" now.
+ */
+static int
+friend_file_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  FILE *temp_friend_handle = cls;
+  struct GNUNET_TESTING_Daemon *peer = value;
+  struct GNUNET_PeerIdentity *temppeer;
+  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
+
+  temppeer = &peer->id;
+  GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc);
+  FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc);
+
+  return GNUNET_YES;
+}
+
+struct BlacklistContext
+{
+  /*
+   * The (open) file handle to write to
+   */
+  FILE *temp_file_handle;
+
+  /*
+   * The transport that this peer will be blacklisted on.
+   */
+  char *transport;
+};
+
+/**
+ * Iterator for writing blacklist data to appropriate files.
+ *
+ * @param cls closure, an open writable file handle
+ * @param key the key the daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that needs to be written.
+ *
+ * @return GNUNET_YES to continue iteration
+ */
+static int
+blacklist_file_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct BlacklistContext *blacklist_ctx = cls;
+  struct GNUNET_TESTING_Daemon *peer = value;
+  struct GNUNET_PeerIdentity *temppeer;
+  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
+
+  temppeer = &peer->id;
+  GNUNET_CRYPTO_hash_to_enc (&temppeer->hashPubKey, &peer_enc);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Writing entry %s:%s to file\n",
+              blacklist_ctx->transport, (char *) &peer_enc);
+  FPRINTF (blacklist_ctx->temp_file_handle, "%s:%s\n", blacklist_ctx->transport,
+           (char *) &peer_enc);
+
+  return GNUNET_YES;
+}
+#endif
+
+/*
+ * Create the friend files based on the PeerConnection's
+ * of each peer in the peer group, and copy the files
+ * to the appropriate place
+ *
+ * @param pg the peer group we are dealing with
+ */
+static int
+create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  FILE *temp_friend_handle;
+  unsigned int pg_iter;
+  char *temp_service_path;
+  struct GNUNET_OS_Process **procarr;
+  char *arg;
+  char *mytemp;
+
+#if NOT_STUPID
+  enum GNUNET_OS_ProcessStatusType type;
+  unsigned long return_code;
+  int count;
+  int max_wait = 10;
+#endif
+  int ret;
+
+  ret = GNUNET_OK;
+#if OLD
+  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
+  struct PeerConnection *conn_iter;
+#endif
+  procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total);
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    mytemp = GNUNET_DISK_mktemp ("friends");
+    GNUNET_assert (mytemp != NULL);
+    temp_friend_handle = FOPEN (mytemp, "wt");
+    GNUNET_assert (temp_friend_handle != NULL);
+#if OLD
+    conn_iter = pg->peers[pg_iter].allowed_peers_head;
+    while (conn_iter != NULL)
+    {
+      GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon->
+                                 id.hashPubKey, &peer_enc);
+      FPRINTF (temp_friend_handle, "%s\n", (char *) &peer_enc);
+      conn_iter = conn_iter->next;
+    }
+#else
+    GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers,
+                                           &friend_file_iterator,
+                                           temp_friend_handle);
+#endif
+    FCLOSE (temp_friend_handle);
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg,
+                                               "PATHS", "SERVICEHOME",
+                                               &temp_service_path))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
+                  "SERVICEHOME", "PATHS");
+      if (UNLINK (mytemp) != 0)
+        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
+      GNUNET_free (mytemp);
+      break;
+    }
+
+    if (pg->peers[pg_iter].daemon->hostname == NULL)    /* Local, just copy the file */
+    {
+      GNUNET_asprintf (&arg, "%s/friends", temp_service_path);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Copying file with RENAME(%s,%s)\n", mytemp, arg);
+      RENAME (mytemp, arg);
+      procarr[pg_iter] = NULL;
+      GNUNET_free (arg);
+    }
+    else                        /* Remote, scp the file to the correct place */
+    {
+      if (NULL != pg->peers[pg_iter].daemon->username)
+        GNUNET_asprintf (&arg, "%s@%s:%s/friends",
+                         pg->peers[pg_iter].daemon->username,
+                         pg->peers[pg_iter].daemon->hostname,
+                         temp_service_path);
+      else
+        GNUNET_asprintf (&arg, "%s:%s/friends",
+                         pg->peers[pg_iter].daemon->hostname,
+                         temp_service_path);
+      procarr[pg_iter] =
+       GNUNET_OS_start_process (GNUNET_NO, 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_destroy (procarr[pg_iter]);
+      if (ret != GNUNET_OK)
+      {
+        /* FIXME: free contents of 'procarr' array */
+        GNUNET_free (procarr);
+        GNUNET_free (temp_service_path);
+        GNUNET_free (mytemp);
+        GNUNET_free (arg);
+        return ret;
+      }
+      procarr[pg_iter] = NULL;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Copying file with command scp %s %s\n", mytemp, arg);
+      GNUNET_free (arg);
+    }
+    GNUNET_free (temp_service_path);
+    GNUNET_free (mytemp);
+  }
+
+#if NOT_STUPID
+  count = 0;
+  ret = GNUNET_SYSERR;
+  while ((count < max_wait) && (ret != GNUNET_OK))
+  {
+    ret = GNUNET_OK;
+    for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Checking copy status of file %d\n",
+                  pg_iter);
+      if (procarr[pg_iter] != NULL)     /* Check for already completed! */
+      {
+        if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) !=
+            GNUNET_OK)
+        {
+          ret = GNUNET_SYSERR;
+        }
+        else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
+        {
+          ret = GNUNET_SYSERR;
+        }
+        else
+        {
+          GNUNET_OS_process_destroy (procarr[pg_iter]);
+          procarr[pg_iter] = NULL;
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter);
+        }
+      }
+    }
+    count++;
+    if (ret == GNUNET_SYSERR)
+    {
+      /* FIXME: why sleep here? -CG */
+      sleep (1);
+    }
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished copying all friend files!\n");
+#endif
+  GNUNET_free (procarr);
+  return ret;
+}
+
+/*
+ * Create the blacklist files based on the PeerConnection's
+ * of each peer in the peer group, and copy the files
+ * to the appropriate place.
+ *
+ * @param pg the peer group we are dealing with
+ * @param transports space delimited list of transports to blacklist
+ */
+static int
+create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg,
+                                 const char *transports)
+{
+  FILE *temp_file_handle;
+  unsigned int pg_iter;
+  char *temp_service_path;
+  struct GNUNET_OS_Process **procarr;
+  char *arg;
+  char *mytemp;
+  enum GNUNET_OS_ProcessStatusType type;
+  unsigned long return_code;
+  int count;
+  int ret;
+  int max_wait = 10;
+  int transport_len;
+  unsigned int i;
+  char *pos;
+  char *temp_transports;
+
+#if OLD
+  struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
+  struct PeerConnection *conn_iter;
+#else
+  static struct BlacklistContext blacklist_ctx;
+#endif
+
+  procarr = GNUNET_malloc (sizeof (struct GNUNET_OS_Process *) * pg->total);
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    mytemp = GNUNET_DISK_mktemp ("blacklist");
+    GNUNET_assert (mytemp != NULL);
+    temp_file_handle = FOPEN (mytemp, "wt");
+    GNUNET_assert (temp_file_handle != NULL);
+    temp_transports = GNUNET_strdup (transports);
+#if !OLD
+    blacklist_ctx.temp_file_handle = temp_file_handle;
+#endif
+    transport_len = strlen (temp_transports) + 1;
+    pos = NULL;
+
+    for (i = 0; i < transport_len; i++)
+    {
+      if ((temp_transports[i] == ' ') && (pos == NULL))
+        continue;               /* At start of string (whitespace) */
+      else if ((temp_transports[i] == ' ') || (temp_transports[i] == '\0'))     /* At end of string */
+      {
+        temp_transports[i] = '\0';
+#if OLD
+        conn_iter = pg->peers[pg_iter].blacklisted_peers_head;
+        while (conn_iter != NULL)
+        {
+          GNUNET_CRYPTO_hash_to_enc (&pg->peers[conn_iter->index].daemon->
+                                     id.hashPubKey, &peer_enc);
+          FPRINTF (temp_file_handle, "%s:%s\n", pos, (char *) &peer_enc);
+          conn_iter = conn_iter->next;
+        }
+#else
+        blacklist_ctx.transport = pos;
+        (void) GNUNET_CONTAINER_multihashmap_iterate (pg->
+                                                      peers
+                                                      [pg_iter].blacklisted_peers,
+                                                      &blacklist_file_iterator,
+                                                      &blacklist_ctx);
+#endif
+        pos = NULL;
+      }                         /* At beginning of actual string */
+      else if (pos == NULL)
+      {
+        pos = &temp_transports[i];
+      }
+    }
+
+    GNUNET_free (temp_transports);
+    FCLOSE (temp_file_handle);
+
+    if (GNUNET_OK !=
+        GNUNET_CONFIGURATION_get_value_string (pg->peers[pg_iter].daemon->cfg,
+                                               "PATHS", "SERVICEHOME",
+                                               &temp_service_path))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
+                  "SERVICEHOME", "PATHS");
+      if (UNLINK (mytemp) != 0)
+        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
+      GNUNET_free (mytemp);
+      break;
+    }
+
+    if (pg->peers[pg_iter].daemon->hostname == NULL)    /* Local, just copy the file */
+    {
+      GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path);
+      RENAME (mytemp, arg);
+      procarr[pg_iter] = NULL;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Copying file with RENAME (%s,%s)\n", mytemp, arg);
+      GNUNET_free (arg);
+    }
+    else                        /* Remote, scp the file to the correct place */
+    {
+      if (NULL != pg->peers[pg_iter].daemon->username)
+        GNUNET_asprintf (&arg, "%s@%s:%s/blacklist",
+                         pg->peers[pg_iter].daemon->username,
+                         pg->peers[pg_iter].daemon->hostname,
+                         temp_service_path);
+      else
+        GNUNET_asprintf (&arg, "%s:%s/blacklist",
+                         pg->peers[pg_iter].daemon->hostname,
+                         temp_service_path);
+      procarr[pg_iter] =
+       GNUNET_OS_start_process (GNUNET_NO, 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! */
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Copying file with command scp %s %s\n", mytemp, arg);
+      GNUNET_free (arg);
+    }
+    GNUNET_free (temp_service_path);
+    GNUNET_free (mytemp);
+  }
+
+  count = 0;
+  ret = GNUNET_SYSERR;
+  while ((count < max_wait) && (ret != GNUNET_OK))
+  {
+    ret = GNUNET_OK;
+    for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Checking copy status of file %d\n", pg_iter);
+      if (procarr[pg_iter] != NULL)     /* Check for already completed! */
+      {
+        if (GNUNET_OS_process_status (procarr[pg_iter], &type, &return_code) !=
+            GNUNET_OK)
+        {
+          ret = GNUNET_SYSERR;
+        }
+        else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
+        {
+          ret = GNUNET_SYSERR;
+        }
+        else
+        {
+          GNUNET_OS_process_destroy (procarr[pg_iter]);
+          procarr[pg_iter] = NULL;
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "File %d copied\n", pg_iter);
+        }
+      }
+    }
+    count++;
+    if (ret == GNUNET_SYSERR)
+    {
+      /* FIXME: why sleep here? -CG */
+      sleep (1);
+    }
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Finished copying all blacklist files!\n");
+  GNUNET_free (procarr);
+  return ret;
+}
+
+/* Forward Declaration */
+static void
+schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Choose a random peer's next connection to create, and
+ * call schedule_connect to set up the connect task.
+ *
+ * @param pg the peer group to connect
+ */
+static void
+preschedule_connect (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct ConnectTopologyContext *ct_ctx = &pg->ct_ctx;
+  struct PeerConnection *connection_iter;
+  struct ConnectContext *connect_context;
+  uint32_t random_peer;
+
+  if (ct_ctx->remaining_connections == 0)
+    return;
+  random_peer =
+      GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
+  while (pg->peers[random_peer].connect_peers_head == NULL)
+    random_peer =
+        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
+
+  connection_iter = pg->peers[random_peer].connect_peers_head;
+  connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
+  connect_context->first_index = random_peer;
+  connect_context->second_index = connection_iter->index;
+  connect_context->ct_ctx = ct_ctx;
+  connect_context->task =
+      GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
+  GNUNET_CONTAINER_DLL_insert (pg->cc_head, pg->cc_tail, connect_context);
+  GNUNET_CONTAINER_DLL_remove (pg->peers[random_peer].connect_peers_head,
+                               pg->peers[random_peer].connect_peers_tail,
+                               connection_iter);
+  GNUNET_free (connection_iter);
+  ct_ctx->remaining_connections--;
+}
+
+#if USE_SEND_HELLOS
+/* Forward declaration */
+static void
+schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
+/**
+ * Close connections and free the hello context.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+free_hello_context (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+
+  if (send_hello_context->peer->daemon->server != NULL)
+  {
+    GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server);
+    send_hello_context->peer->daemon->server = NULL;
+  }
+  if (send_hello_context->peer->daemon->th != NULL)
+  {
+    GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th);
+    send_hello_context->peer->daemon->th = NULL;
+  }
+  if (send_hello_context->core_connect_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (send_hello_context->core_connect_task);
+    send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  send_hello_context->pg->outstanding_connects--;
+  GNUNET_free (send_hello_context);
+}
+
+/**
+ * For peers that haven't yet connected, notify
+ * the caller that they have failed (timeout).
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+notify_remaining_connections_failed (void *cls,
+                                     const struct GNUNET_SCHEDULER_TaskContext
+                                     *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+  struct PeerConnection *connection;
+
+  GNUNET_CORE_disconnect (send_hello_context->peer->daemon->server);
+  send_hello_context->peer->daemon->server = NULL;
+
+  connection = send_hello_context->peer->connect_peers_head;
+
+  while (connection != NULL)
+  {
+    if (pg->notify_connection != NULL)
+    {
+      pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, &pg->peers[connection->index].daemon->id, 0,     /* FIXME */
+                             send_hello_context->peer->daemon->cfg,
+                             pg->peers[connection->index].daemon->cfg,
+                             send_hello_context->peer->daemon,
+                             pg->peers[connection->index].daemon,
+                             "Peers failed to connect (timeout)");
+    }
+    GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head,
+                                 send_hello_context->peer->connect_peers_tail,
+                                 connection);
+    GNUNET_free (connection);
+    connection = connection->next;
+  }
+  GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context);
+#if BAD
+  other_peer = &pg->peers[connection->index];
+#endif
+}
+
+/**
+ * For peers that haven't yet connected, send
+ * CORE connect requests.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+send_core_connect_requests (void *cls,
+                            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct PeerConnection *conn;
+
+  GNUNET_assert (send_hello_context->peer->daemon->server != NULL);
+
+  send_hello_context->core_connect_task = GNUNET_SCHEDULER_NO_TASK;
+
+  send_hello_context->connect_attempts++;
+  if (send_hello_context->connect_attempts <
+      send_hello_context->pg->ct_ctx.connect_attempts)
+  {
+    conn = send_hello_context->peer->connect_peers_head;
+    while (conn != NULL)
+    {
+      GNUNET_TRANSPORT_try_connect (send_hello_context->peer->daemon->th,
+                                    &send_hello_context->pg->peers[conn->
+                                                                   index].daemon->
+                                    id);
+      conn = conn->next;
+    }
+    send_hello_context->core_connect_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
+                                      (send_hello_context->pg->
+                                       ct_ctx.connect_timeout,
+                                       send_hello_context->pg->
+                                       ct_ctx.connect_attempts),
+                                      &send_core_connect_requests,
+                                      send_hello_context);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Timeout before all connections created, marking rest as failed!\n");
+    GNUNET_SCHEDULER_add_now (&notify_remaining_connections_failed,
+                              send_hello_context);
+  }
+
+}
+
+/**
+ * Success, connection is up.  Signal client our success.
+ *
+ * @param cls our "struct SendHelloContext"
+ * @param peer identity of the peer that has connected
+ * @param atsi performance information
+ *
+ * FIXME: remove peers from BOTH lists, call notify twice, should
+ * double the speed of connections as long as the list iteration
+ * doesn't take too long!
+ */
+static void
+core_connect_notify (void *cls, const struct GNUNET_PeerIdentity *peer,
+                     const struct GNUNET_ATS_Information *atsi)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct PeerConnection *connection;
+  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+
+#if BAD
+  struct PeerData *other_peer;
+#endif
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connected peer %s to peer %s\n",
+              ctx->d1->shortname, GNUNET_i2s (peer));
+  if (0 ==
+      memcmp (&send_hello_context->peer->daemon->id, peer,
+              sizeof (struct GNUNET_PeerIdentity)))
+    return;
+
+  connection = send_hello_context->peer->connect_peers_head;
+#if BAD
+  other_peer = NULL;
+#endif
+
+  while ((connection != NULL) &&
+         (0 !=
+          memcmp (&pg->peers[connection->index].daemon->id, peer,
+                  sizeof (struct GNUNET_PeerIdentity))))
+  {
+    connection = connection->next;
+  }
+
+  if (connection == NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Connected peer %s to %s, not in list (no problem(?))\n",
+                GNUNET_i2s (peer), send_hello_context->peer->daemon->shortname);
+  }
+  else
+  {
+#if BAD
+    other_peer = &pg->peers[connection->index];
+#endif
+    if (pg->notify_connection != NULL)
+    {
+      pg->notify_connection (pg->notify_connection_cls, &send_hello_context->peer->daemon->id, peer, 0, /* FIXME */
+                             send_hello_context->peer->daemon->cfg,
+                             pg->peers[connection->index].daemon->cfg,
+                             send_hello_context->peer->daemon,
+                             pg->peers[connection->index].daemon, NULL);
+    }
+    GNUNET_CONTAINER_DLL_remove (send_hello_context->peer->connect_peers_head,
+                                 send_hello_context->peer->connect_peers_tail,
+                                 connection);
+    GNUNET_free (connection);
+  }
+
+#if BAD
+  /* Notify of reverse connection and remove from other peers list of outstanding */
+  if (other_peer != NULL)
+  {
+    connection = other_peer->connect_peers_head;
+    while ((connection != NULL) &&
+           (0 !=
+            memcmp (&send_hello_context->peer->daemon->id,
+                    &pg->peers[connection->index].daemon->id,
+                    sizeof (struct GNUNET_PeerIdentity))))
+    {
+      connection = connection->next;
+    }
+    if (connection != NULL)
+    {
+      if (pg->notify_connection != NULL)
+      {
+        pg->notify_connection (pg->notify_connection_cls, peer, &send_hello_context->peer->daemon->id, 0,       /* FIXME */
+                               pg->peers[connection->index].daemon->cfg,
+                               send_hello_context->peer->daemon->cfg,
+                               pg->peers[connection->index].daemon,
+                               send_hello_context->peer->daemon, NULL);
+      }
+
+      GNUNET_CONTAINER_DLL_remove (other_peer->connect_peers_head,
+                                   other_peer->connect_peers_tail, connection);
+      GNUNET_free (connection);
+    }
+  }
+#endif
+
+  if (send_hello_context->peer->connect_peers_head == NULL)
+  {
+    GNUNET_SCHEDULER_add_now (&free_hello_context, send_hello_context);
+  }
+}
+
+/**
+ * Notify of a successful connection to the core service.
+ *
+ * @param cls a struct SendHelloContext *
+ * @param server handle to the core service
+ * @param my_identity the peer identity of this peer
+ */
+void
+core_init (void *cls, struct GNUNET_CORE_Handle *server,
+           struct GNUNET_PeerIdentity *my_identity)
+{
+  struct SendHelloContext *send_hello_context = cls;
+
+  send_hello_context->core_ready = GNUNET_YES;
+}
+
+/**
+ * Function called once a hello has been sent
+ * to the transport, move on to the next one
+ * or go away forever.
+ *
+ * @param cls the 'struct SendHelloContext *'
+ * @param tc scheduler context
+ */
+static void
+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) != 0)
+  {
+    GNUNET_free (send_hello_context);
+    return;
+  }
+
+  send_hello_context->pg->remaining_hellos--;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sent HELLO, have %d remaining!\n",
+              send_hello_context->pg->remaining_hellos);
+  if (send_hello_context->peer_pos == NULL)     /* All HELLOs (for this peer!) have been transmitted! */
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All hellos for this peer sent, disconnecting transport!\n");
+    GNUNET_assert (send_hello_context->peer->daemon->th != NULL);
+    GNUNET_TRANSPORT_disconnect (send_hello_context->peer->daemon->th);
+    send_hello_context->peer->daemon->th = NULL;
+    GNUNET_assert (send_hello_context->peer->daemon->server == NULL);
+    send_hello_context->peer->daemon->server =
+        GNUNET_CORE_connect (send_hello_context->peer->cfg, 1,
+                             send_hello_context, &core_init,
+                             &core_connect_notify, NULL, NULL, NULL, GNUNET_NO,
+                             NULL, GNUNET_NO, no_handlers);
+
+    send_hello_context->core_connect_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_divide
+                                      (send_hello_context->pg->
+                                       ct_ctx.connect_timeout,
+                                       send_hello_context->pg->
+                                       ct_ctx.connect_attempts),
+                                      &send_core_connect_requests,
+                                      send_hello_context);
+  }
+  else
+    GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context);
+}
+
+/**
+ * Connect to a peer, give it all the HELLO's of those peers
+ * we will later ask it to connect to.
+ *
+ * @param ct_ctx the overall connection context
+ */
+static void
+schedule_send_hellos (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct SendHelloContext *send_hello_context = cls;
+  struct GNUNET_TESTING_PeerGroup *pg = send_hello_context->pg;
+
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+  {
+    GNUNET_free (send_hello_context);
+    return;
+  }
+
+  GNUNET_assert (send_hello_context->peer_pos != NULL); /* All of the HELLO sends to be scheduled have been scheduled! */
+
+  if (((send_hello_context->peer->daemon->th == NULL) &&
+       (pg->outstanding_connects > pg->max_outstanding_connections)) ||
+      (pg->stop_connects == GNUNET_YES))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Delaying connect, we have too many outstanding connections!\n");
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_send_hellos, send_hello_context);
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating connection, outstanding_connections is %d\n",
+                outstanding_connects);
+    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);
+    }
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Offering HELLO of peer %s to peer %s\n",
+                send_hello_context->peer->daemon->shortname,
+                pg->peers[send_hello_context->peer_pos->index].
+                daemon->shortname);
+    GNUNET_TRANSPORT_offer_hello (send_hello_context->peer->daemon->th,
+                                  (const struct GNUNET_MessageHeader *)
+                                  pg->peers[send_hello_context->peer_pos->
+                                            index].daemon->hello,
+                                  &hello_sent_callback, send_hello_context);
+    send_hello_context->peer_pos = send_hello_context->peer_pos->next;
+    GNUNET_assert (send_hello_context->peer->daemon->th != NULL);
+  }
+}
+#endif
+
+/**
+ * Internal notification of a connection, kept so that we can ensure some connections
+ * happen instead of flooding all testing daemons with requests to connect.
+ */
+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)
+{
+  struct ConnectContext *connect_ctx = cls;
+  struct ConnectTopologyContext *ct_ctx = connect_ctx->ct_ctx;
+  struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
+  struct PeerConnection *connection;
+
+  GNUNET_assert (NULL != connect_ctx->cc);
+  connect_ctx->cc = NULL;
+  GNUNET_assert (0 < pg->outstanding_connects);
+  pg->outstanding_connects--;
+  GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, connect_ctx);
+  /*
+   * Check whether the inverse connection has been scheduled yet,
+   * if not, we can remove it from the other peers list and avoid
+   * even trying to connect them again!
+   */
+  connection = pg->peers[connect_ctx->second_index].connect_peers_head;
+#if BAD
+  other_peer = NULL;
+#endif
+
+  while ((connection != NULL) &&
+         (0 !=
+          memcmp (first, &pg->peers[connection->index].daemon->id,
+                  sizeof (struct GNUNET_PeerIdentity))))
+    connection = connection->next;
+
+  if (connection != NULL)       /* Can safely remove! */
+  {
+    GNUNET_assert (0 < ct_ctx->remaining_connections);
+    ct_ctx->remaining_connections--;
+    if (pg->notify_connection != NULL)  /* Notify of reverse connection */
+      pg->notify_connection (pg->notify_connection_cls, second, first, distance,
+                             second_cfg, first_cfg, second_daemon, first_daemon,
+                             emsg);
+
+    GNUNET_CONTAINER_DLL_remove (pg->
+                                 peers[connect_ctx->
+                                       second_index].connect_peers_head,
+                                 pg->peers[connect_ctx->
+                                           second_index].connect_peers_tail,
+                                 connection);
+    GNUNET_free (connection);
+  }
+
+  if (ct_ctx->remaining_connections == 0)
+  {
+    if (ct_ctx->notify_connections_done != NULL)
+    {
+      ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL);
+      ct_ctx->notify_connections_done = NULL;
+    }
+  }
+  else
+    preschedule_connect (pg);
+
+  if (pg->notify_connection != NULL)
+    pg->notify_connection (pg->notify_connection_cls, first, second, distance,
+                           first_cfg, second_cfg, first_daemon, second_daemon,
+                           emsg);
+  GNUNET_free (connect_ctx);
+}
+
+/**
+ * Either delay a connection (because there are too many outstanding)
+ * or schedule it for right now.
+ *
+ * @param cls a connection context
+ * @param tc the task runtime context
+ */
+static void
+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;
+
+  connect_context->task = GNUNET_SCHEDULER_NO_TASK;
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+    return;
+
+  if ((pg->outstanding_connects > pg->max_outstanding_connections) ||
+      (pg->stop_connects == GNUNET_YES))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Delaying connect, we have too many outstanding connections!\n");
+    connect_context->task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                      &schedule_connect, connect_context);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Creating connection, outstanding_connections is %d (max %d)\n",
+              pg->outstanding_connects, pg->max_outstanding_connections);
+  pg->outstanding_connects++;
+  pg->total_connects_scheduled++;
+  GNUNET_assert (NULL == connect_context->cc);
+  connect_context->cc =
+      GNUNET_TESTING_daemons_connect (pg->
+                                      peers[connect_context->
+                                            first_index].daemon,
+                                      pg->peers[connect_context->
+                                                second_index].daemon,
+                                      connect_context->ct_ctx->connect_timeout,
+                                      connect_context->ct_ctx->connect_attempts,
+#if USE_SEND_HELLOS
+                                      GNUNET_NO,
+#else
+                                      GNUNET_YES,
+#endif
+                                      &internal_connect_notify,
+                                      connect_context);
+
+}
+
+#if !OLD
+/**
+ * Iterator for actually scheduling connections to be created
+ * between two peers.
+ *
+ * @param cls closure, a GNUNET_TESTING_Daemon
+ * @param key the key the second Daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that the first is to connect to
+ *
+ * @return GNUNET_YES to continue iteration
+ */
+static int
+connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct ConnectTopologyContext *ct_ctx = cls;
+  struct PeerData *first = ct_ctx->first;
+  struct GNUNET_TESTING_Daemon *second = value;
+  struct ConnectContext *connect_context;
+
+  connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
+  connect_context->first = first->daemon;
+  connect_context->second = second;
+  connect_context->ct_ctx = ct_ctx;
+  connect_context->task =
+      GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
+  GNUNET_CONTAINER_DLL_insert (ct_ctx->pg->cc_head, ct_ctx->pg->cc_tail,
+                               connect_context);
+  return GNUNET_YES;
+}
+#endif
+
+#if !OLD
+/**
+ * Iterator for copying all entries in the allowed hashmap to the
+ * connect hashmap.
+ *
+ * @param cls closure, a GNUNET_TESTING_Daemon
+ * @param key the key the second Daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that the first is to connect to
+ *
+ * @return GNUNET_YES to continue iteration
+ */
+static int
+copy_topology_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct PeerData *first = cls;
+
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONTAINER_multihashmap_put (first->connect_peers, key,
+                                                    value,
+                                                    GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+
+  return GNUNET_YES;
+}
+#endif
+
+/**
+ * Make the peers to connect the same as those that are allowed to be
+ * connected.
+ *
+ * @param pg the peer group
+ */
+static int
+copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  unsigned int pg_iter;
+  int ret;
+  int total;
+
+#if OLD
+  struct PeerConnection *iter;
+#endif
+  total = 0;
+  ret = 0;
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+#if OLD
+    iter = pg->peers[pg_iter].allowed_peers_head;
+    while (iter != NULL)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Creating connection between %d and %d\n", pg_iter,
+                  iter->index);
+      total += add_connections (pg, pg_iter, iter->index, CONNECT, GNUNET_YES);
+      //total += add_actual_connections(pg, pg_iter, iter->index);
+      iter = iter->next;
+    }
+#else
+    ret =
+        GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers,
+                                               &copy_topology_iterator,
+                                               &pg->peers[pg_iter]);
+#endif
+    if (GNUNET_SYSERR == ret)
+      return GNUNET_SYSERR;
+
+    total = total + ret;
+  }
+
+  return total;
+}
+
+/**
+ * Connect the topology as specified by the PeerConnection's
+ * of each peer in the peer group
+ *
+ * @param pg the peer group we are dealing with
+ * @param connect_timeout how long try connecting two peers
+ * @param connect_attempts how many times (max) to attempt
+ * @param notify_callback callback to notify when finished
+ * @param notify_cls closure for notify callback
+ *
+ * @return the number of connections that will be attempted
+ */
+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)
+{
+  unsigned int pg_iter;
+  unsigned int total;
+
+#if OLD
+  struct PeerConnection *connection_iter;
+#endif
+#if USE_SEND_HELLOS
+  struct SendHelloContext *send_hello_context;
+#endif
+
+  total = 0;
+  pg->ct_ctx.notify_connections_done = notify_callback;
+  pg->ct_ctx.notify_cls = notify_cls;
+  pg->ct_ctx.pg = pg;
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+#if OLD
+    connection_iter = pg->peers[pg_iter].connect_peers_head;
+    while (connection_iter != NULL)
+    {
+      connection_iter = connection_iter->next;
+      total++;
+    }
+#else
+    total +=
+        GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].connect_peers);
+#endif
+  }
+
+  if (total == 0)
+    return total;
+
+  pg->ct_ctx.connect_timeout = connect_timeout;
+  pg->ct_ctx.connect_attempts = connect_attempts;
+  pg->ct_ctx.remaining_connections = total;
+
+#if USE_SEND_HELLOS
+  /* First give all peers the HELLO's of other peers (connect to first peer's transport service, give HELLO's of other peers, continue...) */
+  pg->remaining_hellos = total;
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    send_hello_context = GNUNET_malloc (sizeof (struct SendHelloContext));
+    send_hello_context->peer = &pg->peers[pg_iter];
+    send_hello_context->peer_pos = pg->peers[pg_iter].connect_peers_head;
+    send_hello_context->pg = pg;
+    GNUNET_SCHEDULER_add_now (&schedule_send_hellos, send_hello_context);
+  }
+#else
+  for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++)
+  {
+    preschedule_connect (pg);
+  }
+#endif
+  return total;
+
+}
+
+/**
+ * Takes a peer group and creates a topology based on the
+ * one specified.  Creates a topology means generates friend
+ * files for the peers so they can only connect to those allowed
+ * by the topology.  This will only have an effect once peers
+ * are started if the FRIENDS_ONLY option is set in the base
+ * config.  Also takes an optional restrict topology which
+ * disallows connections based on particular transports
+ * UNLESS they are specified in the restricted topology.
+ *
+ * @param pg the peer group struct representing the running peers
+ * @param topology which topology to connect the peers in
+ * @param restrict_topology disallow restrict_transports transport
+ *                          connections to peers NOT in this topology
+ *                          use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions
+ * @param restrict_transports space delimited list of transports to blacklist
+ *                            to create restricted topology
+ *
+ * @return the maximum number of connections were all allowed peers
+ *         connected to each other
+ */
+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)
+{
+  int ret;
+
+  unsigned int num_connections;
+  int unblacklisted_connections;
+  char *filename;
+  struct PeerConnection *conn_iter;
+  struct PeerConnection *temp_conn;
+  unsigned int off;
+
+#if !OLD
+  unsigned int i;
+
+  for (i = 0; i < pg->total; i++)
+  {
+    pg->peers[i].allowed_peers = GNUNET_CONTAINER_multihashmap_create (100);
+    pg->peers[i].connect_peers = GNUNET_CONTAINER_multihashmap_create (100);
+    pg->peers[i].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create (100);
+    pg->peers[i].pg = pg;
+  }
+#endif
+
+  switch (topology)
+  {
+  case GNUNET_TESTING_TOPOLOGY_CLIQUE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating clique topology\n");
+    num_connections = create_clique (pg, &add_connections, ALLOWED, GNUNET_NO);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating small world (ring) topology\n");
+    num_connections = create_small_world_ring (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating small world (2d-torus) topology\n");
+    num_connections = create_small_world (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_RING:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring topology\n");
+    num_connections = create_ring (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating 2d torus topology\n");
+    num_connections = create_2d_torus (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Erdos-Renyi topology\n");
+    num_connections = create_erdos_renyi (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_INTERNAT:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating InterNAT topology\n");
+    num_connections = create_nated_internet (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating Scale Free topology\n");
+    num_connections = create_scale_free (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_LINE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating straight line topology\n");
+    num_connections = create_line (pg, &add_connections, ALLOWED);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_FROM_FILE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating topology from file!\n");
+    if (GNUNET_OK ==
+        GNUNET_CONFIGURATION_get_value_string (pg->cfg, "testing_old",
+                                               "topology_file", &filename))
+      num_connections =
+          create_from_file (pg, filename, &add_connections, ALLOWED);
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  "Missing configuration option TESTING:TOPOLOGY_FILE for creating topology from file!\n");
+      num_connections = 0;
+    }
+    break;
+  case GNUNET_TESTING_TOPOLOGY_NONE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                _
+                ("Creating no allowed topology (all peers can connect at core level)\n"));
+    num_connections = pg->total * pg->total;    /* Clique is allowed! */
+    break;
+  default:
+    num_connections = 0;
+    break;
+  }
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING_OLD", "F2F"))
+  {
+    ret = create_and_copy_friend_files (pg);
+    if (ret != GNUNET_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Failed during friend file copying!\n");
+      return GNUNET_SYSERR;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Friend files created/copied successfully!\n");
+    }
+  }
+
+  /* Use the create clique method to initially set all connections as blacklisted. */
+  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 */
+  switch (restrict_topology)
+  {
+  case GNUNET_TESTING_TOPOLOGY_CLIQUE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but clique topology\n");
+    unblacklisted_connections =
+        create_clique (pg, &remove_connections, BLACKLIST, GNUNET_NO);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but small world (ring) topology\n");
+    unblacklisted_connections =
+        create_small_world_ring (pg, &remove_connections, BLACKLIST);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but small world (2d-torus) topology\n");
+    unblacklisted_connections =
+        create_small_world (pg, &remove_connections, BLACKLIST);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_RING:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but ring topology\n");
+    unblacklisted_connections =
+        create_ring (pg, &remove_connections, BLACKLIST);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but 2d torus topology\n");
+    unblacklisted_connections =
+        create_2d_torus (pg, &remove_connections, BLACKLIST);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but Erdos-Renyi topology\n");
+    unblacklisted_connections =
+        create_erdos_renyi (pg, &remove_connections, BLACKLIST);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_INTERNAT:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but InterNAT topology\n");
+
+#if TOPOLOGY_HACK
+    for (off = 0; off < pg->total; off++)
+    {
+      conn_iter = pg->peers[off].allowed_peers_head;
+      while (conn_iter != NULL)
+      {
+        temp_conn = conn_iter->next;
+        GNUNET_free (conn_iter);
+        conn_iter = temp_conn;
+      }
+      pg->peers[off].allowed_peers_head = NULL;
+      pg->peers[off].allowed_peers_tail = NULL;
+
+      conn_iter = pg->peers[off].connect_peers_head;
+      while (conn_iter != NULL)
+      {
+        temp_conn = conn_iter->next;
+        GNUNET_free (conn_iter);
+        conn_iter = temp_conn;
+      }
+      pg->peers[off].connect_peers_head = NULL;
+      pg->peers[off].connect_peers_tail = NULL;
+    }
+    unblacklisted_connections =
+        create_nated_internet_copy (pg, &remove_connections, BLACKLIST);
+#else
+    unblacklisted_connections =
+        create_nated_internet (pg, &remove_connections, BLACKLIST);
+#endif
+
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but Scale Free topology\n");
+    unblacklisted_connections =
+        create_scale_free (pg, &remove_connections, BLACKLIST);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_LINE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Blacklisting all but straight line topology\n");
+    unblacklisted_connections =
+        create_line (pg, &remove_connections, BLACKLIST);
+  default:
+    break;
+  }
+
+  if ((unblacklisted_connections > 0) && (restrict_transports != NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating blacklist with `%s'\n",
+                restrict_transports);
+    ret = create_and_copy_blacklist_files (pg, restrict_transports);
+    if (ret != GNUNET_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Failed during blacklist file copying!\n");
+      return 0;
+    }
+    else
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Blacklist files created/copied successfully!\n");
+    }
+  }
+  return num_connections;
+}
+
+#if !OLD
+/**
+ * Iterator for choosing random peers to connect.
+ *
+ * @param cls closure, a RandomContext
+ * @param key the key the second Daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that the first is to connect to
+ *
+ * @return GNUNET_YES to continue iteration
+ */
+static int
+random_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct RandomContext *random_ctx = cls;
+  double random_number;
+  uint32_t second_pos;
+  GNUNET_HashCode first_hash;
+
+  random_number =
+      ((double)
+       GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                 UINT64_MAX)) / ((double) UINT64_MAX);
+  if (random_number < random_ctx->percentage)
+  {
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_CONTAINER_multihashmap_put (random_ctx->
+                                                      first->connect_peers_working_set,
+                                                      key, value,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+  }
+
+  /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */
+  uid_from_hash (key, &second_pos);
+  hash_from_uid (random_ctx->first_uid, &first_hash);
+  GNUNET_assert (random_ctx->pg->total > second_pos);
+  GNUNET_assert (GNUNET_YES ==
+                 GNUNET_CONTAINER_multihashmap_remove (random_ctx->
+                                                       pg->peers
+                                                       [second_pos].connect_peers,
+                                                       &first_hash,
+                                                       random_ctx->
+                                                       first->daemon));
+
+  return GNUNET_YES;
+}
+
+/**
+ * Iterator for adding at least X peers to a peers connection set.
+ *
+ * @param cls closure, MinimumContext
+ * @param key the key the second Daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that the first is to connect to
+ *
+ * @return GNUNET_YES to continue iteration
+ */
+static int
+minimum_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct MinimumContext *min_ctx = cls;
+  uint32_t second_pos;
+  GNUNET_HashCode first_hash;
+  unsigned int i;
+
+  if (GNUNET_CONTAINER_multihashmap_size
+      (min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add)
+  {
+    for (i = 0; i < min_ctx->num_to_add; i++)
+    {
+      if (min_ctx->pg_array[i] == min_ctx->current)
+      {
+        GNUNET_assert (GNUNET_OK ==
+                       GNUNET_CONTAINER_multihashmap_put (min_ctx->
+                                                          first->connect_peers_working_set,
+                                                          key, value,
+                                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+        uid_from_hash (key, &second_pos);
+        hash_from_uid (min_ctx->first_uid, &first_hash);
+        GNUNET_assert (min_ctx->pg->total > second_pos);
+        GNUNET_assert (GNUNET_OK ==
+                       GNUNET_CONTAINER_multihashmap_put (min_ctx->
+                                                          pg->peers
+                                                          [second_pos].connect_peers_working_set,
+                                                          &first_hash,
+                                                          min_ctx->first->
+                                                          daemon,
+                                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+        /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */
+        GNUNET_assert (GNUNET_YES ==
+                       GNUNET_CONTAINER_multihashmap_remove (min_ctx->
+                                                             pg->peers
+                                                             [second_pos].connect_peers,
+                                                             &first_hash,
+                                                             min_ctx->
+                                                             first->daemon));
+      }
+    }
+    min_ctx->current++;
+    return GNUNET_YES;
+  }
+  else
+    return GNUNET_NO;           /* We can stop iterating, we have enough peers! */
+
+}
+
+/**
+ * Iterator for adding peers to a connection set based on a depth first search.
+ *
+ * @param cls closure, MinimumContext
+ * @param key the key the second daemon was stored under
+ * @param value the GNUNET_TESTING_Daemon that the first is to connect to
+ *
+ * @return GNUNET_YES to continue iteration
+ */
+static int
+dfs_connect_iterator (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct DFSContext *dfs_ctx = cls;
+  GNUNET_HashCode first_hash;
+
+  if (dfs_ctx->current == dfs_ctx->chosen)
+  {
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_CONTAINER_multihashmap_put (dfs_ctx->
+                                                      first->connect_peers_working_set,
+                                                      key, value,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+    uid_from_hash (key, &dfs_ctx->second_uid);
+    hash_from_uid (dfs_ctx->first_uid, &first_hash);
+    GNUNET_assert (GNUNET_OK ==
+                   GNUNET_CONTAINER_multihashmap_put (dfs_ctx->
+                                                      pg->peers[dfs_ctx->
+                                                                second_uid].connect_peers_working_set,
+                                                      &first_hash,
+                                                      dfs_ctx->first->daemon,
+                                                      GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (dfs_ctx->
+                                                         pg->peers
+                                                         [dfs_ctx->second_uid].connect_peers,
+                                                         &first_hash,
+                                                         dfs_ctx->
+                                                         first->daemon));
+    /* Can't remove second from first yet because we are currently iterating, hence the return value in the DFSContext! */
+    return GNUNET_NO;           /* We have found our peer, don't iterate more */
+  }
+
+  dfs_ctx->current++;
+  return GNUNET_YES;
+}
+#endif
+
+/**
+ * From the set of connections possible, choose percentage percent of connections
+ * to actually connect.
+ *
+ * @param pg the peergroup we are dealing with
+ * @param percentage what percent of total connections to make
+ */
+void
+choose_random_connections (struct GNUNET_TESTING_PeerGroup *pg,
+                           double percentage)
+{
+  uint32_t pg_iter;
+
+#if OLD
+  struct PeerConnection *conn_iter;
+  double random_number;
+#else
+  struct RandomContext random_ctx;
+#endif
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+#if OLD
+    conn_iter = pg->peers[pg_iter].connect_peers_head;
+    while (conn_iter != NULL)
+    {
+      random_number =
+          ((double)
+           GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                     UINT64_MAX)) / ((double) UINT64_MAX);
+      if (random_number < percentage)
+      {
+        add_connections (pg, pg_iter, conn_iter->index, WORKING_SET,
+                         GNUNET_YES);
+      }
+      conn_iter = conn_iter->next;
+    }
+#else
+    random_ctx.first_uid = pg_iter;
+    random_ctx.first = &pg->peers[pg_iter];
+    random_ctx.percentage = percentage;
+    random_ctx.pg = pg;
+    pg->peers[pg_iter].connect_peers_working_set =
+        GNUNET_CONTAINER_multihashmap_create (pg->total);
+    GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers,
+                                           &random_connect_iterator,
+                                           &random_ctx);
+    /* Now remove the old connections */
+    GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers);
+    /* And replace with the random set */
+    pg->peers[pg_iter].connect_peers =
+        pg->peers[pg_iter].connect_peers_working_set;
+#endif
+  }
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    conn_iter = pg->peers[pg_iter].connect_peers_head;
+    while (pg->peers[pg_iter].connect_peers_head != NULL)
+      remove_connections (pg, pg_iter,
+                          pg->peers[pg_iter].connect_peers_head->index, CONNECT,
+                          GNUNET_YES);
+
+    pg->peers[pg_iter].connect_peers_head =
+        pg->peers[pg_iter].connect_peers_working_set_head;
+    pg->peers[pg_iter].connect_peers_tail =
+        pg->peers[pg_iter].connect_peers_working_set_tail;
+    pg->peers[pg_iter].connect_peers_working_set_head = NULL;
+    pg->peers[pg_iter].connect_peers_working_set_tail = NULL;
+  }
+}
+
+/**
+ * Count the number of connections in a linked list of connections.
+ *
+ * @param conn_list the connection list to get the count of
+ *
+ * @return the number of elements in the list
+ */
+static unsigned int
+count_connections (struct PeerConnection *conn_list)
+{
+  struct PeerConnection *iter;
+  unsigned int count;
+
+  count = 0;
+  iter = conn_list;
+  while (iter != NULL)
+  {
+    iter = iter->next;
+    count++;
+  }
+  return count;
+}
+
+static unsigned int
+count_workingset_connections (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  unsigned int count;
+  unsigned int pg_iter;
+
+#if OLD
+  struct PeerConnection *conn_iter;
+#endif
+  count = 0;
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+#if OLD
+    conn_iter = pg->peers[pg_iter].connect_peers_working_set_head;
+    while (conn_iter != NULL)
+    {
+      count++;
+      conn_iter = conn_iter->next;
+    }
+#else
+    count +=
+        GNUNET_CONTAINER_multihashmap_size (pg->
+                                            peers
+                                            [pg_iter].connect_peers_working_set);
+#endif
+  }
+
+  return count;
+}
+
+static unsigned int
+count_allowed_connections (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  unsigned int count;
+  unsigned int pg_iter;
+
+#if OLD
+  struct PeerConnection *conn_iter;
+#endif
+
+  count = 0;
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+#if OLD
+    conn_iter = pg->peers[pg_iter].allowed_peers_head;
+    while (conn_iter != NULL)
+    {
+      count++;
+      conn_iter = conn_iter->next;
+    }
+#else
+    count +=
+        GNUNET_CONTAINER_multihashmap_size (pg->peers[pg_iter].allowed_peers);
+#endif
+  }
+
+  return count;
+}
+
+/**
+ * From the set of connections possible, choose at least num connections per
+ * peer.
+ *
+ * @param pg the peergroup we are dealing with
+ * @param num how many connections at least should each peer have (if possible)?
+ */
+static void
+choose_minimum (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
+{
+#if !OLD
+  struct MinimumContext minimum_ctx;
+#else
+  struct PeerConnection *conn_iter;
+  unsigned int temp_list_size;
+  unsigned int i;
+  unsigned int count;
+  uint32_t random;              /* Random list entry to connect peer to */
+#endif
+  uint32_t pg_iter;
+
+#if OLD
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    temp_list_size = count_connections (pg->peers[pg_iter].connect_peers_head);
+    if (temp_list_size == 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Peer %d has 0 connections!?!?\n",
+                  pg_iter);
+      break;
+    }
+    for (i = 0; i < num; i++)
+    {
+      random =
+          GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_list_size);
+      conn_iter = pg->peers[pg_iter].connect_peers_head;
+      for (count = 0; count < random; count++)
+        conn_iter = conn_iter->next;
+      /* We now have a random connection, connect it! */
+      GNUNET_assert (conn_iter != NULL);
+      add_connections (pg, pg_iter, conn_iter->index, WORKING_SET, GNUNET_YES);
+    }
+  }
+#else
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    pg->peers[pg_iter].connect_peers_working_set =
+        GNUNET_CONTAINER_multihashmap_create (num);
+  }
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    minimum_ctx.first_uid = pg_iter;
+    minimum_ctx.pg_array =
+        GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
+                                      GNUNET_CONTAINER_multihashmap_size
+                                      (pg->peers[pg_iter].connect_peers));
+    minimum_ctx.first = &pg->peers[pg_iter];
+    minimum_ctx.pg = pg;
+    minimum_ctx.num_to_add = num;
+    minimum_ctx.current = 0;
+    GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].connect_peers,
+                                           &minimum_connect_iterator,
+                                           &minimum_ctx);
+  }
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    /* Remove the "old" connections */
+    GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers);
+    /* And replace with the working set */
+    pg->peers[pg_iter].connect_peers =
+        pg->peers[pg_iter].connect_peers_working_set;
+  }
+#endif
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    while (pg->peers[pg_iter].connect_peers_head != NULL)
+    {
+      conn_iter = pg->peers[pg_iter].connect_peers_head;
+      GNUNET_CONTAINER_DLL_remove (pg->peers[pg_iter].connect_peers_head,
+                                   pg->peers[pg_iter].connect_peers_tail,
+                                   conn_iter);
+      GNUNET_free (conn_iter);
+      /*remove_connections(pg, pg_iter, pg->peers[pg_iter].connect_peers_head->index, CONNECT, GNUNET_YES); */
+    }
+
+    pg->peers[pg_iter].connect_peers_head =
+        pg->peers[pg_iter].connect_peers_working_set_head;
+    pg->peers[pg_iter].connect_peers_tail =
+        pg->peers[pg_iter].connect_peers_working_set_tail;
+    pg->peers[pg_iter].connect_peers_working_set_head = NULL;
+    pg->peers[pg_iter].connect_peers_working_set_tail = NULL;
+  }
+}
+
+#if !OLD
+struct FindClosestContext
+{
+    /**
+     * The currently known closest peer.
+     */
+  struct GNUNET_TESTING_Daemon *closest;
+
+    /**
+     * The info for the peer we are adding connections for.
+     */
+  struct PeerData *curr_peer;
+
+    /**
+     * The distance (bits) between the current
+     * peer and the currently known closest.
+     */
+  unsigned int closest_dist;
+
+    /**
+     * The offset of the closest known peer in
+     * the peer group.
+     */
+  unsigned int closest_num;
+};
+
+/**
+ * Iterator over hash map entries of the allowed
+ * peer connections.  Find the closest, not already
+ * connected peer and return it.
+ *
+ * @param cls closure (struct FindClosestContext)
+ * @param key current key code (hash of offset in pg)
+ * @param value value in the hash map - a GNUNET_TESTING_Daemon
+ * @return GNUNET_YES if we should continue to
+ *         iterate,
+ *         GNUNET_NO if not.
+ */
+static int
+find_closest_peers (void *cls, const GNUNET_HashCode * key, void *value)
+{
+  struct FindClosestContext *closest_ctx = cls;
+  struct GNUNET_TESTING_Daemon *daemon = value;
+
+  if (((closest_ctx->closest == NULL) ||
+       (GNUNET_CRYPTO_hash_matching_bits
+        (&daemon->id.hashPubKey,
+         &closest_ctx->curr_peer->daemon->id.hashPubKey) >
+        closest_ctx->closest_dist)) &&
+      (GNUNET_YES !=
+       GNUNET_CONTAINER_multihashmap_contains (closest_ctx->
+                                               curr_peer->connect_peers, key)))
+  {
+    closest_ctx->closest_dist =
+        GNUNET_CRYPTO_hash_matching_bits (&daemon->id.hashPubKey,
+                                          &closest_ctx->curr_peer->daemon->
+                                          id.hashPubKey);
+    closest_ctx->closest = daemon;
+    uid_from_hash (key, &closest_ctx->closest_num);
+  }
+  return GNUNET_YES;
+}
+
+/**
+ * From the set of connections possible, choose at num connections per
+ * peer based on depth which are closest out of those allowed.  Guaranteed
+ * to add num peers to connect to, provided there are that many peers
+ * in the underlay topology to connect to.
+ *
+ * @param pg the peergroup we are dealing with
+ * @param num how many connections at least should each peer have (if possible)?
+ * @param proc processor to actually add the connections
+ * @param list the peer list to use
+ */
+void
+add_closest (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num,
+             GNUNET_TESTING_ConnectionProcessor proc, enum PeerLists list)
+{
+#if OLD
+
+#else
+  struct FindClosestContext closest_ctx;
+#endif
+  uint32_t pg_iter;
+  uint32_t i;
+
+  for (i = 0; i < num; i++)     /* Each time find a closest peer (from those available) */
+  {
+    for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+    {
+      closest_ctx.curr_peer = &pg->peers[pg_iter];
+      closest_ctx.closest = NULL;
+      closest_ctx.closest_dist = 0;
+      closest_ctx.closest_num = 0;
+      GNUNET_CONTAINER_multihashmap_iterate (pg->peers[pg_iter].allowed_peers,
+                                             &find_closest_peers, &closest_ctx);
+      if (closest_ctx.closest != NULL)
+      {
+        GNUNET_assert (closest_ctx.closest_num < pg->total);
+        proc (pg, pg_iter, closest_ctx.closest_num, list);
+      }
+    }
+  }
+}
+#endif
+
+/**
+ * From the set of connections possible, choose at least num connections per
+ * peer based on depth first traversal of peer connections.  If DFS leaves
+ * peers unconnected, ensure those peers get connections.
+ *
+ * @param pg the peergroup we are dealing with
+ * @param num how many connections at least should each peer have (if possible)?
+ */
+void
+perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
+{
+  uint32_t pg_iter;
+  uint32_t dfs_count;
+  uint32_t starting_peer;
+  uint32_t least_connections;
+  uint32_t random_connection;
+
+#if OLD
+  unsigned int temp_count;
+  struct PeerConnection *peer_iter;
+#else
+  struct DFSContext dfs_ctx;
+  GNUNET_HashCode second_hash;
+#endif
+
+#if OLD
+  starting_peer = 0;
+  dfs_count = 0;
+  while ((count_workingset_connections (pg) < num * pg->total) &&
+         (count_allowed_connections (pg) > 0))
+  {
+    if (dfs_count % pg->total == 0)     /* Restart the DFS at some weakly connected peer */
+    {
+      least_connections = -1;   /* Set to very high number */
+      for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+      {
+        temp_count =
+            count_connections (pg->
+                               peers[pg_iter].connect_peers_working_set_head);
+        if (temp_count < least_connections)
+        {
+          starting_peer = pg_iter;
+          least_connections = temp_count;
+        }
+      }
+    }
+
+    temp_count =
+        count_connections (pg->peers[starting_peer].connect_peers_head);
+    if (temp_count == 0)
+      continue;                 /* FIXME: infinite loop? */
+
+    random_connection =
+        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, temp_count);
+    temp_count = 0;
+    peer_iter = pg->peers[starting_peer].connect_peers_head;
+    while (temp_count < random_connection)
+    {
+      peer_iter = peer_iter->next;
+      temp_count++;
+    }
+    GNUNET_assert (peer_iter != NULL);
+    add_connections (pg, starting_peer, peer_iter->index, WORKING_SET,
+                     GNUNET_NO);
+    remove_connections (pg, starting_peer, peer_iter->index, CONNECT,
+                        GNUNET_YES);
+    starting_peer = peer_iter->index;
+    dfs_count++;
+  }
+
+#else
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    pg->peers[pg_iter].connect_peers_working_set =
+        GNUNET_CONTAINER_multihashmap_create (num);
+  }
+
+  starting_peer = 0;
+  dfs_count = 0;
+  while ((count_workingset_connections (pg) < num * pg->total) &&
+         (count_allowed_connections (pg) > 0))
+  {
+    if (dfs_count % pg->total == 0)     /* Restart the DFS at some weakly connected peer */
+    {
+      least_connections = -1;   /* Set to very high number */
+      for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+      {
+        if (GNUNET_CONTAINER_multihashmap_size
+            (pg->peers[pg_iter].connect_peers_working_set) < least_connections)
+        {
+          starting_peer = pg_iter;
+          least_connections =
+              GNUNET_CONTAINER_multihashmap_size (pg->
+                                                  peers
+                                                  [pg_iter].connect_peers_working_set);
+        }
+      }
+    }
+
+    if (GNUNET_CONTAINER_multihashmap_size (pg->peers[starting_peer].connect_peers) == 0)       /* Ensure there is at least one peer left to connect! */
+    {
+      dfs_count = 0;
+      continue;
+    }
+
+    /* Choose a random peer from the chosen peers set of connections to add */
+    dfs_ctx.chosen =
+        GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                  GNUNET_CONTAINER_multihashmap_size (pg->peers
+                                                                      [starting_peer].connect_peers));
+    dfs_ctx.first_uid = starting_peer;
+    dfs_ctx.first = &pg->peers[starting_peer];
+    dfs_ctx.pg = pg;
+    dfs_ctx.current = 0;
+
+    GNUNET_CONTAINER_multihashmap_iterate (pg->
+                                           peers[starting_peer].connect_peers,
+                                           &dfs_connect_iterator, &dfs_ctx);
+    /* Remove the second from the first, since we will be continuing the search and may encounter the first peer again! */
+    hash_from_uid (dfs_ctx.second_uid, &second_hash);
+    GNUNET_assert (GNUNET_YES ==
+                   GNUNET_CONTAINER_multihashmap_remove (pg->peers
+                                                         [starting_peer].connect_peers,
+                                                         &second_hash,
+                                                         pg->
+                                                         peers
+                                                         [dfs_ctx.second_uid].daemon));
+    starting_peer = dfs_ctx.second_uid;
+  }
+
+  for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
+  {
+    /* Remove the "old" connections */
+    GNUNET_CONTAINER_multihashmap_destroy (pg->peers[pg_iter].connect_peers);
+    /* And replace with the working set */
+    pg->peers[pg_iter].connect_peers =
+        pg->peers[pg_iter].connect_peers_working_set;
+  }
+#endif
+}
+
+/**
+ * Internal callback for topology information for a particular peer.
+ */
+static void
+internal_topology_callback (void *cls, const struct GNUNET_PeerIdentity *peer,
+                            const struct GNUNET_ATS_Information *atsi,
+                            unsigned int atsi_count)
+{
+  struct CoreContext *core_ctx = cls;
+  struct TopologyIterateContext *iter_ctx = core_ctx->iter_context;
+
+  if (peer == NULL)             /* Either finished, or something went wrong */
+  {
+    iter_ctx->completed++;
+    iter_ctx->connected--;
+    /* One core context allocated per iteration, must free! */
+    GNUNET_free (core_ctx);
+  }
+  else
+  {
+    iter_ctx->topology_cb (iter_ctx->cls, &core_ctx->daemon->id, peer, NULL);
+  }
+
+  if (iter_ctx->completed == iter_ctx->total)
+  {
+    iter_ctx->topology_cb (iter_ctx->cls, NULL, NULL, NULL);
+    /* Once all are done, free the iteration context */
+    GNUNET_free (iter_ctx);
+  }
+}
+
+/**
+ * Check running topology iteration tasks, if below max start a new one, otherwise
+ * schedule for some time in the future.
+ */
+static void
+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) != 0)
+    return;
+
+  if (topology_context->connected >
+      topology_context->pg->max_outstanding_connections)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Delaying connect, we have too many outstanding connections!\n");
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_get_topology, core_context);
+  }
+  else
+  {
+    topology_context->connected++;
+
+    if (GNUNET_OK !=
+        GNUNET_CORE_iterate_peers (core_context->daemon->cfg,
+                                   &internal_topology_callback, core_context))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Topology iteration failed.\n");
+      internal_topology_callback (core_context, NULL, NULL, 0);
+    }
+  }
+}
+
+/**
+ * Iterate over all (running) peers in the peer group, retrieve
+ * all connections that each currently has.
+ */
+void
+GNUNET_TESTING_get_topology (struct GNUNET_TESTING_PeerGroup *pg,
+                             GNUNET_TESTING_NotifyTopology cb, void *cls)
+{
+  struct TopologyIterateContext *topology_context;
+  struct CoreContext *core_ctx;
+  unsigned int i;
+  unsigned int total_count;
+
+  /* Allocate a single topology iteration context */
+  topology_context = GNUNET_malloc (sizeof (struct TopologyIterateContext));
+  topology_context->topology_cb = cb;
+  topology_context->cls = cls;
+  topology_context->pg = pg;
+  total_count = 0;
+  for (i = 0; i < pg->total; i++)
+  {
+    if (pg->peers[i].daemon->running == GNUNET_YES)
+    {
+      /* Allocate one core context per core we need to connect to */
+      core_ctx = GNUNET_malloc (sizeof (struct CoreContext));
+      core_ctx->daemon = pg->peers[i].daemon;
+      /* Set back pointer to topology iteration context */
+      core_ctx->iter_context = topology_context;
+      GNUNET_SCHEDULER_add_now (&schedule_get_topology, core_ctx);
+      total_count++;
+    }
+  }
+  if (total_count == 0)
+  {
+    cb (cls, NULL, NULL, "Cannot iterate over topology, no running peers!");
+    GNUNET_free (topology_context);
+  }
+  else
+    topology_context->total = total_count;
+  return;
+}
+
+/**
+ * Callback function to process statistic values.
+ * This handler is here only really to insert a peer
+ * identity (or daemon) so the statistics can be uniquely
+ * tied to a single running peer.
+ *
+ * @param cls closure
+ * @param subsystem name of subsystem that created the statistic
+ * @param name the name of the datum
+ * @param value the current value
+ * @param is_persistent GNUNET_YES if the value is persistent, GNUNET_NO if not
+ * @return GNUNET_OK to continue, GNUNET_SYSERR to abort iteration
+ */
+static int
+internal_stats_callback (void *cls, const char *subsystem, const char *name,
+                         uint64_t value, int is_persistent)
+{
+  struct StatsCoreContext *core_context = cls;
+  struct StatsIterateContext *stats_context =
+      (struct StatsIterateContext *) core_context->iter_context;
+
+  return stats_context->proc (stats_context->cls, &core_context->daemon->id,
+                              subsystem, name, value, is_persistent);
+}
+
+
+/**
+ * We don't need the statistics handle anymore, destroy it.
+ * 
+ * @param cls Closure (the statistics handle to destroy)
+ * @param tc Task Context
+ */
+static void
+internal_destroy_statistics (void *cls,
+                             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct GNUNET_STATISTICS_Handle *h = cls;
+
+  GNUNET_STATISTICS_destroy (h, GNUNET_NO);
+}
+
+
+/**
+ * Internal continuation call for statistics iteration.
+ *
+ * @param cls closure, the CoreContext for this iteration
+ * @param success whether or not the statistics iterations
+ *        was canceled or not (we don't care)
+ */
+static void
+internal_stats_cont (void *cls, int success)
+{
+  struct StatsCoreContext *core_context = cls;
+  struct StatsIterateContext *stats_context =
+      (struct StatsIterateContext *) core_context->iter_context;
+
+  stats_context->connected--;
+  stats_context->completed++;
+
+  if (stats_context->completed == stats_context->total)
+  {
+    stats_context->cont (stats_context->cls, GNUNET_YES);
+    GNUNET_free (stats_context);
+  }
+
+  if (core_context->stats_handle != NULL)
+    /* Cannot destroy handle inside the continuation */
+    GNUNET_SCHEDULER_add_now (&internal_destroy_statistics,
+                              core_context->stats_handle);
+
+  GNUNET_free (core_context);
+}
+
+/**
+ * Check running topology iteration tasks, if below max start a new one, otherwise
+ * schedule for some time in the future.
+ */
+static void
+schedule_get_statistics (void *cls,
+                         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) != 0)
+    return;
+
+  if (stats_context->connected > stats_context->pg->max_outstanding_connections)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Delaying connect, we have too many outstanding connections!\n");
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_get_statistics, core_context);
+  }
+  else
+  {
+    stats_context->connected++;
+    core_context->stats_handle =
+        GNUNET_STATISTICS_create ("testing_old", core_context->daemon->cfg);
+    if (core_context->stats_handle == NULL)
+    {
+      internal_stats_cont (core_context, GNUNET_NO);
+      return;
+    }
+
+    core_context->stats_get_handle =
+        GNUNET_STATISTICS_get (core_context->stats_handle, NULL, NULL,
+                               GNUNET_TIME_UNIT_FOREVER_REL,
+                               &internal_stats_cont, &internal_stats_callback,
+                               core_context);
+    if (core_context->stats_get_handle == NULL)
+      internal_stats_cont (core_context, GNUNET_NO);
+
+  }
+}
+
+struct DuplicateStats
+{
+  /**
+   * Next item in the list
+   */
+  struct DuplicateStats *next;
+
+  /**
+   * Nasty string, concatenation of relevant information.
+   */
+  char *unique_string;
+};
+
+/**
+ * Check whether the combination of port/host/unix domain socket
+ * already exists in the list of peers being checked for statistics.
+ *
+ * @param pg the peergroup in question
+ * @param specific_peer the peer we're concerned with
+ * @param stats_list the list to return to the caller
+ *
+ * @return GNUNET_YES if the statistics instance has been seen already,
+ *         GNUNET_NO if not (and we may have added it to the list)
+ */
+static int
+stats_check_existing (struct GNUNET_TESTING_PeerGroup *pg,
+                      struct PeerData *specific_peer,
+                      struct DuplicateStats **stats_list)
+{
+  struct DuplicateStats *pos;
+  char *unix_domain_socket;
+  unsigned long long port;
+  char *to_match;
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "testing_old",
+                                            "single_statistics_per_host"))
+    return GNUNET_NO;           /* Each peer has its own statistics instance, do nothing! */
+
+  pos = *stats_list;
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (specific_peer->cfg, "statistics",
+                                             "unixpath", &unix_domain_socket))
+    return GNUNET_NO;
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (specific_peer->cfg, "statistics",
+                                             "port", &port))
+  {
+    GNUNET_free (unix_domain_socket);
+    return GNUNET_NO;
+  }
+
+  if (specific_peer->daemon->hostname != NULL)
+    GNUNET_asprintf (&to_match, "%s%s%llu", specific_peer->daemon->hostname,
+                     unix_domain_socket, port);
+  else
+    GNUNET_asprintf (&to_match, "%s%llu", unix_domain_socket, port);
+
+  while (pos != NULL)
+  {
+    if (0 == strcmp (to_match, pos->unique_string))
+    {
+      GNUNET_free (unix_domain_socket);
+      GNUNET_free (to_match);
+      return GNUNET_YES;
+    }
+    pos = pos->next;
+  }
+  pos = GNUNET_malloc (sizeof (struct DuplicateStats));
+  pos->unique_string = to_match;
+  pos->next = *stats_list;
+  *stats_list = pos;
+  GNUNET_free (unix_domain_socket);
+  return GNUNET_NO;
+}
+
+/**
+ * Iterate over all (running) peers in the peer group, retrieve
+ * all statistics from each.
+ *
+ * @param pg the peergroup to iterate statistics of
+ * @param cont continuation to call once all stats have been retrieved
+ * @param proc processing function for each statistic from each peer
+ * @param cls closure to pass to proc
+ *
+ */
+void
+GNUNET_TESTING_get_statistics (struct GNUNET_TESTING_PeerGroup *pg,
+                               GNUNET_STATISTICS_Callback cont,
+                               GNUNET_TESTING_STATISTICS_Iterator proc,
+                               void *cls)
+{
+  struct StatsIterateContext *stats_context;
+  struct StatsCoreContext *core_ctx;
+  unsigned int i;
+  unsigned int total_count;
+  struct DuplicateStats *stats_list;
+  struct DuplicateStats *pos;
+
+  stats_list = NULL;
+
+  /* Allocate a single stats iteration context */
+  stats_context = GNUNET_malloc (sizeof (struct StatsIterateContext));
+  stats_context->cont = cont;
+  stats_context->proc = proc;
+  stats_context->cls = cls;
+  stats_context->pg = pg;
+  total_count = 0;
+
+  for (i = 0; i < pg->total; i++)
+  {
+    if ((pg->peers[i].daemon->running == GNUNET_YES) &&
+        (GNUNET_NO == stats_check_existing (pg, &pg->peers[i], &stats_list)))
+    {
+      /* Allocate one core context per core we need to connect to */
+      core_ctx = GNUNET_malloc (sizeof (struct StatsCoreContext));
+      core_ctx->daemon = pg->peers[i].daemon;
+      /* Set back pointer to topology iteration context */
+      core_ctx->iter_context = stats_context;
+      GNUNET_SCHEDULER_add_now (&schedule_get_statistics, core_ctx);
+      total_count++;
+    }
+  }
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Retrieving stats from %u total instances.\n", total_count);
+  if (0 != total_count)
+    stats_context->total = total_count;
+  else
+    GNUNET_free (stats_context);
+  if (stats_list != NULL)
+  {
+    pos = stats_list;
+    while (pos != NULL)
+    {
+      GNUNET_free (pos->unique_string);
+      stats_list = pos->next;
+      GNUNET_free (pos);
+      pos = stats_list->next;
+    }
+  }
+  return;
+}
+
+/**
+ * Stop the connection process temporarily.
+ *
+ * @param pg the peer group to stop connecting
+ */
+void
+GNUNET_TESTING_stop_connections (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  pg->stop_connects = GNUNET_YES;
+}
+
+/**
+ * Resume the connection process temporarily.
+ *
+ * @param pg the peer group to resume connecting
+ */
+void
+GNUNET_TESTING_resume_connections (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  pg->stop_connects = GNUNET_NO;
+}
+
+/**
+ * There are many ways to connect peers that are supported by this function.
+ * To connect peers in the same topology that was created via the
+ * GNUNET_TESTING_create_topology, the topology variable must be set to
+ * GNUNET_TESTING_TOPOLOGY_NONE.  If the topology variable is specified,
+ * a new instance of that topology will be generated and attempted to be
+ * connected.  This could result in some connections being impossible,
+ * because some topologies are non-deterministic.
+ *
+ * @param pg the peer group struct representing the running peers
+ * @param topology which topology to connect the peers in
+ * @param options options for connecting the topology
+ * @param option_modifier modifier for options that take a parameter
+ * @param connect_timeout how long to wait before giving up on connecting
+ *                        two peers
+ * @param connect_attempts how many times to attempt to connect two peers
+ *                         over the connect_timeout duration
+ * @param notify_callback notification to be called once all connections completed
+ * @param notify_cls closure for notification callback
+ *
+ * @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)
+{
+  switch (topology)
+  {
+  case GNUNET_TESTING_TOPOLOGY_CLIQUE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating clique CONNECT topology\n");
+    create_clique (pg, &add_connections, CONNECT, GNUNET_NO);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating small world (ring) CONNECT topology\n");
+    create_small_world_ring (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating small world (2d-torus) CONNECT topology\n");
+    create_small_world (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_RING:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating ring CONNECT topology\n");
+    create_ring (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating 2d torus CONNECT topology\n");
+    create_2d_torus (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating Erdos-Renyi CONNECT topology\n");
+    create_erdos_renyi (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_INTERNAT:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating InterNAT CONNECT topology\n");
+    create_nated_internet (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating Scale Free CONNECT topology\n");
+    create_scale_free (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_LINE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Creating straight line CONNECT topology\n");
+    create_line (pg, &add_connections, CONNECT);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_NONE:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Creating no CONNECT topology\n");
+    copy_allowed_topology (pg);
+    break;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Unknown topology specification, can't connect peers!\n"));
+    return GNUNET_SYSERR;
+  }
+
+  switch (options)
+  {
+  case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Connecting random subset (%'.2f percent) of possible peers\n",
+                100 * option_modifier);
+    choose_random_connections (pg, option_modifier);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Connecting a minimum of %u peers each (if possible)\n",
+                (unsigned int) option_modifier);
+    choose_minimum (pg, (unsigned int) option_modifier);
+    break;
+  case GNUNET_TESTING_TOPOLOGY_OPTION_DFS:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Using DFS to connect a minimum of %u peers each (if possible)\n",
+                (unsigned int) option_modifier);
+#if FIXME
+    perform_dfs (pg, (int) option_modifier);
+#endif
+    break;
+  case GNUNET_TESTING_TOPOLOGY_OPTION_ADD_CLOSEST:
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Finding additional %u closest peers each (if possible)\n",
+                (unsigned int) option_modifier);
+#if FIXME
+    add_closest (pg, (unsigned int) option_modifier, &add_connections, CONNECT);
+#endif
+    break;
+  case GNUNET_TESTING_TOPOLOGY_OPTION_NONE:
+    break;
+  case GNUNET_TESTING_TOPOLOGY_OPTION_ALL:
+    break;
+  default:
+    break;
+  }
+
+  return connect_topology (pg, connect_timeout, connect_attempts,
+                           notify_callback, notify_cls);
+}
+
+/**
+ * Lookup and return the number of SSH connections to a host.
+ *
+ * @param hostname the hostname to lookup in the list
+ * @param pg the peergroup that the host belongs to
+ *
+ * @return the number of current ssh connections to the host
+ */
+static unsigned int
+count_outstanding_at_host (const char *hostname,
+                           struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct OutstandingSSH *pos;
+
+  pos = pg->ssh_head;
+  while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0))
+    pos = pos->next;
+  GNUNET_assert (pos != NULL);
+  return pos->outstanding;
+}
+
+/**
+ * Increment the number of SSH connections to a host by one.
+ *
+ * @param hostname the hostname to lookup in the list
+ * @param pg the peergroup that the host belongs to
+ *
+ */
+static void
+increment_outstanding_at_host (const char *hostname,
+                               struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct OutstandingSSH *pos;
+
+  pos = pg->ssh_head;
+  while ((NULL != pos) && (strcmp (pos->hostname, hostname) != 0))
+    pos = pos->next;
+  GNUNET_assert (NULL != pos);
+  pos->outstanding++;
+}
+
+/**
+ * Decrement the number of SSH connections to a host by one.
+ *
+ * @param hostname the hostname to lookup in the list
+ * @param pg the peergroup that the host belongs to
+ *
+ */
+static void
+decrement_outstanding_at_host (const char *hostname,
+                               struct GNUNET_TESTING_PeerGroup *pg)
+{
+  struct OutstandingSSH *pos;
+
+  pos = pg->ssh_head;
+  while ((pos != NULL) && (strcmp (pos->hostname, hostname) != 0))
+    pos = pos->next;
+  GNUNET_assert (pos != NULL);
+  pos->outstanding--;
+}
+
+/**
+ * Callback that is called whenever a hostkey is generated
+ * for a peer.  Call the real callback and decrement the
+ * starting counter for the peergroup.
+ *
+ * @param cls closure
+ * @param id identifier for the daemon, NULL on error
+ * @param d handle for the daemon
+ * @param emsg error message (NULL on success)
+ */
+static void
+internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                           struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  struct InternalStartContext *internal_context = cls;
+
+  internal_context->peer->pg->starting--;
+  internal_context->peer->pg->started++;
+  if (internal_context->hostname != NULL)
+    decrement_outstanding_at_host (internal_context->hostname,
+                                   internal_context->peer->pg);
+  if (internal_context->hostkey_callback != NULL)
+    internal_context->hostkey_callback (internal_context->hostkey_cls, id, d,
+                                        emsg);
+  else if (internal_context->peer->pg->started ==
+           internal_context->peer->pg->total)
+  {
+    internal_context->peer->pg->started = 0;    /* Internal startup may use this counter! */
+    GNUNET_TESTING_daemons_continue_startup (internal_context->peer->pg);
+  }
+}
+
+/**
+ * Callback that is called whenever a peer has finished starting.
+ * Call the real callback and decrement the starting counter
+ * for the peergroup.
+ *
+ * @param cls closure
+ * @param id identifier for the daemon, NULL on error
+ * @param cfg config
+ * @param d handle for the daemon
+ * @param emsg error message (NULL on success)
+ */
+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)
+{
+  struct InternalStartContext *internal_context = cls;
+
+  internal_context->peer->pg->starting--;
+  if (internal_context->hostname != NULL)
+    decrement_outstanding_at_host (internal_context->hostname,
+                                   internal_context->peer->pg);
+  if (internal_context->start_cb != NULL)
+    internal_context->start_cb (internal_context->start_cb_cls, id, cfg, d,
+                                emsg);
+}
+
+
+/**
+ * Calls GNUNET_TESTING_daemon_continue_startup to set the daemon's state
+ * from HOSTKEY_CREATED to TOPOLOGY_SETUP. Makes sure not to saturate a host
+ * with requests delaying them when needed.
+ *
+ * @param cls closure: internal context of the daemon.
+ * @param tc TaskContext
+ */
+static void
+internal_continue_startup (void *cls,
+                           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct InternalStartContext *internal_context = cls;
+
+  internal_context->peer->startup_task = GNUNET_SCHEDULER_NO_TASK;
+
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+  {
+    return;
+  }
+
+  if ((internal_context->peer->pg->starting <
+       internal_context->peer->pg->max_concurrent_ssh) ||
+      ((internal_context->hostname != NULL) &&
+       (count_outstanding_at_host
+        (internal_context->hostname,
+         internal_context->peer->pg) <
+        internal_context->peer->pg->max_concurrent_ssh)))
+  {
+    if (internal_context->hostname != NULL)
+      increment_outstanding_at_host (internal_context->hostname,
+                                     internal_context->peer->pg);
+    internal_context->peer->pg->starting++;
+    GNUNET_TESTING_daemon_continue_startup (internal_context->peer->daemon);
+  }
+  else
+  {
+    internal_context->peer->startup_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                      (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                      &internal_continue_startup,
+                                      internal_context);
+  }
+}
+
+/**
+ * Callback for informing us about a successful
+ * or unsuccessful churn start call.
+ *
+ * @param cls a ChurnContext
+ * @param id the peer identity of the started peer
+ * @param cfg the handle to the configuration of the peer
+ * @param d handle to the daemon for the peer
+ * @param emsg NULL on success, non-NULL on failure
+ *
+ */
+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)
+{
+  struct ChurnRestartContext *startup_ctx = cls;
+  struct ChurnContext *churn_ctx = startup_ctx->churn_ctx;
+
+  unsigned int total_left;
+  char *error_message;
+
+  error_message = NULL;
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Churn stop callback failed with error `%s'\n", emsg);
+    churn_ctx->num_failed_start++;
+  }
+  else
+  {
+    churn_ctx->num_to_start--;
+  }
+
+  total_left =
+      (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) +
+      (churn_ctx->num_to_start - churn_ctx->num_failed_start);
+
+  if (total_left == 0)
+  {
+    if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
+      GNUNET_asprintf (&error_message,
+                       "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!",
+                       churn_ctx->num_failed_start, churn_ctx->num_failed_stop);
+    churn_ctx->cb (churn_ctx->cb_cls, error_message);
+    GNUNET_free_non_null (error_message);
+    GNUNET_free (churn_ctx);
+    GNUNET_free (startup_ctx);
+  }
+}
+
+static void
+schedule_churn_restart (void *cls,
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerRestartContext *peer_restart_ctx = cls;
+  struct ChurnRestartContext *startup_ctx = peer_restart_ctx->churn_restart_ctx;
+
+  if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh)
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_churn_restart, peer_restart_ctx);
+  else
+  {
+    if (startup_ctx->churn_ctx->service != NULL)
+      GNUNET_TESTING_daemon_start_stopped_service (peer_restart_ctx->daemon,
+                                                   startup_ctx->
+                                                   churn_ctx->service,
+                                                   startup_ctx->timeout,
+                                                   &churn_start_callback,
+                                                   startup_ctx);
+    else
+      GNUNET_TESTING_daemon_start_stopped (peer_restart_ctx->daemon,
+                                           startup_ctx->timeout,
+                                           &churn_start_callback, startup_ctx);
+    GNUNET_free (peer_restart_ctx);
+  }
+}
+
+/**
+ * Callback for informing us about a successful
+ * or unsuccessful churn start call.
+ *
+ * @param cls a struct ServiceStartContext *startup_ctx
+ * @param id the peer identity of the started peer
+ * @param cfg the handle to the configuration of the peer
+ * @param d handle to the daemon for the peer
+ * @param emsg NULL on success, non-NULL on failure
+ *
+ */
+void
+service_start_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                        const struct GNUNET_CONFIGURATION_Handle *cfg,
+                        struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  struct ServiceStartContext *startup_ctx = (struct ServiceStartContext *) cls;
+
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Service start failed with error `%s'\n", emsg);
+  }
+
+  startup_ctx->outstanding--;
+  startup_ctx->remaining--;
+
+  if (startup_ctx->remaining == 0)
+  {
+    startup_ctx->cb (startup_ctx->cb_cls, NULL);
+    GNUNET_free (startup_ctx->service);
+    GNUNET_free (startup_ctx);
+  }
+}
+
+static void
+schedule_service_start (void *cls,
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerServiceStartContext *peer_ctx = cls;
+  struct ServiceStartContext *startup_ctx = peer_ctx->start_ctx;
+
+  if (startup_ctx->outstanding > startup_ctx->pg->max_concurrent_ssh)
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_service_start, peer_ctx);
+  else
+  {
+
+    GNUNET_TESTING_daemon_start_service (peer_ctx->daemon, startup_ctx->service,
+                                         startup_ctx->timeout,
+                                         &service_start_callback, startup_ctx);
+    GNUNET_free (peer_ctx);
+  }
+}
+
+
+static void
+internal_start (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct InternalStartContext *internal_context = cls;
+
+  if ((tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) != 0)
+  {
+    return;
+  }
+
+  if ((internal_context->peer->pg->starting <
+       internal_context->peer->pg->max_concurrent_ssh) ||
+      ((internal_context->hostname != NULL) &&
+       (count_outstanding_at_host
+        (internal_context->hostname,
+         internal_context->peer->pg) <
+        internal_context->peer->pg->max_concurrent_ssh)))
+  {
+    if (internal_context->hostname != NULL)
+      increment_outstanding_at_host (internal_context->hostname,
+                                     internal_context->peer->pg);
+    internal_context->peer->pg->starting++;
+    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,
+                                     internal_context->hostkey,
+                                     &internal_hostkey_callback,
+                                     internal_context,
+                                     &internal_startup_callback,
+                                     internal_context);
+  }
+  else
+  {
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &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_destroy (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 (GNUNET_NO, NULL, NULL, "ssh", "ssh", arg,
+                               "peerStartHelper.pl", tempdir, NULL);
+  GNUNET_assert (helper->proc != NULL);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "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
+ * after successfully generating hostkeys for each peer.
+ *
+ * @param pg the peer group to continue starting
+ *
+ */
+void
+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++)
+    {
+      pg->peers[i].startup_task =
+          GNUNET_SCHEDULER_add_now (&internal_continue_startup,
+                                    &pg->peers[i].internal_context);
+    }
+  }
+#else
+  pg->starting = 0;
+  for (i = 0; i < pg->total; i++)
+  {
+    pg->peers[i].startup_task =
+        GNUNET_SCHEDULER_add_now (&internal_continue_startup,
+                                  &pg->peers[i].internal_context);
+  }
+#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
+ * applications.  The port numbers (any option called "PORT") will be
+ * adjusted to ensure that no two peers running on the same system
+ * have the same port(s) in their respective configurations.
+ *
+ * @param cfg configuration template to use
+ * @param total number of daemons to start
+ * @param max_concurrent_connections for testing, how many peers can
+ *                                   we connect to simultaneously
+ * @param max_concurrent_ssh when starting with ssh, how many ssh
+ *        connections will we allow at once (based on remote hosts allowed!)
+ * @param timeout total time allowed for peers to start
+ * @param hostkey_callback function to call on each peers hostkey generation
+ *        if NULL, peers will be started by this call, if non-null,
+ *        GNUNET_TESTING_daemons_continue_startup must be called after
+ *        successful hostkey generation
+ * @param hostkey_cls closure for hostkey callback
+ * @param cb function to call on each daemon that was started
+ * @param cb_cls closure for cb
+ * @param connect_callback function to call each time two hosts are connected
+ * @param connect_callback_cls closure for connect_callback
+ * @param hostnames linked list of host structs to use to start peers on
+ *                  (NULL to run on localhost only)
+ *
+ * @return NULL on error, otherwise handle to control peer group
+ */
+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)
+{
+  struct GNUNET_TESTING_PeerGroup *pg;
+  const struct GNUNET_TESTING_Host *hostpos;
+  const char *hostname;
+  const char *username;
+  char *baseservicehome;
+  char *newservicehome;
+  char *tmpdir;
+  char *hostkeys_file;
+  char *arg;
+  char *ssh_port_str;
+  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;
+  uint16_t sshport;
+  uint32_t upnum;
+  uint32_t fdnum;
+  uint64_t fs;
+  uint64_t total_hostkeys;
+  struct GNUNET_OS_Process *proc;
+
+  username = NULL;
+  if (0 == total)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+
+  upnum = 0;
+  fdnum = 0;
+  pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup));
+  pg->cfg = cfg;
+  pg->notify_connection = connect_callback;
+  pg->notify_connection_cls = connect_callback_cls;
+  pg->total = total;
+  pg->max_timeout = GNUNET_TIME_relative_to_absolute (timeout);
+  pg->peers = GNUNET_malloc (total * sizeof (struct PeerData));
+  pg->max_outstanding_connections = max_concurrent_connections;
+  pg->max_concurrent_ssh = max_concurrent_ssh;
+  if (NULL != hostnames)
+  {
+    off = 0;
+    hostpos = hostnames;
+    while (hostpos != NULL)
+    {
+      hostpos = hostpos->next;
+      off++;
+    }
+    pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
+    off = 0;
+
+    hostpos = hostnames;
+    while (hostpos != NULL)
+    {
+      pg->hosts[off].minport = LOW_PORT;
+      pg->hosts[off].hostname = GNUNET_strdup (hostpos->hostname);
+      if (hostpos->username != NULL)
+        pg->hosts[off].username = GNUNET_strdup (hostpos->username);
+      pg->hosts[off].sshport = hostpos->port;
+      hostpos = hostpos->next;
+      off++;
+    }
+
+    if (off == 0)
+    {
+      pg->hosts = NULL;
+    }
+    hostcnt = off;
+    minport = 0;
+    pg->num_hosts = off;
+  }
+  else
+  {
+    hostcnt = 0;
+    minport = LOW_PORT;
+  }
+
+  /* Create the servicehome directory for each remote peer */
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS",
+                                                        "SERVICEHOME",
+                                                        &baseservicehome));
+  for (i = 0; i < pg->num_hosts; i++)
+  {
+    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);
+    else
+      GNUNET_asprintf (&arg, "%s", pg->hosts[i].hostname);
+    if (pg->hosts[i].sshport != 0)
+    {
+      GNUNET_asprintf (&ssh_port_str, "%d", pg->hosts[i].sshport);
+      proc =
+       GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", "-P", ssh_port_str,
+                                   "-q",
+                                   arg, "mkdir -p", tmpdir, NULL);
+    }
+    else
+      proc =
+       GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "ssh", "ssh", arg, "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 ", tmpdir);
+    GNUNET_free (tmpdir);
+    GNUNET_free (arg);
+    GNUNET_OS_process_wait (proc);
+    GNUNET_OS_process_destroy (proc);
+  }
+  GNUNET_free (baseservicehome);
+  baseservicehome = NULL;
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "TESTING_OLD", "HOSTKEYSFILE",
+                                             &hostkeys_file))
+  {
+    if (GNUNET_YES != GNUNET_DISK_file_test (hostkeys_file))
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _("Could not read hostkeys file!\n"));
+    else
+    {
+      /* Check hostkey file size, read entire thing into memory */
+      fd = GNUNET_DISK_file_open (hostkeys_file, GNUNET_DISK_OPEN_READ,
+                                  GNUNET_DISK_PERM_NONE);
+      if (NULL == fd)
+      {
+        GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open",
+                                  hostkeys_file);
+        GNUNET_free (hostkeys_file);
+        for (i = 0; i < pg->num_hosts; i++)
+        {
+          GNUNET_free (pg->hosts[i].hostname);
+          GNUNET_free_non_null (pg->hosts[i].username);
+        }
+        GNUNET_free (pg->peers);
+        GNUNET_free (pg->hosts);
+        GNUNET_free (pg);
+        return NULL;
+      }
+
+      if (GNUNET_OK != GNUNET_DISK_file_size (hostkeys_file, &fs, GNUNET_YES, GNUNET_YES))
+        fs = 0;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Found file size %llu for hostkeys\n", fs);
+      if (0 != (fs % HOSTKEYFILESIZE))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                    "File size %llu seems incorrect for hostkeys...\n", fs);
+      }
+      else
+      {
+        total_hostkeys = fs / HOSTKEYFILESIZE;
+        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));
+      }
+      GNUNET_assert (GNUNET_OK == GNUNET_DISK_file_close (fd));
+    }
+    GNUNET_free (hostkeys_file);
+  }
+
+  for (off = 0; off < total; off++)
+  {
+    if (hostcnt > 0)
+    {
+      hostname = pg->hosts[off % hostcnt].hostname;
+      username = pg->hosts[off % hostcnt].username;
+      sshport = pg->hosts[off % hostcnt].sshport;
+      pcfg =
+          GNUNET_TESTING_create_cfg (cfg, off, &pg->hosts[off % hostcnt].minport, &upnum,
+                       hostname, &fdnum);
+    }
+    else
+    {
+      hostname = NULL;
+      username = NULL;
+      sshport = 0;
+      pcfg = GNUNET_TESTING_create_cfg (cfg, off, &minport, &upnum, hostname, &fdnum);
+    }
+
+    if (NULL == pcfg)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Could not create configuration for peer number %u on `%s'!\n"),
+                  off, hostname == NULL ? "localhost" : hostname);
+      continue;
+    }
+
+    if (GNUNET_YES ==
+        GNUNET_CONFIGURATION_get_value_string (pcfg, "PATHS", "SERVICEHOME",
+                                               &baseservicehome))
+    {
+      if (hostname != NULL)
+        GNUNET_asprintf (&newservicehome, "%s/%s/%d/", baseservicehome,
+                         hostname, off);
+      else
+        GNUNET_asprintf (&newservicehome, "%s/%d/", baseservicehome, off);
+      GNUNET_free (baseservicehome);
+      baseservicehome = NULL;
+    }
+    else
+    {
+      tmpdir = getenv ("TMPDIR");
+      tmpdir = tmpdir ? tmpdir : "/tmp";
+      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;
+    pg->peers[off].pg = pg;
+    pg->peers[off].internal_context.peer = &pg->peers[off];
+    pg->peers[off].internal_context.timeout = timeout;
+    pg->peers[off].internal_context.hostname = hostname;
+    pg->peers[off].internal_context.username = username;
+    pg->peers[off].internal_context.sshport = sshport;
+    if (pg->hostkey_data != NULL)
+      pg->peers[off].internal_context.hostkey =
+          &pg->hostkey_data[off * HOSTKEYFILESIZE];
+    pg->peers[off].internal_context.hostkey_callback = hostkey_callback;
+    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++)
+    {
+
+      if (hostcnt > 0)
+      {
+        hostname = pg->hosts[off % hostcnt].hostname;
+        username = pg->hosts[off % hostcnt].username;
+        sshport = pg->hosts[off % hostcnt].sshport;
+      }
+      else
+      {
+        hostname = NULL;
+        username = NULL;
+        sshport = 0;
+      }
+
+      if (GNUNET_YES ==
+          GNUNET_CONFIGURATION_get_value_string (cfg, "PATHS", "SERVICEHOME",
+                                                 &baseservicehome))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "baseservice home is %s\n",
+                    baseservicehome);
+        if (hostname != NULL)
+          GNUNET_asprintf (&newservicehome, "%s/%s/", baseservicehome,
+                           hostname);
+        else
+          GNUNET_asprintf (&newservicehome, "%s/", baseservicehome);
+        GNUNET_free (baseservicehome);
+        baseservicehome = NULL;
+      }
+      else
+      {
+        tmpdir = getenv ("TMPDIR");
+        tmpdir = tmpdir ? tmpdir : "/tmp";
+        if (hostname != NULL)
+          GNUNET_asprintf (&newservicehome, "%s/%s/%s/", tmpdir, hostname,
+                           "gnunet-testing-test-test");
+        else
+          GNUNET_asprintf (&newservicehome, "%s/%s/", tmpdir,
+                           "gnunet-testing-test-test", off);
+      }
+
+      if (NULL != username)
+        GNUNET_asprintf (&arg, "%s@%s:%s", username, pg->hosts[off].hostname,
+                         newservicehome);
+      else
+        GNUNET_asprintf (&arg, "%s:%s", pg->hosts[off].hostname,
+                         newservicehome);
+
+      /* FIXME: Doesn't support ssh_port option! */
+      proc =
+       GNUNET_OS_start_process (GNUNET_NO, NULL, NULL, "rsync", "rsync", "-r",
+                                   newservicehome, arg, NULL);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "copying directory with command rsync -r %s %s\n",
+                  newservicehome, arg);
+      GNUNET_free (newservicehome);
+      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_destroy (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);
+  }
+#endif
+  return pg;
+}
+
+/*
+ * Get a daemon by number, so callers don't have to do nasty
+ * offsetting operation.
+ */
+struct GNUNET_TESTING_Daemon *
+GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg,
+                           unsigned int position)
+{
+  if (position < pg->total)
+    return pg->peers[position].daemon;
+  return NULL;
+}
+
+/*
+ * Get a daemon by peer identity, so callers can
+ * retrieve the daemon without knowing it's offset.
+ *
+ * @param pg the peer group to retrieve the daemon from
+ * @param peer_id the peer identity of the daemon to retrieve
+ *
+ * @return the daemon on success, or NULL if no such peer identity is found
+ */
+struct GNUNET_TESTING_Daemon *
+GNUNET_TESTING_daemon_get_by_id (struct GNUNET_TESTING_PeerGroup *pg,
+                                 const struct GNUNET_PeerIdentity *peer_id)
+{
+  unsigned int i;
+
+  for (i = 0; i < pg->total; i++)
+  {
+    if (0 ==
+        memcmp (&pg->peers[i].daemon->id, peer_id,
+                sizeof (struct GNUNET_PeerIdentity)))
+      return pg->peers[i].daemon;
+  }
+  return NULL;
+}
+
+/**
+ * Prototype of a function that will be called when a
+ * particular operation was completed the testing library.
+ *
+ * @param cls closure (a struct RestartContext)
+ * @param id id of the peer that was restarted
+ * @param cfg handle to the configuration of the peer
+ * @param d handle to the daemon that was restarted
+ * @param emsg NULL on success
+ */
+static void
+restart_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                  const struct GNUNET_CONFIGURATION_Handle *cfg,
+                  struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  struct RestartContext *restart_context = cls;
+
+  if (emsg == NULL)
+  {
+    restart_context->peers_restarted++;
+  }
+  else
+  {
+    restart_context->peers_restart_failed++;
+  }
+
+  if (restart_context->peers_restarted == restart_context->peer_group->total)
+  {
+    restart_context->callback (restart_context->callback_cls, NULL);
+    GNUNET_free (restart_context);
+  }
+  else if (restart_context->peers_restart_failed +
+           restart_context->peers_restarted ==
+           restart_context->peer_group->total)
+  {
+    restart_context->callback (restart_context->callback_cls,
+                               "Failed to restart peers!");
+    GNUNET_free (restart_context);
+  }
+
+}
+
+/**
+ * Callback for informing us about a successful
+ * or unsuccessful churn stop call.
+ *
+ * @param cls a ChurnContext
+ * @param emsg NULL on success, non-NULL on failure
+ *
+ */
+static void
+churn_stop_callback (void *cls, const char *emsg)
+{
+  struct ShutdownContext *shutdown_ctx = cls;
+  struct ChurnContext *churn_ctx = shutdown_ctx->cb_cls;
+  unsigned int total_left;
+  char *error_message;
+
+  error_message = NULL;
+  shutdown_ctx->outstanding--;
+
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Churn stop callback failed with error `%s'\n", emsg);
+    churn_ctx->num_failed_stop++;
+  }
+  else
+  {
+    churn_ctx->num_to_stop--;
+  }
+
+  total_left =
+      (churn_ctx->num_to_stop - churn_ctx->num_failed_stop) +
+      (churn_ctx->num_to_start - churn_ctx->num_failed_start);
+
+  if (total_left == 0)
+  {
+    if ((churn_ctx->num_failed_stop > 0) || (churn_ctx->num_failed_start > 0))
+    {
+      GNUNET_asprintf (&error_message,
+                       "Churn didn't complete successfully, %u peers failed to start %u peers failed to be stopped!",
+                       churn_ctx->num_failed_start, churn_ctx->num_failed_stop);
+    }
+    churn_ctx->cb (churn_ctx->cb_cls, error_message);
+    GNUNET_free_non_null (error_message);
+    GNUNET_free (churn_ctx);
+    GNUNET_free (shutdown_ctx);
+  }
+}
+
+/**
+ * Count the number of running peers.
+ *
+ * @param pg handle for the peer group
+ *
+ * @return the number of currently running peers in the peer group
+ */
+unsigned int
+GNUNET_TESTING_daemons_running (struct GNUNET_TESTING_PeerGroup *pg)
+{
+  unsigned int i;
+  unsigned int running = 0;
+
+  for (i = 0; i < pg->total; i++)
+  {
+    if (pg->peers[i].daemon->running == GNUNET_YES)
+    {
+      GNUNET_assert (running != -1);
+      running++;
+    }
+  }
+  return running;
+}
+
+/**
+ * Task to rate limit the number of outstanding peer shutdown
+ * requests.  This is necessary for making sure we don't do
+ * too many ssh connections at once, but is generally nicer
+ * to any system as well (graduated task starts, as opposed
+ * to calling gnunet-arm N times all at once).
+ */
+static void
+schedule_churn_shutdown_task (void *cls,
+                              const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerShutdownContext *peer_shutdown_ctx = cls;
+  struct ShutdownContext *shutdown_ctx;
+  struct ChurnContext *churn_ctx;
+
+  GNUNET_assert (peer_shutdown_ctx != NULL);
+  shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
+  GNUNET_assert (shutdown_ctx != NULL);
+  churn_ctx = (struct ChurnContext *) shutdown_ctx->cb_cls;
+  if (shutdown_ctx->outstanding > churn_ctx->pg->max_concurrent_ssh)
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_churn_shutdown_task,
+                                  peer_shutdown_ctx);
+  else
+  {
+    shutdown_ctx->outstanding++;
+    if (churn_ctx->service != NULL)
+      GNUNET_TESTING_daemon_stop_service (peer_shutdown_ctx->daemon,
+                                          churn_ctx->service,
+                                          shutdown_ctx->timeout,
+                                          shutdown_ctx->cb, shutdown_ctx);
+    else
+      GNUNET_TESTING_daemon_stop (peer_shutdown_ctx->daemon,
+                                  shutdown_ctx->timeout, shutdown_ctx->cb,
+                                  shutdown_ctx, GNUNET_NO, GNUNET_YES);
+    GNUNET_free (peer_shutdown_ctx);
+  }
+}
+
+
+/**
+ * Simulate churn by stopping some peers (and possibly
+ * re-starting others if churn is called multiple times).  This
+ * function can only be used to create leave-join churn (peers "never"
+ * leave for good).  First "voff" random peers that are currently
+ * online will be taken offline; then "von" random peers that are then
+ * offline will be put back online.  No notifications will be
+ * generated for any of these operations except for the callback upon
+ * completion.
+ *
+ * @param pg handle for the peer group
+ * @param service the service to churn off/on, NULL to churn peer
+ * @param voff number of peers that should go offline
+ * @param von number of peers that should come back online;
+ *            must be zero on first call (since "testbed_start"
+ *            always starts all of the peers)
+ * @param timeout how long to wait for operations to finish before
+ *        giving up
+ * @param cb function to call at the end
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemons_churn (struct GNUNET_TESTING_PeerGroup *pg,
+                              char *service, 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;
+  struct PeerShutdownContext *peer_shutdown_ctx;
+  struct PeerRestartContext *peer_restart_ctx;
+  struct ChurnRestartContext *churn_startup_ctx;
+
+  unsigned int running;
+  unsigned int stopped;
+  unsigned int total_running;
+  unsigned int total_stopped;
+  unsigned int i;
+  unsigned int *running_arr;
+  unsigned int *stopped_arr;
+  unsigned int *running_permute;
+  unsigned int *stopped_permute;
+  char *pos;
+
+  shutdown_ctx = NULL;
+  peer_shutdown_ctx = NULL;
+  peer_restart_ctx = NULL;
+  churn_startup_ctx = NULL;
+
+  running = 0;
+  stopped = 0;
+
+  if ((von == 0) && (voff == 0))        /* No peers at all? */
+  {
+    cb (cb_cls, NULL);
+    return;
+  }
+
+  for (i = 0; i < pg->total; i++)
+  {
+    if (service == NULL)
+    {
+      if (pg->peers[i].daemon->running == GNUNET_YES)
+      {
+        GNUNET_assert (running != -1);
+        running++;
+      }
+      else
+      {
+        GNUNET_assert (stopped != -1);
+        stopped++;
+      }
+    }
+    else
+    {
+      /* FIXME: make churned services a list! */
+      pos = pg->peers[i].daemon->churned_services;
+      /* FIXME: while (pos != NULL) */
+      if (pos != NULL)
+      {
+#if FIXME
+        if (0 == strcasecmp (pos, service))
+        {
+
+          break;
+        }
+#endif
+        GNUNET_assert (stopped != -1);
+        stopped++;
+        /* FIXME: pos = pos->next; */
+      }
+      if (pos == NULL)
+      {
+        GNUNET_assert (running != -1);
+        running++;
+      }
+    }
+  }
+
+  if (voff > running)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Trying to stop more peers (%d) than are currently running (%d)!\n",
+                voff, running);
+    cb (cb_cls, "Trying to stop more peers than are currently running!");
+    return;
+  }
+
+  if (von > stopped)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Trying to start more peers (%d) than are currently stopped (%d)!\n",
+                von, stopped);
+    cb (cb_cls, "Trying to start more peers than are currently stopped!");
+    return;
+  }
+
+  churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext));
+
+  if (service != NULL)
+    churn_ctx->service = GNUNET_strdup (service);
+  running_arr = NULL;
+  if (running > 0)
+    running_arr = GNUNET_malloc (running * sizeof (unsigned int));
+
+  stopped_arr = NULL;
+  if (stopped > 0)
+    stopped_arr = GNUNET_malloc (stopped * sizeof (unsigned int));
+
+  running_permute = NULL;
+  stopped_permute = NULL;
+
+  if (running > 0)
+    running_permute =
+        GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, running);
+  if (stopped > 0)
+    stopped_permute =
+        GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK, stopped);
+
+  total_running = running;
+  total_stopped = stopped;
+  running = 0;
+  stopped = 0;
+
+  churn_ctx->num_to_start = von;
+  churn_ctx->num_to_stop = voff;
+  churn_ctx->cb = cb;
+  churn_ctx->cb_cls = cb_cls;
+  churn_ctx->pg = pg;
+
+  for (i = 0; i < pg->total; i++)
+  {
+    if (service == NULL)
+    {
+      if (pg->peers[i].daemon->running == GNUNET_YES)
+      {
+        GNUNET_assert ((running_arr != NULL) && (total_running > running));
+        running_arr[running] = i;
+        running++;
+      }
+      else
+      {
+        GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped));
+        stopped_arr[stopped] = i;
+        stopped++;
+      }
+    }
+    else
+    {
+      /* FIXME: make churned services a list! */
+      pos = pg->peers[i].daemon->churned_services;
+      /* FIXME: while (pos != NULL) */
+      if (pos != NULL)
+      {
+        GNUNET_assert ((stopped_arr != NULL) && (total_stopped > stopped));
+        stopped_arr[stopped] = i;
+        stopped++;
+        /* FIXME: pos = pos->next; */
+      }
+      if (pos == NULL)
+      {
+        GNUNET_assert ((running_arr != NULL) && (total_running > running));
+        running_arr[running] = i;
+        running++;
+      }
+    }
+  }
+
+  GNUNET_assert (running >= voff);
+  if (voff > 0)
+  {
+    shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
+    shutdown_ctx->cb = &churn_stop_callback;
+    shutdown_ctx->cb_cls = churn_ctx;
+    shutdown_ctx->total_peers = voff;
+    shutdown_ctx->timeout = timeout;
+  }
+
+  for (i = 0; i < voff; i++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Stopping peer %d!\n",
+                running_arr[running_permute[i]]);
+    GNUNET_assert (running_arr != NULL);
+    peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext));
+    peer_shutdown_ctx->daemon =
+        pg->peers[running_arr[running_permute[i]]].daemon;
+    peer_shutdown_ctx->shutdown_ctx = shutdown_ctx;
+    GNUNET_SCHEDULER_add_now (&schedule_churn_shutdown_task, peer_shutdown_ctx);
+  }
+
+  GNUNET_assert (stopped >= von);
+  if (von > 0)
+  {
+    churn_startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext));
+    churn_startup_ctx->churn_ctx = churn_ctx;
+    churn_startup_ctx->timeout = timeout;
+    churn_startup_ctx->pg = pg;
+  }
+  for (i = 0; i < von; i++)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Starting up peer %d!\n",
+                stopped_arr[stopped_permute[i]]);
+    GNUNET_assert (stopped_arr != NULL);
+    peer_restart_ctx = GNUNET_malloc (sizeof (struct PeerRestartContext));
+    peer_restart_ctx->churn_restart_ctx = churn_startup_ctx;
+    peer_restart_ctx->daemon =
+        pg->peers[stopped_arr[stopped_permute[i]]].daemon;
+    GNUNET_SCHEDULER_add_now (&schedule_churn_restart, peer_restart_ctx);
+  }
+
+  GNUNET_free_non_null (running_arr);
+  GNUNET_free_non_null (stopped_arr);
+  GNUNET_free_non_null (running_permute);
+  GNUNET_free_non_null (stopped_permute);
+}
+
+/*
+ * Start a given service for each of the peers in the peer group.
+ *
+ * @param pg handle for the peer group
+ * @param service the service to start
+ * @param timeout how long to wait for operations to finish before
+ *        giving up
+ * @param cb function to call once finished
+ * @param cb_cls closure for cb
+ *
+ */
+void
+GNUNET_TESTING_daemons_start_service (struct GNUNET_TESTING_PeerGroup *pg,
+                                      char *service,
+                                      struct GNUNET_TIME_Relative timeout,
+                                      GNUNET_TESTING_NotifyCompletion cb,
+                                      void *cb_cls)
+{
+  struct ServiceStartContext *start_ctx;
+  struct PeerServiceStartContext *peer_start_ctx;
+  unsigned int i;
+
+  GNUNET_assert (service != NULL);
+
+  start_ctx = GNUNET_malloc (sizeof (struct ServiceStartContext));
+  start_ctx->pg = pg;
+  start_ctx->remaining = pg->total;
+  start_ctx->cb = cb;
+  start_ctx->cb_cls = cb_cls;
+  start_ctx->service = GNUNET_strdup (service);
+  start_ctx->timeout = timeout;
+
+  for (i = 0; i < pg->total; i++)
+  {
+    peer_start_ctx = GNUNET_malloc (sizeof (struct PeerServiceStartContext));
+    peer_start_ctx->start_ctx = start_ctx;
+    peer_start_ctx->daemon = pg->peers[i].daemon;
+    GNUNET_SCHEDULER_add_now (&schedule_service_start, peer_start_ctx);
+  }
+}
+
+/**
+ * Restart all peers in the given group.
+ *
+ * @param pg the handle to the peer group
+ * @param callback function to call on completion (or failure)
+ * @param callback_cls closure for the callback function
+ */
+void
+GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg,
+                                GNUNET_TESTING_NotifyCompletion callback,
+                                void *callback_cls)
+{
+  struct RestartContext *restart_context;
+  unsigned int off;
+
+  if (pg->total > 0)
+  {
+    restart_context = GNUNET_malloc (sizeof (struct RestartContext));
+    restart_context->peer_group = pg;
+    restart_context->peers_restarted = 0;
+    restart_context->callback = callback;
+    restart_context->callback_cls = callback_cls;
+
+    for (off = 0; off < pg->total; off++)
+    {
+      GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback,
+                                     restart_context);
+    }
+  }
+}
+
+
+/**
+ * Start or stop an individual peer from the given group.
+ *
+ * @param pg handle to the peer group
+ * @param offset which peer to start or stop
+ * @param desired_status GNUNET_YES to have it running, GNUNET_NO to stop it
+ * @param timeout how long to wait for shutdown
+ * @param cb function to call at the end
+ * @param cb_cls closure for cb
+ */
+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)
+{
+  struct ShutdownContext *shutdown_ctx;
+  struct ChurnRestartContext *startup_ctx;
+  struct ChurnContext *churn_ctx;
+
+  if (GNUNET_NO == desired_status)
+  {
+    if (NULL != pg->peers[offset].daemon)
+    {
+      shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
+      churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext));
+      churn_ctx->num_to_start = 0;
+      churn_ctx->num_to_stop = 1;
+      churn_ctx->cb = cb;
+      churn_ctx->cb_cls = cb_cls;
+      shutdown_ctx->cb_cls = churn_ctx;
+      GNUNET_TESTING_daemon_stop (pg->peers[offset].daemon, timeout,
+                                  &churn_stop_callback, shutdown_ctx, GNUNET_NO,
+                                  GNUNET_YES);
+    }
+  }
+  else if (GNUNET_YES == desired_status)
+  {
+    if (NULL == pg->peers[offset].daemon)
+    {
+      startup_ctx = GNUNET_malloc (sizeof (struct ChurnRestartContext));
+      churn_ctx = GNUNET_malloc (sizeof (struct ChurnContext));
+      churn_ctx->num_to_start = 1;
+      churn_ctx->num_to_stop = 0;
+      churn_ctx->cb = cb;
+      churn_ctx->cb_cls = cb_cls;
+      startup_ctx->churn_ctx = churn_ctx;
+      GNUNET_TESTING_daemon_start_stopped (pg->peers[offset].daemon, timeout,
+                                           &churn_start_callback, startup_ctx);
+    }
+  }
+  else
+    GNUNET_break (0);
+}
+
+
+/**
+ * Callback for shutting down peers in a peer group.
+ *
+ * @param cls closure (struct ShutdownContext)
+ * @param emsg NULL on success
+ */
+static void
+internal_shutdown_callback (void *cls, const char *emsg)
+{
+  struct PeerShutdownContext *peer_shutdown_ctx = cls;
+  struct ShutdownContext *shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
+  unsigned int off;
+  int i;
+  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++;
+  }
+  else
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, "internal_shutdown_callback",
+                     "Failed to stop a peer: %s\n", emsg);
+    shutdown_ctx->peers_failed++;
+  }
+
+  if ((shutdown_ctx->cb != NULL) &&
+      (shutdown_ctx->peers_down + shutdown_ctx->peers_failed ==
+       shutdown_ctx->total_peers))
+  {
+    if (shutdown_ctx->peers_failed > 0)
+      shutdown_ctx->cb (shutdown_ctx->cb_cls,
+                        "Not all peers successfully shut down!");
+    else
+      shutdown_ctx->cb (shutdown_ctx->cb_cls, NULL);
+
+    for (i = 0; i < shutdown_ctx->pg->total; i++)
+    {
+      if (shutdown_ctx->pg->peers[i].startup_task != GNUNET_SCHEDULER_NO_TASK)
+        GNUNET_SCHEDULER_cancel (shutdown_ctx->pg->peers[i].startup_task);
+    }
+    GNUNET_free (shutdown_ctx->pg->peers);
+    GNUNET_free_non_null (shutdown_ctx->pg->hostkey_data);
+    for (off = 0; off < shutdown_ctx->pg->num_hosts; off++)
+    {
+      GNUNET_free (shutdown_ctx->pg->hosts[off].hostname);
+      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);
+}
+
+
+/**
+ * Task to rate limit the number of outstanding peer shutdown
+ * requests.  This is necessary for making sure we don't do
+ * too many ssh connections at once, but is generally nicer
+ * to any system as well (graduated task starts, as opposed
+ * to calling gnunet-arm N times all at once).
+ */
+static void
+schedule_shutdown_task (void *cls,
+                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerShutdownContext *peer_shutdown_ctx = cls;
+  struct ShutdownContext *shutdown_ctx;
+  struct GNUNET_TESTING_Daemon *d;
+
+  GNUNET_assert (peer_shutdown_ctx != NULL);
+  d = peer_shutdown_ctx->daemon;
+  shutdown_ctx = peer_shutdown_ctx->shutdown_ctx;
+  GNUNET_assert (shutdown_ctx != NULL);
+
+  if ((shutdown_ctx->outstanding < shutdown_ctx->pg->max_concurrent_ssh) ||
+      ((d->hostname != NULL) &&
+       (count_outstanding_at_host
+        (d->hostname,
+         shutdown_ctx->pg) < shutdown_ctx->pg->max_concurrent_ssh)))
+  {
+    if (d->hostname != NULL)
+      increment_outstanding_at_host (d->hostname,
+                                     shutdown_ctx->pg);
+    shutdown_ctx->outstanding++;
+    GNUNET_TESTING_daemon_stop (d,
+                                shutdown_ctx->timeout,
+                                &internal_shutdown_callback, peer_shutdown_ctx,
+                                shutdown_ctx->delete_files, GNUNET_NO);
+  }
+  else
+    GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
+                                  (GNUNET_TIME_UNIT_MILLISECONDS, 100),
+                                  &schedule_shutdown_task, peer_shutdown_ctx);
+
+}
+
+/**
+ * Read a testing hosts file based on a configuration.
+ * Returns a DLL of hosts (caller must free!) on success
+ * or NULL on failure.
+ *
+ * @param cfg a configuration with a testing section
+ *
+ * @return DLL of hosts on success, NULL on failure
+ */
+struct GNUNET_TESTING_Host *
+GNUNET_TESTING_hosts_load (const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+  struct GNUNET_TESTING_Host *hosts;
+  struct GNUNET_TESTING_Host *temphost;
+  char *data;
+  char *buf;
+  char *hostfile;
+  struct stat frstat;
+  int count;
+  int ret;
+
+  /* Check for a hostfile containing user@host:port triples */
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "hostfile",
+                                             &hostfile))
+    return NULL;
+
+  hosts = NULL;
+  temphost = NULL;
+  data = NULL;
+  if (hostfile != NULL)
+  {
+    if (GNUNET_OK != GNUNET_DISK_file_test (hostfile))
+      GNUNET_DISK_fn_write (hostfile, NULL, 0,
+                            GNUNET_DISK_PERM_USER_READ |
+                            GNUNET_DISK_PERM_USER_WRITE);
+    if ((0 != STAT (hostfile, &frstat)) || (frstat.st_size == 0))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not open file specified for host list, ending test!");
+      GNUNET_free (hostfile);
+      return NULL;
+    }
+
+    data = GNUNET_malloc_large (frstat.st_size);
+    GNUNET_assert (data != NULL);
+    if (frstat.st_size != GNUNET_DISK_fn_read (hostfile, data, frstat.st_size))
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  "Could not read file %s specified for host list, ending test!",
+                  hostfile);
+      GNUNET_free (hostfile);
+      GNUNET_free (data);
+      return NULL;
+    }
+
+    GNUNET_free_non_null (hostfile);
+
+    buf = data;
+    count = 0;
+    while (count < frstat.st_size - 1)
+    {
+      count++;
+      if (((data[count] == '\n')) && (buf != &data[count]))
+      {
+        data[count] = '\0';
+        temphost = GNUNET_malloc (sizeof (struct GNUNET_TESTING_Host));
+        ret =
+            SSCANF (buf, "%a[a-zA-Z0-9_]@%a[a-zA-Z0-9.]:%hd",
+                    &temphost->username, &temphost->hostname, &temphost->port);
+        if (3 == ret)
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                      "Successfully read host %s, port %d and user %s from file\n",
+                      temphost->hostname, temphost->port, temphost->username);
+        }
+        else
+        {
+          GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                      "Error reading line `%s' in hostfile\n", buf);
+          GNUNET_free (temphost);
+          buf = &data[count + 1];
+          continue;
+        }
+        temphost->next = hosts;
+        hosts = temphost;
+        buf = &data[count + 1];
+      }
+      else if ((data[count] == '\n') || (data[count] == '\0'))
+        buf = &data[count + 1];
+    }
+  }
+  GNUNET_free_non_null (data);
+
+  return hosts;
+}
+
+/**
+ * Shutdown all peers started in the given group.
+ *
+ * @param pg handle to the peer group
+ * @param timeout how long to wait for shutdown
+ * @param cb callback to notify upon success or failure
+ * @param cb_cls closure for cb
+ */
+void
+GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg,
+                             struct GNUNET_TIME_Relative timeout,
+                             GNUNET_TESTING_NotifyCompletion cb, void *cb_cls)
+{
+  unsigned int off;
+  struct ShutdownContext *shutdown_ctx;
+  struct PeerShutdownContext *peer_shutdown_ctx;
+
+#if OLD
+  struct PeerConnection *conn_iter;
+  struct PeerConnection *temp_conn;
+#endif
+  struct ConnectContext *cc;
+
+  GNUNET_assert (pg->total > 0);
+  while (NULL != (cc = pg->cc_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (pg->cc_head, pg->cc_tail, cc);
+    if (GNUNET_SCHEDULER_NO_TASK != cc->task)
+      GNUNET_SCHEDULER_cancel (cc->task);
+    if (NULL != cc->cc)
+      GNUNET_TESTING_daemons_connect_cancel (cc->cc);
+    GNUNET_free (cc);
+  }
+
+  shutdown_ctx = GNUNET_malloc (sizeof (struct ShutdownContext));
+  shutdown_ctx->delete_files =
+      GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING_OLD", "DELETE_FILES");
+  shutdown_ctx->cb = cb;
+  shutdown_ctx->cb_cls = cb_cls;
+  shutdown_ctx->total_peers = pg->total;
+  shutdown_ctx->timeout = timeout;
+  shutdown_ctx->pg = pg;
+
+  for (off = 0; off < pg->total; off++)
+  {
+    GNUNET_assert (NULL != pg->peers[off].daemon);
+    peer_shutdown_ctx = GNUNET_malloc (sizeof (struct PeerShutdownContext));
+    peer_shutdown_ctx->daemon = pg->peers[off].daemon;
+    peer_shutdown_ctx->shutdown_ctx = shutdown_ctx;
+    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
+// FIXME Do DLL remove for all pg->peers[off].LIST
+    conn_iter = pg->peers[off].allowed_peers_head;
+    while (conn_iter != NULL)
+    {
+      temp_conn = conn_iter->next;
+      GNUNET_free (conn_iter);
+      conn_iter = temp_conn;
+    }
+    pg->peers[off].allowed_peers_head = NULL;
+
+    conn_iter = pg->peers[off].connect_peers_head;
+    while (conn_iter != NULL)
+    {
+      temp_conn = conn_iter->next;
+      GNUNET_free (conn_iter);
+      conn_iter = temp_conn;
+    }
+    pg->peers[off].connect_peers_head = NULL;
+
+    conn_iter = pg->peers[off].blacklisted_peers_head;
+    while (conn_iter != NULL)
+    {
+      temp_conn = conn_iter->next;
+      GNUNET_free (conn_iter);
+      conn_iter = temp_conn;
+    }
+    pg->peers[off].blacklisted_peers_head = NULL;
+
+    conn_iter = pg->peers[off].connect_peers_working_set_head;
+    while (conn_iter != NULL)
+    {
+      temp_conn = conn_iter->next;
+      GNUNET_free (conn_iter);
+      conn_iter = temp_conn;
+    }
+    pg->peers[off].connect_peers_working_set_head = NULL;
+#else
+    if (pg->peers[off].allowed_peers != NULL)
+      GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].allowed_peers);
+    if (pg->peers[off].connect_peers != NULL)
+      GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].connect_peers);
+    if (pg->peers[off].blacklisted_peers != NULL)
+      GNUNET_CONTAINER_multihashmap_destroy (pg->peers[off].blacklisted_peers);
+#endif
+  }
+}
+
+/* end of testing_group.c */
diff --git a/src/testing_old/testing_peergroup.c b/src/testing_old/testing_peergroup.c
new file mode 100644 (file)
index 0000000..d4451cc
--- /dev/null
@@ -0,0 +1,1017 @@
+/*
+ This file is part of GNUnet
+ (C) 2008-2011 Christian Grothoff (and other contributing authors)
+
+ 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 3, or (at your
+ option) any later version.
+
+ GNUnet is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GNUnet; see the file COPYING.  If not, write to the
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * @file testing/testing_peergroup.c
+ * @brief API implementation for easy peer group creation
+ * @author Nathan Evans
+ * @author Christian Grothoff
+ *
+ */
+#include "platform.h"
+#include "gnunet_constants.h"
+#include "gnunet_arm_service.h"
+#include "gnunet_testing_lib.h"
+#include "gnunet_core_service.h"
+#include "gnunet_disk_lib.h"
+
+/** Globals **/
+#define DEFAULT_CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+
+#define DEFAULT_CONNECT_ATTEMPTS 2
+
+/** Struct definitions **/
+
+struct PeerGroupStartupContext
+{
+  struct GNUNET_TESTING_PeerGroup *pg;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
+  unsigned int total;
+  unsigned int peers_left;
+  unsigned long long max_concurrent_connections;
+
+  /**
+   * Maximum attemps to connect two daemons.
+   */
+  unsigned long long connect_attempts;
+
+  /**
+   * How long to spend trying to establish all the connections?
+   */
+  struct GNUNET_TIME_Relative connect_timeout;
+
+  unsigned long long max_concurrent_ssh;
+  struct GNUNET_TIME_Absolute timeout;
+  GNUNET_TESTING_NotifyConnection connect_cb;
+  GNUNET_TESTING_NotifyCompletion peergroup_cb;
+
+  /**
+   * Closure for all peergroup callbacks.
+   */
+  void *cls;
+
+  const struct GNUNET_TESTING_Host *hostnames;
+  
+  /**
+   * FIXME document
+   */
+  enum GNUNET_TESTING_Topology topology;
+
+  float topology_percentage;
+
+  float topology_probability;
+
+  /**
+   * FIXME document
+   */
+  enum GNUNET_TESTING_Topology restrict_topology;
+  
+  /**
+   * FIXME document
+   */
+  char *restrict_transports;
+  
+  /**
+   * Initial connections
+   */
+  enum GNUNET_TESTING_Topology connect_topology;
+  enum GNUNET_TESTING_TopologyOption connect_topology_option;
+  double connect_topology_option_modifier;
+  int verbose;
+
+  struct ProgressMeter *hostkey_meter;
+  struct ProgressMeter *peer_start_meter;
+  struct ProgressMeter *connect_meter;
+
+  /**
+   * Task used to kill the peergroup.
+   */
+  GNUNET_SCHEDULER_TaskIdentifier die_task;
+
+  char *fail_reason;
+
+  /**
+   * Variable used to store the number of connections we should wait for.
+   */
+  unsigned int expected_connections;
+
+  /**
+   * Time when the connecting peers was started.
+   */
+  struct GNUNET_TIME_Absolute connect_start_time;
+
+  /**
+   * The total number of connections that have been created so far.
+   */
+  unsigned int total_connections;
+
+  /**
+   * The total number of connections that have failed so far.
+   */
+  unsigned int failed_connections;
+
+  /**
+   * File handle to write out topology in dot format.
+   */
+  struct GNUNET_DISK_FileHandle *topology_output_file;
+};
+
+struct TopologyOutputContext
+{
+  struct GNUNET_DISK_FileHandle *file;
+  GNUNET_TESTING_NotifyCompletion notify_cb;
+  void *notify_cb_cls;
+};
+
+/**
+ * Simple struct to keep track of progress, and print a
+ * percentage meter for long running tasks.
+ */
+struct ProgressMeter
+{
+  /**
+   * Total number of tasks to complete.
+   */
+  unsigned int total;
+
+  /**
+   * Print percentage done after modnum tasks.
+   */
+  unsigned int modnum;
+
+  /**
+   * Print a . each dotnum tasks.
+   */
+  unsigned int dotnum;
+
+  /**
+   * Total number completed thus far.
+   */
+  unsigned int completed;
+
+  /**
+   * Whether or not to print.
+   */
+  int print;
+
+  /**
+   * Startup string for progress meter.
+   */
+  char *startup_string;
+};
+
+
+/** Utility functions **/
+
+/**
+ * Create a meter to keep track of the progress of some task.
+ *
+ * @param total the total number of items to complete
+ * @param start_string a string to prefix the meter with (if printing)
+ * @param print GNUNET_YES to print the meter, GNUNET_NO to count
+ *              internally only
+ *
+ * @return the progress meter
+ */
+static struct ProgressMeter *
+create_meter (unsigned int total, char *start_string, int print)
+{
+  struct ProgressMeter *ret;
+
+  ret = GNUNET_malloc (sizeof (struct ProgressMeter));
+  ret->print = print;
+  ret->total = total;
+  ret->modnum = (total / 4 == 0) ? 1 : (total / 4);
+  ret->dotnum = (total / 50) + 1;
+  if (start_string != NULL)
+    ret->startup_string = GNUNET_strdup (start_string);
+  else
+    ret->startup_string = GNUNET_strdup ("");
+
+  return ret;
+}
+
+/**
+ * Update progress meter (increment by one).
+ *
+ * @param meter the meter to update and print info for
+ *
+ * @return GNUNET_YES if called the total requested,
+ *         GNUNET_NO if more items expected
+ */
+static int
+update_meter (struct ProgressMeter *meter)
+{
+  if (meter->print == GNUNET_YES)
+  {
+    if (meter->completed % meter->modnum == 0)
+    {
+      if (meter->completed == 0)
+      {
+        FPRINTF (stdout, "%sProgress: [0%%", meter->startup_string);
+      }
+      else
+        FPRINTF (stdout, "%d%%",
+                 (int) (((float) meter->completed / meter->total) * 100));
+    }
+    else if (meter->completed % meter->dotnum == 0)
+      FPRINTF (stdout, "%s",  ".");
+
+    if (meter->completed + 1 == meter->total)
+      FPRINTF (stdout, "%d%%]\n", 100);
+    fflush (stdout);
+  }
+  meter->completed++;
+
+  if (meter->completed == meter->total)
+    return GNUNET_YES;
+  return GNUNET_NO;
+}
+
+/**
+ * Reset progress meter.
+ *
+ * @param meter the meter to reset
+ *
+ * @return GNUNET_YES if meter reset,
+ *         GNUNET_SYSERR on error
+ */
+static int
+reset_meter (struct ProgressMeter *meter)
+{
+  if (meter == NULL)
+    return GNUNET_SYSERR;
+
+  meter->completed = 0;
+  return GNUNET_YES;
+}
+
+/**
+ * Release resources for meter
+ *
+ * @param meter the meter to free
+ */
+static void
+free_meter (struct ProgressMeter *meter)
+{
+  GNUNET_free_non_null (meter->startup_string);
+  GNUNET_free (meter);
+}
+
+
+/** Functions for creating, starting and connecting the peergroup **/
+
+/**
+ * Check whether peers successfully shut down.
+ */
+static void
+internal_shutdown_callback (void *cls, const char *emsg)
+{
+  struct PeerGroupStartupContext *pg_start_ctx = cls;
+
+  if (emsg != NULL)
+    pg_start_ctx->peergroup_cb (pg_start_ctx->cls, emsg);
+  else
+    pg_start_ctx->peergroup_cb (pg_start_ctx->cls, pg_start_ctx->fail_reason);
+}
+
+/**
+ * Check if the get_handle is being used, if so stop the request.  Either
+ * way, schedule the end_badly_cont function which actually shuts down the
+ * test.
+ */
+static void
+end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct PeerGroupStartupContext *pg_start_ctx = cls;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Failing peer group startup with error: `%s'!\n",
+              pg_start_ctx->fail_reason);
+
+  GNUNET_TESTING_daemons_stop (pg_start_ctx->pg,
+                               GNUNET_TIME_absolute_get_remaining
+                               (pg_start_ctx->timeout),
+                               &internal_shutdown_callback, pg_start_ctx);
+
+  if (pg_start_ctx->hostkey_meter != NULL)
+  {
+    free_meter (pg_start_ctx->hostkey_meter);
+    pg_start_ctx->hostkey_meter = NULL;
+  }
+  if (pg_start_ctx->peer_start_meter != NULL)
+  {
+    free_meter (pg_start_ctx->peer_start_meter);
+    pg_start_ctx->peer_start_meter = NULL;
+  }
+  if (pg_start_ctx->connect_meter != NULL)
+  {
+    free_meter (pg_start_ctx->connect_meter);
+    pg_start_ctx->connect_meter = NULL;
+  }
+}
+
+/**
+ * This function is called whenever a connection attempt is finished between two of
+ * the started peers (started with GNUNET_TESTING_daemons_start).  The total
+ * number of times this function is called should equal the number returned
+ * from the GNUNET_TESTING_connect_topology call.
+ *
+ * The emsg variable is NULL on success (peers connected), and non-NULL on
+ * failure (peers failed to connect).
+ */
+static void
+internal_topology_callback (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)
+{
+  struct PeerGroupStartupContext *pg_start_ctx = cls;
+  char *temp_str;
+  char *second_str;
+  int temp;
+
+#if TIMING
+  unsigned long long duration;
+  unsigned long long total_duration;
+  unsigned int new_connections;
+  unsigned int new_failed_connections;
+  double conns_per_sec_recent;
+  double conns_per_sec_total;
+  double failed_conns_per_sec_recent;
+  double failed_conns_per_sec_total;
+#endif
+
+#if TIMING
+  if (GNUNET_TIME_absolute_get_difference
+      (connect_last_time,
+       GNUNET_TIME_absolute_get ()).rel_value >
+      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
+                                     CONN_UPDATE_DURATION).rel_value)
+  {
+    /* Get number of new connections */
+    new_connections = total_connections - previous_connections;
+
+    /* Get number of new FAILED connections */
+    new_failed_connections = failed_connections - previous_failed_connections;
+
+    /* Get duration in seconds */
+    duration =
+        GNUNET_TIME_absolute_get_difference (connect_last_time,
+                                             GNUNET_TIME_absolute_get
+                                             ()).rel_value / 1000;
+    total_duration =
+        GNUNET_TIME_absolute_get_difference (connect_start_time,
+                                             GNUNET_TIME_absolute_get
+                                             ()).rel_value / 1000;
+
+    failed_conns_per_sec_recent = (double) new_failed_connections / duration;
+    failed_conns_per_sec_total = (double) failed_connections / total_duration;
+    conns_per_sec_recent = (double) new_connections / duration;
+    conns_per_sec_total = (double) total_connections / total_duration;
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Recent: %.2f/s, Total: %.2f/s, Recent failed: %.2f/s, total failed %.2f/s\n",
+                conns_per_sec_recent, CONN_UPDATE_DURATION, conns_per_sec_total,
+                failed_conns_per_sec_recent, failed_conns_per_sec_total);
+    connect_last_time = GNUNET_TIME_absolute_get ();
+    previous_connections = total_connections;
+    previous_failed_connections = failed_connections;
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "have %u total_connections, %u failed\n", total_connections,
+                failed_connections);
+  }
+#endif
+
+
+  if (emsg == NULL)
+  {
+    pg_start_ctx->total_connections++;
+#if VERBOSE > 1
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "connected peer %s to peer %s, distance %u\n",
+                first_daemon->shortname, second_daemon->shortname, distance);
+#endif
+    if (pg_start_ctx->topology_output_file != NULL)
+    {
+      second_str = GNUNET_strdup (GNUNET_i2s (second));
+      temp =
+          GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n",
+                           GNUNET_i2s (first), second_str);
+      GNUNET_free (second_str);
+      if (temp > 0)
+        GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str,
+                                temp);
+      GNUNET_free (temp_str);
+    }
+  }
+  else
+  {
+    pg_start_ctx->failed_connections++;
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Failed to connect peer %s to peer %s with error :\n%s\n",
+                first_daemon->shortname, second_daemon->shortname, emsg);
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to connect peer %s to peer %s with error :\n%s\n",
+                first_daemon->shortname, second_daemon->shortname, emsg);
+#endif
+  }
+
+  GNUNET_assert (pg_start_ctx->connect_meter != NULL);
+  if (pg_start_ctx->connect_cb != NULL)
+    pg_start_ctx->connect_cb (pg_start_ctx->cls, first, second, distance,
+                              first_cfg, second_cfg, first_daemon,
+                              second_daemon, emsg);
+  if (GNUNET_YES != update_meter (pg_start_ctx->connect_meter))
+  {
+    /* No finished yet */
+    return;
+  }
+#if VERBOSE
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Created %d total connections, which is our target number!  Starting next phase of testing.\n",
+              pg_start_ctx->total_connections);
+#endif
+
+#if TIMING
+  total_duration =
+      GNUNET_TIME_absolute_get_difference (connect_start_time,
+                                            GNUNET_TIME_absolute_get
+                                            ()).rel_value / 1000;
+  failed_conns_per_sec_total = (double) failed_connections / total_duration;
+  conns_per_sec_total = (double) total_connections / total_duration;
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Overall connection info --- Total: %u, Total Failed %u/s\n",
+              total_connections, failed_connections);
+  GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+              "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n",
+              conns_per_sec_total, failed_conns_per_sec_total);
+#endif
+
+  GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
+  GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+
+  /* Call final callback, signifying that the peer group has been started and connected */
+  if (pg_start_ctx->peergroup_cb != NULL)
+    pg_start_ctx->peergroup_cb (pg_start_ctx->cls, NULL);
+
+  if (pg_start_ctx->topology_output_file != NULL)
+  {
+    temp = GNUNET_asprintf (&temp_str, "}\n");
+    if (temp > 0)
+      GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str,
+                              temp);
+    GNUNET_free (temp_str);
+    GNUNET_DISK_file_close (pg_start_ctx->topology_output_file);
+  }
+  GNUNET_free_non_null (pg_start_ctx->fail_reason);
+  if (NULL != pg_start_ctx->hostkey_meter)
+    free_meter(pg_start_ctx->hostkey_meter);
+  if (NULL != pg_start_ctx->peer_start_meter)
+    free_meter(pg_start_ctx->peer_start_meter);
+  if (NULL != pg_start_ctx->connect_meter)
+    free_meter(pg_start_ctx->connect_meter);
+  GNUNET_free (pg_start_ctx);
+}
+
+
+/**
+ * Callback called for each started daemon.
+ *
+ * @param cls Clause (PG Context).
+ * @param id PeerIdentidy of started daemon.
+ * @param cfg Configuration used by the daemon.
+ * @param d Handle for the daemon.
+ * @param emsg Error message, NULL on success.
+ */
+static void
+internal_peers_started_callback (void *cls,
+                                 const struct GNUNET_PeerIdentity *id,
+                                 const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                 struct GNUNET_TESTING_Daemon *d,
+                                 const char *emsg)
+{
+  struct PeerGroupStartupContext *pg_start_ctx = cls;
+
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Failed to start daemon with error: `%s'\n", emsg);
+    return;
+  }
+  GNUNET_assert (id != NULL);
+
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
+              (pg_start_ctx->total - pg_start_ctx->peers_left) + 1,
+              pg_start_ctx->total);
+#endif
+
+  pg_start_ctx->peers_left--;
+
+  if (NULL == pg_start_ctx->peer_start_meter)
+  {
+    /* Cancelled Ctrl-C or error */
+    return;
+  }
+  if (GNUNET_YES == update_meter (pg_start_ctx->peer_start_meter))
+  {
+#if VERBOSE
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "All %d daemons started, now connecting peers!\n",
+                pg_start_ctx->total);
+#endif
+    GNUNET_assert (pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
+    GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+
+    pg_start_ctx->expected_connections = UINT_MAX;
+    // FIXME: why whould peers_left be != 0?? Or pg NULL?
+    if ((pg_start_ctx->pg != NULL) && (pg_start_ctx->peers_left == 0))
+    {
+      pg_start_ctx->connect_start_time = GNUNET_TIME_absolute_get ();
+      pg_start_ctx->expected_connections =
+          GNUNET_TESTING_connect_topology (pg_start_ctx->pg,
+                                           pg_start_ctx->connect_topology,
+                                           pg_start_ctx->connect_topology_option,
+                                           pg_start_ctx->connect_topology_option_modifier,
+                                           pg_start_ctx->connect_timeout,
+                                           pg_start_ctx->connect_attempts, NULL,
+                                           NULL);
+
+      pg_start_ctx->connect_meter =
+          create_meter (pg_start_ctx->expected_connections, "Peer connection ",
+                        pg_start_ctx->verbose);
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Have %d expected connections\n",
+                  pg_start_ctx->expected_connections);
+    }
+
+    if (pg_start_ctx->expected_connections == 0)
+    {
+      GNUNET_free_non_null (pg_start_ctx->fail_reason);
+      pg_start_ctx->fail_reason =
+          GNUNET_strdup ("from connect topology (bad return)");
+      pg_start_ctx->die_task =
+          GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx);
+      return;
+    }
+
+    GNUNET_free_non_null (pg_start_ctx->fail_reason);
+    pg_start_ctx->fail_reason =
+        GNUNET_strdup ("from connect topology (timeout)");
+    pg_start_ctx->die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                      (pg_start_ctx->timeout), &end_badly,
+                                      pg_start_ctx);
+  }
+}
+
+/**
+ * Callback indicating that the hostkey was created for a peer.
+ *
+ * @param cls NULL
+ * @param id the peer identity
+ * @param d the daemon handle (pretty useless at this point, remove?)
+ * @param emsg non-null on failure
+ */
+static void
+internal_hostkey_callback (void *cls, const struct GNUNET_PeerIdentity *id,
+                           struct GNUNET_TESTING_Daemon *d, const char *emsg)
+{
+  struct PeerGroupStartupContext *pg_start_ctx = cls;
+  unsigned int create_expected_connections;
+
+  if (emsg != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Hostkey callback received error: %s\n", emsg);
+  }
+
+#if VERBOSE > 1
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Hostkey (%d/%d) created for peer `%s'\n",
+              pg_start_ctx->total - pg_start_ctx->peers_left + 1,
+              pg_start_ctx->total, GNUNET_i2s (id));
+#endif
+
+  pg_start_ctx->peers_left--;
+  if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter))
+  {
+    GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+    GNUNET_free_non_null (pg_start_ctx->fail_reason);
+    /* Set up task in case topology creation doesn't finish
+     * within a reasonable amount of time */
+    pg_start_ctx->fail_reason = GNUNET_strdup ("from create_topology");
+    pg_start_ctx->die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                      (pg_start_ctx->timeout), &end_badly,
+                                      pg_start_ctx);
+    pg_start_ctx->peers_left = pg_start_ctx->total;     /* Reset counter */
+    create_expected_connections =
+        GNUNET_TESTING_create_topology (pg_start_ctx->pg,
+                                        pg_start_ctx->topology,
+                                        pg_start_ctx->restrict_topology,
+                                        pg_start_ctx->restrict_transports);
+    if (create_expected_connections > 0)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                  "Topology set up, have %u expected connections, now starting peers!\n",
+                  create_expected_connections);
+      GNUNET_TESTING_daemons_continue_startup (pg_start_ctx->pg);
+    }
+    else
+    {
+      GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+      GNUNET_free_non_null (pg_start_ctx->fail_reason);
+      pg_start_ctx->fail_reason =
+          GNUNET_strdup ("from create topology (bad return)");
+      pg_start_ctx->die_task =
+          GNUNET_SCHEDULER_add_now (&end_badly, pg_start_ctx);
+      return;
+    }
+
+    GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+    GNUNET_free_non_null (pg_start_ctx->fail_reason);
+    pg_start_ctx->fail_reason =
+        GNUNET_strdup ("from continue startup (timeout)");
+    pg_start_ctx->die_task =
+        GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                      (pg_start_ctx->timeout), &end_badly,
+                                      pg_start_ctx);
+  }
+}
+
+
+/**
+ * Prototype of a callback function indicating that two peers
+ * are currently connected.
+ *
+ * @param cls closure
+ * @param first peer id for first daemon
+ * @param second peer id for the second daemon
+ * @param emsg error message (NULL on success)
+ */
+void
+write_topology_cb (void *cls, const struct GNUNET_PeerIdentity *first,
+                   const struct GNUNET_PeerIdentity *second, const char *emsg)
+{
+  struct TopologyOutputContext *topo_ctx;
+  int temp;
+  char *temp_str;
+  char *temp_pid2;
+
+  topo_ctx = (struct TopologyOutputContext *) cls;
+  GNUNET_assert (topo_ctx->file != NULL);
+  if ((emsg == NULL) && (first != NULL) && (second != NULL))
+  {
+    GNUNET_assert (first != NULL);
+    GNUNET_assert (second != NULL);
+    temp_pid2 = GNUNET_strdup (GNUNET_i2s (second));
+    temp =
+        GNUNET_asprintf (&temp_str, "\t\"%s\" -- \"%s\"\n", GNUNET_i2s (first),
+                         temp_pid2);
+    GNUNET_free (temp_pid2);
+    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
+  }
+  else if ((emsg == NULL) && (first == NULL) && (second == NULL))
+  {
+    temp = GNUNET_asprintf (&temp_str, "}\n");
+    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
+    GNUNET_DISK_file_close (topo_ctx->file);
+    topo_ctx->notify_cb (topo_ctx->notify_cb_cls, NULL);
+    GNUNET_free (topo_ctx);
+  }
+  else
+  {
+    temp = GNUNET_asprintf (&temp_str, "}\n");
+    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
+    GNUNET_DISK_file_close (topo_ctx->file);
+    topo_ctx->notify_cb (topo_ctx->notify_cb_cls, emsg);
+    GNUNET_free (topo_ctx);
+  }
+}
+
+/**
+ * Print current topology to a graphviz readable file.
+ *
+ * @param pg a currently running peergroup to print to file
+ * @param output_filename the file to write the topology to
+ * @param notify_cb callback to call upon completion or failure
+ * @param notify_cb_cls closure for notify_cb
+ *
+ */
+void
+GNUNET_TESTING_peergroup_topology_to_file (struct GNUNET_TESTING_PeerGroup *pg,
+                                           const char *output_filename,
+                                           GNUNET_TESTING_NotifyCompletion
+                                           notify_cb, void *notify_cb_cls)
+{
+  struct TopologyOutputContext *topo_ctx;
+  int temp;
+  char *temp_str;
+
+  topo_ctx = GNUNET_malloc (sizeof (struct TopologyOutputContext));
+
+  topo_ctx->notify_cb = notify_cb;
+  topo_ctx->notify_cb_cls = notify_cb_cls;
+  topo_ctx->file =
+      GNUNET_DISK_file_open (output_filename,
+                             GNUNET_DISK_OPEN_READWRITE |
+                             GNUNET_DISK_OPEN_CREATE,
+                             GNUNET_DISK_PERM_USER_READ |
+                             GNUNET_DISK_PERM_USER_WRITE);
+  if (topo_ctx->file == NULL)
+  {
+    notify_cb (notify_cb_cls, "Failed to open output file!");
+    GNUNET_free (topo_ctx);
+    return;
+  }
+
+  temp = GNUNET_asprintf (&temp_str, "strict graph G {\n");
+  if (temp > 0)
+    GNUNET_DISK_file_write (topo_ctx->file, temp_str, temp);
+  GNUNET_free_non_null (temp_str);
+  GNUNET_TESTING_get_topology (pg, &write_topology_cb, topo_ctx);
+}
+
+/**
+ * Start a peer group with a given number of peers.  Notify
+ * on completion of peer startup and connection based on given
+ * topological constraints.  Optionally notify on each
+ * established connection.
+ *
+ * @param cfg configuration template to use
+ * @param total number of daemons to start
+ * @param timeout total time allowed for peers to start
+ * @param connect_cb function to call each time two daemons are connected
+ * @param peergroup_cb function to call once all peers are up and connected
+ * @param peergroup_cls closure for peergroup callbacks
+ * @param hostnames linked list of host structs to use to start peers on
+ *                  (NULL to run on localhost only)
+ *
+ * @return NULL on error, otherwise handle to control peer group
+ */
+struct GNUNET_TESTING_PeerGroup *
+GNUNET_TESTING_peergroup_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                unsigned int total,
+                                struct GNUNET_TIME_Relative timeout,
+                                GNUNET_TESTING_NotifyConnection connect_cb,
+                                GNUNET_TESTING_NotifyCompletion peergroup_cb,
+                                void *peergroup_cls,
+                                const struct GNUNET_TESTING_Host *hostnames)
+{
+  struct PeerGroupStartupContext *pg_start_ctx;
+  char *temp_str;
+  int temp;
+  struct GNUNET_TIME_Relative rtimeout;
+
+  GNUNET_assert (total > 0);
+  GNUNET_assert (cfg != NULL);
+
+  pg_start_ctx = GNUNET_malloc (sizeof (struct PeerGroupStartupContext));
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old", "connect_attempts",
+                                             &pg_start_ctx->connect_attempts))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing_old", "connect_attempts");
+    GNUNET_free (pg_start_ctx);
+    return NULL;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg, "testing_old", "CONNECT_TIMEOUT",
+                                           &pg_start_ctx->connect_timeout))
+  {
+    pg_start_ctx->connect_timeout = DEFAULT_CONNECT_TIMEOUT;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old",
+                                             "max_outstanding_connections",
+                                             &pg_start_ctx->max_concurrent_connections))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing_old", "max_outstanding_connections");
+    GNUNET_free (pg_start_ctx);
+    return NULL;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_number (cfg, "testing_old",
+                                             "max_concurrent_ssh",
+                                             &pg_start_ctx->max_concurrent_ssh))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing_old", "max_concurrent_ssh");
+    GNUNET_free (pg_start_ctx);
+    return NULL;
+  }
+
+  if (GNUNET_SYSERR ==
+      (pg_start_ctx->verbose =
+       GNUNET_CONFIGURATION_get_value_yesno (cfg, "testing_old",
+                                             "use_progressbars")))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing_old", "use_progressbars");
+    GNUNET_free (pg_start_ctx);
+    return NULL;
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_time (cfg, "testing_old", "PEERGROUP_TIMEOUT",
+                                           &rtimeout))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
+                "testing_old", "PEERGROUP_TIMEOUT");
+    GNUNET_free (pg_start_ctx);
+    return NULL;
+  }
+  pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute (rtimeout);
+
+
+  /* Read topology related options from the configuration file */
+  temp_str = NULL;
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "topology",
+                                              &temp_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_get (&pg_start_ctx->topology, temp_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid topology `%s' given for section %s option %s\n",
+                temp_str, "TESTING_old", "TOPOLOGY");
+    pg_start_ctx->topology = GNUNET_TESTING_TOPOLOGY_CLIQUE;    /* Defaults to NONE, so set better default here */
+  }
+  GNUNET_free_non_null (temp_str);
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old",
+                                             "topology_output_file", &temp_str))
+  {
+    pg_start_ctx->topology_output_file =
+        GNUNET_DISK_file_open (temp_str,
+                               GNUNET_DISK_OPEN_READWRITE |
+                               GNUNET_DISK_OPEN_CREATE,
+                               GNUNET_DISK_PERM_USER_READ |
+                               GNUNET_DISK_PERM_USER_WRITE);
+    if (pg_start_ctx->topology_output_file != NULL)
+    {
+      GNUNET_free (temp_str);
+      temp = GNUNET_asprintf (&temp_str, "strict graph G {\n");
+      if (temp > 0)
+        GNUNET_DISK_file_write (pg_start_ctx->topology_output_file, temp_str,
+                                temp);
+    }
+    GNUNET_free (temp_str);
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "percentage",
+                                             &temp_str))
+    pg_start_ctx->topology_percentage = 0.5;
+  else
+  {
+    pg_start_ctx->topology_percentage = atof (temp_str);
+    GNUNET_free (temp_str);
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old", "probability",
+                                             &temp_str))
+    pg_start_ctx->topology_probability = 0.5;
+  else
+  {
+    pg_start_ctx->topology_probability = atof (temp_str);
+    GNUNET_free (temp_str);
+  }
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old",
+                                              "connect_topology", &temp_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_get (&pg_start_ctx->connect_topology, temp_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid connect topology `%s' given for section %s option %s\n",
+                temp_str, "TESTING_old", "CONNECT_TOPOLOGY");
+  }
+  GNUNET_free_non_null (temp_str);
+
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old",
+                                              "connect_topology_option",
+                                              &temp_str)) &&
+      (GNUNET_NO ==
+       GNUNET_TESTING_topology_option_get
+       (&pg_start_ctx->connect_topology_option, temp_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid connect topology option `%s' given for section %s option %s\n",
+                temp_str, "TESTING_old", "CONNECT_TOPOLOGY_OPTION");
+    pg_start_ctx->connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */
+  }
+  GNUNET_free_non_null (temp_str);
+
+  if (GNUNET_YES ==
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old",
+                                             "connect_topology_option_modifier",
+                                             &temp_str))
+  {
+    if (SSCANF
+        (temp_str, "%lf", &pg_start_ctx->connect_topology_option_modifier) != 1)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                  _
+                  ("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
+                  temp_str, "connect_topology_option_modifier", "TESTING_old");
+      GNUNET_free (temp_str);
+      GNUNET_free (pg_start_ctx);
+      return NULL;
+    }
+    GNUNET_free (temp_str);
+  }
+
+  if (GNUNET_YES !=
+      GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old",
+                                             "blacklist_transports",
+                                             &pg_start_ctx->restrict_transports))
+    pg_start_ctx->restrict_transports = NULL;
+
+  pg_start_ctx->restrict_topology = GNUNET_TESTING_TOPOLOGY_NONE;
+  if ((GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_string (cfg, "testing_old",
+                                              "blacklist_topology", &temp_str))
+      && (GNUNET_NO ==
+          GNUNET_TESTING_topology_get (&pg_start_ctx->restrict_topology,
+                                       temp_str)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Invalid topology `%s' given for section %s option %s\n",
+                temp_str, "TESTING_OLD", "BLACKLIST_TOPOLOGY");
+  }
+
+  GNUNET_free_non_null (temp_str);
+
+  pg_start_ctx->cfg = cfg;
+  pg_start_ctx->total = total;
+  pg_start_ctx->peers_left = total;
+  pg_start_ctx->connect_cb = connect_cb;
+  pg_start_ctx->peergroup_cb = peergroup_cb;
+  pg_start_ctx->cls = peergroup_cls;
+  pg_start_ctx->hostnames = hostnames;
+  pg_start_ctx->hostkey_meter =
+      create_meter (pg_start_ctx->peers_left, "Hostkeys created ",
+                    pg_start_ctx->verbose);
+  pg_start_ctx->peer_start_meter =
+      create_meter (pg_start_ctx->peers_left, "Peers started ",
+                    pg_start_ctx->verbose);
+  /* Make compilers happy */
+  reset_meter (pg_start_ctx->peer_start_meter);
+  pg_start_ctx->fail_reason =
+      GNUNET_strdup
+      ("didn't generate all hostkeys within allowed startup time!");
+  pg_start_ctx->die_task =
+      GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
+                                    (pg_start_ctx->timeout), &end_badly,
+                                    pg_start_ctx);
+
+  pg_start_ctx->pg =
+      GNUNET_TESTING_daemons_start (pg_start_ctx->cfg, pg_start_ctx->peers_left,
+                                    pg_start_ctx->max_concurrent_connections,
+                                    pg_start_ctx->max_concurrent_ssh,
+                                    GNUNET_TIME_absolute_get_remaining
+                                    (pg_start_ctx->timeout),
+                                    &internal_hostkey_callback, pg_start_ctx,
+                                    &internal_peers_started_callback,
+                                    pg_start_ctx, &internal_topology_callback,
+                                    pg_start_ctx, pg_start_ctx->hostnames);
+
+  return pg_start_ctx->pg;
+}
+
+/* end of testing_peergroup.c */
index 261be86190cc8a79cafd04d0da90dcfbc1f4e66e..4234625d60da56f18549f4e59f6b327e44f8c362 100644 (file)
@@ -36,7 +36,7 @@ endif
 test_gnunet_daemon_topology_SOURCES = \
  test_gnunet_daemon_topology.c
 test_gnunet_daemon_topology_LDADD = \
- $(top_builddir)/src/testing/libgnunettesting.la \
+ $(top_builddir)/src/testing_old/libgnunettesting_old.la \
  $(top_builddir)/src/util/libgnunetutil.la  
 
 EXTRA_DIST = \