aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/testbed_api.c')
-rw-r--r--src/testbed/testbed_api.c428
1 files changed, 2 insertions, 426 deletions
diff --git a/src/testbed/testbed_api.c b/src/testbed/testbed_api.c
index ad77003fc..eba4544eb 100644
--- a/src/testbed/testbed_api.c
+++ b/src/testbed/testbed_api.c
@@ -1,6 +1,6 @@
1/* 1/*
2 This file is part of GNUnet 2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors) 3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
4 4
5 GNUnet is free software; you can redistribute it and/or modify 5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published 6 it under the terms of the GNU General Public License as published
@@ -69,54 +69,6 @@
69 69
70 70
71/** 71/**
72 * Handle for controller process
73 */
74struct GNUNET_TESTBED_ControllerProc
75{
76 /**
77 * The process handle
78 */
79 struct GNUNET_HELPER_Handle *helper;
80
81 /**
82 * The arguments used to start the helper
83 */
84 char **helper_argv;
85
86 /**
87 * The host where the helper is run
88 */
89 struct GNUNET_TESTBED_Host *host;
90
91 /**
92 * The controller error callback
93 */
94 GNUNET_TESTBED_ControllerStatusCallback cb;
95
96 /**
97 * The closure for the above callback
98 */
99 void *cls;
100
101 /**
102 * The send handle for the helper
103 */
104 struct GNUNET_HELPER_SendHandle *shandle;
105
106 /**
107 * The message corresponding to send handle
108 */
109 struct GNUNET_MessageHeader *msg;
110
111 /**
112 * The configuration of the running testbed service
113 */
114 struct GNUNET_CONFIGURATION_Handle *cfg;
115
116};
117
118
119/**
120 * The message queue for sending messages to the controller service 72 * The message queue for sending messages to the controller service
121 */ 73 */
122struct MessageQueue 74struct MessageQueue
@@ -1131,98 +1083,6 @@ GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1131 1083
1132 1084
1133/** 1085/**
1134 * Functions with this signature are called whenever a
1135 * complete message is received by the tokenizer.
1136 *
1137 * Do not call GNUNET_SERVER_mst_destroy in callback
1138 *
1139 * @param cls closure
1140 * @param client identification of the client
1141 * @param message the actual message
1142 *
1143 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1144 */
1145static int
1146helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1147{
1148 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1149 const struct GNUNET_TESTBED_HelperReply *msg;
1150 const char *hostname;
1151 char *config;
1152 uLongf config_size;
1153 uLongf xconfig_size;
1154
1155 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1156 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1157 ntohs (msg->header.size));
1158 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1159 ntohs (msg->header.type));
1160 config_size = (uLongf) ntohs (msg->config_size);
1161 xconfig_size =
1162 (uLongf) (ntohs (msg->header.size) -
1163 sizeof (struct GNUNET_TESTBED_HelperReply));
1164 config = GNUNET_malloc (config_size);
1165 GNUNET_assert (Z_OK ==
1166 uncompress ((Bytef *) config, &config_size,
1167 (const Bytef *) &msg[1], xconfig_size));
1168 GNUNET_assert (NULL == cp->cfg);
1169 cp->cfg = GNUNET_CONFIGURATION_create ();
1170 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1171 (cp->cfg, config, config_size, GNUNET_NO));
1172 GNUNET_free (config);
1173 if ((NULL == cp->host) ||
1174 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
1175 hostname = "localhost";
1176 /* Change the hostname so that we can connect to it */
1177 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1178 hostname);
1179 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1180 return GNUNET_OK;
1181}
1182
1183
1184/**
1185 * Continuation function from GNUNET_HELPER_send()
1186 *
1187 * @param cls closure
1188 * @param result GNUNET_OK on success,
1189 * GNUNET_NO if helper process died
1190 * GNUNET_SYSERR during GNUNET_HELPER_stop
1191 */
1192static void
1193clear_msg (void *cls, int result)
1194{
1195 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1196
1197 GNUNET_assert (NULL != cp->shandle);
1198 cp->shandle = NULL;
1199 GNUNET_free (cp->msg);
1200}
1201
1202
1203/**
1204 * Callback that will be called when the helper process dies. This is not called
1205 * when the helper process is stoped using GNUNET_HELPER_stop()
1206 *
1207 * @param cls the closure from GNUNET_HELPER_start()
1208 */
1209static void
1210helper_exp_cb (void *cls)
1211{
1212 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1213 GNUNET_TESTBED_ControllerStatusCallback cb;
1214 void *cb_cls;
1215
1216 cb = cp->cb;
1217 cb_cls = cp->cls;
1218 cp->helper = NULL;
1219 GNUNET_TESTBED_controller_stop (cp);
1220 if (NULL != cb)
1221 cb (cb_cls, NULL, GNUNET_SYSERR);
1222}
1223
1224
1225/**
1226 * Function to call to start a link-controllers type operation once all queues 1086 * Function to call to start a link-controllers type operation once all queues
1227 * the operation is part of declare that the operation can be activated. 1087 * the operation is part of declare that the operation can be activated.
1228 * 1088 *
@@ -1322,290 +1182,6 @@ oprelease_get_slave_config (void *cls)
1322 1182
1323 1183
1324/** 1184/**
1325 * Function to copy NULL terminated list of arguments
1326 *
1327 * @param argv the NULL terminated list of arguments. Cannot be NULL.
1328 * @return the copied NULL terminated arguments
1329 */
1330static char **
1331copy_argv (const char *const *argv)
1332{
1333 char **argv_dup;
1334 unsigned int argp;
1335
1336 GNUNET_assert (NULL != argv);
1337 for (argp = 0; NULL != argv[argp]; argp++) ;
1338 argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
1339 for (argp = 0; NULL != argv[argp]; argp++)
1340 argv_dup[argp] = strdup (argv[argp]);
1341 return argv_dup;
1342}
1343
1344
1345/**
1346 * Function to join NULL terminated list of arguments
1347 *
1348 * @param argv1 the NULL terminated list of arguments. Cannot be NULL.
1349 * @param argv2 the NULL terminated list of arguments. Cannot be NULL.
1350 * @return the joined NULL terminated arguments
1351 */
1352static char **
1353join_argv (const char *const *argv1, const char *const *argv2)
1354{
1355 char **argvj;
1356 char *argv;
1357 unsigned int carg;
1358 unsigned int cnt;
1359
1360 carg = 0;
1361 argvj = NULL;
1362 for (cnt = 0; NULL != argv1[cnt]; cnt++)
1363 {
1364 argv = GNUNET_strdup (argv1[cnt]);
1365 GNUNET_array_append (argvj, carg, argv);
1366 }
1367 for (cnt = 0; NULL != argv2[cnt]; cnt++)
1368 {
1369 argv = GNUNET_strdup (argv2[cnt]);
1370 GNUNET_array_append (argvj, carg, argv);
1371 }
1372 GNUNET_array_append (argvj, carg, NULL);
1373 return argvj;
1374}
1375
1376
1377/**
1378 * Frees the given NULL terminated arguments
1379 *
1380 * @param argv the NULL terminated list of arguments
1381 */
1382static void
1383free_argv (char **argv)
1384{
1385 unsigned int argp;
1386
1387 for (argp = 0; NULL != argv[argp]; argp++)
1388 GNUNET_free (argv[argp]);
1389 GNUNET_free (argv);
1390}
1391
1392
1393/**
1394 * Generates arguments for opening a remote shell. Builds up the arguments
1395 * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable
1396 * should not mention `-p' (port) option and destination address as these will
1397 * be set locally in the function from its parameteres. If the environmental
1398 * variable is not found then it defaults to `ssh -o BatchMode=yes -o
1399 * NoHostAuthenticationForLocalhost=yes'
1400 *
1401 * @param port the destination port number
1402 * @param dst the destination address
1403 * @return NULL terminated list of arguments
1404 */
1405static char **
1406gen_rsh_args (const char *port, const char *dst)
1407{
1408 static const char *default_ssh_args[] = {
1409 "ssh",
1410 "-o",
1411 "BatchMode=yes",
1412 "-o",
1413 "NoHostAuthenticationForLocalhost=yes",
1414 NULL
1415 };
1416 char **ssh_args;
1417 char *ssh_cmd;
1418 char *ssh_cmd_cp;
1419 char *arg;
1420 unsigned int cnt;
1421
1422 ssh_args = NULL;
1423 if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD")))
1424 {
1425 ssh_cmd = GNUNET_strdup (ssh_cmd);
1426 ssh_cmd_cp = ssh_cmd;
1427 for (cnt = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
1428 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (arg));
1429 GNUNET_free (ssh_cmd_cp);
1430 }
1431 else
1432 {
1433 ssh_args = copy_argv (default_ssh_args);
1434 cnt = (sizeof (default_ssh_args)) / (sizeof (const char *));
1435 GNUNET_array_grow (ssh_args, cnt, cnt - 1);
1436 }
1437 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup ("-p"));
1438 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (port));
1439 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (dst));
1440 GNUNET_array_append (ssh_args, cnt, NULL);
1441 return ssh_args;
1442}
1443
1444
1445/**
1446 * Generates the arguments needed for executing the given binary in a remote
1447 * shell. Builds the arguments from the environmental variable
1448 * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found,
1449 * only the given binary name will be present in the returned arguments
1450 *
1451 * @param helper_binary_path the path of the binary to execute
1452 * @return NULL-terminated args
1453 */
1454static char **
1455gen_rsh_suffix_args (const char *helper_binary_path)
1456{
1457 char **rshell_args;
1458 char *rshell_cmd;
1459 char *rshell_cmd_cp;
1460 char *arg;
1461 unsigned int cnt;
1462
1463 rshell_args = NULL;
1464 cnt = 0;
1465 if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX")))
1466 {
1467 rshell_cmd = GNUNET_strdup (rshell_cmd);
1468 rshell_cmd_cp = rshell_cmd;
1469 for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL)
1470 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg));
1471 GNUNET_free (rshell_cmd_cp);
1472 }
1473 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (helper_binary_path));
1474 GNUNET_array_append (rshell_args, cnt, NULL);
1475 return rshell_args;
1476}
1477
1478
1479/**
1480 * Starts a controller process at the given host
1481 *
1482 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1483 * HOST(all connections form this ip are permitted by the testbed) when
1484 * starting testbed controller at host. This can either be a single ip
1485 * address or a network address in CIDR notation.
1486 * @param host the host where the controller has to be started; NULL for
1487 * localhost
1488 * @param cfg template configuration to use for the remote controller; the
1489 * remote controller will be started with a slightly modified
1490 * configuration (port numbers, unix domain sockets and service home
1491 * values are changed as per TESTING library on the remote host)
1492 * @param cb function called when the controller is successfully started or
1493 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1494 * called if cb is called with GNUNET_SYSERR as status. Will never be
1495 * called in the same task as 'GNUNET_TESTBED_controller_start'
1496 * (synchronous errors will be signalled by returning NULL). This
1497 * parameter cannot be NULL.
1498 * @param cls closure for above callbacks
1499 * @return the controller process handle, NULL on errors
1500 */
1501struct GNUNET_TESTBED_ControllerProc *
1502GNUNET_TESTBED_controller_start (const char *trusted_ip,
1503 struct GNUNET_TESTBED_Host *host,
1504 const struct GNUNET_CONFIGURATION_Handle *cfg,
1505 GNUNET_TESTBED_ControllerStatusCallback cb,
1506 void *cls)
1507{
1508 struct GNUNET_TESTBED_ControllerProc *cp;
1509 struct GNUNET_TESTBED_HelperInit *msg;
1510 const char *hostname;
1511
1512 static char *const binary_argv[] = {
1513 HELPER_TESTBED_BINARY, NULL
1514 };
1515
1516 hostname = NULL;
1517 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1518 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1519 {
1520 cp->helper =
1521 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1522 &helper_mst, &helper_exp_cb, cp);
1523 }
1524 else
1525 {
1526 char *helper_binary_path;
1527 char **ssh_args;
1528 char **rshell_args;
1529 const char *username;
1530 char *port;
1531 char *dst;
1532
1533 username = GNUNET_TESTBED_host_get_username_ (host);
1534 hostname = GNUNET_TESTBED_host_get_hostname (host);
1535 GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1536 if (NULL == username)
1537 GNUNET_asprintf (&dst, "%s", hostname);
1538 else
1539 GNUNET_asprintf (&dst, "%s@%s", username, hostname);
1540 LOG_DEBUG ("Starting SSH to destination %s\n", dst);
1541
1542 if (GNUNET_OK !=
1543 GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1544 "HELPER_BINARY_PATH",
1545 &helper_binary_path))
1546 helper_binary_path =
1547 GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1548 ssh_args = gen_rsh_args (port, dst);
1549 rshell_args = gen_rsh_suffix_args (helper_binary_path);
1550 cp->helper_argv =
1551 join_argv ((const char **) ssh_args, (const char **) rshell_args);
1552 free_argv (ssh_args);
1553 free_argv (rshell_args);
1554 GNUNET_free (port);
1555 GNUNET_free (dst);
1556 cp->helper =
1557 GNUNET_HELPER_start (GNUNET_NO, "ssh", cp->helper_argv, &helper_mst,
1558 &helper_exp_cb, cp);
1559 GNUNET_free (helper_binary_path);
1560 }
1561 if (NULL == cp->helper)
1562 {
1563 if (NULL != cp->helper_argv)
1564 free_argv (cp->helper_argv);
1565 GNUNET_free (cp);
1566 return NULL;
1567 }
1568 cp->host = host;
1569 cp->cb = cb;
1570 cp->cls = cls;
1571 msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
1572 cp->msg = &msg->header;
1573 cp->shandle =
1574 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1575 if (NULL == cp->shandle)
1576 {
1577 GNUNET_free (msg);
1578 GNUNET_TESTBED_controller_stop (cp);
1579 return NULL;
1580 }
1581 return cp;
1582}
1583
1584
1585/**
1586 * Stop the controller process (also will terminate all peers and controllers
1587 * dependent on this controller). This function blocks until the testbed has
1588 * been fully terminated (!). The controller status cb from
1589 * GNUNET_TESTBED_controller_start() will not be called.
1590 *
1591 * @param cproc the controller process handle
1592 */
1593void
1594GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1595{
1596 if (NULL != cproc->shandle)
1597 GNUNET_HELPER_send_cancel (cproc->shandle);
1598 if (NULL != cproc->helper)
1599 GNUNET_HELPER_soft_stop (cproc->helper);
1600 if (NULL != cproc->cfg)
1601 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1602 if (NULL != cproc->helper_argv)
1603 free_argv (cproc->helper_argv);
1604 GNUNET_free (cproc);
1605}
1606
1607
1608/**
1609 * Start a controller process using the given configuration at the 1185 * Start a controller process using the given configuration at the
1610 * given host. 1186 * given host.
1611 * 1187 *
@@ -1672,7 +1248,7 @@ GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1672 } 1248 }
1673 if (NULL == host) 1249 if (NULL == host)
1674 { 1250 {
1675 host = GNUNET_TESTBED_host_create_by_id_ (0); 1251 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1676 if (NULL == host) /* If the above host create fails */ 1252 if (NULL == host) /* If the above host create fails */
1677 { 1253 {
1678 LOG (GNUNET_ERROR_TYPE_WARNING, 1254 LOG (GNUNET_ERROR_TYPE_WARNING,