aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--contrib/testbed_infiniband.conf6
-rw-r--r--src/include/gnunet_testbed_service.h14
-rw-r--r--src/nse/gnunet-nse-profiler.c4
-rw-r--r--src/regex/gnunet-regex-profiler.c2
-rw-r--r--src/testbed/Makefile.am8
-rw-r--r--src/testbed/gnunet-service-testbed.c8
-rw-r--r--src/testbed/test_testbed_api.c10
-rw-r--r--src/testbed/test_testbed_api_2peers_1controller.c10
-rw-r--r--src/testbed/test_testbed_api_3peers_3controllers.c8
-rw-r--r--src/testbed/test_testbed_api_controllerlink.c12
-rw-r--r--src/testbed/test_testbed_api_hosts.c19
-rw-r--r--src/testbed/testbed.h14
-rw-r--r--src/testbed/testbed_api.c428
-rw-r--r--src/testbed/testbed_api_hosts.c589
-rw-r--r--src/testbed/testbed_api_hosts.h17
-rw-r--r--src/testbed/testbed_api_testbed.c7
16 files changed, 639 insertions, 517 deletions
diff --git a/contrib/testbed_infiniband.conf b/contrib/testbed_infiniband.conf
index 568ddf7c5..d4f105793 100644
--- a/contrib/testbed_infiniband.conf
+++ b/contrib/testbed_infiniband.conf
@@ -4,7 +4,9 @@ PORT = 12113
4ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24; 4ACCEPT_FROM = 127.0.0.1; 192.168.1.0/24;
5HOSTNAME = localhost 5HOSTNAME = localhost
6MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5 6MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS = 5
7OVERLAY_TOPOLOGY = CLIQUE 7OVERLAY_TOPOLOGY = RANDOM
8OVERLAY_RANDOM_LINKS = 1000
9OPERATION_TIMEOUT = 5 s
8# LOG_FILE = /tmp/testbed.log 10# LOG_FILE = /tmp/testbed.log
9#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args 11#PREFIX = xterm -geometry 100x85 -T peer1 -e libtool --mode=execute gdb --args
10 12
@@ -35,7 +37,7 @@ QUOTA = 1 MB
35DATABASE = sqlite 37DATABASE = sqlite
36 38
37[transport] 39[transport]
38PLUGINS = udp 40PLUGINS = unix
39DEBUG = NO 41DEBUG = NO
40ACCEPT_FROM6 = ::1; 42ACCEPT_FROM6 = ::1;
41ACCEPT_FROM = 127.0.0.1; 43ACCEPT_FROM = 127.0.0.1;
diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h
index 3c2d93272..25378e890 100644
--- a/src/include/gnunet_testbed_service.h
+++ b/src/include/gnunet_testbed_service.h
@@ -75,12 +75,16 @@ struct GNUNET_TESTBED_Controller;
75 * 75 *
76 * @param hostname name of the host, use "NULL" for localhost 76 * @param hostname name of the host, use "NULL" for localhost
77 * @param username username to use for the login; may be NULL 77 * @param username username to use for the login; may be NULL
78 * @param cfg the configuration to use as a template while starting a controller
79 * on this host. Operation queue sizes specific to a host are also
80 * read from this configuration handle
78 * @param port port number to use for ssh; use 0 to let ssh decide 81 * @param port port number to use for ssh; use 0 to let ssh decide
79 * @return handle to the host, NULL on error 82 * @return handle to the host, NULL on error
80 */ 83 */
81struct GNUNET_TESTBED_Host * 84struct GNUNET_TESTBED_Host *
82GNUNET_TESTBED_host_create (const char *hostname, 85GNUNET_TESTBED_host_create (const char *hostname,
83 const char *username, 86 const char *username,
87 const struct GNUNET_CONFIGURATION_Handle *cfg,
84 uint16_t port); 88 uint16_t port);
85 89
86 90
@@ -94,6 +98,9 @@ GNUNET_TESTBED_host_create (const char *hostname,
94 * reserved to always mean 'localhost' 98 * reserved to always mean 'localhost'
95 * @param hostname name of the host, use "NULL" for localhost 99 * @param hostname name of the host, use "NULL" for localhost
96 * @param username username to use for the login; may be NULL 100 * @param username username to use for the login; may be NULL
101 * @param cfg the configuration to use as a template while starting a controller
102 * on this host. Operation queue sizes specific to a host are also
103 * read from this configuration handle
97 * @param port port number to use for ssh; use 0 to let ssh decide 104 * @param port port number to use for ssh; use 0 to let ssh decide
98 * @return handle to the host, NULL on error 105 * @return handle to the host, NULL on error
99 */ 106 */
@@ -101,6 +108,8 @@ struct GNUNET_TESTBED_Host *
101GNUNET_TESTBED_host_create_with_id (uint32_t id, 108GNUNET_TESTBED_host_create_with_id (uint32_t id,
102 const char *hostname, 109 const char *hostname,
103 const char *username, 110 const char *username,
111 const struct GNUNET_CONFIGURATION_Handle
112 *cfg,
104 uint16_t port); 113 uint16_t port);
105 114
106 115
@@ -108,12 +117,17 @@ GNUNET_TESTBED_host_create_with_id (uint32_t id,
108 * Load a set of hosts from a configuration file. 117 * Load a set of hosts from a configuration file.
109 * 118 *
110 * @param filename file with the host specification 119 * @param filename file with the host specification
120 * @param cfg the configuration to use as a template while starting a controller
121 * on any of the loaded hosts. Operation queue sizes specific to a host
122 * are also read from this configuration handle
111 * @param hosts set to the hosts found in the file; caller must free this if 123 * @param hosts set to the hosts found in the file; caller must free this if
112 * number of hosts returned is greater than 0 124 * number of hosts returned is greater than 0
113 * @return number of hosts returned in 'hosts', 0 on error 125 * @return number of hosts returned in 'hosts', 0 on error
114 */ 126 */
115unsigned int 127unsigned int
116GNUNET_TESTBED_hosts_load_from_file (const char *filename, 128GNUNET_TESTBED_hosts_load_from_file (const char *filename,
129 const struct GNUNET_CONFIGURATION_Handle
130 *cfg,
117 struct GNUNET_TESTBED_Host ***hosts); 131 struct GNUNET_TESTBED_Host ***hosts);
118 132
119 133
diff --git a/src/nse/gnunet-nse-profiler.c b/src/nse/gnunet-nse-profiler.c
index 225a4202a..850817bdd 100644
--- a/src/nse/gnunet-nse-profiler.c
+++ b/src/nse/gnunet-nse-profiler.c
@@ -299,6 +299,9 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
299 // FIXME: what about closing other files!? 299 // FIXME: what about closing other files!?
300 if (NULL != data_file) 300 if (NULL != data_file)
301 GNUNET_DISK_file_close (data_file); 301 GNUNET_DISK_file_close (data_file);
302 if (NULL != testing_cfg)
303 GNUNET_CONFIGURATION_destroy (testing_cfg);
304 testing_cfg = NULL;
302} 305}
303 306
304 307
@@ -891,6 +894,7 @@ controller_start_cb (void *cls,
891 return; 894 return;
892 } 895 }
893 num_hosts = GNUNET_TESTBED_hosts_load_from_file (hosts_file, 896 num_hosts = GNUNET_TESTBED_hosts_load_from_file (hosts_file,
897 testing_cfg,
894 &hosts); 898 &hosts);
895 if (0 == num_hosts) 899 if (0 == num_hosts)
896 { 900 {
diff --git a/src/regex/gnunet-regex-profiler.c b/src/regex/gnunet-regex-profiler.c
index 25d4874bc..8d460ef74 100644
--- a/src/regex/gnunet-regex-profiler.c
+++ b/src/regex/gnunet-regex-profiler.c
@@ -1987,7 +1987,7 @@ run (void *cls, char *const *args, const char *cfgfile,
1987 fprintf (stderr, _("No policy directory specified on command line. Exiting.\n")); 1987 fprintf (stderr, _("No policy directory specified on command line. Exiting.\n"));
1988 return; 1988 return;
1989 } 1989 }
1990 num_hosts = GNUNET_TESTBED_hosts_load_from_file (args[0], &hosts); 1990 num_hosts = GNUNET_TESTBED_hosts_load_from_file (args[0], config, &hosts);
1991 if (0 == num_hosts) 1991 if (0 == num_hosts)
1992 { 1992 {
1993 fprintf (stderr, _("No hosts loaded. Need at least one host\n")); 1993 fprintf (stderr, _("No hosts loaded. Need at least one host\n"));
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am
index 53a90c325..1253f6d0e 100644
--- a/src/testbed/Makefile.am
+++ b/src/testbed/Makefile.am
@@ -136,12 +136,12 @@ if ENABLE_TEST_RUN
136 TESTS = \ 136 TESTS = \
137 test_testbed_api \ 137 test_testbed_api \
138 test_testbed_api_sd \ 138 test_testbed_api_sd \
139 test_testbed_api_hosts \
140 test_testbed_api_2peers_1controller \
141 test_testbed_api_3peers_3controllers \
142 test_testbed_api_operations \ 139 test_testbed_api_operations \
140 test_testbed_api_hosts \
143 test_gnunet_helper_testbed \ 141 test_gnunet_helper_testbed \
142 test_testbed_api_2peers_1controller \
144 test_testbed_api_controllerlink \ 143 test_testbed_api_controllerlink \
144 test_testbed_api_3peers_3controllers \
145 test_testbed_api_testbed_run \ 145 test_testbed_api_testbed_run \
146 test_testbed_api_test \ 146 test_testbed_api_test \
147 test_testbed_api_topology \ 147 test_testbed_api_topology \
@@ -150,9 +150,9 @@ if ENABLE_TEST_RUN
150 test_testbed_api_testbed_run_topologyline \ 150 test_testbed_api_testbed_run_topologyline \
151 test_testbed_api_testbed_run_topologyclique \ 151 test_testbed_api_testbed_run_topologyclique \
152 test_testbed_api_testbed_run_topologyring \ 152 test_testbed_api_testbed_run_topologyring \
153 test_testbed_api_testbed_run_topologysmallworldring \
154 test_testbed_api_testbed_run_topology2dtorus \ 153 test_testbed_api_testbed_run_topology2dtorus \
155 test_testbed_api_testbed_run_topologysmallworld \ 154 test_testbed_api_testbed_run_topologysmallworld \
155 test_testbed_api_testbed_run_topologysmallworldring \
156 test_testbed_api_testbed_run_topologyfromfile \ 156 test_testbed_api_testbed_run_topologyfromfile \
157 test_testbed_api_testbed_run_topologyscalefree 157 test_testbed_api_testbed_run_topologyscalefree
158endif 158endif
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c
index cb8c4a5f5..059423e96 100644
--- a/src/testbed/gnunet-service-testbed.c
+++ b/src/testbed/gnunet-service-testbed.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet. 2 This file is part of GNUnet.
3 (C) 2012 Christian Grothoff (and other contributing authors) 3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -945,7 +945,8 @@ handle_init (void *cls, struct GNUNET_SERVER_Client *client,
945 hostname); 945 hostname);
946 host = 946 host =
947 GNUNET_TESTBED_host_create_with_id (GST_context->host_id, 947 GNUNET_TESTBED_host_create_with_id (GST_context->host_id,
948 GST_context->master_ip, NULL, 0); 948 GST_context->master_ip, NULL,
949 our_config, 0);
949 host_list_add (host); 950 host_list_add (host);
950 LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id); 951 LOG_DEBUG ("Created master context with host ID: %u\n", GST_context->host_id);
951 GNUNET_SERVER_receive_done (client, GNUNET_OK); 952 GNUNET_SERVER_receive_done (client, GNUNET_OK);
@@ -1004,9 +1005,10 @@ handle_add_host (void *cls, struct GNUNET_SERVER_Client *client,
1004 username = NULL; 1005 username = NULL;
1005 } 1006 }
1006 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port)); 1007 LOG_DEBUG ("-------ssh port: %u\n", ntohs (msg->ssh_port));
1008 /* FIXME: should use configuration from ADDHOST message */
1007 host = 1009 host =
1008 GNUNET_TESTBED_host_create_with_id (host_id, hostname, username, 1010 GNUNET_TESTBED_host_create_with_id (host_id, hostname, username,
1009 ntohs (msg->ssh_port)); 1011 our_config, ntohs (msg->ssh_port));
1010 GNUNET_assert (NULL != host); 1012 GNUNET_assert (NULL != host);
1011 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage); 1013 reply_size = sizeof (struct GNUNET_TESTBED_HostConfirmedMessage);
1012 if (GNUNET_OK != host_list_add (host)) 1014 if (GNUNET_OK != host_list_add (host))
diff --git a/src/testbed/test_testbed_api.c b/src/testbed/test_testbed_api.c
index fabe956ca..2927c3798 100644
--- a/src/testbed/test_testbed_api.c
+++ b/src/testbed/test_testbed_api.c
@@ -407,7 +407,7 @@ registration_comp (void *cls, const char *emsg)
407 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case 407 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
408 */ 408 */
409static void 409static void
410status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status) 410status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status)
411{ 411{
412 uint64_t event_mask; 412 uint64_t event_mask;
413 413
@@ -423,10 +423,10 @@ status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status)
423 event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); 423 event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
424 event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); 424 event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
425 controller = 425 controller =
426 GNUNET_TESTBED_controller_connect (cfg, host, event_mask, &controller_cb, 426 GNUNET_TESTBED_controller_connect (cfg_, host, event_mask, &controller_cb,
427 NULL); 427 NULL);
428 FAIL_TEST (NULL != controller, return); 428 FAIL_TEST (NULL != controller, return);
429 neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, 0); 429 neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0);
430 FAIL_TEST (NULL != neighbour, return); 430 FAIL_TEST (NULL != neighbour, return);
431 reg_handle = 431 reg_handle =
432 GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp, 432 GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp,
@@ -448,9 +448,9 @@ static void
448run (void *cls, char *const *args, const char *cfgfile, 448run (void *cls, char *const *args, const char *cfgfile,
449 const struct GNUNET_CONFIGURATION_Handle *config) 449 const struct GNUNET_CONFIGURATION_Handle *config)
450{ 450{
451 host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
452 FAIL_TEST (NULL != host, return);
453 cfg = GNUNET_CONFIGURATION_dup (config); 451 cfg = GNUNET_CONFIGURATION_dup (config);
452 host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
453 FAIL_TEST (NULL != host, return);
454 cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb, 454 cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb,
455 NULL); 455 NULL);
456 abort_task = 456 abort_task =
diff --git a/src/testbed/test_testbed_api_2peers_1controller.c b/src/testbed/test_testbed_api_2peers_1controller.c
index 3b033cfac..581a1c1f5 100644
--- a/src/testbed/test_testbed_api_2peers_1controller.c
+++ b/src/testbed/test_testbed_api_2peers_1controller.c
@@ -454,7 +454,7 @@ registration_comp (void *cls, const char *emsg)
454 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case 454 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
455 */ 455 */
456static void 456static void
457status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status) 457status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg_, int status)
458{ 458{
459 uint64_t event_mask; 459 uint64_t event_mask;
460 460
@@ -469,10 +469,10 @@ status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, int status)
469 event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT); 469 event_mask |= (1L << GNUNET_TESTBED_ET_CONNECT);
470 event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED); 470 event_mask |= (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED);
471 controller = 471 controller =
472 GNUNET_TESTBED_controller_connect (cfg, host, event_mask, &controller_cb, 472 GNUNET_TESTBED_controller_connect (cfg_, host, event_mask, &controller_cb,
473 NULL); 473 NULL);
474 FAIL_TEST (NULL != controller); 474 FAIL_TEST (NULL != controller);
475 neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, 0); 475 neighbour = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0);
476 FAIL_TEST (NULL != neighbour); 476 FAIL_TEST (NULL != neighbour);
477 reg_handle = 477 reg_handle =
478 GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp, 478 GNUNET_TESTBED_register_host (controller, neighbour, &registration_comp,
@@ -494,9 +494,9 @@ static void
494run (void *cls, char *const *args, const char *cfgfile, 494run (void *cls, char *const *args, const char *cfgfile,
495 const struct GNUNET_CONFIGURATION_Handle *config) 495 const struct GNUNET_CONFIGURATION_Handle *config)
496{ 496{
497 host = GNUNET_TESTBED_host_create (NULL, NULL, 0);
498 FAIL_TEST (NULL != host);
499 cfg = GNUNET_CONFIGURATION_dup (config); 497 cfg = GNUNET_CONFIGURATION_dup (config);
498 host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
499 FAIL_TEST (NULL != host);
500 cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb, 500 cp = GNUNET_TESTBED_controller_start ("127.0.0.1", host, cfg, status_cb,
501 NULL); 501 NULL);
502 abort_task = 502 abort_task =
diff --git a/src/testbed/test_testbed_api_3peers_3controllers.c b/src/testbed/test_testbed_api_3peers_3controllers.c
index 47ad81021..526386f01 100644
--- a/src/testbed/test_testbed_api_3peers_3controllers.c
+++ b/src/testbed/test_testbed_api_3peers_3controllers.c
@@ -736,7 +736,7 @@ registration_comp (void *cls, const char *emsg)
736 reg_handle = NULL; 736 reg_handle = NULL;
737 if (cls == neighbour1) 737 if (cls == neighbour1)
738 { 738 {
739 neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, 0); 739 neighbour2 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0);
740 if (NULL == neighbour2) 740 if (NULL == neighbour2)
741 { 741 {
742 GNUNET_break (0); 742 GNUNET_break (0);
@@ -812,7 +812,7 @@ status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *config,
812 return; 812 return;
813 } 813 }
814 result = CONTROLLER1_UP; 814 result = CONTROLLER1_UP;
815 neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, 0); 815 neighbour1 = GNUNET_TESTBED_host_create ("127.0.0.1", NULL, cfg, 0);
816 if (NULL == neighbour1) 816 if (NULL == neighbour1)
817 { 817 {
818 GNUNET_break (0); 818 GNUNET_break (0);
@@ -881,7 +881,8 @@ static void
881run (void *cls, char *const *args, const char *cfgfile, 881run (void *cls, char *const *args, const char *cfgfile,
882 const struct GNUNET_CONFIGURATION_Handle *config) 882 const struct GNUNET_CONFIGURATION_Handle *config)
883{ 883{
884 host = GNUNET_TESTBED_host_create (NULL, NULL, 0); 884 cfg = GNUNET_CONFIGURATION_dup (config);
885 host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
885 if (NULL == host) 886 if (NULL == host)
886 { 887 {
887 GNUNET_break (0); 888 GNUNET_break (0);
@@ -902,7 +903,6 @@ run (void *cls, char *const *args, const char *cfgfile,
902 result = SKIP; 903 result = SKIP;
903 return; 904 return;
904 } 905 }
905 cfg = GNUNET_CONFIGURATION_dup (config);
906 abort_task = 906 abort_task =
907 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 907 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
908 (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort, 908 (GNUNET_TIME_UNIT_MINUTES, 3), &do_abort,
diff --git a/src/testbed/test_testbed_api_controllerlink.c b/src/testbed/test_testbed_api_controllerlink.c
index f0ce4daa5..c10451703 100644
--- a/src/testbed/test_testbed_api_controllerlink.c
+++ b/src/testbed/test_testbed_api_controllerlink.c
@@ -484,7 +484,7 @@ controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
484 FAIL_TEST (event->details.peer_start.peer == master_peer); 484 FAIL_TEST (event->details.peer_start.peer == master_peer);
485 GNUNET_TESTBED_operation_done (op); 485 GNUNET_TESTBED_operation_done (op);
486 result = MASTER_PEER_START_SUCCESS; 486 result = MASTER_PEER_START_SUCCESS;
487 slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, 0); 487 slave = GNUNET_TESTBED_host_create_with_id (1, "127.0.0.1", NULL, cfg, 0);
488 FAIL_TEST (NULL != slave); 488 FAIL_TEST (NULL != slave);
489 rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL); 489 rh = GNUNET_TESTBED_register_host (mc, slave, &registration_cont, NULL);
490 FAIL_TEST (NULL != rh); 490 FAIL_TEST (NULL != rh);
@@ -548,7 +548,7 @@ controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
548 GNUNET_TESTBED_operation_done (op); 548 GNUNET_TESTBED_operation_done (op);
549 op = NULL; 549 op = NULL;
550 result = SLAVE2_PEER_DESTROY_SUCCESS; 550 result = SLAVE2_PEER_DESTROY_SUCCESS;
551 slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, 0); 551 slave3 = GNUNET_TESTBED_host_create_with_id (3, "127.0.0.1", NULL, cfg, 0);
552 rh = GNUNET_TESTBED_register_host (mc, slave3, &registration_cont, NULL); 552 rh = GNUNET_TESTBED_register_host (mc, slave3, &registration_cont, NULL);
553 break; 553 break;
554 case SLAVE3_REGISTERED: 554 case SLAVE3_REGISTERED:
@@ -607,7 +607,7 @@ registration_cont (void *cls, const char *emsg)
607 FAIL_TEST (NULL == emsg); 607 FAIL_TEST (NULL == emsg);
608 FAIL_TEST (NULL != mc); 608 FAIL_TEST (NULL != mc);
609 result = SLAVE1_REGISTERED; 609 result = SLAVE1_REGISTERED;
610 slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, 0); 610 slave2 = GNUNET_TESTBED_host_create_with_id (2, "127.0.0.1", NULL, cfg, 0);
611 FAIL_TEST (NULL != slave2); 611 FAIL_TEST (NULL != slave2);
612 rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL); 612 rh = GNUNET_TESTBED_register_host (mc, slave2, &registration_cont, NULL);
613 FAIL_TEST (NULL != rh); 613 FAIL_TEST (NULL != rh);
@@ -717,7 +717,8 @@ static void
717run (void *cls, char *const *args, const char *cfgfile, 717run (void *cls, char *const *args, const char *cfgfile,
718 const struct GNUNET_CONFIGURATION_Handle *config) 718 const struct GNUNET_CONFIGURATION_Handle *config)
719{ 719{
720 host = GNUNET_TESTBED_host_create (NULL, NULL, 0); 720 cfg = GNUNET_CONFIGURATION_dup (config);
721 host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
721 FAIL_TEST (NULL != host); 722 FAIL_TEST (NULL != host);
722 if (NULL == 723 if (NULL ==
723 (hc_handle = 724 (hc_handle =
@@ -725,6 +726,8 @@ run (void *cls, char *const *args, const char *cfgfile,
725 NULL))) 726 NULL)))
726 { 727 {
727 GNUNET_TESTBED_host_destroy (host); 728 GNUNET_TESTBED_host_destroy (host);
729 GNUNET_CONFIGURATION_destroy (cfg);
730 cfg = NULL;
728 host = NULL; 731 host = NULL;
729 (void) PRINTF ("%s", 732 (void) PRINTF ("%s",
730 "Unable to run the test as this system is not configured " 733 "Unable to run the test as this system is not configured "
@@ -733,7 +736,6 @@ run (void *cls, char *const *args, const char *cfgfile,
733 result = SKIP; 736 result = SKIP;
734 return; 737 return;
735 } 738 }
736 cfg = GNUNET_CONFIGURATION_dup (config);
737 abort_task = 739 abort_task =
738 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply 740 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply
739 (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort, 741 (GNUNET_TIME_UNIT_MINUTES, 5), &do_abort,
diff --git a/src/testbed/test_testbed_api_hosts.c b/src/testbed/test_testbed_api_hosts.c
index 51284eaab..85677b2b8 100644
--- a/src/testbed/test_testbed_api_hosts.c
+++ b/src/testbed/test_testbed_api_hosts.c
@@ -34,6 +34,11 @@
34 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec) 34 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
35 35
36/** 36/**
37 * configuration handle to use as template configuration while creating hosts
38 */
39static struct GNUNET_CONFIGURATION_Handle *cfg;
40
41/**
37 * Host we are creating and using 42 * Host we are creating and using
38 */ 43 */
39static struct GNUNET_TESTBED_Host *host; 44static struct GNUNET_TESTBED_Host *host;
@@ -74,6 +79,11 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
74 num_hosts--; 79 num_hosts--;
75 } 80 }
76 GNUNET_free (hosts); 81 GNUNET_free (hosts);
82 if (NULL != cfg)
83 {
84 GNUNET_CONFIGURATION_destroy (cfg);
85 cfg = NULL;
86 }
77} 87}
78 88
79 89
@@ -87,18 +97,19 @@ do_shutdown (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
87 */ 97 */
88static void 98static void
89run (void *cls, char *const *args, const char *cfgfile, 99run (void *cls, char *const *args, const char *cfgfile,
90 const struct GNUNET_CONFIGURATION_Handle *cfg) 100 const struct GNUNET_CONFIGURATION_Handle *config)
91{ 101{
92 host = GNUNET_TESTBED_host_create ("localhost", NULL, 0); 102 cfg = GNUNET_CONFIGURATION_dup (config);
103 host = GNUNET_TESTBED_host_create ("localhost", NULL, cfg, 0);
93 GNUNET_assert (NULL != host); 104 GNUNET_assert (NULL != host);
94 GNUNET_assert (0 != GNUNET_TESTBED_host_get_id_ (host)); 105 GNUNET_assert (0 != GNUNET_TESTBED_host_get_id_ (host));
95 GNUNET_TESTBED_host_destroy (host); 106 GNUNET_TESTBED_host_destroy (host);
96 host = GNUNET_TESTBED_host_create (NULL, NULL, 0); 107 host = GNUNET_TESTBED_host_create (NULL, NULL, cfg, 0);
97 GNUNET_assert (NULL != host); 108 GNUNET_assert (NULL != host);
98 GNUNET_assert (0 == GNUNET_TESTBED_host_get_id_ (host)); 109 GNUNET_assert (0 == GNUNET_TESTBED_host_get_id_ (host));
99 GNUNET_assert (host == GNUNET_TESTBED_host_lookup_by_id_ (0)); 110 GNUNET_assert (host == GNUNET_TESTBED_host_lookup_by_id_ (0));
100 hosts = NULL; 111 hosts = NULL;
101 num_hosts = GNUNET_TESTBED_hosts_load_from_file ("sample_hosts.txt", &hosts); 112 num_hosts = GNUNET_TESTBED_hosts_load_from_file ("sample_hosts.txt", cfg, &hosts);
102 GNUNET_assert (15 == num_hosts); 113 GNUNET_assert (15 == num_hosts);
103 GNUNET_assert (NULL != hosts); 114 GNUNET_assert (NULL != hosts);
104 status = GNUNET_YES; 115 status = GNUNET_YES;
diff --git a/src/testbed/testbed.h b/src/testbed/testbed.h
index 180464bd7..880a44864 100644
--- a/src/testbed/testbed.h
+++ b/src/testbed/testbed.h
@@ -87,9 +87,19 @@ struct GNUNET_TESTBED_AddHostMessage
87 */ 87 */
88 uint16_t user_name_length GNUNET_PACKED; 88 uint16_t user_name_length GNUNET_PACKED;
89 89
90 /* followed by 0-terminated user name */ 90 /**
91 * Number of bytes in the host name (excluding 0-termination) that follows the
92 * user name; cannot be 0
93 */
94 uint16_t hostname_length GNUNET_PACKED;
95
96 /* followed by non 0-terminated user name */
97
98 /* followed by non 0-terminated host name */
91 99
92 /* followed by 0-terminated host name */ 100 /* followed by gzip compressed configuration to start or connect to a
101 controller on this host. While starting the controller this configration
102 is used as a template */
93 103
94}; 104};
95 105
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index ad77003fc..eba4544eb 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors) 3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 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 6 it under the terms of the GNU General Public License as published
@@ -69,54 +69,6 @@
69 69
70 70
71/** 71/**
72 * Handle for controller process
73 */
74struct GNUNET_TESTBED_ControllerProc
75{
76 /**
77 * The process handle
78 */
79 struct GNUNET_HELPER_Handle *helper;
80
81 /**
82 * The arguments used to start the helper
83 */
84 char **helper_argv;
85
86 /**
87 * The host where the helper is run
88 */
89 struct GNUNET_TESTBED_Host *host;
90
91 /**
92 * The controller error callback
93 */
94 GNUNET_TESTBED_ControllerStatusCallback cb;
95
96 /**
97 * The closure for the above callback
98 */
99 void *cls;
100
101 /**
102 * The send handle for the helper
103 */
104 struct GNUNET_HELPER_SendHandle *shandle;
105
106 /**
107 * The message corresponding to send handle
108 */
109 struct GNUNET_MessageHeader *msg;
110
111 /**
112 * The configuration of the running testbed service
113 */
114 struct GNUNET_CONFIGURATION_Handle *cfg;
115
116};
117
118
119/**
120 * The message queue for sending messages to the controller service 72 * The message queue for sending messages to the controller service
121 */ 73 */
122struct MessageQueue 74struct MessageQueue
@@ -1131,98 +1083,6 @@ GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1131 1083
1132 1084
1133/** 1085/**
1134 * Functions with this signature are called whenever a
1135 * complete message is received by the tokenizer.
1136 *
1137 * Do not call GNUNET_SERVER_mst_destroy in callback
1138 *
1139 * @param cls closure
1140 * @param client identification of the client
1141 * @param message the actual message
1142 *
1143 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1144 */
1145static int
1146helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1147{
1148 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1149 const struct GNUNET_TESTBED_HelperReply *msg;
1150 const char *hostname;
1151 char *config;
1152 uLongf config_size;
1153 uLongf xconfig_size;
1154
1155 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1156 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1157 ntohs (msg->header.size));
1158 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1159 ntohs (msg->header.type));
1160 config_size = (uLongf) ntohs (msg->config_size);
1161 xconfig_size =
1162 (uLongf) (ntohs (msg->header.size) -
1163 sizeof (struct GNUNET_TESTBED_HelperReply));
1164 config = GNUNET_malloc (config_size);
1165 GNUNET_assert (Z_OK ==
1166 uncompress ((Bytef *) config, &config_size,
1167 (const Bytef *) &msg[1], xconfig_size));
1168 GNUNET_assert (NULL == cp->cfg);
1169 cp->cfg = GNUNET_CONFIGURATION_create ();
1170 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1171 (cp->cfg, config, config_size, GNUNET_NO));
1172 GNUNET_free (config);
1173 if ((NULL == cp->host) ||
1174 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
1175 hostname = "localhost";
1176 /* Change the hostname so that we can connect to it */
1177 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1178 hostname);
1179 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1180 return GNUNET_OK;
1181}
1182
1183
1184/**
1185 * Continuation function from GNUNET_HELPER_send()
1186 *
1187 * @param cls closure
1188 * @param result GNUNET_OK on success,
1189 * GNUNET_NO if helper process died
1190 * GNUNET_SYSERR during GNUNET_HELPER_stop
1191 */
1192static void
1193clear_msg (void *cls, int result)
1194{
1195 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1196
1197 GNUNET_assert (NULL != cp->shandle);
1198 cp->shandle = NULL;
1199 GNUNET_free (cp->msg);
1200}
1201
1202
1203/**
1204 * Callback that will be called when the helper process dies. This is not called
1205 * when the helper process is stoped using GNUNET_HELPER_stop()
1206 *
1207 * @param cls the closure from GNUNET_HELPER_start()
1208 */
1209static void
1210helper_exp_cb (void *cls)
1211{
1212 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1213 GNUNET_TESTBED_ControllerStatusCallback cb;
1214 void *cb_cls;
1215
1216 cb = cp->cb;
1217 cb_cls = cp->cls;
1218 cp->helper = NULL;
1219 GNUNET_TESTBED_controller_stop (cp);
1220 if (NULL != cb)
1221 cb (cb_cls, NULL, GNUNET_SYSERR);
1222}
1223
1224
1225/**
1226 * Function to call to start a link-controllers type operation once all queues 1086 * Function to call to start a link-controllers type operation once all queues
1227 * the operation is part of declare that the operation can be activated. 1087 * the operation is part of declare that the operation can be activated.
1228 * 1088 *
@@ -1322,290 +1182,6 @@ oprelease_get_slave_config (void *cls)
1322 1182
1323 1183
1324/** 1184/**
1325 * Function to copy NULL terminated list of arguments
1326 *
1327 * @param argv the NULL terminated list of arguments. Cannot be NULL.
1328 * @return the copied NULL terminated arguments
1329 */
1330static char **
1331copy_argv (const char *const *argv)
1332{
1333 char **argv_dup;
1334 unsigned int argp;
1335
1336 GNUNET_assert (NULL != argv);
1337 for (argp = 0; NULL != argv[argp]; argp++) ;
1338 argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
1339 for (argp = 0; NULL != argv[argp]; argp++)
1340 argv_dup[argp] = strdup (argv[argp]);
1341 return argv_dup;
1342}
1343
1344
1345/**
1346 * Function to join NULL terminated list of arguments
1347 *
1348 * @param argv1 the NULL terminated list of arguments. Cannot be NULL.
1349 * @param argv2 the NULL terminated list of arguments. Cannot be NULL.
1350 * @return the joined NULL terminated arguments
1351 */
1352static char **
1353join_argv (const char *const *argv1, const char *const *argv2)
1354{
1355 char **argvj;
1356 char *argv;
1357 unsigned int carg;
1358 unsigned int cnt;
1359
1360 carg = 0;
1361 argvj = NULL;
1362 for (cnt = 0; NULL != argv1[cnt]; cnt++)
1363 {
1364 argv = GNUNET_strdup (argv1[cnt]);
1365 GNUNET_array_append (argvj, carg, argv);
1366 }
1367 for (cnt = 0; NULL != argv2[cnt]; cnt++)
1368 {
1369 argv = GNUNET_strdup (argv2[cnt]);
1370 GNUNET_array_append (argvj, carg, argv);
1371 }
1372 GNUNET_array_append (argvj, carg, NULL);
1373 return argvj;
1374}
1375
1376
1377/**
1378 * Frees the given NULL terminated arguments
1379 *
1380 * @param argv the NULL terminated list of arguments
1381 */
1382static void
1383free_argv (char **argv)
1384{
1385 unsigned int argp;
1386
1387 for (argp = 0; NULL != argv[argp]; argp++)
1388 GNUNET_free (argv[argp]);
1389 GNUNET_free (argv);
1390}
1391
1392
1393/**
1394 * Generates arguments for opening a remote shell. Builds up the arguments
1395 * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable
1396 * should not mention `-p' (port) option and destination address as these will
1397 * be set locally in the function from its parameteres. If the environmental
1398 * variable is not found then it defaults to `ssh -o BatchMode=yes -o
1399 * NoHostAuthenticationForLocalhost=yes'
1400 *
1401 * @param port the destination port number
1402 * @param dst the destination address
1403 * @return NULL terminated list of arguments
1404 */
1405static char **
1406gen_rsh_args (const char *port, const char *dst)
1407{
1408 static const char *default_ssh_args[] = {
1409 "ssh",
1410 "-o",
1411 "BatchMode=yes",
1412 "-o",
1413 "NoHostAuthenticationForLocalhost=yes",
1414 NULL
1415 };
1416 char **ssh_args;
1417 char *ssh_cmd;
1418 char *ssh_cmd_cp;
1419 char *arg;
1420 unsigned int cnt;
1421
1422 ssh_args = NULL;
1423 if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD")))
1424 {
1425 ssh_cmd = GNUNET_strdup (ssh_cmd);
1426 ssh_cmd_cp = ssh_cmd;
1427 for (cnt = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
1428 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (arg));
1429 GNUNET_free (ssh_cmd_cp);
1430 }
1431 else
1432 {
1433 ssh_args = copy_argv (default_ssh_args);
1434 cnt = (sizeof (default_ssh_args)) / (sizeof (const char *));
1435 GNUNET_array_grow (ssh_args, cnt, cnt - 1);
1436 }
1437 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup ("-p"));
1438 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (port));
1439 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (dst));
1440 GNUNET_array_append (ssh_args, cnt, NULL);
1441 return ssh_args;
1442}
1443
1444
1445/**
1446 * Generates the arguments needed for executing the given binary in a remote
1447 * shell. Builds the arguments from the environmental variable
1448 * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found,
1449 * only the given binary name will be present in the returned arguments
1450 *
1451 * @param helper_binary_path the path of the binary to execute
1452 * @return NULL-terminated args
1453 */
1454static char **
1455gen_rsh_suffix_args (const char *helper_binary_path)
1456{
1457 char **rshell_args;
1458 char *rshell_cmd;
1459 char *rshell_cmd_cp;
1460 char *arg;
1461 unsigned int cnt;
1462
1463 rshell_args = NULL;
1464 cnt = 0;
1465 if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX")))
1466 {
1467 rshell_cmd = GNUNET_strdup (rshell_cmd);
1468 rshell_cmd_cp = rshell_cmd;
1469 for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL)
1470 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg));
1471 GNUNET_free (rshell_cmd_cp);
1472 }
1473 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (helper_binary_path));
1474 GNUNET_array_append (rshell_args, cnt, NULL);
1475 return rshell_args;
1476}
1477
1478
1479/**
1480 * Starts a controller process at the given host
1481 *
1482 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1483 * HOST(all connections form this ip are permitted by the testbed) when
1484 * starting testbed controller at host. This can either be a single ip
1485 * address or a network address in CIDR notation.
1486 * @param host the host where the controller has to be started; NULL for
1487 * localhost
1488 * @param cfg template configuration to use for the remote controller; the
1489 * remote controller will be started with a slightly modified
1490 * configuration (port numbers, unix domain sockets and service home
1491 * values are changed as per TESTING library on the remote host)
1492 * @param cb function called when the controller is successfully started or
1493 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1494 * called if cb is called with GNUNET_SYSERR as status. Will never be
1495 * called in the same task as 'GNUNET_TESTBED_controller_start'
1496 * (synchronous errors will be signalled by returning NULL). This
1497 * parameter cannot be NULL.
1498 * @param cls closure for above callbacks
1499 * @return the controller process handle, NULL on errors
1500 */
1501struct GNUNET_TESTBED_ControllerProc *
1502GNUNET_TESTBED_controller_start (const char *trusted_ip,
1503 struct GNUNET_TESTBED_Host *host,
1504 const struct GNUNET_CONFIGURATION_Handle *cfg,
1505 GNUNET_TESTBED_ControllerStatusCallback cb,
1506 void *cls)
1507{
1508 struct GNUNET_TESTBED_ControllerProc *cp;
1509 struct GNUNET_TESTBED_HelperInit *msg;
1510 const char *hostname;
1511
1512 static char *const binary_argv[] = {
1513 HELPER_TESTBED_BINARY, NULL
1514 };
1515
1516 hostname = NULL;
1517 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1518 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1519 {
1520 cp->helper =
1521 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1522 &helper_mst, &helper_exp_cb, cp);
1523 }
1524 else
1525 {
1526 char *helper_binary_path;
1527 char **ssh_args;
1528 char **rshell_args;
1529 const char *username;
1530 char *port;
1531 char *dst;
1532
1533 username = GNUNET_TESTBED_host_get_username_ (host);
1534 hostname = GNUNET_TESTBED_host_get_hostname (host);
1535 GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1536 if (NULL == username)
1537 GNUNET_asprintf (&dst, "%s", hostname);
1538 else
1539 GNUNET_asprintf (&dst, "%s@%s", username, hostname);
1540 LOG_DEBUG ("Starting SSH to destination %s\n", dst);
1541
1542 if (GNUNET_OK !=
1543 GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1544 "HELPER_BINARY_PATH",
1545 &helper_binary_path))
1546 helper_binary_path =
1547 GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1548 ssh_args = gen_rsh_args (port, dst);
1549 rshell_args = gen_rsh_suffix_args (helper_binary_path);
1550 cp->helper_argv =
1551 join_argv ((const char **) ssh_args, (const char **) rshell_args);
1552 free_argv (ssh_args);
1553 free_argv (rshell_args);
1554 GNUNET_free (port);
1555 GNUNET_free (dst);
1556 cp->helper =
1557 GNUNET_HELPER_start (GNUNET_NO, "ssh", cp->helper_argv, &helper_mst,
1558 &helper_exp_cb, cp);
1559 GNUNET_free (helper_binary_path);
1560 }
1561 if (NULL == cp->helper)
1562 {
1563 if (NULL != cp->helper_argv)
1564 free_argv (cp->helper_argv);
1565 GNUNET_free (cp);
1566 return NULL;
1567 }
1568 cp->host = host;
1569 cp->cb = cb;
1570 cp->cls = cls;
1571 msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
1572 cp->msg = &msg->header;
1573 cp->shandle =
1574 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1575 if (NULL == cp->shandle)
1576 {
1577 GNUNET_free (msg);
1578 GNUNET_TESTBED_controller_stop (cp);
1579 return NULL;
1580 }
1581 return cp;
1582}
1583
1584
1585/**
1586 * Stop the controller process (also will terminate all peers and controllers
1587 * dependent on this controller). This function blocks until the testbed has
1588 * been fully terminated (!). The controller status cb from
1589 * GNUNET_TESTBED_controller_start() will not be called.
1590 *
1591 * @param cproc the controller process handle
1592 */
1593void
1594GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1595{
1596 if (NULL != cproc->shandle)
1597 GNUNET_HELPER_send_cancel (cproc->shandle);
1598 if (NULL != cproc->helper)
1599 GNUNET_HELPER_soft_stop (cproc->helper);
1600 if (NULL != cproc->cfg)
1601 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1602 if (NULL != cproc->helper_argv)
1603 free_argv (cproc->helper_argv);
1604 GNUNET_free (cproc);
1605}
1606
1607
1608/**
1609 * Start a controller process using the given configuration at the 1185 * Start a controller process using the given configuration at the
1610 * given host. 1186 * given host.
1611 * 1187 *
@@ -1672,7 +1248,7 @@ GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1672 } 1248 }
1673 if (NULL == host) 1249 if (NULL == host)
1674 { 1250 {
1675 host = GNUNET_TESTBED_host_create_by_id_ (0); 1251 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1676 if (NULL == host) /* If the above host create fails */ 1252 if (NULL == host) /* If the above host create fails */
1677 { 1253 {
1678 LOG (GNUNET_ERROR_TYPE_WARNING, 1254 LOG (GNUNET_ERROR_TYPE_WARNING,
diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c
index 1fb69e30b..d979d575b 100644
--- a/src/testbed/testbed_api_hosts.c
+++ b/src/testbed/testbed_api_hosts.c
@@ -36,6 +36,8 @@
36#include "testbed_api_operations.h" 36#include "testbed_api_operations.h"
37#include "testbed_api_sd.h" 37#include "testbed_api_sd.h"
38 38
39#include <zlib.h>
40
39/** 41/**
40 * Generic logging shorthand 42 * Generic logging shorthand
41 */ 43 */
@@ -43,6 +45,12 @@
43 GNUNET_log_from (kind, "testbed-api-hosts", __VA_ARGS__); 45 GNUNET_log_from (kind, "testbed-api-hosts", __VA_ARGS__);
44 46
45/** 47/**
48 * Debug logging shorthand
49 */
50#define LOG_DEBUG(...) \
51 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
52
53/**
46 * Number of extra elements we create space for when we grow host list 54 * Number of extra elements we create space for when we grow host list
47 */ 55 */
48#define HOST_LIST_GROW_STEP 10 56#define HOST_LIST_GROW_STEP 10
@@ -121,6 +129,13 @@ struct GNUNET_TESTBED_Host
121 const char *username; 129 const char *username;
122 130
123 /** 131 /**
132 * the configuration to use as a template while starting a controller on this
133 * host. Operation queue size specific to a host are also read from this
134 * configuration handle
135 */
136 struct GNUNET_CONFIGURATION_Handle *cfg;
137
138 /**
124 * The head for the list of controllers where this host is registered 139 * The head for the list of controllers where this host is registered
125 */ 140 */
126 struct RegisteredController *rc_head; 141 struct RegisteredController *rc_head;
@@ -146,7 +161,7 @@ struct GNUNET_TESTBED_Host
146 * Handle for SD calculations amount parallel overlay connect operation finish 161 * Handle for SD calculations amount parallel overlay connect operation finish
147 * times 162 * times
148 */ 163 */
149 struct SDHandle *poc_sd; 164 struct SDHandle *poc_sd;
150 165
151 /** 166 /**
152 * The number of parallel overlay connects we do currently 167 * The number of parallel overlay connects we do currently
@@ -159,6 +174,11 @@ struct GNUNET_TESTBED_Host
159 unsigned int tslots_filled; 174 unsigned int tslots_filled;
160 175
161 /** 176 /**
177 * Is a controller started on this host?
178 */
179 int controller_started;
180
181 /**
162 * Global ID we use to refer to a host on the network 182 * Global ID we use to refer to a host on the network
163 */ 183 */
164 uint32_t id; 184 uint32_t id;
@@ -205,12 +225,17 @@ GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id)
205 * 225 *
206 * @param id global host ID assigned to the host; 0 is 226 * @param id global host ID assigned to the host; 0 is
207 * reserved to always mean 'localhost' 227 * reserved to always mean 'localhost'
228 * @param cfg the configuration to use as a template while starting a controller
229 * on this host. Operation queue sizes specific to a host are also
230 * read from this configuration handle
208 * @return handle to the host, NULL on error 231 * @return handle to the host, NULL on error
209 */ 232 */
210struct GNUNET_TESTBED_Host * 233struct GNUNET_TESTBED_Host *
211GNUNET_TESTBED_host_create_by_id_ (uint32_t id) 234GNUNET_TESTBED_host_create_by_id_ (uint32_t id,
235 const struct GNUNET_CONFIGURATION_Handle
236 *cfg)
212{ 237{
213 return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, 0); 238 return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, cfg, 0);
214} 239}
215 240
216 241
@@ -268,18 +293,50 @@ GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host * host)
268 293
269 294
270/** 295/**
296 * Check whether a controller is already started on the given host
297 *
298 * @param host the handle to the host
299 * @return GNUNET_YES if the controller is already started; GNUNET_NO if not
300 */
301int
302GNUNET_TESTBED_host_controller_started (const struct GNUNET_TESTBED_Host *host)
303{
304 return host->controller_started;
305}
306
307
308/**
309 * Obtain the host's configuration template
310 *
311 * @param host handle to the host
312 * @return the host's configuration template
313 */
314const struct GNUNET_CONFIGURATION_Handle *
315GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host)
316{
317 return host->cfg;
318}
319
320
321/**
271 * Create a host to run peers and controllers on. 322 * Create a host to run peers and controllers on.
272 * 323 *
273 * @param id global host ID assigned to the host; 0 is 324 * @param id global host ID assigned to the host; 0 is
274 * reserved to always mean 'localhost' 325 * reserved to always mean 'localhost'
275 * @param hostname name of the host, use "NULL" for localhost 326 * @param hostname name of the host, use "NULL" for localhost
276 * @param username username to use for the login; may be NULL 327 * @param username username to use for the login; may be NULL
328 * @param cfg the configuration to use as a template while starting a controller
329 * on this host. Operation queue sizes specific to a host are also
330 * read from this configuration handle
277 * @param port port number to use for ssh; use 0 to let ssh decide 331 * @param port port number to use for ssh; use 0 to let ssh decide
278 * @return handle to the host, NULL on error 332 * @return handle to the host, NULL on error
279 */ 333 */
280struct GNUNET_TESTBED_Host * 334struct GNUNET_TESTBED_Host *
281GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname, 335GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname,
282 const char *username, uint16_t port) 336 const char *username,
337 const struct GNUNET_CONFIGURATION_Handle
338 *cfg,
339 uint16_t port)
283{ 340{
284 struct GNUNET_TESTBED_Host *host; 341 struct GNUNET_TESTBED_Host *host;
285 unsigned int new_size; 342 unsigned int new_size;
@@ -293,7 +350,8 @@ GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname,
293 host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL; 350 host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL;
294 host->username = (NULL != username) ? GNUNET_strdup (username) : NULL; 351 host->username = (NULL != username) ? GNUNET_strdup (username) : NULL;
295 host->id = id; 352 host->id = id;
296 host->port = (0 == port) ? 22 : port; 353 host->port = (0 == port) ? 22 : port;
354 host->cfg = GNUNET_CONFIGURATION_dup (cfg);
297 host->opq_parallel_overlay_connect_operations = 355 host->opq_parallel_overlay_connect_operations =
298 GNUNET_TESTBED_operation_queue_create_ (0); 356 GNUNET_TESTBED_operation_queue_create_ (0);
299 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (host, 1); 357 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (host, 1);
@@ -315,19 +373,24 @@ GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname,
315 * 373 *
316 * @param hostname name of the host, use "NULL" for localhost 374 * @param hostname name of the host, use "NULL" for localhost
317 * @param username username to use for the login; may be NULL 375 * @param username username to use for the login; may be NULL
376 * @param cfg the configuration to use as a template while starting a controller
377 * on this host. Operation queue sizes specific to a host are also
378 * read from this configuration handle
318 * @param port port number to use for ssh; use 0 to let ssh decide 379 * @param port port number to use for ssh; use 0 to let ssh decide
319 * @return handle to the host, NULL on error 380 * @return handle to the host, NULL on error
320 */ 381 */
321struct GNUNET_TESTBED_Host * 382struct GNUNET_TESTBED_Host *
322GNUNET_TESTBED_host_create (const char *hostname, const char *username, 383GNUNET_TESTBED_host_create (const char *hostname, const char *username,
384 const struct GNUNET_CONFIGURATION_Handle *cfg,
323 uint16_t port) 385 uint16_t port)
324{ 386{
325 static uint32_t uid_generator; 387 static uint32_t uid_generator;
326 388
327 if (NULL == hostname) 389 if (NULL == hostname)
328 return GNUNET_TESTBED_host_create_with_id (0, hostname, username, port); 390 return GNUNET_TESTBED_host_create_with_id (0, hostname, username,
391 cfg, port);
329 return GNUNET_TESTBED_host_create_with_id (++uid_generator, hostname, 392 return GNUNET_TESTBED_host_create_with_id (++uid_generator, hostname,
330 username, port); 393 username, cfg, port);
331} 394}
332 395
333 396
@@ -335,12 +398,17 @@ GNUNET_TESTBED_host_create (const char *hostname, const char *username,
335 * Load a set of hosts from a configuration file. 398 * Load a set of hosts from a configuration file.
336 * 399 *
337 * @param filename file with the host specification 400 * @param filename file with the host specification
401 * @param cfg the configuration to use as a template while starting a controller
402 * on any of the loaded hosts. Operation queue sizes specific to a host
403 * are also read from this configuration handle
338 * @param hosts set to the hosts found in the file; caller must free this if 404 * @param hosts set to the hosts found in the file; caller must free this if
339 * number of hosts returned is greater than 0 405 * number of hosts returned is greater than 0
340 * @return number of hosts returned in 'hosts', 0 on error 406 * @return number of hosts returned in 'hosts', 0 on error
341 */ 407 */
342unsigned int 408unsigned int
343GNUNET_TESTBED_hosts_load_from_file (const char *filename, 409GNUNET_TESTBED_hosts_load_from_file (const char *filename,
410 const struct GNUNET_CONFIGURATION_Handle
411 *cfg,
344 struct GNUNET_TESTBED_Host ***hosts) 412 struct GNUNET_TESTBED_Host ***hosts)
345{ 413{
346 //struct GNUNET_TESTBED_Host **host_array; 414 //struct GNUNET_TESTBED_Host **host_array;
@@ -399,9 +467,10 @@ GNUNET_TESTBED_hosts_load_from_file (const char *filename,
399 /* We store hosts in a static list; hence we only require the starting 467 /* We store hosts in a static list; hence we only require the starting
400 * host pointer in that list to access the newly created list of hosts */ 468 * host pointer in that list to access the newly created list of hosts */
401 if (NULL == starting_host) 469 if (NULL == starting_host)
402 starting_host = GNUNET_TESTBED_host_create (hostname, username, port); 470 starting_host = GNUNET_TESTBED_host_create (hostname, username, cfg,
471 port);
403 else 472 else
404 (void) GNUNET_TESTBED_host_create (hostname, username, port); 473 (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port);
405 count++; 474 count++;
406 } 475 }
407 else 476 else
@@ -449,6 +518,7 @@ GNUNET_TESTBED_host_destroy (struct GNUNET_TESTBED_Host *host)
449 (host->opq_parallel_overlay_connect_operations); 518 (host->opq_parallel_overlay_connect_operations);
450 GNUNET_TESTBED_SD_destroy_ (host->poc_sd); 519 GNUNET_TESTBED_SD_destroy_ (host->poc_sd);
451 GNUNET_free_non_null (host->tslots); 520 GNUNET_free_non_null (host->tslots);
521 GNUNET_CONFIGURATION_destroy (host->cfg);
452 GNUNET_free (host); 522 GNUNET_free (host);
453 while (host_list_size >= HOST_LIST_GROW_STEP) 523 while (host_list_size >= HOST_LIST_GROW_STEP)
454 { 524 {
@@ -521,6 +591,437 @@ GNUNET_TESTBED_is_host_registered_ (const struct GNUNET_TESTBED_Host *host,
521 591
522 592
523/** 593/**
594 * Handle for controller process
595 */
596struct GNUNET_TESTBED_ControllerProc
597{
598 /**
599 * The process handle
600 */
601 struct GNUNET_HELPER_Handle *helper;
602
603 /**
604 * The arguments used to start the helper
605 */
606 char **helper_argv;
607
608 /**
609 * The host where the helper is run
610 */
611 struct GNUNET_TESTBED_Host *host;
612
613 /**
614 * The controller error callback
615 */
616 GNUNET_TESTBED_ControllerStatusCallback cb;
617
618 /**
619 * The closure for the above callback
620 */
621 void *cls;
622
623 /**
624 * The send handle for the helper
625 */
626 struct GNUNET_HELPER_SendHandle *shandle;
627
628 /**
629 * The message corresponding to send handle
630 */
631 struct GNUNET_MessageHeader *msg;
632
633 /**
634 * The configuration of the running testbed service
635 */
636 struct GNUNET_CONFIGURATION_Handle *cfg;
637
638};
639
640
641/**
642 * Function to copy NULL terminated list of arguments
643 *
644 * @param argv the NULL terminated list of arguments. Cannot be NULL.
645 * @return the copied NULL terminated arguments
646 */
647static char **
648copy_argv (const char *const *argv)
649{
650 char **argv_dup;
651 unsigned int argp;
652
653 GNUNET_assert (NULL != argv);
654 for (argp = 0; NULL != argv[argp]; argp++) ;
655 argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
656 for (argp = 0; NULL != argv[argp]; argp++)
657 argv_dup[argp] = strdup (argv[argp]);
658 return argv_dup;
659}
660
661
662/**
663 * Function to join NULL terminated list of arguments
664 *
665 * @param argv1 the NULL terminated list of arguments. Cannot be NULL.
666 * @param argv2 the NULL terminated list of arguments. Cannot be NULL.
667 * @return the joined NULL terminated arguments
668 */
669static char **
670join_argv (const char *const *argv1, const char *const *argv2)
671{
672 char **argvj;
673 char *argv;
674 unsigned int carg;
675 unsigned int cnt;
676
677 carg = 0;
678 argvj = NULL;
679 for (cnt = 0; NULL != argv1[cnt]; cnt++)
680 {
681 argv = GNUNET_strdup (argv1[cnt]);
682 GNUNET_array_append (argvj, carg, argv);
683 }
684 for (cnt = 0; NULL != argv2[cnt]; cnt++)
685 {
686 argv = GNUNET_strdup (argv2[cnt]);
687 GNUNET_array_append (argvj, carg, argv);
688 }
689 GNUNET_array_append (argvj, carg, NULL);
690 return argvj;
691}
692
693
694/**
695 * Frees the given NULL terminated arguments
696 *
697 * @param argv the NULL terminated list of arguments
698 */
699static void
700free_argv (char **argv)
701{
702 unsigned int argp;
703
704 for (argp = 0; NULL != argv[argp]; argp++)
705 GNUNET_free (argv[argp]);
706 GNUNET_free (argv);
707}
708
709
710/**
711 * Generates arguments for opening a remote shell. Builds up the arguments
712 * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable
713 * should not mention `-p' (port) option and destination address as these will
714 * be set locally in the function from its parameteres. If the environmental
715 * variable is not found then it defaults to `ssh -o BatchMode=yes -o
716 * NoHostAuthenticationForLocalhost=yes'
717 *
718 * @param port the destination port number
719 * @param dst the destination address
720 * @return NULL terminated list of arguments
721 */
722static char **
723gen_rsh_args (const char *port, const char *dst)
724{
725 static const char *default_ssh_args[] = {
726 "ssh",
727 "-o",
728 "BatchMode=yes",
729 "-o",
730 "NoHostAuthenticationForLocalhost=yes",
731 NULL
732 };
733 char **ssh_args;
734 char *ssh_cmd;
735 char *ssh_cmd_cp;
736 char *arg;
737 unsigned int cnt;
738
739 ssh_args = NULL;
740 if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD")))
741 {
742 ssh_cmd = GNUNET_strdup (ssh_cmd);
743 ssh_cmd_cp = ssh_cmd;
744 for (cnt = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
745 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (arg));
746 GNUNET_free (ssh_cmd_cp);
747 }
748 else
749 {
750 ssh_args = copy_argv (default_ssh_args);
751 cnt = (sizeof (default_ssh_args)) / (sizeof (const char *));
752 GNUNET_array_grow (ssh_args, cnt, cnt - 1);
753 }
754 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup ("-p"));
755 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (port));
756 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (dst));
757 GNUNET_array_append (ssh_args, cnt, NULL);
758 return ssh_args;
759}
760
761
762/**
763 * Generates the arguments needed for executing the given binary in a remote
764 * shell. Builds the arguments from the environmental variable
765 * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found,
766 * only the given binary name will be present in the returned arguments
767 *
768 * @param append_args the arguments to append after generating the suffix
769 * arguments. Can be NULL; if not must be NULL terminated 'char *' array
770 * @return NULL-terminated args
771 */
772static char **
773gen_rsh_suffix_args (const char * const *append_args)
774{
775 char **rshell_args;
776 char *rshell_cmd;
777 char *rshell_cmd_cp;
778 char *arg;
779 unsigned int cnt;
780 unsigned int append_cnt;
781
782 rshell_args = NULL;
783 cnt = 0;
784 if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX")))
785 {
786 rshell_cmd = GNUNET_strdup (rshell_cmd);
787 rshell_cmd_cp = rshell_cmd;
788 for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL)
789 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg));
790 GNUNET_free (rshell_cmd_cp);
791 }
792 if (NULL != append_args)
793 {
794 for (append_cnt = 0; NULL != append_args[append_cnt]; append_cnt++)
795 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (append_args[append_cnt]));
796 }
797 GNUNET_array_append (rshell_args, cnt, NULL);
798 return rshell_args;
799}
800
801
802/**
803 * Functions with this signature are called whenever a
804 * complete message is received by the tokenizer.
805 *
806 * Do not call GNUNET_SERVER_mst_destroy in callback
807 *
808 * @param cls closure
809 * @param client identification of the client
810 * @param message the actual message
811 *
812 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
813 */
814static int
815helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
816{
817 struct GNUNET_TESTBED_ControllerProc *cp = cls;
818 const struct GNUNET_TESTBED_HelperReply *msg;
819 const char *hostname;
820 char *config;
821 uLongf config_size;
822 uLongf xconfig_size;
823
824 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
825 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
826 ntohs (msg->header.size));
827 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
828 ntohs (msg->header.type));
829 config_size = (uLongf) ntohs (msg->config_size);
830 xconfig_size =
831 (uLongf) (ntohs (msg->header.size) -
832 sizeof (struct GNUNET_TESTBED_HelperReply));
833 config = GNUNET_malloc (config_size);
834 GNUNET_assert (Z_OK ==
835 uncompress ((Bytef *) config, &config_size,
836 (const Bytef *) &msg[1], xconfig_size));
837 GNUNET_assert (NULL == cp->cfg);
838 cp->cfg = GNUNET_CONFIGURATION_create ();
839 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
840 (cp->cfg, config, config_size, GNUNET_NO));
841 GNUNET_free (config);
842 if ((NULL == cp->host) ||
843 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
844 hostname = "localhost";
845 /* Change the hostname so that we can connect to it */
846 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
847 hostname);
848 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
849 return GNUNET_OK;
850}
851
852
853/**
854 * Continuation function from GNUNET_HELPER_send()
855 *
856 * @param cls closure
857 * @param result GNUNET_OK on success,
858 * GNUNET_NO if helper process died
859 * GNUNET_SYSERR during GNUNET_HELPER_stop
860 */
861static void
862clear_msg (void *cls, int result)
863{
864 struct GNUNET_TESTBED_ControllerProc *cp = cls;
865
866 GNUNET_assert (NULL != cp->shandle);
867 cp->shandle = NULL;
868 GNUNET_free (cp->msg);
869}
870
871
872/**
873 * Callback that will be called when the helper process dies. This is not called
874 * when the helper process is stoped using GNUNET_HELPER_stop()
875 *
876 * @param cls the closure from GNUNET_HELPER_start()
877 */
878static void
879helper_exp_cb (void *cls)
880{
881 struct GNUNET_TESTBED_ControllerProc *cp = cls;
882 GNUNET_TESTBED_ControllerStatusCallback cb;
883 void *cb_cls;
884
885 cb = cp->cb;
886 cb_cls = cp->cls;
887 cp->helper = NULL;
888 GNUNET_TESTBED_controller_stop (cp);
889 if (NULL != cb)
890 cb (cb_cls, NULL, GNUNET_SYSERR);
891}
892
893
894/**
895 * Starts a controller process at the given host
896 *
897 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
898 * HOST(all connections form this ip are permitted by the testbed) when
899 * starting testbed controller at host. This can either be a single ip
900 * address or a network address in CIDR notation.
901 * @param host the host where the controller has to be started; NULL for
902 * localhost
903 * @param cfg template configuration to use for the remote controller; the
904 * remote controller will be started with a slightly modified
905 * configuration (port numbers, unix domain sockets and service home
906 * values are changed as per TESTING library on the remote host)
907 * @param cb function called when the controller is successfully started or
908 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
909 * called if cb is called with GNUNET_SYSERR as status. Will never be
910 * called in the same task as 'GNUNET_TESTBED_controller_start'
911 * (synchronous errors will be signalled by returning NULL). This
912 * parameter cannot be NULL.
913 * @param cls closure for above callbacks
914 * @return the controller process handle, NULL on errors
915 */
916struct GNUNET_TESTBED_ControllerProc *
917GNUNET_TESTBED_controller_start (const char *trusted_ip,
918 struct GNUNET_TESTBED_Host *host,
919 const struct GNUNET_CONFIGURATION_Handle *cfg,
920 GNUNET_TESTBED_ControllerStatusCallback cb,
921 void *cls)
922{
923 struct GNUNET_TESTBED_ControllerProc *cp;
924 struct GNUNET_TESTBED_HelperInit *msg;
925 const char *hostname;
926
927 static char *const binary_argv[] = {
928 HELPER_TESTBED_BINARY, NULL
929 };
930
931 hostname = NULL;
932 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
933 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
934 {
935 cp->helper =
936 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
937 &helper_mst, &helper_exp_cb, cp);
938 }
939 else
940 {
941 char *helper_binary_path_args[2];
942 char **rsh_args;
943 char **rsh_suffix_args;
944 const char *username;
945 char *port;
946 char *dst;
947
948 username = GNUNET_TESTBED_host_get_username_ (host);
949 hostname = GNUNET_TESTBED_host_get_hostname (host);
950 GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
951 if (NULL == username)
952 GNUNET_asprintf (&dst, "%s", hostname);
953 else
954 GNUNET_asprintf (&dst, "%s@%s", username, hostname);
955 LOG_DEBUG ("Starting SSH to destination %s\n", dst);
956
957 if (GNUNET_OK !=
958 GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
959 "HELPER_BINARY_PATH",
960 &helper_binary_path_args[0]))
961 helper_binary_path_args[0] =
962 GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
963 helper_binary_path_args[1] = NULL;
964 rsh_args = gen_rsh_args (port, dst);
965 rsh_suffix_args = gen_rsh_suffix_args ((const char **) helper_binary_path_args);
966 cp->helper_argv =
967 join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args);
968 free_argv (rsh_args);
969 free_argv (rsh_suffix_args);
970 GNUNET_free (port);
971 GNUNET_free (dst);
972 cp->helper =
973 GNUNET_HELPER_start (GNUNET_NO, cp->helper_argv[0], cp->helper_argv, &helper_mst,
974 &helper_exp_cb, cp);
975 GNUNET_free (helper_binary_path_args[0]);
976 }
977 if (NULL == cp->helper)
978 {
979 if (NULL != cp->helper_argv)
980 free_argv (cp->helper_argv);
981 GNUNET_free (cp);
982 return NULL;
983 }
984 cp->host = host;
985 cp->cb = cb;
986 cp->cls = cls;
987 msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
988 cp->msg = &msg->header;
989 cp->shandle =
990 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
991 if (NULL == cp->shandle)
992 {
993 GNUNET_free (msg);
994 GNUNET_TESTBED_controller_stop (cp);
995 return NULL;
996 }
997 return cp;
998}
999
1000
1001/**
1002 * Stop the controller process (also will terminate all peers and controllers
1003 * dependent on this controller). This function blocks until the testbed has
1004 * been fully terminated (!). The controller status cb from
1005 * GNUNET_TESTBED_controller_start() will not be called.
1006 *
1007 * @param cproc the controller process handle
1008 */
1009void
1010GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1011{
1012 if (NULL != cproc->shandle)
1013 GNUNET_HELPER_send_cancel (cproc->shandle);
1014 if (NULL != cproc->helper)
1015 GNUNET_HELPER_soft_stop (cproc->helper);
1016 if (NULL != cproc->cfg)
1017 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1018 if (NULL != cproc->helper_argv)
1019 free_argv (cproc->helper_argv);
1020 GNUNET_free (cproc);
1021}
1022
1023
1024/**
524 * The handle for whether a host is habitable or not 1025 * The handle for whether a host is habitable or not
525 */ 1026 */
526struct GNUNET_TESTBED_HostHabitableCheckHandle 1027struct GNUNET_TESTBED_HostHabitableCheckHandle
@@ -551,19 +1052,9 @@ struct GNUNET_TESTBED_HostHabitableCheckHandle
551 struct GNUNET_OS_Process *auxp; 1052 struct GNUNET_OS_Process *auxp;
552 1053
553 /** 1054 /**
554 * The SSH destination address string 1055 * The arguments used to start the helper
555 */
556 char *ssh_addr;
557
558 /**
559 * The destination port string
560 */ 1056 */
561 char *portstr; 1057 char **helper_argv;
562
563 /**
564 * The path for hte testbed helper binary
565 */
566 char *helper_binary_path;
567 1058
568 /** 1059 /**
569 * Task id for the habitability check task 1060 * Task id for the habitability check task
@@ -616,9 +1107,6 @@ habitability_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
616 ret = (0 != code) ? GNUNET_NO : GNUNET_YES; 1107 ret = (0 != code) ? GNUNET_NO : GNUNET_YES;
617 1108
618call_cb: 1109call_cb:
619 GNUNET_free (h->ssh_addr);
620 GNUNET_free (h->portstr);
621 GNUNET_free (h->helper_binary_path);
622 if (NULL != h->auxp) 1110 if (NULL != h->auxp)
623 GNUNET_OS_process_destroy (h->auxp); 1111 GNUNET_OS_process_destroy (h->auxp);
624 cb = h->cb; 1112 cb = h->cb;
@@ -649,9 +1137,12 @@ GNUNET_TESTBED_is_host_habitable (const struct GNUNET_TESTBED_Host *host,
649 void *cb_cls) 1137 void *cb_cls)
650{ 1138{
651 struct GNUNET_TESTBED_HostHabitableCheckHandle *h; 1139 struct GNUNET_TESTBED_HostHabitableCheckHandle *h;
652 char *remote_args[11]; 1140 char **rsh_args;
1141 char **rsh_suffix_args;
1142 char *stat_args[3];
653 const char *hostname; 1143 const char *hostname;
654 unsigned int argp; 1144 char *port;
1145 char *dst;
655 1146
656 h = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostHabitableCheckHandle)); 1147 h = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostHabitableCheckHandle));
657 h->cb = cb; 1148 h->cb = cb;
@@ -659,38 +1150,34 @@ GNUNET_TESTBED_is_host_habitable (const struct GNUNET_TESTBED_Host *host,
659 h->host = host; 1150 h->host = host;
660 hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname; 1151 hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname;
661 if (NULL == host->username) 1152 if (NULL == host->username)
662 h->ssh_addr = GNUNET_strdup (hostname); 1153 dst = GNUNET_strdup (hostname);
663 else 1154 else
664 GNUNET_asprintf (&h->ssh_addr, "%s@%s", host->username, hostname); 1155 GNUNET_asprintf (&dst, "%s@%s", host->username, hostname);
665 if (GNUNET_OK != 1156 if (GNUNET_OK !=
666 GNUNET_CONFIGURATION_get_value_string (config, "testbed", 1157 GNUNET_CONFIGURATION_get_value_string (config, "testbed",
667 "HELPER_BINARY_PATH", 1158 "HELPER_BINARY_PATH",
668 &h->helper_binary_path)) 1159 &stat_args[1]))
669 h->helper_binary_path = 1160 stat_args[1] =
670 GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY); 1161 GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
671 argp = 0; 1162 GNUNET_asprintf (&port, "%u", host->port);
672 remote_args[argp++] = "ssh"; 1163 rsh_args = gen_rsh_args (port, dst);
673 GNUNET_asprintf (&h->portstr, "%u", host->port); 1164 GNUNET_free (port);
674 remote_args[argp++] = "-p"; 1165 GNUNET_free (dst);
675 remote_args[argp++] = h->portstr; 1166 port = NULL;
676 remote_args[argp++] = "-o"; 1167 dst = NULL;
677 remote_args[argp++] = "BatchMode=yes"; 1168 stat_args[0] = "stat";
678 remote_args[argp++] = "-o"; 1169 stat_args[2] = NULL;
679 remote_args[argp++] = "NoHostAuthenticationForLocalhost=yes"; 1170 rsh_suffix_args = gen_rsh_suffix_args ((const char **) stat_args);
680 remote_args[argp++] = h->ssh_addr; 1171 h->helper_argv = join_argv ((const char **) rsh_args,
681 remote_args[argp++] = "stat"; 1172 (const char **) rsh_suffix_args);
682 remote_args[argp++] = h->helper_binary_path; 1173 GNUNET_free (rsh_suffix_args);
683 remote_args[argp++] = NULL; 1174 GNUNET_free (rsh_args);
684 GNUNET_assert (argp == 11);
685 h->auxp = 1175 h->auxp =
686 GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL, 1176 GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL,
687 NULL, "ssh", remote_args); 1177 NULL, h->helper_argv[0], h->helper_argv);
688 if (NULL == h->auxp) 1178 if (NULL == h->auxp)
689 { 1179 {
690 GNUNET_break (0); /* Cannot exec SSH? */ 1180 GNUNET_break (0); /* Cannot exec SSH? */
691 GNUNET_free (h->ssh_addr);
692 GNUNET_free (h->portstr);
693 GNUNET_free (h->helper_binary_path);
694 GNUNET_free (h); 1181 GNUNET_free (h);
695 return NULL; 1182 return NULL;
696 } 1183 }
@@ -715,9 +1202,7 @@ GNUNET_TESTBED_is_host_habitable_cancel (struct
715 (void) GNUNET_OS_process_kill (handle->auxp, SIGTERM); 1202 (void) GNUNET_OS_process_kill (handle->auxp, SIGTERM);
716 (void) GNUNET_OS_process_wait (handle->auxp); 1203 (void) GNUNET_OS_process_wait (handle->auxp);
717 GNUNET_OS_process_destroy (handle->auxp); 1204 GNUNET_OS_process_destroy (handle->auxp);
718 GNUNET_free (handle->ssh_addr); 1205 free_argv (handle->helper_argv);
719 GNUNET_free (handle->portstr);
720 GNUNET_free (handle->helper_binary_path);
721 GNUNET_free (handle); 1206 GNUNET_free (handle);
722} 1207}
723 1208
diff --git a/src/testbed/testbed_api_hosts.h b/src/testbed/testbed_api_hosts.h
index 69d18bcbf..2d25fd596 100644
--- a/src/testbed/testbed_api_hosts.h
+++ b/src/testbed/testbed_api_hosts.h
@@ -49,10 +49,15 @@ GNUNET_TESTBED_host_lookup_by_id_ (uint32_t id);
49 * 49 *
50 * @param id global host ID assigned to the host; 0 is 50 * @param id global host ID assigned to the host; 0 is
51 * reserved to always mean 'localhost' 51 * reserved to always mean 'localhost'
52 * @param cfg the configuration to use as a template while starting a controller
53 * on this host. Operation queue sizes specific to a host are also
54 * read from this configuration handle
52 * @return handle to the host, NULL on error 55 * @return handle to the host, NULL on error
53 */ 56 */
54struct GNUNET_TESTBED_Host * 57struct GNUNET_TESTBED_Host *
55GNUNET_TESTBED_host_create_by_id_ (uint32_t id); 58GNUNET_TESTBED_host_create_by_id_ (uint32_t id,
59 const struct GNUNET_CONFIGURATION_Handle
60 *cfg);
56 61
57 62
58/** 63/**
@@ -87,6 +92,16 @@ GNUNET_TESTBED_host_get_ssh_port_ (const struct GNUNET_TESTBED_Host *host);
87 92
88 93
89/** 94/**
95 * Obtain the host's configuration template
96 *
97 * @param host handle to the host
98 * @return the host's configuration template
99 */
100const struct GNUNET_CONFIGURATION_Handle *
101GNUNET_TESTBED_host_get_cfg_ (const struct GNUNET_TESTBED_Host *host);
102
103
104/**
90 * Marks a host as registered with a controller 105 * Marks a host as registered with a controller
91 * 106 *
92 * @param host the host to mark 107 * @param host the host to mark
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c
index a2f60c8cc..d57c3bf4c 100644
--- a/src/testbed/testbed_api_testbed.c
+++ b/src/testbed/testbed_api_testbed.c
@@ -1049,10 +1049,12 @@ GNUNET_TESTBED_run (const char *host_filename,
1049 1049
1050 GNUNET_assert (num_peers > 0); 1050 GNUNET_assert (num_peers > 0);
1051 rc = GNUNET_malloc (sizeof (struct RunContext)); 1051 rc = GNUNET_malloc (sizeof (struct RunContext));
1052 rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1052 if (NULL != host_filename) 1053 if (NULL != host_filename)
1053 { 1054 {
1054 rc->num_hosts = 1055 rc->num_hosts =
1055 GNUNET_TESTBED_hosts_load_from_file (host_filename, &rc->hosts); 1056 GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg,
1057 &rc->hosts);
1056 if (0 == rc->num_hosts) 1058 if (0 == rc->num_hosts)
1057 { 1059 {
1058 LOG (GNUNET_ERROR_TYPE_WARNING, 1060 LOG (GNUNET_ERROR_TYPE_WARNING,
@@ -1061,8 +1063,7 @@ GNUNET_TESTBED_run (const char *host_filename,
1061 } 1063 }
1062 } 1064 }
1063 else 1065 else
1064 rc->h = GNUNET_TESTBED_host_create (NULL, NULL, 0); 1066 rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0);
1065 rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1066 rc->num_peers = num_peers; 1067 rc->num_peers = num_peers;
1067 rc->event_mask = event_mask; 1068 rc->event_mask = event_mask;
1068 rc->cc = cc; 1069 rc->cc = cc;