aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2011-04-05 14:37:56 +0000
committerNathan S. Evans <evans@in.tum.de>2011-04-05 14:37:56 +0000
commit8da74da33f616eecdba93e9c94715a3e6244876f (patch)
tree0dc800404f4fc630206768eae09ff24921731a86
parent143df85a4543bad389083f959329a98023c78ee4 (diff)
initial peergroup convenience implementation
-rw-r--r--src/testing/Makefile.am3
-rw-r--r--src/testing/test_testing_group_remote.c2
-rw-r--r--src/testing/testing_peergroup.c644
3 files changed, 647 insertions, 2 deletions
diff --git a/src/testing/Makefile.am b/src/testing/Makefile.am
index 8084a97798..1d7806a2a5 100644
--- a/src/testing/Makefile.am
+++ b/src/testing/Makefile.am
@@ -13,7 +13,8 @@ lib_LTLIBRARIES = libgnunettesting.la
libgnunettesting_la_SOURCES = \
testing.c \
- testing_group.c
+ testing_group.c \
+ testing_peergroup.c
libgnunettesting_la_LIBADD = $(XLIB) \
$(top_builddir)/src/core/libgnunetcore.la \
$(top_builddir)/src/statistics/libgnunetstatistics.la \
diff --git a/src/testing/test_testing_group_remote.c b/src/testing/test_testing_group_remote.c
index 6a4d0cc1e4..58f3c4143f 100644
--- a/src/testing/test_testing_group_remote.c
+++ b/src/testing/test_testing_group_remote.c
@@ -56,7 +56,7 @@ shutdown_callback (void *cls, const char *emsg)
if (emsg != NULL)
{
#if VERBOSE
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed!\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown of peers failed (error %s)!\n", emsg);
#endif
if (ok == 0)
ok = 666;
diff --git a/src/testing/testing_peergroup.c b/src/testing/testing_peergroup.c
new file mode 100644
index 0000000000..bd725fedc7
--- /dev/null
+++ b/src/testing/testing_peergroup.c
@@ -0,0 +1,644 @@
+/*
+ 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"
+
+/** 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 int max_concurrent_connections;
+ unsigned int max_concurrent_ssh;
+ struct GNUNET_TIME_Absolute timeout;
+ GNUNET_TESTING_NotifyConnection connect_cb;
+ void *connect_cb_cls;
+ GNUNET_TESTING_NotifyCompletion peergroup_cb;
+ void *peergroup_cb_cls;
+ const struct GNUNET_TESTING_Host *hostnames;
+ enum GNUNET_TESTING_Topology topology;
+ enum GNUNET_TESTING_Topology restrict_topology;
+ const char *restrict_transports;
+ 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;
+};
+
+/**
+ * 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;
+ 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, ".");
+
+ 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->peergroup_cb_cls, emsg);
+ else
+ pg_start_ctx->peergroup_cb(pg_start_ctx->peergroup_cb_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);
+ if (pg_start_ctx->peer_start_meter != NULL)
+ free_meter (pg_start_ctx->peer_start_meter);
+ if (pg_start_ctx->connect_meter != NULL)
+ free_meter (pg_start_ctx->connect_meter);
+}
+
+/**
+ * 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;
+#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
+ }
+ 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->connect_cb_cls, first,
+ second,
+ distance,
+ first_cfg,
+ second_cfg,
+ first_daemon,
+ second_daemon,
+ emsg);
+ if (GNUNET_YES == update_meter (pg_start_ctx->connect_meter))
+ {
+#if VERBOSE
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Created %d total connections, which is our target number! Starting next phase of testing.\n",
+ 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 */
+ }
+}
+
+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",
+ (num_peers - peers_left) + 1, num_peers);
+#endif
+
+ pg_start_ctx->peers_left--;
+
+ 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",
+ num_peers);
+#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;
+ 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,
+ DEFAULT_CONNECT_TIMEOUT,
+ DEFAULT_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);
+ }
+
+ 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",
+ num_peers - peers_left, num_peers, GNUNET_i2s(id));
+#endif
+
+ pg_start_ctx->peers_left--;
+ if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "All %d hostkeys created, now creating topology!\n",
+ pg_start_ctx->total);
+ GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+ /* Set up task in case topology creation doesn't finish
+ * within a reasonable amount of time */
+ pg_start_ctx->die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
+ &end_badly,
+ "from create_topology");
+ 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);
+ pg_start_ctx->die_task = GNUNET_SCHEDULER_add_now (&end_badly,
+ "from create topology (bad return)");
+ }
+
+ GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
+ pg_start_ctx->die_task
+ = GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
+ &end_badly,
+ "from continue startup (timeout)");
+ }
+}
+
+
+/**
+ * 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 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 connect_cb function to call each time two daemons are connected
+ * @param connect_cb_cls closure for connect_callback
+ * @param peergroup_cb function to call once all peers are up and connected
+ * @param peergroup_cb_cls closure for peergroup_cb
+ * @param hostnames linked list of host structs to use to start peers on
+ * (NULL to run on localhost only)
+ * @param topology allowed overlay topology
+ * @param restrict_topology blacklist connections to this topology
+ * @param restrict_transports specific transports to blacklist
+ * @param connect_topology topology to connect peers in (defaults to allowed
+ * topology)
+ * @param connect_topology_options options for connect topology
+ * @param connect_topology_option_modifier option modifier for connect topology
+ * @param verbose GNUNET_YES to print progress bars, GNUNET_NO otherwise
+ *
+ * @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,
+ unsigned int max_concurrent_connections,
+ unsigned int max_concurrent_ssh,
+ struct GNUNET_TIME_Relative timeout,
+ GNUNET_TESTING_NotifyConnection connect_cb,
+ void *connect_cb_cls,
+ GNUNET_TESTING_NotifyCompletion peergroup_cb,
+ void *peergroup_cb_cls,
+ const struct GNUNET_TESTING_Host *hostnames,
+ enum GNUNET_TESTING_Topology topology,
+ enum GNUNET_TESTING_Topology restrict_topology,
+ const char *restrict_transports,
+ enum GNUNET_TESTING_Topology connect_topology,
+ enum GNUNET_TESTING_TopologyOption connect_topology_options,
+ double connect_topology_option_modifier, int verbose)
+{
+ struct PeerGroupStartupContext *pg_start_ctx;
+
+ GNUNET_assert(total > 0);
+ GNUNET_assert(cfg != NULL);
+
+ pg_start_ctx = GNUNET_malloc(sizeof(struct PeerGroupStartupContext));
+ pg_start_ctx->cfg = cfg;
+ pg_start_ctx->total = total;
+ pg_start_ctx->peers_left = total;
+ pg_start_ctx->max_concurrent_connections = max_concurrent_connections;
+ pg_start_ctx->max_concurrent_ssh = max_concurrent_ssh;
+ pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute(timeout);
+ pg_start_ctx->connect_cb = connect_cb_cls;
+ pg_start_ctx->peergroup_cb = peergroup_cb;
+ pg_start_ctx->peergroup_cb_cls = peergroup_cb_cls;
+ pg_start_ctx->hostnames = hostnames;
+ pg_start_ctx->topology = topology;
+ pg_start_ctx->restrict_topology = restrict_topology;
+ pg_start_ctx->restrict_transports = restrict_transports;
+ pg_start_ctx->connect_topology = connect_topology;
+ pg_start_ctx->connect_topology_option = connect_topology_options;
+ pg_start_ctx->connect_topology_option_modifier = connect_topology_option_modifier;
+ pg_start_ctx->verbose = verbose;
+ 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->die_task
+ = GNUNET_SCHEDULER_add_delayed (
+ GNUNET_TIME_absolute_get_remaining (
+ pg_start_ctx->timeout),
+ &end_badly,
+ "didn't generate all hostkeys within allowed startup time!");
+
+ 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 */