/*
This file is part of GNUnet
- (C) 2008--2012 Christian Grothoff (and other contributing authors)
+ Copyright (C) 2008--2013 GNUnet e.V.
GNUnet is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published
You should have received a copy of the GNU General Public License
along with GNUnet; see the file COPYING. If not, write to the
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
*/
/**
#include "testbed_api_hosts.h"
#include "testbed_helper.h"
#include "testbed_api_operations.h"
-#include "testbed_api_sd.h"
#include <zlib.h>
+#include <regex.h>
/**
* Generic logging shorthand
};
-/**
- * A slot to record time taken by an overlay connect operation
- */
-struct TimeSlot
-{
- /**
- * A key to identify this timeslot
- */
- void *key;
-
- /**
- * Time
- */
- struct GNUNET_TIME_Relative time;
-
- /**
- * Number of timing values accumulated
- */
- unsigned int nvals;
-};
-
-
/**
* Opaque handle to a host running experiments managed by the testing framework.
* The master process must be able to SSH to this host without password (via
struct GNUNET_TESTBED_Host
{
- /**
- * The next pointer for DLL
- */
- struct GNUNET_TESTBED_Host *next;
-
- /**
- * The prev pointer for DLL
- */
- struct GNUNET_TESTBED_Host *prev;
-
/**
* The hostname of the host; NULL for localhost
*/
*/
struct OperationQueue *opq_parallel_overlay_connect_operations;
- /**
- * An array of timing slots; size should be equal to the current number of parallel
- * overlay connects
- */
- struct TimeSlot *tslots;
-
- /**
- * Handle for SD calculations amount parallel overlay connect operation finish
- * times
- */
- struct SDHandle *poc_sd;
-
- /**
- * The number of parallel overlay connects we do currently
- */
- unsigned int num_parallel_connects;
-
- /**
- * Counter to indicate when all the available time slots are filled
- */
- unsigned int tslots_filled;
-
/**
* Is a controller started on this host? FIXME: Is this needed?
*/
*/
struct GNUNET_TESTBED_Host *
GNUNET_TESTBED_host_create_by_id_ (uint32_t id,
- const struct GNUNET_CONFIGURATION_Handle
- *cfg)
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
{
return GNUNET_TESTBED_host_create_with_id (id, NULL, NULL, cfg, 0);
}
*/
struct GNUNET_TESTBED_Host *
GNUNET_TESTBED_host_create_with_id (uint32_t id, const char *hostname,
- const char *username,
+ const char *username,
const struct GNUNET_CONFIGURATION_Handle
*cfg,
uint16_t port)
LOG (GNUNET_ERROR_TYPE_WARNING, "Host with id: %u already created\n", id);
return NULL;
}
- host = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host));
+ host = GNUNET_new (struct GNUNET_TESTBED_Host);
host->hostname = (NULL != hostname) ? GNUNET_strdup (hostname) : NULL;
host->username = (NULL != username) ? GNUNET_strdup (username) : NULL;
host->id = id;
host->port = (0 == port) ? 22 : port;
host->cfg = GNUNET_CONFIGURATION_dup (cfg);
host->opq_parallel_overlay_connect_operations =
- GNUNET_TESTBED_operation_queue_create_ (0);
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (host, 1);
- host->poc_sd = GNUNET_TESTBED_SD_init_ (10);
+ GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_ADAPTIVE,
+ UINT_MAX);
new_size = host_list_size;
while (id >= new_size)
new_size += HOST_LIST_GROW_STEP;
static uint32_t uid_generator;
if (NULL == hostname)
- return GNUNET_TESTBED_host_create_with_id (0, hostname, username,
+ return GNUNET_TESTBED_host_create_with_id (0, hostname, username,
cfg, port);
return GNUNET_TESTBED_host_create_with_id (++uid_generator, hostname,
username, cfg, port);
*cfg,
struct GNUNET_TESTBED_Host ***hosts)
{
- //struct GNUNET_TESTBED_Host **host_array;
struct GNUNET_TESTBED_Host *starting_host;
char *data;
char *buf;
- char username[256];
- char hostname[256];
+ char *username;
+ char *hostname;
+ regex_t rex;
+ regmatch_t pmatch[6];
uint64_t fs;
short int port;
- int ret;
unsigned int offset;
unsigned int count;
offset = 0;
starting_host = NULL;
count = 0;
+ /* refer RFC 952 and RFC 1123 for valid hostnames */
+ GNUNET_assert (0 == regcomp (&rex,
+ "^(([[:alnum:]]+)@)?" /* username */
+ "([[:alnum:]]+[-[:alnum:]_\\.]+)" /* hostname */
+ "(:([[:digit:]]{1,5}))?", /* port */
+ REG_EXTENDED | REG_ICASE));
while (offset < (fs - 1))
{
offset++;
if (((data[offset] == '\n')) && (buf != &data[offset]))
{
+ unsigned int size;
+
data[offset] = '\0';
- ret =
- SSCANF (buf, "%255[a-zA-Z0-9_]@%255[a-zA-Z0-9.]:%5hd", username,
- hostname, &port);
- if (3 == ret)
+ username = NULL;
+ hostname = NULL;
+ port = 0;
+ if ((REG_NOMATCH == regexec (&rex, buf, 6, pmatch, 0))
+ || (-1 == pmatch[3].rm_so))
{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Successfully read host %s, port %d and user %s from file\n",
- hostname, port, username);
- /* We store hosts in a static list; hence we only require the starting
- * host pointer in that list to access the newly created list of hosts */
- if (NULL == starting_host)
- starting_host = GNUNET_TESTBED_host_create (hostname, username, cfg,
- port);
- else
- (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port);
- count++;
- }
- else
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"Error reading line `%s' in hostfile\n", buf);
+ buf = &data[offset + 1];
+ continue;
+ }
+ if (-1 != pmatch[2].rm_so)
+ {
+ size = pmatch[2].rm_eo - pmatch[2].rm_so;
+ username = GNUNET_malloc (size + 1);
+ username[size] = '\0';
+ GNUNET_assert (NULL != strncpy (username, buf + pmatch[2].rm_so, size));
+ }
+ if (-1 != pmatch[5].rm_so)
+ {
+ (void) SSCANF (buf + pmatch[5].rm_so, "%5hd", &port);
+ }
+ size = pmatch[3].rm_eo - pmatch[3].rm_so;
+ hostname = GNUNET_malloc (size + 1);
+ hostname[size] = '\0';
+ GNUNET_assert (NULL != strncpy (hostname, buf + pmatch[3].rm_so, size));
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Successfully read host %s, port %d and user %s from file\n",
+ (NULL == hostname) ? "NULL" : hostname,
+ port,
+ (NULL == username) ? "NULL" : username);
+ /* We store hosts in a static list; hence we only require the starting
+ * host pointer in that list to access the newly created list of hosts */
+ if (NULL == starting_host)
+ starting_host = GNUNET_TESTBED_host_create (hostname, username, cfg,
+ port);
+ else
+ (void) GNUNET_TESTBED_host_create (hostname, username, cfg, port);
+ count++;
+ GNUNET_free_non_null (username);
+ GNUNET_free (hostname);
buf = &data[offset + 1];
}
else if ((data[offset] == '\n') || (data[offset] == '\0'))
buf = &data[offset + 1];
}
+ regfree (&rex);
GNUNET_free (data);
if (NULL == starting_host)
return 0;
simple_resolve (const char *host)
{
struct addrinfo *res;
- const struct sockaddr_in *in_addr;
+ const struct sockaddr_in *in_addr;
char *hostip;
struct addrinfo hint;
unsigned int rc;
in_addr = (const struct sockaddr_in *) res->ai_addr;
hostip = inet_ntoa (in_addr->sin_addr);
GNUNET_assert (NULL != hostip);
+ freeaddrinfo (res);
LOG_DEBUG ("Resolved [%s] to [%s]\n", host, hostip);
return hostip;
}
GNUNET_CONFIGURATION_Handle *cfg,
struct GNUNET_TESTBED_Host ***hosts)
{
-#ifndef WITH_LL
- LOG (GNUNET_ERROR_TYPE_ERROR,
+#if !ENABLE_SUPERMUC
+ LOG (GNUNET_ERROR_TYPE_ERROR,
_("The function %s is only available when compiled with (--with-ll)\n"),
__func__);
GNUNET_assert (0);
#else
const char *hostfile;
- char *buf;
- char *hostname;
- char **hostnames;
- char **hostaddrs;
- const char *hostip;
- struct GNUNET_TESTBED_Host **host_list;
- ssize_t rsize;
- uint64_t size;
- uint64_t offset;
- enum {
- SCAN,
- SKIP,
- TRIM,
- READHOST
- } pstep;
- unsigned int host;
- unsigned int nhosts;
- unsigned int nhostaddrs;
-
+
if (NULL == (hostfile = getenv ("MP_SAVEHOSTFILE")))
{
GNUNET_break (0);
return 0;
}
- if (GNUNET_SYSERR == GNUNET_DISK_file_size (hostfile, &size, GNUNET_YES,
- GNUNET_YES))
- {
- GNUNET_break (0);
- return 0;
- }
- if (0 == size)
- {
- GNUNET_break (0);
- return 0;
- }
- buf = GNUNET_malloc (size + 1);
- rsize = GNUNET_DISK_fn_read (hostfile, buf, (size_t) size);
- if ( (GNUNET_SYSERR == rsize) || ((ssize_t) size != rsize) )
- {
- GNUNET_free (buf);
- GNUNET_break (0);
- return 0;
- }
- size++;
- offset = 0;
- pstep = SCAN;
- hostname = NULL;
- hostnames = NULL;
- hostaddrs = NULL;
- nhosts = 0;
- nhostaddrs = 0;
- while (offset < size)
- {
- switch (pstep)
- {
- case SCAN:
- if ('!' == buf[offset])
- pstep = SKIP;
- else
- pstep = TRIM;
- break;
- case SKIP:
- if ('\n' == buf[offset])
- pstep = SCAN;
- break;
- case TRIM:
- if ('!' == buf[offset])
- {
- pstep = SKIP;
- break;
- }
- if ( (' ' == buf[offset])
- || ('\t' == buf[offset])
- || ('\r' == buf[offset]) )
- pstep = TRIM;
- else
- {
- pstep = READHOST;
- hostname = &buf[offset];
- }
- break;
- case READHOST:
- if (isspace (buf[offset]))
- {
- buf[offset] = '\0';
- for (host = 0; host < nhosts; host++)
- if (0 == strcmp (hostnames[host], hostname))
- break;
- if (host == nhosts)
- {
- LOG_DEBUG ("Adding host [%s]\n", hostname);
- hostname = GNUNET_strdup (hostname);
- GNUNET_array_append (hostnames, nhosts, hostname);
- }
- else
- LOG_DEBUG ("Not adding host [%s] as it is already included\n", hostname);
- hostname = NULL;
- pstep = SCAN;
- }
- break;
- }
- offset++;
- }
- GNUNET_free_non_null (buf);
- if (NULL == hostnames)
- return 0;
- for (host = 0; host < nhosts; host++)
- {
- hostip = simple_resolve (hostnames[host]);
- if (NULL == hostip)
- {
- nhosts = 0;
- goto cleanup;
- }
- GNUNET_array_append (hostaddrs, nhostaddrs, GNUNET_strdup (hostip));
- }
- GNUNET_assert (nhostaddrs == nhosts);
- if (NULL == hosts)
- goto cleanup;
- host_list = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * nhostaddrs);
- for (host = 0; host < nhosts; host++)
- host_list[host] = GNUNET_TESTBED_host_create (hostaddrs[host], NULL, cfg, 0);
- *hosts = host_list;
-
- cleanup:
- for (host = 0; host < nhosts; host++)
- GNUNET_free (hostnames[host]);
- GNUNET_free(hostnames);
- for (host = 0; (NULL != hostaddrs) && (host < nhostaddrs); host++)
- GNUNET_free (hostaddrs[host]);
- GNUNET_free (hostaddrs);
- return nhosts;
+ return GNUNET_TESTBED_hosts_load_from_file (hostfile, cfg, hosts);
#endif
}
GNUNET_free_non_null ((char *) host->hostname);
GNUNET_TESTBED_operation_queue_destroy_
(host->opq_parallel_overlay_connect_operations);
- GNUNET_TESTBED_SD_destroy_ (host->poc_sd);
- GNUNET_free_non_null (host->tslots);
GNUNET_CONFIGURATION_destroy (host->cfg);
GNUNET_free (host);
while (host_list_size >= HOST_LIST_GROW_STEP)
return;
}
}
- rc = GNUNET_malloc (sizeof (struct RegisteredController));
+ rc = GNUNET_new (struct RegisteredController);
rc->controller = controller;
GNUNET_CONTAINER_DLL_insert_tail (host->rc_head, host->rc_tail, rc);
}
+/**
+ * Unmarks a host registered at a controller
+ *
+ * @param host the host to unmark
+ * @param controller the controller at which this host has to be unmarked
+ */
+void
+GNUNET_TESTBED_deregister_host_at_ (struct GNUNET_TESTBED_Host *host,
+ const struct GNUNET_TESTBED_Controller
+ *const controller)
+{
+ struct RegisteredController *rc;
+
+ for (rc = host->rc_head; NULL != rc; rc=rc->next)
+ if (controller == rc->controller)
+ break;
+ if (NULL == rc)
+ {
+ GNUNET_break (0);
+ return;
+ }
+ GNUNET_CONTAINER_DLL_remove (host->rc_head, host->rc_tail, rc);
+ GNUNET_free (rc);
+}
+
+
/**
* Checks whether a host has been registered
*
for (argp = 0; NULL != argv[argp]; argp++) ;
argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
for (argp = 0; NULL != argv[argp]; argp++)
- argv_dup[argp] = strdup (argv[argp]);
+ argv_dup[argp] = GNUNET_strdup (argv[argp]);
return argv_dup;
}
* should not mention `-p' (port) option and destination address as these will
* be set locally in the function from its parameteres. If the environmental
* variable is not found then it defaults to `ssh -o BatchMode=yes -o
- * NoHostAuthenticationForLocalhost=yes'
+ * NoHostAuthenticationForLocalhost=yes -o StrictHostkeyChecking=no -o
+ * PasswordAuthentication=noc'
*
* @param port the destination port number
- * @param dst the destination address
+ * @param hostname the hostname of the target host
+ * @param username the username to use while connecting to target host
* @return NULL terminated list of arguments
*/
static char **
-gen_rsh_args (const char *port, const char *dst)
+gen_rsh_args (const char *port, const char *hostname, const char *username)
{
static const char *default_ssh_args[] = {
"ssh",
"BatchMode=yes",
"-o",
"NoHostAuthenticationForLocalhost=yes",
+ "-o",
+ "StrictHostKeyChecking=no",
+ "-o",
+ "PasswordAuthentication=no",
+ "%h",
NULL
};
char **ssh_args;
char *ssh_cmd;
char *ssh_cmd_cp;
char *arg;
+ const char *new_arg;
+ unsigned int size;
unsigned int cnt;
ssh_args = NULL;
{
ssh_cmd = GNUNET_strdup (ssh_cmd);
ssh_cmd_cp = ssh_cmd;
- for (cnt = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
- GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (arg));
+ for (size = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
+ GNUNET_array_append (ssh_args, size, GNUNET_strdup (arg));
GNUNET_free (ssh_cmd_cp);
}
else
{
ssh_args = copy_argv (default_ssh_args);
- cnt = (sizeof (default_ssh_args)) / (sizeof (const char *));
- GNUNET_array_grow (ssh_args, cnt, cnt - 1);
+ size = (sizeof (default_ssh_args)) / (sizeof (const char *));
+ GNUNET_array_grow (ssh_args, size, size - 1);
+ }
+ for (cnt = 0; cnt < size; cnt++)
+ {
+ arg = ssh_args[cnt];
+ if ('%' != arg[0])
+ continue;
+ switch (arg[1])
+ {
+ case 'p':
+ new_arg = port;
+ break;
+
+ case 'u':
+ new_arg = username;
+ break;
+
+ case 'h':
+ new_arg = hostname;
+ break;
+
+ default:
+ continue;
+ }
+ if (NULL == new_arg)
+ continue;
+ GNUNET_free (arg);
+ ssh_args[cnt] = GNUNET_strdup (new_arg);
}
- GNUNET_array_append (ssh_args, cnt, GNUNET_strdup ("-p"));
- GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (port));
- GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (dst));
- GNUNET_array_append (ssh_args, cnt, NULL);
+ GNUNET_array_append (ssh_args, size, NULL);
return ssh_args;
}
}
if (NULL != append_args)
{
- for (append_cnt = 0; NULL != append_args[append_cnt]; append_cnt++)
+ for (append_cnt = 0; NULL != append_args[append_cnt]; append_cnt++)
GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (append_args[append_cnt]));
}
GNUNET_array_append (rshell_args, cnt, NULL);
GNUNET_assert (GNUNET_CONFIGURATION_deserialize
(cp->host->cfg, config, config_size, GNUNET_NO));
GNUNET_free (config);
- if ((NULL == cp->host) ||
- (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
+ if (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host)))
hostname = "localhost";
/* Change the hostname so that we can connect to it */
GNUNET_CONFIGURATION_set_value_string (cp->host->cfg, "testbed", "hostname",
GNUNET_assert (NULL != cp->shandle);
cp->shandle = NULL;
GNUNET_free (cp->msg);
+ cp->msg = NULL;
}
/**
- * Starts a controller process at the given host
+ * Starts a controller process at the given host. The given host's configration
+ * is used as a Template configuration to use for the remote controller; the
+ * remote controller will be started with a slightly modified configuration
+ * (port numbers, unix domain sockets and service home values are changed as per
+ * TESTING library on the remote host). The modified configuration replaces the
+ * host's existing configuration before signalling success through the
+ * GNUNET_TESTBED_ControllerStatusCallback()
*
* @param trusted_ip the ip address of the controller which will be set as TRUSTED
* HOST(all connections form this ip are permitted by the testbed) when
* starting testbed controller at host. This can either be a single ip
* address or a network address in CIDR notation.
- * @param host the host where the controller has to be started; NULL for
- * localhost
- * @param cfg template configuration to use for the remote controller; the
- * remote controller will be started with a slightly modified
- * configuration (port numbers, unix domain sockets and service home
- * values are changed as per TESTING library on the remote host)
+ * @param host the host where the controller has to be started. CANNOT be NULL.
* @param cb function called when the controller is successfully started or
* dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
* called if cb is called with GNUNET_SYSERR as status. Will never be
struct GNUNET_TESTBED_ControllerProc *
GNUNET_TESTBED_controller_start (const char *trusted_ip,
struct GNUNET_TESTBED_Host *host,
- const struct GNUNET_CONFIGURATION_Handle *cfg,
GNUNET_TESTBED_ControllerStatusCallback cb,
void *cls)
{
struct GNUNET_TESTBED_ControllerProc *cp;
struct GNUNET_TESTBED_HelperInit *msg;
+ const struct GNUNET_CONFIGURATION_Handle *cfg;
const char *hostname;
-
static char *const binary_argv[] = {
HELPER_TESTBED_BINARY, NULL
};
+ GNUNET_assert (NULL != host);
+ GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
hostname = NULL;
API_VIOLATION (GNUNET_NO == host->locked,
"Host is already locked by a previous call to GNUNET_TESTBED_controller_start()");
host->locked = GNUNET_YES;
API_VIOLATION (GNUNET_NO == host->controller_started,
"Attempting to start a controller on a host which is already started a controller");
- cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
- if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
+ cp = GNUNET_new (struct GNUNET_TESTBED_ControllerProc);
+ if (0 == GNUNET_TESTBED_host_get_id_ (host))
{
cp->helper =
GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
char **rsh_suffix_args;
const char *username;
char *port;
- char *dst;
-
- username = GNUNET_TESTBED_host_get_username_ (host);
- hostname = GNUNET_TESTBED_host_get_hostname (host);
- GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
- if (NULL == username)
- GNUNET_asprintf (&dst, "%s", hostname);
- else
- GNUNET_asprintf (&dst, "%s@%s", username, hostname);
- LOG_DEBUG ("Starting SSH to destination %s\n", dst);
-
+ char *argstr;
+ char *aux;
+ unsigned int cnt;
+
+ username = host->username;
+ hostname = host->hostname;
+ GNUNET_asprintf (&port, "%u", host->port);
+ LOG_DEBUG ("Starting remote connection to destination %s\n", hostname);
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
+ GNUNET_CONFIGURATION_get_value_filename (cfg, "testbed",
"HELPER_BINARY_PATH",
&helper_binary_path_args[0]))
helper_binary_path_args[0] =
GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
helper_binary_path_args[1] = NULL;
- rsh_args = gen_rsh_args (port, dst);
+ rsh_args = gen_rsh_args (port, hostname, username);
rsh_suffix_args = gen_rsh_suffix_args ((const char **) helper_binary_path_args);
cp->helper_argv =
join_argv ((const char **) rsh_args, (const char **) rsh_suffix_args);
free_argv (rsh_args);
free_argv (rsh_suffix_args);
GNUNET_free (port);
- GNUNET_free (dst);
+ argstr = GNUNET_strdup ("");
+ for (cnt = 0; NULL != cp->helper_argv[cnt]; cnt++)
+ {
+ aux = argstr;
+ GNUNET_assert (0 < GNUNET_asprintf (&argstr, "%s %s", aux, cp->helper_argv[cnt]));
+ GNUNET_free (aux);
+ }
+ LOG_DEBUG ("Helper cmd str: %s\n", argstr);
+ GNUNET_free (argstr);
cp->helper =
GNUNET_HELPER_start (GNUNET_NO, cp->helper_argv[0], cp->helper_argv, &helper_mst,
&helper_exp_cb, cp);
/**
- * Stop the controller process (also will terminate all peers and controllers
- * dependent on this controller). This function blocks until the testbed has
- * been fully terminated (!). The controller status cb from
- * GNUNET_TESTBED_controller_start() will not be called.
+ * Sends termination signal to the controller's helper process
*
- * @param cproc the controller process handle
+ * @param cproc the handle to the controller's helper process
*/
void
-GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
+GNUNET_TESTBED_controller_kill_ (struct GNUNET_TESTBED_ControllerProc *cproc)
{
if (NULL != cproc->shandle)
GNUNET_HELPER_send_cancel (cproc->shandle);
if (NULL != cproc->helper)
- GNUNET_HELPER_soft_stop (cproc->helper);
+ GNUNET_HELPER_kill (cproc->helper, GNUNET_YES);
+}
+
+
+/**
+ * Cleans-up the controller's helper process handle
+ *
+ * @param cproc the handle to the controller's helper process
+ */
+void
+GNUNET_TESTBED_controller_destroy_ (struct GNUNET_TESTBED_ControllerProc *cproc)
+{
+ if (NULL != cproc->helper)
+ {
+ GNUNET_break (GNUNET_OK == GNUNET_HELPER_wait (cproc->helper));
+ GNUNET_HELPER_destroy (cproc->helper);
+ }
if (NULL != cproc->helper_argv)
free_argv (cproc->helper_argv);
cproc->host->controller_started = GNUNET_NO;
cproc->host->locked = GNUNET_NO;
+ GNUNET_free_non_null (cproc->msg);
GNUNET_free (cproc);
}
+/**
+ * Stop the controller process (also will terminate all peers and controllers
+ * dependent on this controller). This function blocks until the testbed has
+ * been fully terminated (!). The controller status cb from
+ * GNUNET_TESTBED_controller_start() will not be called.
+ *
+ * @param cproc the controller process handle
+ */
+void
+GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
+{
+ GNUNET_TESTBED_controller_kill_ (cproc);
+ GNUNET_TESTBED_controller_destroy_ (cproc);
+}
+
+
/**
* The handle for whether a host is habitable or not
*/
/**
* Task id for the habitability check task
*/
- GNUNET_SCHEDULER_TaskIdentifier habitability_check_task;
+ struct GNUNET_SCHEDULER_Task * habitability_check_task;
/**
* How long we wait before checking the process status. Should grow
* Task for checking whether a host is habitable or not
*
* @param cls GNUNET_TESTBED_HostHabitableCheckHandle
- * @param tc the scheduler task context
*/
static void
-habitability_check (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+habitability_check (void *cls)
{
struct GNUNET_TESTBED_HostHabitableCheckHandle *h = cls;
void *cb_cls;
enum GNUNET_OS_ProcessStatusType type;
int ret;
- h->habitability_check_task = GNUNET_SCHEDULER_NO_TASK;
+ h->habitability_check_task = NULL;
ret = GNUNET_OS_process_status (h->auxp, &type, &code);
if (GNUNET_SYSERR == ret)
{
cb = h->cb;
cb_cls = h->cb_cls;
host = h->host;
+ free_argv (h->helper_argv);
GNUNET_free (h);
if (NULL != cb)
cb (cb_cls, host, ret);
char *stat_args[3];
const char *hostname;
char *port;
- char *dst;
- h = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostHabitableCheckHandle));
+ h = GNUNET_new (struct GNUNET_TESTBED_HostHabitableCheckHandle);
h->cb = cb;
h->cb_cls = cb_cls;
h->host = host;
hostname = (NULL == host->hostname) ? "127.0.0.1" : host->hostname;
- if (NULL == host->username)
- dst = GNUNET_strdup (hostname);
- else
- GNUNET_asprintf (&dst, "%s@%s", host->username, hostname);
if (GNUNET_OK !=
- GNUNET_CONFIGURATION_get_value_string (config, "testbed",
+ GNUNET_CONFIGURATION_get_value_filename (config, "testbed",
"HELPER_BINARY_PATH",
&stat_args[1]))
stat_args[1] =
- GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
+ GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
GNUNET_asprintf (&port, "%u", host->port);
- rsh_args = gen_rsh_args (port, dst);
+ rsh_args = gen_rsh_args (port, hostname, host->username);
GNUNET_free (port);
- GNUNET_free (dst);
port = NULL;
- dst = NULL;
stat_args[0] = "stat";
stat_args[2] = NULL;
rsh_suffix_args = gen_rsh_suffix_args ((const char **) stat_args);
+ GNUNET_free (stat_args[1]);
h->helper_argv = join_argv ((const char **) rsh_args,
(const char **) rsh_suffix_args);
- GNUNET_free (rsh_suffix_args);
- GNUNET_free (rsh_args);
+ free_argv (rsh_suffix_args);
+ free_argv (rsh_args);
h->auxp =
GNUNET_OS_start_process_vap (GNUNET_NO, GNUNET_OS_INHERIT_STD_ERR, NULL,
- NULL, h->helper_argv[0], h->helper_argv);
+ NULL, NULL, h->helper_argv[0], h->helper_argv);
if (NULL == h->auxp)
{
GNUNET_break (0); /* Cannot exec SSH? */
*handle)
{
GNUNET_SCHEDULER_cancel (handle->habitability_check_task);
- (void) GNUNET_OS_process_kill (handle->auxp, SIGTERM);
+ (void) GNUNET_OS_process_kill (handle->auxp, GNUNET_TERM_SIG);
(void) GNUNET_OS_process_wait (handle->auxp);
GNUNET_OS_process_destroy (handle->auxp);
free_argv (handle->helper_argv);
}
-/**
- * handle for host registration
- */
-struct GNUNET_TESTBED_HostRegistrationHandle
-{
- /**
- * The host being registered
- */
- struct GNUNET_TESTBED_Host *host;
-
- /**
- * The controller at which this host is being registered
- */
- struct GNUNET_TESTBED_Controller *c;
-
- /**
- * The Registartion completion callback
- */
- GNUNET_TESTBED_HostRegistrationCompletion cc;
-
- /**
- * The closure for above callback
- */
- void *cc_cls;
-};
-
-
/**
* Register a host with the controller
*
(NULL == hostname) ? "localhost" : hostname);
return NULL;
}
- rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
+ rh = GNUNET_new (struct GNUNET_TESTBED_HostRegistrationHandle);
rh->host = host;
rh->c = controller;
GNUNET_assert (NULL != cc);
}
-/**
- * Initializes the operation queue for parallel overlay connects
- *
- * @param h the host handle
- * @param npoc the number of parallel overlay connects - the queue size
- */
-void
-GNUNET_TESTBED_set_num_parallel_overlay_connects_ (struct
- GNUNET_TESTBED_Host *h,
- unsigned int npoc)
-{
- //fprintf (stderr, "%d", npoc);
- GNUNET_free_non_null (h->tslots);
- h->tslots_filled = 0;
- h->num_parallel_connects = npoc;
- h->tslots = GNUNET_malloc (npoc * sizeof (struct TimeSlot));
- GNUNET_TESTBED_operation_queue_reset_max_active_
- (h->opq_parallel_overlay_connect_operations, npoc);
-}
-
-
-/**
- * Returns a timing slot which will be exclusively locked
- *
- * @param h the host handle
- * @param key a pointer which is associated to the returned slot; should not be
- * NULL. It serves as a key to determine the correct owner of the slot
- * @return the time slot index in the array of time slots in the controller
- * handle
- */
-unsigned int
-GNUNET_TESTBED_get_tslot_ (struct GNUNET_TESTBED_Host *h, void *key)
-{
- unsigned int slot;
-
- GNUNET_assert (NULL != h->tslots);
- GNUNET_assert (NULL != key);
- for (slot = 0; slot < h->num_parallel_connects; slot++)
- if (NULL == h->tslots[slot].key)
- {
- h->tslots[slot].key = key;
- return slot;
- }
- GNUNET_assert (0); /* We should always find a free tslot */
-}
-
-
-/**
- * Decides whether any change in the number of parallel overlay connects is
- * necessary to adapt to the load on the system
- *
- * @param h the host handle
- */
-static void
-decide_npoc (struct GNUNET_TESTBED_Host *h)
-{
- struct GNUNET_TIME_Relative avg;
- int sd;
- unsigned int slot;
- unsigned int nvals;
-
- if (h->tslots_filled != h->num_parallel_connects)
- return;
- avg = GNUNET_TIME_UNIT_ZERO;
- nvals = 0;
- for (slot = 0; slot < h->num_parallel_connects; slot++)
- {
- avg = GNUNET_TIME_relative_add (avg, h->tslots[slot].time);
- nvals += h->tslots[slot].nvals;
- }
- GNUNET_assert (nvals >= h->num_parallel_connects);
- avg = GNUNET_TIME_relative_divide (avg, nvals);
- GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value != avg.rel_value);
- sd = GNUNET_TESTBED_SD_deviation_factor_ (h->poc_sd, (unsigned int) avg.rel_value);
- if ( (sd <= 5) ||
- (0 == GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
- h->num_parallel_connects)) )
- GNUNET_TESTBED_SD_add_data_ (h->poc_sd, (unsigned int) avg.rel_value);
- if (GNUNET_SYSERR == sd)
- {
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h,
- h->num_parallel_connects);
- return;
- }
- GNUNET_assert (0 <= sd);
- if (0 == sd)
- {
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h,
- h->num_parallel_connects
- * 2);
- return;
- }
- if (1 == sd)
- {
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h,
- h->num_parallel_connects
- + 1);
- return;
- }
- if (1 == h->num_parallel_connects)
- {
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h, 1);
- return;
- }
- if (2 == sd)
- {
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h,
- h->num_parallel_connects
- - 1);
- return;
- }
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h,
- h->num_parallel_connects /
- 2);
-}
-
-
-/**
- * Releases a time slot thus making it available for be used again
- *
- * @param h the host handle
- * @param index the index of the the time slot
- * @param key the key to prove ownership of the timeslot
- * @return GNUNET_YES if the time slot is successfully removed; GNUNET_NO if the
- * time slot cannot be removed - this could be because of the index
- * greater than existing number of time slots or `key' being different
- */
-int
-GNUNET_TESTBED_release_time_slot_ (struct GNUNET_TESTBED_Host *h,
- unsigned int index, void *key)
-{
- struct TimeSlot *slot;
-
- GNUNET_assert (NULL != key);
- if (index >= h->num_parallel_connects)
- return GNUNET_NO;
- slot = &h->tslots[index];
- if (key != slot->key)
- return GNUNET_NO;
- slot->key = NULL;
- return GNUNET_YES;
-}
-
-
-/**
- * Function to update a time slot
- *
- * @param h the host handle
- * @param index the index of the time slot to update
- * @param key the key to identify ownership of the slot
- * @param time the new time
- * @param failed should this reading be treated as coming from a fail event
- */
-void
-GNUNET_TESTBED_update_time_slot_ (struct GNUNET_TESTBED_Host *h,
- unsigned int index, void *key,
- struct GNUNET_TIME_Relative time, int failed)
-{
- struct TimeSlot *slot;
-
- if (GNUNET_YES == failed)
- {
- if (1 == h->num_parallel_connects)
- {
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h, 1);
- return;
- }
- GNUNET_TESTBED_set_num_parallel_overlay_connects_ (h,
- h->num_parallel_connects
- - 1);
- }
- if (GNUNET_NO == GNUNET_TESTBED_release_time_slot_ (h, index, key))
- return;
- slot = &h->tslots[index];
- slot->nvals++;
- if (GNUNET_TIME_UNIT_ZERO.rel_value == slot->time.rel_value)
- {
- slot->time = time;
- h->tslots_filled++;
- decide_npoc (h);
- return;
- }
- slot->time = GNUNET_TIME_relative_add (slot->time, time);
-}
-
-
/**
* Queues the given operation in the queue for parallel overlay connects of the
* given host
*
* @param h the host handle
* @param op the operation to queue in the given host's parally overlay connect
- * queue
+ * queue
*/
void
-GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h,
+GNUNET_TESTBED_host_queue_oc_ (struct GNUNET_TESTBED_Host *h,
struct GNUNET_TESTBED_Operation *op)
-{
+{
GNUNET_TESTBED_operation_queue_insert_
(h->opq_parallel_overlay_connect_operations, op);
}
/**
- * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
- * controller (testbed service)
+ * Resolves the hostname of the host to an ip address
*
- * @param c the controller handler
- * @param msg message received
- * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
- * not
+ * @param host the host whose hostname is to be resolved
*/
-int
-GNUNET_TESTBED_host_handle_addhostconfirm_ (struct GNUNET_TESTBED_Controller *c,
- const struct
- GNUNET_TESTBED_HostConfirmedMessage
- *msg)
+void
+GNUNET_TESTBED_host_resolve_ (struct GNUNET_TESTBED_Host *host)
{
- struct GNUNET_TESTBED_HostRegistrationHandle *rh;
- char *emsg;
- uint16_t msg_size;
+ char *hostname;
- rh = c->rh;
- if (NULL == rh)
- {
- return GNUNET_OK;
- }
- if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
- {
- LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
- GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
- return GNUNET_OK;
- }
- c->rh = NULL;
- msg_size = ntohs (msg->header.size);
- if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
- {
- LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
- GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
- rh->cc (rh->cc_cls, NULL);
- GNUNET_free (rh);
- return GNUNET_OK;
- }
- /* We have an error message */
- emsg = (char *) &msg[1];
- if ('\0' !=
- emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
+ hostname = (char *) host->hostname;
+ host->hostname = simple_resolve (hostname);
+ if (NULL == host->hostname)
{
GNUNET_break (0);
- GNUNET_free (rh);
- return GNUNET_NO;
+ host->hostname = hostname;
+ return;
}
- LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
- ntohl (msg->host_id), emsg);
- rh->cc (rh->cc_cls, emsg);
- GNUNET_free (rh);
- return GNUNET_OK;
+ GNUNET_free (hostname);
+ host->hostname = GNUNET_strdup (host->hostname);
}
/* end of testbed_api_hosts.c */