diff options
Diffstat (limited to 'src/testbed/testbed_api_hosts.c')
-rw-r--r-- | src/testbed/testbed_api_hosts.c | 589 |
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 | */ |
210 | struct GNUNET_TESTBED_Host * | 233 | struct GNUNET_TESTBED_Host * |
211 | GNUNET_TESTBED_host_create_by_id_ (uint32_t id) | 234 | GNUNET_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 | */ | ||
301 | int | ||
302 | GNUNET_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 | */ | ||
314 | const struct GNUNET_CONFIGURATION_Handle * | ||
315 | GNUNET_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 | */ |
280 | struct GNUNET_TESTBED_Host * | 334 | struct GNUNET_TESTBED_Host * |
281 | GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname, | 335 | GNUNET_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 | */ |
321 | struct GNUNET_TESTBED_Host * | 382 | struct GNUNET_TESTBED_Host * |
322 | GNUNET_TESTBED_host_create (const char *hostname, const char *username, | 383 | GNUNET_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 | */ |
342 | unsigned int | 408 | unsigned int |
343 | GNUNET_TESTBED_hosts_load_from_file (const char *filename, | 409 | GNUNET_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 | */ | ||
596 | struct 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 | */ | ||
647 | static char ** | ||
648 | copy_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 | */ | ||
669 | static char ** | ||
670 | join_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 | */ | ||
699 | static void | ||
700 | free_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 | */ | ||
722 | static char ** | ||
723 | gen_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 | */ | ||
772 | static char ** | ||
773 | gen_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 | */ | ||
814 | static int | ||
815 | helper_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 | */ | ||
861 | static void | ||
862 | clear_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 | */ | ||
878 | static void | ||
879 | helper_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 | */ | ||
916 | struct GNUNET_TESTBED_ControllerProc * | ||
917 | GNUNET_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 | */ | ||
1009 | void | ||
1010 | GNUNET_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 | */ |
526 | struct GNUNET_TESTBED_HostHabitableCheckHandle | 1027 | struct 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 | ||
618 | call_cb: | 1109 | call_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 | ||