diff options
Diffstat (limited to 'src/testbed/testbed_api.c')
-rw-r--r-- | src/testbed/testbed_api.c | 428 |
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 | */ | ||
74 | struct 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 | */ |
122 | struct MessageQueue | 74 | struct 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 | */ | ||
1145 | static int | ||
1146 | helper_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 | */ | ||
1192 | static void | ||
1193 | clear_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 | */ | ||
1209 | static void | ||
1210 | helper_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 | */ | ||
1330 | static char ** | ||
1331 | copy_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 | */ | ||
1352 | static char ** | ||
1353 | join_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 | */ | ||
1382 | static void | ||
1383 | free_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 | */ | ||
1405 | static char ** | ||
1406 | gen_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 | */ | ||
1454 | static char ** | ||
1455 | gen_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 | */ | ||
1501 | struct GNUNET_TESTBED_ControllerProc * | ||
1502 | GNUNET_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 | */ | ||
1593 | void | ||
1594 | GNUNET_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, |