aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api_hosts.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/testbed_api_hosts.c')
-rw-r--r--src/testbed/testbed_api_hosts.c589
1 files changed, 537 insertions, 52 deletions
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