diff options
Diffstat (limited to 'src/testing/testing_peergroup.c')
-rw-r--r-- | src/testing/testing_peergroup.c | 1017 |
1 files changed, 0 insertions, 1017 deletions
diff --git a/src/testing/testing_peergroup.c b/src/testing/testing_peergroup.c deleted file mode 100644 index 87504ed..0000000 --- a/src/testing/testing_peergroup.c +++ /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 */ |