2 This file is part of GNUnet
3 (C) 2008-2011 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testing/testing_peergroup.c
23 * @brief API implementation for easy peer group creation
24 * @author Nathan Evans
25 * @author Christian Grothoff
29 #include "gnunet_constants.h"
30 #include "gnunet_arm_service.h"
31 #include "gnunet_testing_lib.h"
32 #include "gnunet_core_service.h"
33 #include "gnunet_disk_lib.h"
36 #define DEFAULT_CONNECT_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
38 #define DEFAULT_CONNECT_ATTEMPTS 2
40 /** Struct definitions **/
42 struct PeerGroupStartupContext
44 struct GNUNET_TESTING_PeerGroup *pg;
45 const struct GNUNET_CONFIGURATION_Handle *cfg;
47 unsigned int peers_left;
48 unsigned long long max_concurrent_connections;
49 unsigned long long connect_attempts;
50 unsigned long long max_concurrent_ssh;
51 struct GNUNET_TIME_Absolute timeout;
52 GNUNET_TESTING_NotifyConnection connect_cb;
53 GNUNET_TESTING_NotifyCompletion peergroup_cb;
56 * Closure for all peergroup callbacks.
60 const struct GNUNET_TESTING_Host *hostnames;
61 enum GNUNET_TESTING_Topology topology;
63 float topology_percentage;
65 float topology_probability;
67 enum GNUNET_TESTING_Topology restrict_topology;
68 char *restrict_transports;
69 enum GNUNET_TESTING_Topology connect_topology;
70 enum GNUNET_TESTING_TopologyOption connect_topology_option;
71 double connect_topology_option_modifier;
74 struct ProgressMeter *hostkey_meter;
75 struct ProgressMeter *peer_start_meter;
76 struct ProgressMeter *connect_meter;
79 * Task used to kill the peergroup.
81 GNUNET_SCHEDULER_TaskIdentifier die_task;
86 * Variable used to store the number of connections we should wait for.
88 unsigned int expected_connections;
91 * Time when the connecting peers was started.
93 struct GNUNET_TIME_Absolute connect_start_time;
96 * The total number of connections that have been created so far.
98 unsigned int total_connections;
101 * The total number of connections that have failed so far.
103 unsigned int failed_connections;
106 * File handle to write out topology in dot format.
108 struct GNUNET_DISK_FileHandle *topology_output_file;
112 * Simple struct to keep track of progress, and print a
113 * percentage meter for long running tasks.
118 * Total number of tasks to complete.
123 * Print percentage done after modnum tasks.
128 * Print a . each dotnum tasks.
133 * Total number completed thus far.
135 unsigned int completed;
138 * Whether or not to print.
143 * Startup string for progress meter.
145 char *startup_string;
149 /** Utility functions **/
152 * Create a meter to keep track of the progress of some task.
154 * @param total the total number of items to complete
155 * @param start_string a string to prefix the meter with (if printing)
156 * @param print GNUNET_YES to print the meter, GNUNET_NO to count
159 * @return the progress meter
161 static struct ProgressMeter *
162 create_meter(unsigned int total, char * start_string, int print)
164 struct ProgressMeter *ret;
165 ret = GNUNET_malloc(sizeof(struct ProgressMeter));
168 ret->modnum = total / 4;
169 ret->dotnum = (total / 50) + 1;
170 if (start_string != NULL)
171 ret->startup_string = GNUNET_strdup(start_string);
173 ret->startup_string = GNUNET_strdup("");
179 * Update progress meter (increment by one).
181 * @param meter the meter to update and print info for
183 * @return GNUNET_YES if called the total requested,
184 * GNUNET_NO if more items expected
187 update_meter(struct ProgressMeter *meter)
189 if (meter->print == GNUNET_YES)
191 if (meter->completed % meter->modnum == 0)
193 if (meter->completed == 0)
195 fprintf (stdout, "%sProgress: [0%%", meter->startup_string);
198 fprintf (stdout, "%d%%", (int) (((float) meter->completed
199 / meter->total) * 100));
201 else if (meter->completed % meter->dotnum == 0)
202 fprintf (stdout, ".");
204 if (meter->completed + 1 == meter->total)
205 fprintf (stdout, "%d%%]\n", 100);
210 if (meter->completed == meter->total)
216 * Reset progress meter.
218 * @param meter the meter to reset
220 * @return GNUNET_YES if meter reset,
221 * GNUNET_SYSERR on error
224 reset_meter(struct ProgressMeter *meter)
227 return GNUNET_SYSERR;
229 meter->completed = 0;
234 * Release resources for meter
236 * @param meter the meter to free
239 free_meter(struct ProgressMeter *meter)
241 GNUNET_free_non_null (meter->startup_string);
246 /** Functions for creating, starting and connecting the peergroup **/
249 * Check whether peers successfully shut down.
252 internal_shutdown_callback(void *cls, const char *emsg)
254 struct PeerGroupStartupContext *pg_start_ctx = cls;
256 pg_start_ctx->peergroup_cb(pg_start_ctx->cls, emsg);
258 pg_start_ctx->peergroup_cb(pg_start_ctx->cls, pg_start_ctx->fail_reason);
262 * Check if the get_handle is being used, if so stop the request. Either
263 * way, schedule the end_badly_cont function which actually shuts down the
267 end_badly(void *cls, const struct GNUNET_SCHEDULER_TaskContext * tc)
269 struct PeerGroupStartupContext *pg_start_ctx = cls;
270 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failing peer group startup with error: `%s'!\n",
271 pg_start_ctx->fail_reason);
273 GNUNET_TESTING_daemons_stop (pg_start_ctx->pg, GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout), &internal_shutdown_callback, pg_start_ctx);
275 if (pg_start_ctx->hostkey_meter != NULL)
276 free_meter (pg_start_ctx->hostkey_meter);
277 if (pg_start_ctx->peer_start_meter != NULL)
278 free_meter (pg_start_ctx->peer_start_meter);
279 if (pg_start_ctx->connect_meter != NULL)
280 free_meter (pg_start_ctx->connect_meter);
284 * This function is called whenever a connection attempt is finished between two of
285 * the started peers (started with GNUNET_TESTING_daemons_start). The total
286 * number of times this function is called should equal the number returned
287 * from the GNUNET_TESTING_connect_topology call.
289 * The emsg variable is NULL on success (peers connected), and non-NULL on
290 * failure (peers failed to connect).
293 internal_topology_callback(
295 const struct GNUNET_PeerIdentity *first,
296 const struct GNUNET_PeerIdentity *second,
298 const struct GNUNET_CONFIGURATION_Handle *first_cfg,
299 const struct GNUNET_CONFIGURATION_Handle *second_cfg,
300 struct GNUNET_TESTING_Daemon *first_daemon,
301 struct GNUNET_TESTING_Daemon *second_daemon,
304 struct PeerGroupStartupContext *pg_start_ctx = cls;
309 unsigned long long duration;
310 unsigned long long total_duration;
311 unsigned int new_connections;
312 unsigned int new_failed_connections;
313 double conns_per_sec_recent;
314 double conns_per_sec_total;
315 double failed_conns_per_sec_recent;
316 double failed_conns_per_sec_total;
320 if (GNUNET_TIME_absolute_get_difference (connect_last_time,
321 GNUNET_TIME_absolute_get ()).rel_value
322 > GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
323 CONN_UPDATE_DURATION).rel_value)
325 /* Get number of new connections */
326 new_connections = total_connections - previous_connections;
328 /* Get number of new FAILED connections */
329 new_failed_connections = failed_connections - previous_failed_connections;
331 /* Get duration in seconds */
333 = GNUNET_TIME_absolute_get_difference (connect_last_time,
334 GNUNET_TIME_absolute_get ()).rel_value
337 = GNUNET_TIME_absolute_get_difference (connect_start_time,
338 GNUNET_TIME_absolute_get ()).rel_value
341 failed_conns_per_sec_recent = (double) new_failed_connections / duration;
342 failed_conns_per_sec_total = (double) failed_connections / total_duration;
343 conns_per_sec_recent = (double) new_connections / duration;
344 conns_per_sec_total = (double) total_connections / total_duration;
346 GNUNET_ERROR_TYPE_WARNING,
347 "Recent: %.2f/s, Total: %.2f/s, Recent failed: %.2f/s, total failed %.2f/s\n",
348 conns_per_sec_recent, CONN_UPDATE_DURATION,
349 conns_per_sec_total, failed_conns_per_sec_recent,
350 failed_conns_per_sec_total);
351 connect_last_time = GNUNET_TIME_absolute_get ();
352 previous_connections = total_connections;
353 previous_failed_connections = failed_connections;
354 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
355 "have %u total_connections, %u failed\n", total_connections,
363 pg_start_ctx->total_connections++;
365 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "connected peer %s to peer %s, distance %u\n",
366 first_daemon->shortname,
367 second_daemon->shortname,
370 if (pg_start_ctx->topology_output_file != NULL)
372 second_str = GNUNET_strdup(GNUNET_i2s(second));
373 temp = GNUNET_asprintf(&temp_str, "\t\"%s\" -> \"%s\"\n", GNUNET_i2s(first), second_str);
374 GNUNET_free(second_str);
376 GNUNET_DISK_file_write(pg_start_ctx->topology_output_file, temp_str, temp);
377 GNUNET_free(temp_str);
382 pg_start_ctx->failed_connections++;
384 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Failed to connect peer %s to peer %s with error :\n%s\n",
385 first_daemon->shortname,
386 second_daemon->shortname, emsg);
388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Failed to connect peer %s to peer %s with error :\n%s\n",
389 first_daemon->shortname,
390 second_daemon->shortname, emsg);
394 GNUNET_assert(pg_start_ctx->connect_meter != NULL);
395 if (pg_start_ctx->connect_cb != NULL)
396 pg_start_ctx->connect_cb(pg_start_ctx->cls, first,
404 if (GNUNET_YES == update_meter (pg_start_ctx->connect_meter))
407 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
408 "Created %d total connections, which is our target number! Starting next phase of testing.\n",
414 = GNUNET_TIME_absolute_get_difference (connect_start_time,
415 GNUNET_TIME_absolute_get ()).rel_value
417 failed_conns_per_sec_total = (double) failed_connections / total_duration;
418 conns_per_sec_total = (double) total_connections / total_duration;
419 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
420 "Overall connection info --- Total: %u, Total Failed %u/s\n",
421 total_connections, failed_connections);
423 GNUNET_ERROR_TYPE_WARNING,
424 "Overall connection info --- Total: %.2f/s, Total Failed %.2f/s\n",
425 conns_per_sec_total, failed_conns_per_sec_total);
428 GNUNET_assert(pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
429 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
431 /* Call final callback, signifying that the peer group has been started and connected */
432 if (pg_start_ctx->peergroup_cb != NULL)
433 pg_start_ctx->peergroup_cb(pg_start_ctx->cls, NULL);
435 if (pg_start_ctx->topology_output_file != NULL)
437 temp = GNUNET_asprintf(&temp_str, "}\n");
439 GNUNET_DISK_file_write(pg_start_ctx->topology_output_file, temp_str, temp);
440 GNUNET_free(temp_str);
441 GNUNET_DISK_file_close(pg_start_ctx->topology_output_file);
447 internal_peers_started_callback(void *cls, const struct GNUNET_PeerIdentity *id,
448 const struct GNUNET_CONFIGURATION_Handle *cfg,
449 struct GNUNET_TESTING_Daemon *d, const char *emsg)
451 struct PeerGroupStartupContext *pg_start_ctx = cls;
454 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
455 "Failed to start daemon with error: `%s'\n", emsg);
458 GNUNET_assert (id != NULL);
461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started daemon %llu out of %llu\n",
462 (num_peers - peers_left) + 1, num_peers);
465 pg_start_ctx->peers_left--;
467 if (GNUNET_YES == update_meter (pg_start_ctx->peer_start_meter))
470 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471 "All %d daemons started, now connecting peers!\n",
474 GNUNET_assert(pg_start_ctx->die_task != GNUNET_SCHEDULER_NO_TASK);
475 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
477 pg_start_ctx->expected_connections = UINT_MAX;
478 if ((pg_start_ctx->pg != NULL) && (pg_start_ctx->peers_left == 0))
480 pg_start_ctx->connect_start_time = GNUNET_TIME_absolute_get ();
481 pg_start_ctx->expected_connections
482 = GNUNET_TESTING_connect_topology (
484 pg_start_ctx->connect_topology,
485 pg_start_ctx->connect_topology_option,
486 pg_start_ctx->connect_topology_option_modifier,
487 DEFAULT_CONNECT_TIMEOUT,
488 pg_start_ctx->connect_attempts,
491 pg_start_ctx->connect_meter
492 = create_meter (pg_start_ctx->expected_connections,
493 "Peer connection ", pg_start_ctx->verbose);
494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
495 "Have %d expected connections\n",
496 pg_start_ctx->expected_connections);
499 if (pg_start_ctx->expected_connections == 0)
501 GNUNET_free_non_null(pg_start_ctx->fail_reason);
502 pg_start_ctx->fail_reason = GNUNET_strdup("from connect topology (bad return)");
503 pg_start_ctx->die_task
504 = GNUNET_SCHEDULER_add_now (&end_badly,
508 GNUNET_free_non_null(pg_start_ctx->fail_reason);
509 pg_start_ctx->fail_reason = GNUNET_strdup("from connect topology (timeout)");
510 pg_start_ctx->die_task
511 = GNUNET_SCHEDULER_add_delayed (
512 GNUNET_TIME_absolute_get_remaining (pg_start_ctx->timeout),
519 * Callback indicating that the hostkey was created for a peer.
522 * @param id the peer identity
523 * @param d the daemon handle (pretty useless at this point, remove?)
524 * @param emsg non-null on failure
527 internal_hostkey_callback(void *cls, const struct GNUNET_PeerIdentity *id,
528 struct GNUNET_TESTING_Daemon *d, const char *emsg)
530 struct PeerGroupStartupContext *pg_start_ctx = cls;
531 unsigned int create_expected_connections;
535 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
536 "Hostkey callback received error: %s\n", emsg);
540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
541 "Hostkey (%d/%d) created for peer `%s'\n",
542 num_peers - peers_left, num_peers, GNUNET_i2s(id));
545 pg_start_ctx->peers_left--;
546 if (GNUNET_YES == update_meter (pg_start_ctx->hostkey_meter))
548 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
549 /* Set up task in case topology creation doesn't finish
550 * within a reasonable amount of time */
551 pg_start_ctx->die_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
553 "from create_topology");
554 pg_start_ctx->peers_left = pg_start_ctx->total; /* Reset counter */
555 create_expected_connections = GNUNET_TESTING_create_topology (pg_start_ctx->pg, pg_start_ctx->topology, pg_start_ctx->restrict_topology,
556 pg_start_ctx->restrict_transports);
557 if (create_expected_connections > 0)
559 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
560 "Topology set up, have %u expected connections, now starting peers!\n", create_expected_connections);
561 GNUNET_TESTING_daemons_continue_startup (pg_start_ctx->pg);
565 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
566 pg_start_ctx->die_task = GNUNET_SCHEDULER_add_now (&end_badly,
567 "from create topology (bad return)");
570 GNUNET_SCHEDULER_cancel (pg_start_ctx->die_task);
571 pg_start_ctx->die_task
572 = GNUNET_SCHEDULER_add_delayed (
573 GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
575 "from continue startup (timeout)");
581 * Start a peer group with a given number of peers. Notify
582 * on completion of peer startup and connection based on given
583 * topological constraints. Optionally notify on each
584 * established connection.
586 * @param cfg configuration template to use
587 * @param total number of daemons to start
588 * @param timeout total time allowed for peers to start
589 * @param connect_cb function to call each time two daemons are connected
590 * @param peergroup_cb function to call once all peers are up and connected
591 * @param peergroup_cls closure for peergroup callbacks
592 * @param hostnames linked list of host structs to use to start peers on
593 * (NULL to run on localhost only)
595 * @return NULL on error, otherwise handle to control peer group
597 struct GNUNET_TESTING_PeerGroup *
598 GNUNET_TESTING_peergroup_start(
599 const struct GNUNET_CONFIGURATION_Handle *cfg,
601 struct GNUNET_TIME_Relative timeout,
602 GNUNET_TESTING_NotifyConnection connect_cb,
603 GNUNET_TESTING_NotifyCompletion peergroup_cb,
605 const struct GNUNET_TESTING_Host *hostnames)
607 struct PeerGroupStartupContext *pg_start_ctx;
608 unsigned long long temp_config_number;
611 GNUNET_assert(total > 0);
612 GNUNET_assert(cfg != NULL);
614 pg_start_ctx = GNUNET_malloc(sizeof(struct PeerGroupStartupContext));
616 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
618 &pg_start_ctx->connect_attempts))
620 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
621 "testing", "connect_attempts");
622 GNUNET_free(pg_start_ctx);
627 != GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
628 "max_outstanding_connections",
629 &pg_start_ctx->max_concurrent_connections))
631 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
632 "testing", "max_outstanding_connections");
633 GNUNET_free(pg_start_ctx);
637 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
638 "max_concurrent_ssh",
639 &pg_start_ctx->max_concurrent_ssh))
641 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
642 "testing", "max_concurrent_ssh");
643 GNUNET_free(pg_start_ctx);
647 if (GNUNET_SYSERR == (pg_start_ctx->verbose = GNUNET_CONFIGURATION_get_value_yesno (cfg, "testing",
648 "use_progressbars")))
650 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
651 "testing", "use_progressbars");
652 GNUNET_free(pg_start_ctx);
656 if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_number (cfg, "testing",
658 &temp_config_number))
659 pg_start_ctx->timeout = GNUNET_TIME_relative_to_absolute(GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
660 temp_config_number));
663 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Must provide option %s:%s!\n",
664 "testing", "peergroup_timeout");
665 GNUNET_free(pg_start_ctx);
670 /* Read topology related options from the configuration file */
672 if ((GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
675 && (GNUNET_NO == GNUNET_TESTING_topology_get (&pg_start_ctx->topology, temp_str)))
677 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
678 "Invalid topology `%s' given for section %s option %s\n",
679 temp_str, "TESTING", "TOPOLOGY");
680 pg_start_ctx->topology = GNUNET_TESTING_TOPOLOGY_CLIQUE; /* Defaults to NONE, so set better default here */
682 GNUNET_free_non_null(temp_str);
684 if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string(cfg, "testing", "topology_output_file", &temp_str))
686 pg_start_ctx->topology_output_file = GNUNET_DISK_file_open (temp_str, GNUNET_DISK_OPEN_READWRITE
687 | GNUNET_DISK_OPEN_CREATE,
688 GNUNET_DISK_PERM_USER_READ |
689 GNUNET_DISK_PERM_USER_WRITE);
690 if (pg_start_ctx->topology_output_file != NULL)
692 GNUNET_free(temp_str);
693 temp = GNUNET_asprintf(&temp_str, "digraph G {\n");
695 GNUNET_DISK_file_write(pg_start_ctx->topology_output_file, temp_str, temp);
697 GNUNET_free(temp_str);
701 != GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "percentage",
703 pg_start_ctx->topology_percentage = 0.5;
706 pg_start_ctx->topology_percentage = atof (temp_str);
707 GNUNET_free(temp_str);
711 != GNUNET_CONFIGURATION_get_value_string (cfg, "testing", "probability",
713 pg_start_ctx->topology_probability = 0.5;
716 pg_start_ctx->topology_probability = atof (temp_str);
717 GNUNET_free(temp_str);
721 == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
724 && (GNUNET_NO == GNUNET_TESTING_topology_get (&pg_start_ctx->connect_topology,
728 GNUNET_ERROR_TYPE_WARNING,
729 "Invalid connect topology `%s' given for section %s option %s\n",
730 temp_str, "TESTING", "CONNECT_TOPOLOGY");
732 GNUNET_free_non_null(temp_str);
735 == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
736 "connect_topology_option",
739 == GNUNET_TESTING_topology_option_get (&pg_start_ctx->connect_topology_option,
743 GNUNET_ERROR_TYPE_WARNING,
744 "Invalid connect topology option `%s' given for section %s option %s\n",
746 "CONNECT_TOPOLOGY_OPTION");
747 pg_start_ctx->connect_topology_option = GNUNET_TESTING_TOPOLOGY_OPTION_ALL; /* Defaults to NONE, set to ALL */
749 GNUNET_free_non_null(temp_str);
752 == GNUNET_CONFIGURATION_get_value_string (
755 "connect_topology_option_modifier",
758 if (sscanf (temp_str, "%lf",
759 &pg_start_ctx->connect_topology_option_modifier) != 1)
762 GNUNET_ERROR_TYPE_WARNING,
763 _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
765 "connect_topology_option_modifier", "TESTING");
766 GNUNET_free (temp_str);
767 GNUNET_free(pg_start_ctx);
770 GNUNET_free (temp_str);
774 != GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
775 "blacklist_transports",
776 &pg_start_ctx->restrict_transports))
777 pg_start_ctx->restrict_transports = NULL;
780 == GNUNET_CONFIGURATION_get_value_string (cfg, "testing",
781 "blacklist_topology",
783 && (GNUNET_NO == GNUNET_TESTING_topology_get (&pg_start_ctx->restrict_topology,
786 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
787 "Invalid topology `%s' given for section %s option %s\n",
788 temp_str, "TESTING", "BLACKLIST_TOPOLOGY");
790 GNUNET_free_non_null(temp_str);
792 pg_start_ctx->cfg = cfg;
793 pg_start_ctx->total = total;
794 pg_start_ctx->peers_left = total;
795 pg_start_ctx->connect_cb = connect_cb;
796 pg_start_ctx->peergroup_cb = peergroup_cb;
797 pg_start_ctx->cls = peergroup_cls;
798 pg_start_ctx->hostnames = hostnames;
799 pg_start_ctx->hostkey_meter = create_meter (pg_start_ctx->peers_left, "Hostkeys created ", pg_start_ctx->verbose);
800 pg_start_ctx->peer_start_meter = create_meter (pg_start_ctx->peers_left, "Peers started ", pg_start_ctx->verbose);
801 /* Make compilers happy */
802 reset_meter(pg_start_ctx->peer_start_meter);
803 pg_start_ctx->die_task
804 = GNUNET_SCHEDULER_add_delayed (
805 GNUNET_TIME_absolute_get_remaining (
806 pg_start_ctx->timeout),
808 "didn't generate all hostkeys within allowed startup time!");
811 = GNUNET_TESTING_daemons_start (
813 pg_start_ctx->peers_left,
814 pg_start_ctx->max_concurrent_connections,
815 pg_start_ctx->max_concurrent_ssh,
816 GNUNET_TIME_absolute_get_remaining(pg_start_ctx->timeout),
817 &internal_hostkey_callback, pg_start_ctx,
818 &internal_peers_started_callback,
820 &internal_topology_callback,
821 pg_start_ctx, pg_start_ctx->hostnames);
823 return pg_start_ctx->pg;
826 /* end of testing_peergroup.c */