diff options
author | Sree Harsha Totakura <totakura@in.tum.de> | 2013-04-08 09:31:53 +0000 |
---|---|---|
committer | Sree Harsha Totakura <totakura@in.tum.de> | 2013-04-08 09:31:53 +0000 |
commit | 6f3ff8ff3db35d2a5c02e8cc88a912e9e0106d7c (patch) | |
tree | f6937fbccd377d56489da30d1bfdb24cc82a3b92 | |
parent | f2257ba6dd452dddb4a425689a1c137433b5f578 (diff) | |
download | gnunet-6f3ff8ff3db35d2a5c02e8cc88a912e9e0106d7c.tar.gz gnunet-6f3ff8ff3db35d2a5c02e8cc88a912e9e0106d7c.zip |
- restructure
-rw-r--r-- | src/testbed/Makefile.am | 3 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed.c | 1112 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed.h | 159 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_oc.c | 9 | ||||
-rw-r--r-- | src/testbed/gnunet-service-testbed_peers.c | 1138 |
5 files changed, 1322 insertions, 1099 deletions
diff --git a/src/testbed/Makefile.am b/src/testbed/Makefile.am index d980e8b6e..97e304ff3 100644 --- a/src/testbed/Makefile.am +++ b/src/testbed/Makefile.am | |||
@@ -30,8 +30,9 @@ bin_PROGRAMS = \ | |||
30 | gnunet-testbed-profiler | 30 | gnunet-testbed-profiler |
31 | 31 | ||
32 | gnunet_service_testbed_SOURCES = \ | 32 | gnunet_service_testbed_SOURCES = \ |
33 | gnunet-service-testbed.c \ | ||
34 | gnunet-service-testbed.h \ | 33 | gnunet-service-testbed.h \ |
34 | gnunet-service-testbed.c \ | ||
35 | gnunet-service-testbed_peers.c \ | ||
35 | gnunet-service-testbed_cache.c \ | 36 | gnunet-service-testbed_cache.c \ |
36 | gnunet-service-testbed_oc.c \ | 37 | gnunet-service-testbed_oc.c \ |
37 | gnunet-service-testbed_cpustatus.c | 38 | gnunet-service-testbed_cpustatus.c |
diff --git a/src/testbed/gnunet-service-testbed.c b/src/testbed/gnunet-service-testbed.c index a1c7f02be..05668284b 100644 --- a/src/testbed/gnunet-service-testbed.c +++ b/src/testbed/gnunet-service-testbed.c | |||
@@ -25,28 +25,6 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include "gnunet-service-testbed.h" | 27 | #include "gnunet-service-testbed.h" |
28 | #include "gnunet_arm_service.h" | ||
29 | |||
30 | #include <zlib.h> | ||
31 | |||
32 | |||
33 | /** | ||
34 | * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler | ||
35 | */ | ||
36 | struct HandlerContext_ShutdownPeers | ||
37 | { | ||
38 | /** | ||
39 | * The number of slave we expect to hear from since we forwarded the | ||
40 | * GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them | ||
41 | */ | ||
42 | unsigned int nslaves; | ||
43 | |||
44 | /** | ||
45 | * Did we observe a timeout with respect to this operation at any of the | ||
46 | * slaves | ||
47 | */ | ||
48 | int timeout; | ||
49 | }; | ||
50 | 28 | ||
51 | 29 | ||
52 | /***********/ | 30 | /***********/ |
@@ -69,11 +47,6 @@ struct Context *GST_context; | |||
69 | struct Slave **GST_slave_list; | 47 | struct Slave **GST_slave_list; |
70 | 48 | ||
71 | /** | 49 | /** |
72 | * A list of peers we know about | ||
73 | */ | ||
74 | struct Peer **GST_peer_list; | ||
75 | |||
76 | /** | ||
77 | * Array of hosts | 50 | * Array of hosts |
78 | */ | 51 | */ |
79 | struct GNUNET_TESTBED_Host **GST_host_list; | 52 | struct GNUNET_TESTBED_Host **GST_host_list; |
@@ -277,30 +250,6 @@ GST_queue_message (struct GNUNET_SERVER_Client *client, | |||
277 | 250 | ||
278 | 251 | ||
279 | /** | 252 | /** |
280 | * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow() | ||
281 | * several times we call it only once. The array is also made to grow in steps | ||
282 | * of LIST_GROW_STEP. | ||
283 | * | ||
284 | * @param ptr the array pointer to grow | ||
285 | * @param size the size of array | ||
286 | * @param accommodate_size the size which the array has to accommdate; after | ||
287 | * this call the array will be big enough to accommdate sizes upto | ||
288 | * accommodate_size | ||
289 | */ | ||
290 | #define array_grow_large_enough(ptr, size, accommodate_size) \ | ||
291 | do \ | ||
292 | { \ | ||
293 | unsigned int growth_size; \ | ||
294 | GNUNET_assert (size <= accommodate_size); \ | ||
295 | growth_size = size; \ | ||
296 | while (growth_size <= accommodate_size) \ | ||
297 | growth_size += LIST_GROW_STEP; \ | ||
298 | GNUNET_array_grow (ptr, size, growth_size); \ | ||
299 | GNUNET_assert (size > accommodate_size); \ | ||
300 | } while (0) | ||
301 | |||
302 | |||
303 | /** | ||
304 | * Function to add a host to the current list of known hosts | 253 | * Function to add a host to the current list of known hosts |
305 | * | 254 | * |
306 | * @param host the host to add | 255 | * @param host the host to add |
@@ -314,7 +263,7 @@ host_list_add (struct GNUNET_TESTBED_Host *host) | |||
314 | 263 | ||
315 | host_id = GNUNET_TESTBED_host_get_id_ (host); | 264 | host_id = GNUNET_TESTBED_host_get_id_ (host); |
316 | if (GST_host_list_size <= host_id) | 265 | if (GST_host_list_size <= host_id) |
317 | array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); | 266 | GST_array_grow_large_enough (GST_host_list, GST_host_list_size, host_id); |
318 | if (NULL != GST_host_list[host_id]) | 267 | if (NULL != GST_host_list[host_id]) |
319 | { | 268 | { |
320 | LOG_DEBUG ("A host with id: %u already exists\n", host_id); | 269 | LOG_DEBUG ("A host with id: %u already exists\n", host_id); |
@@ -334,7 +283,7 @@ static void | |||
334 | route_list_add (struct Route *route) | 283 | route_list_add (struct Route *route) |
335 | { | 284 | { |
336 | if (route->dest >= route_list_size) | 285 | if (route->dest >= route_list_size) |
337 | array_grow_large_enough (route_list, route_list_size, route->dest); | 286 | GST_array_grow_large_enough (route_list, route_list_size, route->dest); |
338 | GNUNET_assert (NULL == route_list[route->dest]); | 287 | GNUNET_assert (NULL == route_list[route->dest]); |
339 | route_list[route->dest] = route; | 288 | route_list[route->dest] = route; |
340 | } | 289 | } |
@@ -349,61 +298,14 @@ static void | |||
349 | slave_list_add (struct Slave *slave) | 298 | slave_list_add (struct Slave *slave) |
350 | { | 299 | { |
351 | if (slave->host_id >= GST_slave_list_size) | 300 | if (slave->host_id >= GST_slave_list_size) |
352 | array_grow_large_enough (GST_slave_list, GST_slave_list_size, | 301 | GST_array_grow_large_enough (GST_slave_list, GST_slave_list_size, |
353 | slave->host_id); | 302 | slave->host_id); |
354 | GNUNET_assert (NULL == GST_slave_list[slave->host_id]); | 303 | GNUNET_assert (NULL == GST_slave_list[slave->host_id]); |
355 | GST_slave_list[slave->host_id] = slave; | 304 | GST_slave_list[slave->host_id] = slave; |
356 | } | 305 | } |
357 | 306 | ||
358 | 307 | ||
359 | /** | 308 | /** |
360 | * Adds a peer to the peer array | ||
361 | * | ||
362 | * @param peer the peer to add | ||
363 | */ | ||
364 | static void | ||
365 | peer_list_add (struct Peer *peer) | ||
366 | { | ||
367 | if (peer->id >= GST_peer_list_size) | ||
368 | array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id); | ||
369 | GNUNET_assert (NULL == GST_peer_list[peer->id]); | ||
370 | GST_peer_list[peer->id] = peer; | ||
371 | } | ||
372 | |||
373 | |||
374 | /** | ||
375 | * Removes a the give peer from the peer array | ||
376 | * | ||
377 | * @param peer the peer to be removed | ||
378 | */ | ||
379 | static void | ||
380 | peer_list_remove (struct Peer *peer) | ||
381 | { | ||
382 | unsigned int orig_size; | ||
383 | uint32_t id; | ||
384 | |||
385 | GST_peer_list[peer->id] = NULL; | ||
386 | orig_size = GST_peer_list_size; | ||
387 | while (GST_peer_list_size >= LIST_GROW_STEP) | ||
388 | { | ||
389 | for (id = GST_peer_list_size - 1; | ||
390 | (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); | ||
391 | id--) | ||
392 | if (NULL != GST_peer_list[id]) | ||
393 | break; | ||
394 | if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1)) | ||
395 | break; | ||
396 | GST_peer_list_size -= LIST_GROW_STEP; | ||
397 | } | ||
398 | if (orig_size == GST_peer_list_size) | ||
399 | return; | ||
400 | GST_peer_list = | ||
401 | GNUNET_realloc (GST_peer_list, | ||
402 | sizeof (struct Peer *) * GST_peer_list_size); | ||
403 | } | ||
404 | |||
405 | |||
406 | /** | ||
407 | * Finds the route with directly connected host as destination through which | 309 | * Finds the route with directly connected host as destination through which |
408 | * the destination host can be reached | 310 | * the destination host can be reached |
409 | * | 311 | * |
@@ -476,9 +378,9 @@ GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, | |||
476 | * @param client the client to send the message to | 378 | * @param client the client to send the message to |
477 | * @param operation_id the id of the operation which was successful | 379 | * @param operation_id the id of the operation which was successful |
478 | */ | 380 | */ |
479 | static void | 381 | void |
480 | send_operation_success_msg (struct GNUNET_SERVER_Client *client, | 382 | GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, |
481 | uint64_t operation_id) | 383 | uint64_t operation_id) |
482 | { | 384 | { |
483 | struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; | 385 | struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg; |
484 | uint16_t msize; | 386 | uint16_t msize; |
@@ -1415,530 +1317,6 @@ handle_link_controllers (void *cls, struct GNUNET_SERVER_Client *client, | |||
1415 | 1317 | ||
1416 | 1318 | ||
1417 | /** | 1319 | /** |
1418 | * The task to be executed if the forwarded peer create operation has been | ||
1419 | * timed out | ||
1420 | * | ||
1421 | * @param cls the FowardedOperationContext | ||
1422 | * @param tc the TaskContext from the scheduler | ||
1423 | */ | ||
1424 | static void | ||
1425 | peer_create_forward_timeout (void *cls, | ||
1426 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1427 | { | ||
1428 | struct ForwardedOperationContext *fopc = cls; | ||
1429 | |||
1430 | GNUNET_free (fopc->cls); | ||
1431 | GST_forwarded_operation_timeout (fopc, tc); | ||
1432 | } | ||
1433 | |||
1434 | |||
1435 | /** | ||
1436 | * Callback to be called when forwarded peer create operation is successfull. We | ||
1437 | * have to relay the reply msg back to the client | ||
1438 | * | ||
1439 | * @param cls ForwardedOperationContext | ||
1440 | * @param msg the peer create success message | ||
1441 | */ | ||
1442 | static void | ||
1443 | peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) | ||
1444 | { | ||
1445 | struct ForwardedOperationContext *fopc = cls; | ||
1446 | struct Peer *remote_peer; | ||
1447 | |||
1448 | if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS) | ||
1449 | { | ||
1450 | GNUNET_assert (NULL != fopc->cls); | ||
1451 | remote_peer = fopc->cls; | ||
1452 | peer_list_add (remote_peer); | ||
1453 | } | ||
1454 | GST_forwarded_operation_reply_relay (fopc, msg); | ||
1455 | } | ||
1456 | |||
1457 | |||
1458 | /** | ||
1459 | * Function to destroy a peer | ||
1460 | * | ||
1461 | * @param peer the peer structure to destroy | ||
1462 | */ | ||
1463 | void | ||
1464 | GST_destroy_peer (struct Peer *peer) | ||
1465 | { | ||
1466 | GNUNET_break (0 == peer->reference_cnt); | ||
1467 | if (GNUNET_YES == peer->is_remote) | ||
1468 | { | ||
1469 | peer_list_remove (peer); | ||
1470 | GNUNET_free (peer); | ||
1471 | return; | ||
1472 | } | ||
1473 | if (GNUNET_YES == peer->details.local.is_running) | ||
1474 | { | ||
1475 | GNUNET_TESTING_peer_stop (peer->details.local.peer); | ||
1476 | peer->details.local.is_running = GNUNET_NO; | ||
1477 | } | ||
1478 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
1479 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
1480 | peer_list_remove (peer); | ||
1481 | GNUNET_free (peer); | ||
1482 | } | ||
1483 | |||
1484 | |||
1485 | /** | ||
1486 | * Callback to be called when forwarded peer destroy operation is successfull. We | ||
1487 | * have to relay the reply msg back to the client | ||
1488 | * | ||
1489 | * @param cls ForwardedOperationContext | ||
1490 | * @param msg the peer create success message | ||
1491 | */ | ||
1492 | static void | ||
1493 | peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) | ||
1494 | { | ||
1495 | struct ForwardedOperationContext *fopc = cls; | ||
1496 | struct Peer *remote_peer; | ||
1497 | |||
1498 | if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS == | ||
1499 | ntohs (msg->type)) | ||
1500 | { | ||
1501 | remote_peer = fopc->cls; | ||
1502 | GNUNET_assert (NULL != remote_peer); | ||
1503 | remote_peer->destroy_flag = GNUNET_YES; | ||
1504 | if (0 == remote_peer->reference_cnt) | ||
1505 | GST_destroy_peer (remote_peer); | ||
1506 | } | ||
1507 | GST_forwarded_operation_reply_relay (fopc, msg); | ||
1508 | } | ||
1509 | |||
1510 | |||
1511 | |||
1512 | /** | ||
1513 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
1514 | * | ||
1515 | * @param cls NULL | ||
1516 | * @param client identification of the client | ||
1517 | * @param message the actual message | ||
1518 | */ | ||
1519 | static void | ||
1520 | handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, | ||
1521 | const struct GNUNET_MessageHeader *message) | ||
1522 | { | ||
1523 | const struct GNUNET_TESTBED_PeerCreateMessage *msg; | ||
1524 | struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; | ||
1525 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
1526 | struct ForwardedOperationContext *fo_ctxt; | ||
1527 | struct Route *route; | ||
1528 | struct Peer *peer; | ||
1529 | char *config; | ||
1530 | size_t dest_size; | ||
1531 | int ret; | ||
1532 | uint32_t config_size; | ||
1533 | uint32_t host_id; | ||
1534 | uint32_t peer_id; | ||
1535 | uint16_t msize; | ||
1536 | |||
1537 | |||
1538 | msize = ntohs (message->size); | ||
1539 | if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage)) | ||
1540 | { | ||
1541 | GNUNET_break (0); /* We need configuration */ | ||
1542 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1543 | return; | ||
1544 | } | ||
1545 | msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message; | ||
1546 | host_id = ntohl (msg->host_id); | ||
1547 | peer_id = ntohl (msg->peer_id); | ||
1548 | if (UINT32_MAX == peer_id) | ||
1549 | { | ||
1550 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
1551 | "Cannot create peer with given ID"); | ||
1552 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1553 | return; | ||
1554 | } | ||
1555 | if (host_id == GST_context->host_id) | ||
1556 | { | ||
1557 | char *emsg; | ||
1558 | |||
1559 | /* We are responsible for this peer */ | ||
1560 | msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage); | ||
1561 | config_size = ntohl (msg->config_size); | ||
1562 | config = GNUNET_malloc (config_size); | ||
1563 | dest_size = config_size; | ||
1564 | if (Z_OK != | ||
1565 | (ret = | ||
1566 | uncompress ((Bytef *) config, (uLongf *) & dest_size, | ||
1567 | (const Bytef *) &msg[1], (uLong) msize))) | ||
1568 | { | ||
1569 | GNUNET_break (0); /* uncompression error */ | ||
1570 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1571 | return; | ||
1572 | } | ||
1573 | if (config_size != dest_size) | ||
1574 | { | ||
1575 | GNUNET_break (0); /* Uncompressed config size mismatch */ | ||
1576 | GNUNET_free (config); | ||
1577 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1578 | return; | ||
1579 | } | ||
1580 | cfg = GNUNET_CONFIGURATION_create (); | ||
1581 | if (GNUNET_OK != | ||
1582 | GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO)) | ||
1583 | { | ||
1584 | GNUNET_break (0); /* Configuration parsing error */ | ||
1585 | GNUNET_free (config); | ||
1586 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1587 | return; | ||
1588 | } | ||
1589 | GNUNET_free (config); | ||
1590 | GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID", | ||
1591 | (unsigned long long) peer_id); | ||
1592 | peer = GNUNET_malloc (sizeof (struct Peer)); | ||
1593 | peer->is_remote = GNUNET_NO; | ||
1594 | peer->details.local.cfg = cfg; | ||
1595 | peer->id = peer_id; | ||
1596 | LOG_DEBUG ("Creating peer with id: %u\n", (unsigned int) peer->id); | ||
1597 | peer->details.local.peer = | ||
1598 | GNUNET_TESTING_peer_configure (GST_context->system, | ||
1599 | peer->details.local.cfg, peer->id, | ||
1600 | NULL /* Peer id */ , | ||
1601 | &emsg); | ||
1602 | if (NULL == peer->details.local.peer) | ||
1603 | { | ||
1604 | LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg); | ||
1605 | GNUNET_free (emsg); | ||
1606 | GNUNET_free (peer); | ||
1607 | GNUNET_break (0); | ||
1608 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
1609 | return; | ||
1610 | } | ||
1611 | peer->details.local.is_running = GNUNET_NO; | ||
1612 | peer_list_add (peer); | ||
1613 | reply = | ||
1614 | GNUNET_malloc (sizeof | ||
1615 | (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); | ||
1616 | reply->header.size = | ||
1617 | htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); | ||
1618 | reply->header.type = | ||
1619 | htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); | ||
1620 | reply->peer_id = msg->peer_id; | ||
1621 | reply->operation_id = msg->operation_id; | ||
1622 | GST_queue_message (client, &reply->header); | ||
1623 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1624 | return; | ||
1625 | } | ||
1626 | |||
1627 | /* Forward peer create request */ | ||
1628 | route = GST_find_dest_route (host_id); | ||
1629 | if (NULL == route) | ||
1630 | { | ||
1631 | GNUNET_break (0); | ||
1632 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1633 | return; | ||
1634 | } | ||
1635 | |||
1636 | peer = GNUNET_malloc (sizeof (struct Peer)); | ||
1637 | peer->is_remote = GNUNET_YES; | ||
1638 | peer->id = peer_id; | ||
1639 | peer->details.remote.slave = GST_slave_list[route->dest]; | ||
1640 | peer->details.remote.remote_host_id = host_id; | ||
1641 | fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
1642 | GNUNET_SERVER_client_keep (client); | ||
1643 | fo_ctxt->client = client; | ||
1644 | fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); | ||
1645 | fo_ctxt->cls = peer; //GST_slave_list[route->dest]->controller; | ||
1646 | fo_ctxt->type = OP_PEER_CREATE; | ||
1647 | fo_ctxt->opc = | ||
1648 | GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list | ||
1649 | [route->dest]->controller, | ||
1650 | fo_ctxt->operation_id, | ||
1651 | &msg->header, | ||
1652 | peer_create_success_cb, fo_ctxt); | ||
1653 | fo_ctxt->timeout_task = | ||
1654 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &peer_create_forward_timeout, | ||
1655 | fo_ctxt); | ||
1656 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); | ||
1657 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1658 | } | ||
1659 | |||
1660 | |||
1661 | /** | ||
1662 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
1663 | * | ||
1664 | * @param cls NULL | ||
1665 | * @param client identification of the client | ||
1666 | * @param message the actual message | ||
1667 | */ | ||
1668 | static void | ||
1669 | handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, | ||
1670 | const struct GNUNET_MessageHeader *message) | ||
1671 | { | ||
1672 | const struct GNUNET_TESTBED_PeerDestroyMessage *msg; | ||
1673 | struct ForwardedOperationContext *fopc; | ||
1674 | struct Peer *peer; | ||
1675 | uint32_t peer_id; | ||
1676 | |||
1677 | msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message; | ||
1678 | peer_id = ntohl (msg->peer_id); | ||
1679 | LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n", | ||
1680 | peer_id, GNUNET_ntohll (msg->operation_id)); | ||
1681 | if ((GST_peer_list_size <= peer_id) || (NULL == GST_peer_list[peer_id])) | ||
1682 | { | ||
1683 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1684 | "Asked to destroy a non existent peer with id: %u\n", peer_id); | ||
1685 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
1686 | "Peer doesn't exist"); | ||
1687 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1688 | return; | ||
1689 | } | ||
1690 | peer = GST_peer_list[peer_id]; | ||
1691 | if (GNUNET_YES == peer->is_remote) | ||
1692 | { | ||
1693 | /* Forward the destory message to sub controller */ | ||
1694 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
1695 | GNUNET_SERVER_client_keep (client); | ||
1696 | fopc->client = client; | ||
1697 | fopc->cls = peer; | ||
1698 | fopc->type = OP_PEER_DESTROY; | ||
1699 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
1700 | fopc->opc = | ||
1701 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1702 | slave->controller, | ||
1703 | fopc->operation_id, &msg->header, | ||
1704 | &peer_destroy_success_cb, fopc); | ||
1705 | fopc->timeout_task = | ||
1706 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
1707 | fopc); | ||
1708 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
1709 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1710 | return; | ||
1711 | } | ||
1712 | peer->destroy_flag = GNUNET_YES; | ||
1713 | if (0 == peer->reference_cnt) | ||
1714 | GST_destroy_peer (peer); | ||
1715 | else | ||
1716 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
1717 | "Delaying peer destroy as peer is currently in use\n"); | ||
1718 | send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id)); | ||
1719 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1720 | } | ||
1721 | |||
1722 | |||
1723 | /** | ||
1724 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
1725 | * | ||
1726 | * @param cls NULL | ||
1727 | * @param client identification of the client | ||
1728 | * @param message the actual message | ||
1729 | */ | ||
1730 | static void | ||
1731 | handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, | ||
1732 | const struct GNUNET_MessageHeader *message) | ||
1733 | { | ||
1734 | const struct GNUNET_TESTBED_PeerStartMessage *msg; | ||
1735 | struct GNUNET_TESTBED_PeerEventMessage *reply; | ||
1736 | struct ForwardedOperationContext *fopc; | ||
1737 | struct Peer *peer; | ||
1738 | uint32_t peer_id; | ||
1739 | |||
1740 | msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message; | ||
1741 | peer_id = ntohl (msg->peer_id); | ||
1742 | if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) | ||
1743 | { | ||
1744 | GNUNET_break (0); | ||
1745 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
1746 | "Asked to start a non existent peer with id: %u\n", peer_id); | ||
1747 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1748 | return; | ||
1749 | } | ||
1750 | peer = GST_peer_list[peer_id]; | ||
1751 | if (GNUNET_YES == peer->is_remote) | ||
1752 | { | ||
1753 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
1754 | GNUNET_SERVER_client_keep (client); | ||
1755 | fopc->client = client; | ||
1756 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
1757 | fopc->type = OP_PEER_START; | ||
1758 | fopc->opc = | ||
1759 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1760 | slave->controller, | ||
1761 | fopc->operation_id, &msg->header, | ||
1762 | &GST_forwarded_operation_reply_relay, | ||
1763 | fopc); | ||
1764 | fopc->timeout_task = | ||
1765 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
1766 | fopc); | ||
1767 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
1768 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1769 | return; | ||
1770 | } | ||
1771 | if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) | ||
1772 | { | ||
1773 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
1774 | "Failed to start"); | ||
1775 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1776 | return; | ||
1777 | } | ||
1778 | peer->details.local.is_running = GNUNET_YES; | ||
1779 | reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
1780 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); | ||
1781 | reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
1782 | reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); | ||
1783 | reply->host_id = htonl (GST_context->host_id); | ||
1784 | reply->peer_id = msg->peer_id; | ||
1785 | reply->operation_id = msg->operation_id; | ||
1786 | GST_queue_message (client, &reply->header); | ||
1787 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1788 | } | ||
1789 | |||
1790 | |||
1791 | /** | ||
1792 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
1793 | * | ||
1794 | * @param cls NULL | ||
1795 | * @param client identification of the client | ||
1796 | * @param message the actual message | ||
1797 | */ | ||
1798 | static void | ||
1799 | handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, | ||
1800 | const struct GNUNET_MessageHeader *message) | ||
1801 | { | ||
1802 | const struct GNUNET_TESTBED_PeerStopMessage *msg; | ||
1803 | struct GNUNET_TESTBED_PeerEventMessage *reply; | ||
1804 | struct ForwardedOperationContext *fopc; | ||
1805 | struct Peer *peer; | ||
1806 | uint32_t peer_id; | ||
1807 | |||
1808 | msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message; | ||
1809 | peer_id = ntohl (msg->peer_id); | ||
1810 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id); | ||
1811 | if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) | ||
1812 | { | ||
1813 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
1814 | "Peer not found"); | ||
1815 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1816 | return; | ||
1817 | } | ||
1818 | peer = GST_peer_list[peer_id]; | ||
1819 | if (GNUNET_YES == peer->is_remote) | ||
1820 | { | ||
1821 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarding PEER_STOP for peer %u\n", | ||
1822 | peer_id); | ||
1823 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
1824 | GNUNET_SERVER_client_keep (client); | ||
1825 | fopc->client = client; | ||
1826 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
1827 | fopc->type = OP_PEER_STOP; | ||
1828 | fopc->opc = | ||
1829 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1830 | slave->controller, | ||
1831 | fopc->operation_id, &msg->header, | ||
1832 | &GST_forwarded_operation_reply_relay, | ||
1833 | fopc); | ||
1834 | fopc->timeout_task = | ||
1835 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
1836 | fopc); | ||
1837 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
1838 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1839 | return; | ||
1840 | } | ||
1841 | if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) | ||
1842 | { | ||
1843 | LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id); | ||
1844 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
1845 | "Peer not running"); | ||
1846 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1847 | return; | ||
1848 | } | ||
1849 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id); | ||
1850 | peer->details.local.is_running = GNUNET_NO; | ||
1851 | reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
1852 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); | ||
1853 | reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
1854 | reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); | ||
1855 | reply->host_id = htonl (GST_context->host_id); | ||
1856 | reply->peer_id = msg->peer_id; | ||
1857 | reply->operation_id = msg->operation_id; | ||
1858 | GST_queue_message (client, &reply->header); | ||
1859 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1860 | GNUNET_TESTING_peer_wait (peer->details.local.peer); | ||
1861 | } | ||
1862 | |||
1863 | |||
1864 | /** | ||
1865 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages | ||
1866 | * | ||
1867 | * @param cls NULL | ||
1868 | * @param client identification of the client | ||
1869 | * @param message the actual message | ||
1870 | */ | ||
1871 | static void | ||
1872 | handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, | ||
1873 | const struct GNUNET_MessageHeader *message) | ||
1874 | { | ||
1875 | const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; | ||
1876 | struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; | ||
1877 | struct Peer *peer; | ||
1878 | char *config; | ||
1879 | char *xconfig; | ||
1880 | size_t c_size; | ||
1881 | size_t xc_size; | ||
1882 | uint32_t peer_id; | ||
1883 | uint16_t msize; | ||
1884 | |||
1885 | msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message; | ||
1886 | peer_id = ntohl (msg->peer_id); | ||
1887 | if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) | ||
1888 | { | ||
1889 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
1890 | "Peer not found"); | ||
1891 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1892 | return; | ||
1893 | } | ||
1894 | peer = GST_peer_list[peer_id]; | ||
1895 | if (GNUNET_YES == peer->is_remote) | ||
1896 | { | ||
1897 | struct ForwardedOperationContext *fopc; | ||
1898 | |||
1899 | LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id); | ||
1900 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
1901 | GNUNET_SERVER_client_keep (client); | ||
1902 | fopc->client = client; | ||
1903 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
1904 | fopc->type = OP_PEER_INFO; | ||
1905 | fopc->opc = | ||
1906 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
1907 | slave->controller, | ||
1908 | fopc->operation_id, &msg->header, | ||
1909 | &GST_forwarded_operation_reply_relay, | ||
1910 | fopc); | ||
1911 | fopc->timeout_task = | ||
1912 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
1913 | fopc); | ||
1914 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
1915 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1916 | return; | ||
1917 | } | ||
1918 | LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", peer_id); | ||
1919 | config = | ||
1920 | GNUNET_CONFIGURATION_serialize (GST_peer_list[peer_id]->details.local.cfg, | ||
1921 | &c_size); | ||
1922 | xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig); | ||
1923 | GNUNET_free (config); | ||
1924 | msize = | ||
1925 | xc_size + | ||
1926 | sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage); | ||
1927 | reply = GNUNET_realloc (xconfig, msize); | ||
1928 | (void) memmove (&reply[1], reply, xc_size); | ||
1929 | reply->header.size = htons (msize); | ||
1930 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION); | ||
1931 | reply->peer_id = msg->peer_id; | ||
1932 | reply->operation_id = msg->operation_id; | ||
1933 | GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, | ||
1934 | &reply->peer_identity); | ||
1935 | reply->config_size = htons ((uint16_t) c_size); | ||
1936 | GST_queue_message (client, &reply->header); | ||
1937 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1938 | } | ||
1939 | |||
1940 | |||
1941 | /** | ||
1942 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages | 1320 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG messages |
1943 | * | 1321 | * |
1944 | * @param cls NULL | 1322 | * @param cls NULL |
@@ -1991,286 +1369,12 @@ handle_slave_get_config (void *cls, struct GNUNET_SERVER_Client *client, | |||
1991 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | 1369 | GNUNET_SERVER_receive_done (client, GNUNET_OK); |
1992 | } | 1370 | } |
1993 | 1371 | ||
1994 | struct ManageServiceContext | ||
1995 | { | ||
1996 | |||
1997 | struct ManageServiceContext *next; | ||
1998 | |||
1999 | struct ManageServiceContext *prev; | ||
2000 | |||
2001 | struct GNUNET_ARM_Handle *ah; | ||
2002 | |||
2003 | struct Peer *peer; | ||
2004 | |||
2005 | struct GNUNET_SERVER_Client *client; | ||
2006 | |||
2007 | uint64_t op_id; | ||
2008 | |||
2009 | uint8_t start; | ||
2010 | |||
2011 | uint8_t expired; | ||
2012 | |||
2013 | }; | ||
2014 | |||
2015 | static struct ManageServiceContext *mctx_head; | ||
2016 | |||
2017 | static struct ManageServiceContext *mctx_tail; | ||
2018 | |||
2019 | static void | ||
2020 | cleanup_mctx (struct ManageServiceContext *mctx) | ||
2021 | { | ||
2022 | mctx->expired = GNUNET_YES; | ||
2023 | GNUNET_CONTAINER_DLL_remove (mctx_head, mctx_tail, mctx); | ||
2024 | GNUNET_SERVER_client_drop (mctx->client); | ||
2025 | GNUNET_ARM_disconnect_and_free (mctx->ah); | ||
2026 | GNUNET_assert (0 < mctx->peer->reference_cnt); | ||
2027 | mctx->peer->reference_cnt--; | ||
2028 | if ( (GNUNET_YES == mctx->peer->destroy_flag) | ||
2029 | && (0 == mctx->peer->reference_cnt) ) | ||
2030 | GST_destroy_peer (mctx->peer); | ||
2031 | GNUNET_free (mctx); | ||
2032 | } | ||
2033 | |||
2034 | static void | ||
2035 | free_mctxq () | ||
2036 | { | ||
2037 | while (NULL != mctx_head) | ||
2038 | cleanup_mctx (mctx_head); | ||
2039 | } | ||
2040 | |||
2041 | static const char * | ||
2042 | arm_req_string (enum GNUNET_ARM_RequestStatus rs) | ||
2043 | { | ||
2044 | switch (rs) | ||
2045 | { | ||
2046 | case GNUNET_ARM_REQUEST_SENT_OK: | ||
2047 | return _("Message was sent successfully"); | ||
2048 | case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR: | ||
2049 | return _("Misconfiguration (can't connect to the ARM service)"); | ||
2050 | case GNUNET_ARM_REQUEST_DISCONNECTED: | ||
2051 | return _("We disconnected from ARM before we could send a request"); | ||
2052 | case GNUNET_ARM_REQUEST_BUSY: | ||
2053 | return _("ARM API is busy"); | ||
2054 | case GNUNET_ARM_REQUEST_TOO_LONG: | ||
2055 | return _("Request doesn't fit into a message"); | ||
2056 | case GNUNET_ARM_REQUEST_TIMEOUT: | ||
2057 | return _("Request timed out"); | ||
2058 | } | ||
2059 | return _("Unknown request status"); | ||
2060 | } | ||
2061 | |||
2062 | static const char * | ||
2063 | arm_ret_string (enum GNUNET_ARM_Result result) | ||
2064 | { | ||
2065 | switch (result) | ||
2066 | { | ||
2067 | case GNUNET_ARM_RESULT_STOPPED: | ||
2068 | return _("%s is stopped"); | ||
2069 | case GNUNET_ARM_RESULT_STARTING: | ||
2070 | return _("%s is starting"); | ||
2071 | case GNUNET_ARM_RESULT_STOPPING: | ||
2072 | return _("%s is stopping"); | ||
2073 | case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: | ||
2074 | return _("%s is starting already"); | ||
2075 | case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: | ||
2076 | return _("%s is stopping already"); | ||
2077 | case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: | ||
2078 | return _("%s is started already"); | ||
2079 | case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: | ||
2080 | return _("%s is stopped already"); | ||
2081 | case GNUNET_ARM_RESULT_IS_NOT_KNOWN: | ||
2082 | return _("%s service is not known to ARM"); | ||
2083 | case GNUNET_ARM_RESULT_START_FAILED: | ||
2084 | return _("%s service failed to start"); | ||
2085 | case GNUNET_ARM_RESULT_IN_SHUTDOWN: | ||
2086 | return _("%s service can't be started because ARM is shutting down"); | ||
2087 | } | ||
2088 | return _("%.s Unknown result code."); | ||
2089 | } | ||
2090 | |||
2091 | static void | ||
2092 | service_manage_result_cb (void *cls, struct GNUNET_ARM_Handle *arm, | ||
2093 | enum GNUNET_ARM_RequestStatus rs, | ||
2094 | const char *service, enum GNUNET_ARM_Result result) | ||
2095 | { | ||
2096 | struct ManageServiceContext *mctx = cls; | ||
2097 | char *emsg; | ||
2098 | |||
2099 | emsg = NULL; | ||
2100 | if (GNUNET_YES == mctx->expired) | ||
2101 | return; | ||
2102 | if (GNUNET_ARM_REQUEST_SENT_OK != rs) | ||
2103 | { | ||
2104 | GNUNET_asprintf (&emsg, "Error communicating with Peer %u's ARM: %s", | ||
2105 | mctx->peer->id, arm_req_string (rs)); | ||
2106 | goto ret; | ||
2107 | } | ||
2108 | if (1 == mctx->start) | ||
2109 | goto service_start_check; | ||
2110 | if (! ((GNUNET_ARM_RESULT_STOPPED == result) | ||
2111 | || (GNUNET_ARM_RESULT_STOPPING == result) | ||
2112 | || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result) | ||
2113 | || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) ) | ||
2114 | { | ||
2115 | /* stopping a service failed */ | ||
2116 | GNUNET_asprintf (&emsg, arm_ret_string (result), service); | ||
2117 | goto ret; | ||
2118 | } | ||
2119 | /* service stopped successfully */ | ||
2120 | goto ret; | ||
2121 | |||
2122 | service_start_check: | ||
2123 | if (! ((GNUNET_ARM_RESULT_STARTING == result) | ||
2124 | || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result) | ||
2125 | || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) ) | ||
2126 | { | ||
2127 | /* starting a service failed */ | ||
2128 | GNUNET_asprintf (&emsg, arm_ret_string (result), service); | ||
2129 | goto ret; | ||
2130 | } | ||
2131 | /* service started successfully */ | ||
2132 | |||
2133 | ret: | ||
2134 | if (NULL != emsg) | ||
2135 | { | ||
2136 | LOG_DEBUG ("%s\n", emsg); | ||
2137 | GST_send_operation_fail_msg (mctx->client, mctx->op_id, emsg); | ||
2138 | } | ||
2139 | else | ||
2140 | send_operation_success_msg (mctx->client, mctx->op_id); | ||
2141 | GNUNET_free_non_null (emsg); | ||
2142 | cleanup_mctx (mctx); | ||
2143 | } | ||
2144 | |||
2145 | static void | ||
2146 | handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, | ||
2147 | const struct GNUNET_MessageHeader *message) | ||
2148 | { | ||
2149 | const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; | ||
2150 | const char* service; | ||
2151 | struct Peer *peer; | ||
2152 | char *emsg; | ||
2153 | struct GNUNET_ARM_Handle *ah; | ||
2154 | struct ManageServiceContext *mctx; | ||
2155 | struct ForwardedOperationContext *fopc; | ||
2156 | uint64_t op_id; | ||
2157 | uint32_t peer_id; | ||
2158 | uint16_t msize; | ||
2159 | |||
2160 | |||
2161 | msize = ntohs (message->size); | ||
2162 | if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage)) | ||
2163 | { | ||
2164 | GNUNET_break_op (0); | ||
2165 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
2166 | return; | ||
2167 | } | ||
2168 | msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message; | ||
2169 | service = (const char *) &msg[1]; | ||
2170 | if ('\0' != service[msize - sizeof | ||
2171 | (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) | ||
2172 | { | ||
2173 | GNUNET_break_op (0); | ||
2174 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
2175 | return; | ||
2176 | } | ||
2177 | if (1 < msg->start) | ||
2178 | { | ||
2179 | GNUNET_break_op (0); | ||
2180 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
2181 | return; | ||
2182 | } | ||
2183 | peer_id = ntohl (msg->peer_id); | ||
2184 | op_id = GNUNET_ntohll (msg->operation_id); | ||
2185 | LOG_DEBUG ("Received request to manage service %s on peer %u\n", | ||
2186 | service, (unsigned int) peer_id); | ||
2187 | if ((GST_peer_list_size <= peer_id) | ||
2188 | || (NULL == (peer = GST_peer_list[peer_id]))) | ||
2189 | { | ||
2190 | GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer " | ||
2191 | "with id: %u", peer_id); | ||
2192 | goto err_ret; | ||
2193 | } | ||
2194 | if (0 == strcasecmp ("arm", service)) | ||
2195 | { | ||
2196 | emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service. " | ||
2197 | "Use peer start/stop for that"); | ||
2198 | goto err_ret; | ||
2199 | } | ||
2200 | if (GNUNET_YES == peer->is_remote) | ||
2201 | { | ||
2202 | /* Forward the destory message to sub controller */ | ||
2203 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
2204 | GNUNET_SERVER_client_keep (client); | ||
2205 | fopc->client = client; | ||
2206 | fopc->cls = peer; | ||
2207 | fopc->type = OP_MANAGE_SERVICE; | ||
2208 | fopc->operation_id = op_id; | ||
2209 | fopc->opc = | ||
2210 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
2211 | slave->controller, | ||
2212 | fopc->operation_id, &msg->header, | ||
2213 | &GST_forwarded_operation_reply_relay, | ||
2214 | fopc); | ||
2215 | fopc->timeout_task = | ||
2216 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
2217 | fopc); | ||
2218 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
2219 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
2220 | return; | ||
2221 | } | ||
2222 | if ((0 != peer->reference_cnt) | ||
2223 | && ( (0 == strcasecmp ("core", service)) | ||
2224 | || (0 == strcasecmp ("transport", service)) ) ) | ||
2225 | { | ||
2226 | GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u " | ||
2227 | "since it is required by existing operations", | ||
2228 | service, peer_id); | ||
2229 | goto err_ret; | ||
2230 | } | ||
2231 | ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL); | ||
2232 | if (NULL == ah) | ||
2233 | { | ||
2234 | GNUNET_asprintf (&emsg, | ||
2235 | "Cannot connect to ARM service of peer with id: %u", | ||
2236 | peer_id); | ||
2237 | goto err_ret; | ||
2238 | } | ||
2239 | mctx = GNUNET_malloc (sizeof (struct ManageServiceContext)); | ||
2240 | mctx->peer = peer; | ||
2241 | peer->reference_cnt++; | ||
2242 | mctx->op_id = op_id; | ||
2243 | mctx->ah = ah; | ||
2244 | GNUNET_SERVER_client_keep (client); | ||
2245 | mctx->client = client; | ||
2246 | mctx->start = msg->start; | ||
2247 | GNUNET_CONTAINER_DLL_insert_tail (mctx_head, mctx_tail, mctx); | ||
2248 | if (1 == mctx->start) | ||
2249 | GNUNET_ARM_request_service_start (mctx->ah, service, | ||
2250 | GNUNET_OS_INHERIT_STD_ERR, | ||
2251 | GST_timeout, | ||
2252 | service_manage_result_cb, | ||
2253 | mctx); | ||
2254 | else | ||
2255 | GNUNET_ARM_request_service_stop (mctx->ah, service, | ||
2256 | GST_timeout, | ||
2257 | service_manage_result_cb, | ||
2258 | mctx); | ||
2259 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
2260 | return; | ||
2261 | |||
2262 | err_ret: | ||
2263 | LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
2264 | GST_send_operation_fail_msg (client, op_id, emsg); | ||
2265 | GNUNET_free (emsg); | ||
2266 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
2267 | } | ||
2268 | 1372 | ||
2269 | /** | 1373 | /** |
2270 | * Clears the forwarded operations queue | 1374 | * Clears the forwarded operations queue |
2271 | */ | 1375 | */ |
2272 | static void | 1376 | void |
2273 | clear_fopcq () | 1377 | GST_clear_fopcq () |
2274 | { | 1378 | { |
2275 | struct ForwardedOperationContext *fopc; | 1379 | struct ForwardedOperationContext *fopc; |
2276 | 1380 | ||
@@ -2314,184 +1418,6 @@ clear_fopcq () | |||
2314 | 1418 | ||
2315 | 1419 | ||
2316 | /** | 1420 | /** |
2317 | * Task run upon timeout of forwarded SHUTDOWN_PEERS operation | ||
2318 | * | ||
2319 | * @param cls the ForwardedOperationContext | ||
2320 | * @param tc the scheduler task context | ||
2321 | */ | ||
2322 | static void | ||
2323 | shutdown_peers_timeout_cb (void *cls, | ||
2324 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
2325 | { | ||
2326 | struct ForwardedOperationContext *fo_ctxt = cls; | ||
2327 | struct HandlerContext_ShutdownPeers *hc; | ||
2328 | |||
2329 | fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
2330 | hc = fo_ctxt->cls; | ||
2331 | hc->timeout = GNUNET_YES; | ||
2332 | GNUNET_assert (0 < hc->nslaves); | ||
2333 | hc->nslaves--; | ||
2334 | if (0 == hc->nslaves) | ||
2335 | GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, | ||
2336 | "Timeout at a slave controller"); | ||
2337 | GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc); | ||
2338 | GNUNET_SERVER_client_drop (fo_ctxt->client); | ||
2339 | GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); | ||
2340 | GNUNET_free (fo_ctxt); | ||
2341 | } | ||
2342 | |||
2343 | |||
2344 | /** | ||
2345 | * The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a | ||
2346 | * success reply is received from all clients and then sends the success message | ||
2347 | * to the client | ||
2348 | * | ||
2349 | * @param cls ForwardedOperationContext | ||
2350 | * @param msg the message to relay | ||
2351 | */ | ||
2352 | static void | ||
2353 | shutdown_peers_reply_cb (void *cls, | ||
2354 | const struct GNUNET_MessageHeader *msg) | ||
2355 | { | ||
2356 | struct ForwardedOperationContext *fo_ctxt = cls; | ||
2357 | struct HandlerContext_ShutdownPeers *hc; | ||
2358 | |||
2359 | hc = fo_ctxt->cls; | ||
2360 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != fo_ctxt->timeout_task); | ||
2361 | GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task); | ||
2362 | fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
2363 | GNUNET_assert (0 < hc->nslaves); | ||
2364 | hc->nslaves--; | ||
2365 | if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != | ||
2366 | ntohs (msg->type)) | ||
2367 | hc->timeout = GNUNET_YES; | ||
2368 | if (0 == hc->nslaves) | ||
2369 | { | ||
2370 | if (GNUNET_YES == hc->timeout) | ||
2371 | GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, | ||
2372 | "Timeout at a slave controller"); | ||
2373 | else | ||
2374 | send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id); | ||
2375 | } | ||
2376 | GNUNET_SERVER_client_drop (fo_ctxt->client); | ||
2377 | GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); | ||
2378 | GNUNET_free (fo_ctxt); | ||
2379 | } | ||
2380 | |||
2381 | |||
2382 | /** | ||
2383 | * Stops and destroys all peers | ||
2384 | */ | ||
2385 | static void | ||
2386 | destroy_peers () | ||
2387 | { | ||
2388 | struct Peer *peer; | ||
2389 | unsigned int id; | ||
2390 | |||
2391 | if (NULL == GST_peer_list) | ||
2392 | return; | ||
2393 | for (id = 0; id < GST_peer_list_size; id++) | ||
2394 | { | ||
2395 | peer = GST_peer_list[id]; | ||
2396 | if (NULL == peer) | ||
2397 | continue; | ||
2398 | /* If destroy flag is set it means that this peer should have been | ||
2399 | * destroyed by a context which we destroy before */ | ||
2400 | GNUNET_break (GNUNET_NO == peer->destroy_flag); | ||
2401 | /* counter should be zero as we free all contexts before */ | ||
2402 | GNUNET_break (0 == peer->reference_cnt); | ||
2403 | if ((GNUNET_NO == peer->is_remote) && | ||
2404 | (GNUNET_YES == peer->details.local.is_running)) | ||
2405 | GNUNET_TESTING_peer_kill (peer->details.local.peer); | ||
2406 | } | ||
2407 | for (id = 0; id < GST_peer_list_size; id++) | ||
2408 | { | ||
2409 | peer = GST_peer_list[id]; | ||
2410 | if (NULL == peer) | ||
2411 | continue; | ||
2412 | if (GNUNET_NO == peer->is_remote) | ||
2413 | { | ||
2414 | if (GNUNET_YES == peer->details.local.is_running) | ||
2415 | GNUNET_TESTING_peer_wait (peer->details.local.peer); | ||
2416 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
2417 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
2418 | } | ||
2419 | GNUNET_free (peer); | ||
2420 | } | ||
2421 | GNUNET_free_non_null (GST_peer_list); | ||
2422 | GST_peer_list = NULL; | ||
2423 | GST_peer_list_size = 0; | ||
2424 | } | ||
2425 | |||
2426 | |||
2427 | /** | ||
2428 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages | ||
2429 | * | ||
2430 | * @param cls NULL | ||
2431 | * @param client identification of the client | ||
2432 | * @param message the actual message | ||
2433 | */ | ||
2434 | static void | ||
2435 | handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, | ||
2436 | const struct GNUNET_MessageHeader *message) | ||
2437 | { | ||
2438 | const struct GNUNET_TESTBED_ShutdownPeersMessage *msg; | ||
2439 | struct HandlerContext_ShutdownPeers *hc; | ||
2440 | struct Slave *slave; | ||
2441 | struct ForwardedOperationContext *fo_ctxt; | ||
2442 | uint64_t op_id; | ||
2443 | unsigned int cnt; | ||
2444 | |||
2445 | msg = (const struct GNUNET_TESTBED_ShutdownPeersMessage *) message; | ||
2446 | LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); | ||
2447 | /* Stop and destroy all peers */ | ||
2448 | free_mctxq (); | ||
2449 | GST_free_occq (); | ||
2450 | GST_free_roccq (); | ||
2451 | clear_fopcq (); | ||
2452 | /* Forward to all slaves which we have started */ | ||
2453 | op_id = GNUNET_ntohll (msg->operation_id); | ||
2454 | hc = GNUNET_malloc (sizeof (struct HandlerContext_ShutdownPeers)); | ||
2455 | /* FIXME: have a better implementation where we track which slaves are | ||
2456 | started by this controller */ | ||
2457 | for (cnt = 0; cnt < GST_slave_list_size; cnt++) | ||
2458 | { | ||
2459 | slave = GST_slave_list[cnt]; | ||
2460 | if (NULL == slave) | ||
2461 | continue; | ||
2462 | if (NULL == slave->controller_proc) /* We didn't start the slave */ | ||
2463 | continue; | ||
2464 | LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); | ||
2465 | hc->nslaves++; | ||
2466 | fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
2467 | GNUNET_SERVER_client_keep (client); | ||
2468 | fo_ctxt->client = client; | ||
2469 | fo_ctxt->operation_id = op_id; | ||
2470 | fo_ctxt->cls = hc; | ||
2471 | fo_ctxt->type = OP_SHUTDOWN_PEERS; | ||
2472 | fo_ctxt->opc = | ||
2473 | GNUNET_TESTBED_forward_operation_msg_ (slave->controller, | ||
2474 | fo_ctxt->operation_id, | ||
2475 | &msg->header, | ||
2476 | shutdown_peers_reply_cb, | ||
2477 | fo_ctxt); | ||
2478 | fo_ctxt->timeout_task = | ||
2479 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &shutdown_peers_timeout_cb, | ||
2480 | fo_ctxt); | ||
2481 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); | ||
2482 | } | ||
2483 | LOG_DEBUG ("Shutting down peers\n"); | ||
2484 | destroy_peers (); | ||
2485 | if (0 == hc->nslaves) | ||
2486 | { | ||
2487 | send_operation_success_msg (client, op_id); | ||
2488 | GNUNET_free (hc); | ||
2489 | } | ||
2490 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
2491 | } | ||
2492 | |||
2493 | |||
2494 | /** | ||
2495 | * Iterator over hash map entries. | 1421 | * Iterator over hash map entries. |
2496 | * | 1422 | * |
2497 | * @param cls closure | 1423 | * @param cls closure |
@@ -2568,7 +1494,7 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
2568 | NULL); | 1494 | NULL); |
2569 | GNUNET_CONTAINER_multihashmap_destroy (ss_map); | 1495 | GNUNET_CONTAINER_multihashmap_destroy (ss_map); |
2570 | /* cleanup any remaining forwarded operations */ | 1496 | /* cleanup any remaining forwarded operations */ |
2571 | clear_fopcq (); | 1497 | GST_clear_fopcq (); |
2572 | if (NULL != lcfq_head) | 1498 | if (NULL != lcfq_head) |
2573 | { | 1499 | { |
2574 | if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id) | 1500 | if (GNUNET_SCHEDULER_NO_TASK != lcf_proc_task_id) |
@@ -2587,11 +1513,11 @@ shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) | |||
2587 | GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); | 1513 | GNUNET_CONTAINER_DLL_remove (lcfq_head, lcfq_tail, lcfq); |
2588 | GNUNET_free (lcfq); | 1514 | GNUNET_free (lcfq); |
2589 | } | 1515 | } |
2590 | free_mctxq (); | 1516 | GST_free_mctxq (); |
2591 | GST_free_occq (); | 1517 | GST_free_occq (); |
2592 | GST_free_roccq (); | 1518 | GST_free_roccq (); |
2593 | /* Clear peer list */ | 1519 | /* Clear peer list */ |
2594 | destroy_peers (); | 1520 | GST_destroy_peers (); |
2595 | /* Clear host list */ | 1521 | /* Clear host list */ |
2596 | for (id = 0; id < GST_host_list_size; id++) | 1522 | for (id = 0; id < GST_host_list_size; id++) |
2597 | if (NULL != GST_host_list[id]) | 1523 | if (NULL != GST_host_list[id]) |
@@ -2699,14 +1625,14 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
2699 | GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0}, | 1625 | GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE, 0}, |
2700 | {&handle_link_controllers, NULL, | 1626 | {&handle_link_controllers, NULL, |
2701 | GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 0}, | 1627 | GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS, 0}, |
2702 | {&handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0}, | 1628 | {&GST_handle_peer_create, NULL, GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER, 0}, |
2703 | {&handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, | 1629 | {&GST_handle_peer_destroy, NULL, GNUNET_MESSAGE_TYPE_TESTBED_DESTROY_PEER, |
2704 | sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)}, | 1630 | sizeof (struct GNUNET_TESTBED_PeerDestroyMessage)}, |
2705 | {&handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, | 1631 | {&GST_handle_peer_start, NULL, GNUNET_MESSAGE_TYPE_TESTBED_START_PEER, |
2706 | sizeof (struct GNUNET_TESTBED_PeerStartMessage)}, | 1632 | sizeof (struct GNUNET_TESTBED_PeerStartMessage)}, |
2707 | {&handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, | 1633 | {&GST_handle_peer_stop, NULL, GNUNET_MESSAGE_TYPE_TESTBED_STOP_PEER, |
2708 | sizeof (struct GNUNET_TESTBED_PeerStopMessage)}, | 1634 | sizeof (struct GNUNET_TESTBED_PeerStopMessage)}, |
2709 | {&handle_peer_get_config, NULL, | 1635 | {&GST_handle_peer_get_config, NULL, |
2710 | GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION, | 1636 | GNUNET_MESSAGE_TYPE_TESTBED_GET_PEER_CONFIGURATION, |
2711 | sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, | 1637 | sizeof (struct GNUNET_TESTBED_PeerGetConfigurationMessage)}, |
2712 | {&GST_handle_overlay_connect, NULL, | 1638 | {&GST_handle_overlay_connect, NULL, |
@@ -2714,12 +1640,12 @@ testbed_run (void *cls, struct GNUNET_SERVER_Handle *server, | |||
2714 | sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)}, | 1640 | sizeof (struct GNUNET_TESTBED_OverlayConnectMessage)}, |
2715 | {&GST_handle_remote_overlay_connect, NULL, | 1641 | {&GST_handle_remote_overlay_connect, NULL, |
2716 | GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0}, | 1642 | GNUNET_MESSAGE_TYPE_TESTBED_REMOTE_OVERLAY_CONNECT, 0}, |
2717 | {&handle_manage_peer_service, NULL, | 1643 | {&GST_handle_manage_peer_service, NULL, |
2718 | GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0}, | 1644 | GNUNET_MESSAGE_TYPE_TESTBED_MANAGE_PEER_SERVICE, 0}, |
2719 | {&handle_slave_get_config, NULL, | 1645 | {&handle_slave_get_config, NULL, |
2720 | GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, | 1646 | GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION, |
2721 | sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)}, | 1647 | sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage)}, |
2722 | {&handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, | 1648 | {&GST_handle_shutdown_peers, NULL, GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS, |
2723 | sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)}, | 1649 | sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage)}, |
2724 | {NULL} | 1650 | {NULL} |
2725 | }; | 1651 | }; |
diff --git a/src/testbed/gnunet-service-testbed.h b/src/testbed/gnunet-service-testbed.h index 700bbfcd8..aa3ab0b83 100644 --- a/src/testbed/gnunet-service-testbed.h +++ b/src/testbed/gnunet-service-testbed.h | |||
@@ -600,6 +600,25 @@ struct LCFContextQueue | |||
600 | 600 | ||
601 | 601 | ||
602 | /** | 602 | /** |
603 | * Context data for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS handler | ||
604 | */ | ||
605 | struct HandlerContext_ShutdownPeers | ||
606 | { | ||
607 | /** | ||
608 | * The number of slave we expect to hear from since we forwarded the | ||
609 | * GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS message to them | ||
610 | */ | ||
611 | unsigned int nslaves; | ||
612 | |||
613 | /** | ||
614 | * Did we observe a timeout with respect to this operation at any of the | ||
615 | * slaves | ||
616 | */ | ||
617 | int timeout; | ||
618 | }; | ||
619 | |||
620 | |||
621 | /** | ||
603 | * Our configuration | 622 | * Our configuration |
604 | */ | 623 | */ |
605 | struct GNUNET_CONFIGURATION_Handle *our_config; | 624 | struct GNUNET_CONFIGURATION_Handle *our_config; |
@@ -666,6 +685,30 @@ extern char *GST_stats_dir; | |||
666 | 685 | ||
667 | 686 | ||
668 | /** | 687 | /** |
688 | * Similar to GNUNET_array_grow(); however instead of calling GNUNET_array_grow() | ||
689 | * several times we call it only once. The array is also made to grow in steps | ||
690 | * of LIST_GROW_STEP. | ||
691 | * | ||
692 | * @param ptr the array pointer to grow | ||
693 | * @param size the size of array | ||
694 | * @param accommodate_size the size which the array has to accommdate; after | ||
695 | * this call the array will be big enough to accommdate sizes upto | ||
696 | * accommodate_size | ||
697 | */ | ||
698 | #define GST_array_grow_large_enough(ptr, size, accommodate_size) \ | ||
699 | do \ | ||
700 | { \ | ||
701 | unsigned int growth_size; \ | ||
702 | GNUNET_assert (size <= accommodate_size); \ | ||
703 | growth_size = size; \ | ||
704 | while (growth_size <= accommodate_size) \ | ||
705 | growth_size += LIST_GROW_STEP; \ | ||
706 | GNUNET_array_grow (ptr, size, growth_size); \ | ||
707 | GNUNET_assert (size > accommodate_size); \ | ||
708 | } while (0) | ||
709 | |||
710 | |||
711 | /** | ||
669 | * Queues a message in send queue for sending to the service | 712 | * Queues a message in send queue for sending to the service |
670 | * | 713 | * |
671 | * @param client the client to whom the queued message has to be sent | 714 | * @param client the client to whom the queued message has to be sent |
@@ -686,6 +729,13 @@ GST_destroy_peer (struct Peer *peer); | |||
686 | 729 | ||
687 | 730 | ||
688 | /** | 731 | /** |
732 | * Stops and destroys all peers | ||
733 | */ | ||
734 | void | ||
735 | GST_destroy_peers (); | ||
736 | |||
737 | |||
738 | /** | ||
689 | * Finds the route with directly connected host as destination through which | 739 | * Finds the route with directly connected host as destination through which |
690 | * the destination host can be reached | 740 | * the destination host can be reached |
691 | * | 741 | * |
@@ -747,6 +797,13 @@ GST_forwarded_operation_timeout (void *cls, | |||
747 | 797 | ||
748 | 798 | ||
749 | /** | 799 | /** |
800 | * Clears the forwarded operations queue | ||
801 | */ | ||
802 | void | ||
803 | GST_clear_fopcq (); | ||
804 | |||
805 | |||
806 | /** | ||
750 | * Send operation failure message to client | 807 | * Send operation failure message to client |
751 | * | 808 | * |
752 | * @param client the client to which the failure message has to be sent to | 809 | * @param client the client to which the failure message has to be sent to |
@@ -759,6 +816,17 @@ GST_send_operation_fail_msg (struct GNUNET_SERVER_Client *client, | |||
759 | 816 | ||
760 | 817 | ||
761 | /** | 818 | /** |
819 | * Function to send generic operation success message to given client | ||
820 | * | ||
821 | * @param client the client to send the message to | ||
822 | * @param operation_id the id of the operation which was successful | ||
823 | */ | ||
824 | void | ||
825 | GST_send_operation_success_msg (struct GNUNET_SERVER_Client *client, | ||
826 | uint64_t operation_id); | ||
827 | |||
828 | |||
829 | /** | ||
762 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages | 830 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_REQUESTCONNECT messages |
763 | * | 831 | * |
764 | * @param cls NULL | 832 | * @param cls NULL |
@@ -772,6 +840,97 @@ GST_handle_remote_overlay_connect (void *cls, | |||
772 | 840 | ||
773 | 841 | ||
774 | /** | 842 | /** |
843 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
844 | * | ||
845 | * @param cls NULL | ||
846 | * @param client identification of the client | ||
847 | * @param message the actual message | ||
848 | */ | ||
849 | void | ||
850 | GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, | ||
851 | const struct GNUNET_MessageHeader *message); | ||
852 | |||
853 | |||
854 | /** | ||
855 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
856 | * | ||
857 | * @param cls NULL | ||
858 | * @param client identification of the client | ||
859 | * @param message the actual message | ||
860 | */ | ||
861 | void | ||
862 | GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, | ||
863 | const struct GNUNET_MessageHeader *message); | ||
864 | |||
865 | |||
866 | /** | ||
867 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
868 | * | ||
869 | * @param cls NULL | ||
870 | * @param client identification of the client | ||
871 | * @param message the actual message | ||
872 | */ | ||
873 | void | ||
874 | GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, | ||
875 | const struct GNUNET_MessageHeader *message); | ||
876 | |||
877 | |||
878 | /** | ||
879 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
880 | * | ||
881 | * @param cls NULL | ||
882 | * @param client identification of the client | ||
883 | * @param message the actual message | ||
884 | */ | ||
885 | void | ||
886 | GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, | ||
887 | const struct GNUNET_MessageHeader *message); | ||
888 | |||
889 | |||
890 | /** | ||
891 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages | ||
892 | * | ||
893 | * @param cls NULL | ||
894 | * @param client identification of the client | ||
895 | * @param message the actual message | ||
896 | */ | ||
897 | void | ||
898 | GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, | ||
899 | const struct GNUNET_MessageHeader *message); | ||
900 | |||
901 | |||
902 | /** | ||
903 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages | ||
904 | * | ||
905 | * @param cls NULL | ||
906 | * @param client identification of the client | ||
907 | * @param message the actual message | ||
908 | */ | ||
909 | void | ||
910 | GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, | ||
911 | const struct GNUNET_MessageHeader *message); | ||
912 | |||
913 | |||
914 | /** | ||
915 | * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message | ||
916 | * | ||
917 | * @param cls NULL | ||
918 | * @param client identification of client | ||
919 | * @param message the actual message | ||
920 | */ | ||
921 | void | ||
922 | GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, | ||
923 | const struct GNUNET_MessageHeader *message); | ||
924 | |||
925 | |||
926 | /** | ||
927 | * Frees the ManageServiceContext queue | ||
928 | */ | ||
929 | void | ||
930 | GST_free_mctxq (); | ||
931 | |||
932 | |||
933 | /** | ||
775 | * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext | 934 | * Processes a forwarded overlay connect context in the queue of the given RegisteredHostContext |
776 | * | 935 | * |
777 | * @param rhc the RegisteredHostContext | 936 | * @param rhc the RegisteredHostContext |
diff --git a/src/testbed/gnunet-service-testbed_oc.c b/src/testbed/gnunet-service-testbed_oc.c index 7fdf14586..3199d71af 100644 --- a/src/testbed/gnunet-service-testbed_oc.c +++ b/src/testbed/gnunet-service-testbed_oc.c | |||
@@ -942,7 +942,6 @@ occ_cache_get_handle_core_cb (void *cls, struct GNUNET_CORE_Handle *ch, | |||
942 | occ->peer->details.local.cfg, | 942 | occ->peer->details.local.cfg, |
943 | p1_transport_connect_cache_callback, occ, | 943 | p1_transport_connect_cache_callback, occ, |
944 | NULL, NULL, NULL); | 944 | NULL, NULL, NULL); |
945 | return; | ||
946 | } | 945 | } |
947 | 946 | ||
948 | 947 | ||
@@ -998,13 +997,12 @@ registeredhost_registration_completion (void *cls, const char *emsg) | |||
998 | const struct GNUNET_CONFIGURATION_Handle *cfg; | 997 | const struct GNUNET_CONFIGURATION_Handle *cfg; |
999 | uint32_t peer2_host_id; | 998 | uint32_t peer2_host_id; |
1000 | 999 | ||
1001 | /* if (NULL != rhc->focc_dll_head) */ | ||
1002 | /* TESTBED_process_next_focc (rhc); */ | ||
1003 | peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host); | 1000 | peer2_host_id = GNUNET_TESTBED_host_get_id_ (rhc->reg_host); |
1004 | GNUNET_assert (RHC_INIT == rhc->state); | 1001 | GNUNET_assert (RHC_INIT == rhc->state); |
1005 | GNUNET_assert (NULL == rhc->sub_op); | 1002 | GNUNET_assert (NULL == rhc->sub_op); |
1006 | if ((NULL == rhc->gateway2) || ((peer2_host_id < GST_host_list_size) /* Check if we have the needed config */ | 1003 | if ((NULL == rhc->gateway2) || |
1007 | && (NULL != GST_host_list[peer2_host_id]))) | 1004 | ( (peer2_host_id < GST_host_list_size) /* Check if we have the needed config */ |
1005 | && (NULL != GST_host_list[peer2_host_id]) ) ) | ||
1008 | { | 1006 | { |
1009 | rhc->state = RHC_LINK; | 1007 | rhc->state = RHC_LINK; |
1010 | cfg = | 1008 | cfg = |
@@ -1233,6 +1231,7 @@ GST_handle_overlay_connect (void *cls, struct GNUNET_SERVER_Client *client, | |||
1233 | if ((peer2_host_id >= GST_slave_list_size) || | 1231 | if ((peer2_host_id >= GST_slave_list_size) || |
1234 | (NULL == GST_slave_list[peer2_host_id])) | 1232 | (NULL == GST_slave_list[peer2_host_id])) |
1235 | { | 1233 | { |
1234 | GNUNET_break (0); | ||
1236 | LOG (GNUNET_ERROR_TYPE_WARNING, | 1235 | LOG (GNUNET_ERROR_TYPE_WARNING, |
1237 | "0x%llx: Configuration of peer2's controller missing for connecting peers" | 1236 | "0x%llx: Configuration of peer2's controller missing for connecting peers" |
1238 | "%u and %u\n", operation_id, p1, p2); | 1237 | "%u and %u\n", operation_id, p1, p2); |
diff --git a/src/testbed/gnunet-service-testbed_peers.c b/src/testbed/gnunet-service-testbed_peers.c new file mode 100644 index 000000000..65cfe342c --- /dev/null +++ b/src/testbed/gnunet-service-testbed_peers.c | |||
@@ -0,0 +1,1138 @@ | |||
1 | /* | ||
2 | This file is part of GNUnet. | ||
3 | (C) 2008--2013 Christian Grothoff (and other contributing authors) | ||
4 | |||
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 | ||
7 | by the Free Software Foundation; either version 2, or (at your | ||
8 | option) any later version. | ||
9 | |||
10 | GNUnet is distributed in the hope that it will be useful, but | ||
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | General Public License for more details. | ||
14 | |||
15 | You should have received a copy of the GNU General Public License | ||
16 | along with GNUnet; see the file COPYING. If not, write to the | ||
17 | Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
18 | Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | |||
22 | /** | ||
23 | * @file testbed/gnunet-service-testbed_peers.c | ||
24 | * @brief implementation of TESTBED service that deals with peer management | ||
25 | * @author Sree Harsha Totakura <sreeharsha@totakura.in> | ||
26 | */ | ||
27 | |||
28 | #include "gnunet-service-testbed.h" | ||
29 | #include "gnunet_arm_service.h" | ||
30 | #include <zlib.h> | ||
31 | |||
32 | |||
33 | /** | ||
34 | * A list of peers we know about | ||
35 | */ | ||
36 | struct Peer **GST_peer_list; | ||
37 | |||
38 | |||
39 | /** | ||
40 | * Context information to manage peers' services | ||
41 | */ | ||
42 | struct ManageServiceContext | ||
43 | { | ||
44 | /** | ||
45 | * DLL next ptr | ||
46 | */ | ||
47 | struct ManageServiceContext *next; | ||
48 | |||
49 | /** | ||
50 | * DLL prev ptr | ||
51 | */ | ||
52 | struct ManageServiceContext *prev; | ||
53 | |||
54 | /** | ||
55 | * The ARM handle of the peer | ||
56 | */ | ||
57 | struct GNUNET_ARM_Handle *ah; | ||
58 | |||
59 | /** | ||
60 | * peer whose service has to be managed | ||
61 | */ | ||
62 | struct Peer *peer; | ||
63 | |||
64 | /** | ||
65 | * The client which requested to manage the peer's service | ||
66 | */ | ||
67 | struct GNUNET_SERVER_Client *client; | ||
68 | |||
69 | /** | ||
70 | * The operation id of the associated request | ||
71 | */ | ||
72 | uint64_t op_id; | ||
73 | |||
74 | /** | ||
75 | * 1 if the service at the peer has to be started; 0 if it has to be stopped | ||
76 | */ | ||
77 | uint8_t start; | ||
78 | |||
79 | /** | ||
80 | * Is this context expired? Do not work on this context if it is set to | ||
81 | * GNUNET_YES | ||
82 | */ | ||
83 | uint8_t expired; | ||
84 | }; | ||
85 | |||
86 | |||
87 | /** | ||
88 | * DLL head for queue of manage service requests | ||
89 | */ | ||
90 | static struct ManageServiceContext *mctx_head; | ||
91 | |||
92 | /** | ||
93 | * DLL tail for queue of manage service requests | ||
94 | */ | ||
95 | static struct ManageServiceContext *mctx_tail; | ||
96 | |||
97 | |||
98 | /** | ||
99 | * Adds a peer to the peer array | ||
100 | * | ||
101 | * @param peer the peer to add | ||
102 | */ | ||
103 | static void | ||
104 | peer_list_add (struct Peer *peer) | ||
105 | { | ||
106 | if (peer->id >= GST_peer_list_size) | ||
107 | GST_array_grow_large_enough (GST_peer_list, GST_peer_list_size, peer->id); | ||
108 | GNUNET_assert (NULL == GST_peer_list[peer->id]); | ||
109 | GST_peer_list[peer->id] = peer; | ||
110 | } | ||
111 | |||
112 | |||
113 | /** | ||
114 | * Removes a the give peer from the peer array | ||
115 | * | ||
116 | * @param peer the peer to be removed | ||
117 | */ | ||
118 | static void | ||
119 | peer_list_remove (struct Peer *peer) | ||
120 | { | ||
121 | unsigned int orig_size; | ||
122 | uint32_t id; | ||
123 | |||
124 | GST_peer_list[peer->id] = NULL; | ||
125 | orig_size = GST_peer_list_size; | ||
126 | while (GST_peer_list_size >= LIST_GROW_STEP) | ||
127 | { | ||
128 | for (id = GST_peer_list_size - 1; | ||
129 | (id >= GST_peer_list_size - LIST_GROW_STEP) && (id != UINT32_MAX); | ||
130 | id--) | ||
131 | if (NULL != GST_peer_list[id]) | ||
132 | break; | ||
133 | if (id != ((GST_peer_list_size - LIST_GROW_STEP) - 1)) | ||
134 | break; | ||
135 | GST_peer_list_size -= LIST_GROW_STEP; | ||
136 | } | ||
137 | if (orig_size == GST_peer_list_size) | ||
138 | return; | ||
139 | GST_peer_list = | ||
140 | GNUNET_realloc (GST_peer_list, | ||
141 | sizeof (struct Peer *) * GST_peer_list_size); | ||
142 | } | ||
143 | |||
144 | |||
145 | /** | ||
146 | * The task to be executed if the forwarded peer create operation has been | ||
147 | * timed out | ||
148 | * | ||
149 | * @param cls the FowardedOperationContext | ||
150 | * @param tc the TaskContext from the scheduler | ||
151 | */ | ||
152 | static void | ||
153 | peer_create_forward_timeout (void *cls, | ||
154 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
155 | { | ||
156 | struct ForwardedOperationContext *fopc = cls; | ||
157 | |||
158 | GNUNET_free (fopc->cls); | ||
159 | GST_forwarded_operation_timeout (fopc, tc); | ||
160 | } | ||
161 | |||
162 | |||
163 | /** | ||
164 | * Callback to be called when forwarded peer create operation is successfull. We | ||
165 | * have to relay the reply msg back to the client | ||
166 | * | ||
167 | * @param cls ForwardedOperationContext | ||
168 | * @param msg the peer create success message | ||
169 | */ | ||
170 | static void | ||
171 | peer_create_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) | ||
172 | { | ||
173 | struct ForwardedOperationContext *fopc = cls; | ||
174 | struct Peer *remote_peer; | ||
175 | |||
176 | if (ntohs (msg->type) == GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS) | ||
177 | { | ||
178 | GNUNET_assert (NULL != fopc->cls); | ||
179 | remote_peer = fopc->cls; | ||
180 | peer_list_add (remote_peer); | ||
181 | } | ||
182 | GST_forwarded_operation_reply_relay (fopc, msg); | ||
183 | } | ||
184 | |||
185 | |||
186 | /** | ||
187 | * Function to destroy a peer | ||
188 | * | ||
189 | * @param peer the peer structure to destroy | ||
190 | */ | ||
191 | void | ||
192 | GST_destroy_peer (struct Peer *peer) | ||
193 | { | ||
194 | GNUNET_break (0 == peer->reference_cnt); | ||
195 | if (GNUNET_YES == peer->is_remote) | ||
196 | { | ||
197 | peer_list_remove (peer); | ||
198 | GNUNET_free (peer); | ||
199 | return; | ||
200 | } | ||
201 | if (GNUNET_YES == peer->details.local.is_running) | ||
202 | { | ||
203 | GNUNET_TESTING_peer_stop (peer->details.local.peer); | ||
204 | peer->details.local.is_running = GNUNET_NO; | ||
205 | } | ||
206 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
207 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
208 | peer_list_remove (peer); | ||
209 | GNUNET_free (peer); | ||
210 | } | ||
211 | |||
212 | |||
213 | /** | ||
214 | * Callback to be called when forwarded peer destroy operation is successfull. We | ||
215 | * have to relay the reply msg back to the client | ||
216 | * | ||
217 | * @param cls ForwardedOperationContext | ||
218 | * @param msg the peer create success message | ||
219 | */ | ||
220 | static void | ||
221 | peer_destroy_success_cb (void *cls, const struct GNUNET_MessageHeader *msg) | ||
222 | { | ||
223 | struct ForwardedOperationContext *fopc = cls; | ||
224 | struct Peer *remote_peer; | ||
225 | |||
226 | if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS == | ||
227 | ntohs (msg->type)) | ||
228 | { | ||
229 | remote_peer = fopc->cls; | ||
230 | GNUNET_assert (NULL != remote_peer); | ||
231 | remote_peer->destroy_flag = GNUNET_YES; | ||
232 | if (0 == remote_peer->reference_cnt) | ||
233 | GST_destroy_peer (remote_peer); | ||
234 | } | ||
235 | GST_forwarded_operation_reply_relay (fopc, msg); | ||
236 | } | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_CREATEPEER messages | ||
241 | * | ||
242 | * @param cls NULL | ||
243 | * @param client identification of the client | ||
244 | * @param message the actual message | ||
245 | */ | ||
246 | void | ||
247 | GST_handle_peer_create (void *cls, struct GNUNET_SERVER_Client *client, | ||
248 | const struct GNUNET_MessageHeader *message) | ||
249 | { | ||
250 | const struct GNUNET_TESTBED_PeerCreateMessage *msg; | ||
251 | struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *reply; | ||
252 | struct GNUNET_CONFIGURATION_Handle *cfg; | ||
253 | struct ForwardedOperationContext *fo_ctxt; | ||
254 | struct Route *route; | ||
255 | struct Peer *peer; | ||
256 | char *config; | ||
257 | size_t dest_size; | ||
258 | int ret; | ||
259 | uint32_t config_size; | ||
260 | uint32_t host_id; | ||
261 | uint32_t peer_id; | ||
262 | uint16_t msize; | ||
263 | |||
264 | |||
265 | msize = ntohs (message->size); | ||
266 | if (msize <= sizeof (struct GNUNET_TESTBED_PeerCreateMessage)) | ||
267 | { | ||
268 | GNUNET_break (0); /* We need configuration */ | ||
269 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
270 | return; | ||
271 | } | ||
272 | msg = (const struct GNUNET_TESTBED_PeerCreateMessage *) message; | ||
273 | host_id = ntohl (msg->host_id); | ||
274 | peer_id = ntohl (msg->peer_id); | ||
275 | if (UINT32_MAX == peer_id) | ||
276 | { | ||
277 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
278 | "Cannot create peer with given ID"); | ||
279 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
280 | return; | ||
281 | } | ||
282 | if (host_id == GST_context->host_id) | ||
283 | { | ||
284 | char *emsg; | ||
285 | |||
286 | /* We are responsible for this peer */ | ||
287 | msize -= sizeof (struct GNUNET_TESTBED_PeerCreateMessage); | ||
288 | config_size = ntohl (msg->config_size); | ||
289 | config = GNUNET_malloc (config_size); | ||
290 | dest_size = config_size; | ||
291 | if (Z_OK != | ||
292 | (ret = | ||
293 | uncompress ((Bytef *) config, (uLongf *) & dest_size, | ||
294 | (const Bytef *) &msg[1], (uLong) msize))) | ||
295 | { | ||
296 | GNUNET_break (0); /* uncompression error */ | ||
297 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
298 | return; | ||
299 | } | ||
300 | if (config_size != dest_size) | ||
301 | { | ||
302 | GNUNET_break (0); /* Uncompressed config size mismatch */ | ||
303 | GNUNET_free (config); | ||
304 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
305 | return; | ||
306 | } | ||
307 | cfg = GNUNET_CONFIGURATION_create (); | ||
308 | if (GNUNET_OK != | ||
309 | GNUNET_CONFIGURATION_deserialize (cfg, config, config_size, GNUNET_NO)) | ||
310 | { | ||
311 | GNUNET_break (0); /* Configuration parsing error */ | ||
312 | GNUNET_free (config); | ||
313 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
314 | return; | ||
315 | } | ||
316 | GNUNET_free (config); | ||
317 | GNUNET_CONFIGURATION_set_value_number (cfg, "TESTBED", "PEERID", | ||
318 | (unsigned long long) peer_id); | ||
319 | peer = GNUNET_malloc (sizeof (struct Peer)); | ||
320 | peer->is_remote = GNUNET_NO; | ||
321 | peer->details.local.cfg = cfg; | ||
322 | peer->id = peer_id; | ||
323 | LOG_DEBUG ("Creating peer with id: %u\n", (unsigned int) peer->id); | ||
324 | peer->details.local.peer = | ||
325 | GNUNET_TESTING_peer_configure (GST_context->system, | ||
326 | peer->details.local.cfg, peer->id, | ||
327 | NULL /* Peer id */ , | ||
328 | &emsg); | ||
329 | if (NULL == peer->details.local.peer) | ||
330 | { | ||
331 | LOG (GNUNET_ERROR_TYPE_WARNING, "Configuring peer failed: %s\n", emsg); | ||
332 | GNUNET_free (emsg); | ||
333 | GNUNET_free (peer); | ||
334 | GNUNET_break (0); | ||
335 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
336 | return; | ||
337 | } | ||
338 | peer->details.local.is_running = GNUNET_NO; | ||
339 | peer_list_add (peer); | ||
340 | reply = | ||
341 | GNUNET_malloc (sizeof | ||
342 | (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); | ||
343 | reply->header.size = | ||
344 | htons (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage)); | ||
345 | reply->header.type = | ||
346 | htons (GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS); | ||
347 | reply->peer_id = msg->peer_id; | ||
348 | reply->operation_id = msg->operation_id; | ||
349 | GST_queue_message (client, &reply->header); | ||
350 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | /* Forward peer create request */ | ||
355 | route = GST_find_dest_route (host_id); | ||
356 | if (NULL == route) | ||
357 | { | ||
358 | GNUNET_break (0); | ||
359 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
360 | return; | ||
361 | } | ||
362 | |||
363 | peer = GNUNET_malloc (sizeof (struct Peer)); | ||
364 | peer->is_remote = GNUNET_YES; | ||
365 | peer->id = peer_id; | ||
366 | peer->details.remote.slave = GST_slave_list[route->dest]; | ||
367 | peer->details.remote.remote_host_id = host_id; | ||
368 | fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
369 | GNUNET_SERVER_client_keep (client); | ||
370 | fo_ctxt->client = client; | ||
371 | fo_ctxt->operation_id = GNUNET_ntohll (msg->operation_id); | ||
372 | fo_ctxt->cls = peer; //GST_slave_list[route->dest]->controller; | ||
373 | fo_ctxt->type = OP_PEER_CREATE; | ||
374 | fo_ctxt->opc = | ||
375 | GNUNET_TESTBED_forward_operation_msg_ (GST_slave_list | ||
376 | [route->dest]->controller, | ||
377 | fo_ctxt->operation_id, | ||
378 | &msg->header, | ||
379 | peer_create_success_cb, fo_ctxt); | ||
380 | fo_ctxt->timeout_task = | ||
381 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &peer_create_forward_timeout, | ||
382 | fo_ctxt); | ||
383 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); | ||
384 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
385 | } | ||
386 | |||
387 | |||
388 | /** | ||
389 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
390 | * | ||
391 | * @param cls NULL | ||
392 | * @param client identification of the client | ||
393 | * @param message the actual message | ||
394 | */ | ||
395 | void | ||
396 | GST_handle_peer_destroy (void *cls, struct GNUNET_SERVER_Client *client, | ||
397 | const struct GNUNET_MessageHeader *message) | ||
398 | { | ||
399 | const struct GNUNET_TESTBED_PeerDestroyMessage *msg; | ||
400 | struct ForwardedOperationContext *fopc; | ||
401 | struct Peer *peer; | ||
402 | uint32_t peer_id; | ||
403 | |||
404 | msg = (const struct GNUNET_TESTBED_PeerDestroyMessage *) message; | ||
405 | peer_id = ntohl (msg->peer_id); | ||
406 | LOG_DEBUG ("Received peer destory on peer: %u and operation id: %ul\n", | ||
407 | peer_id, GNUNET_ntohll (msg->operation_id)); | ||
408 | if ((GST_peer_list_size <= peer_id) || (NULL == GST_peer_list[peer_id])) | ||
409 | { | ||
410 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
411 | "Asked to destroy a non existent peer with id: %u\n", peer_id); | ||
412 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
413 | "Peer doesn't exist"); | ||
414 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
415 | return; | ||
416 | } | ||
417 | peer = GST_peer_list[peer_id]; | ||
418 | if (GNUNET_YES == peer->is_remote) | ||
419 | { | ||
420 | /* Forward the destory message to sub controller */ | ||
421 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
422 | GNUNET_SERVER_client_keep (client); | ||
423 | fopc->client = client; | ||
424 | fopc->cls = peer; | ||
425 | fopc->type = OP_PEER_DESTROY; | ||
426 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
427 | fopc->opc = | ||
428 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
429 | slave->controller, | ||
430 | fopc->operation_id, &msg->header, | ||
431 | &peer_destroy_success_cb, fopc); | ||
432 | fopc->timeout_task = | ||
433 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
434 | fopc); | ||
435 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
436 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
437 | return; | ||
438 | } | ||
439 | peer->destroy_flag = GNUNET_YES; | ||
440 | if (0 == peer->reference_cnt) | ||
441 | GST_destroy_peer (peer); | ||
442 | else | ||
443 | LOG (GNUNET_ERROR_TYPE_DEBUG, | ||
444 | "Delaying peer destroy as peer is currently in use\n"); | ||
445 | GST_send_operation_success_msg (client, GNUNET_ntohll (msg->operation_id)); | ||
446 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
447 | } | ||
448 | |||
449 | |||
450 | /** | ||
451 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
452 | * | ||
453 | * @param cls NULL | ||
454 | * @param client identification of the client | ||
455 | * @param message the actual message | ||
456 | */ | ||
457 | void | ||
458 | GST_handle_peer_start (void *cls, struct GNUNET_SERVER_Client *client, | ||
459 | const struct GNUNET_MessageHeader *message) | ||
460 | { | ||
461 | const struct GNUNET_TESTBED_PeerStartMessage *msg; | ||
462 | struct GNUNET_TESTBED_PeerEventMessage *reply; | ||
463 | struct ForwardedOperationContext *fopc; | ||
464 | struct Peer *peer; | ||
465 | uint32_t peer_id; | ||
466 | |||
467 | msg = (const struct GNUNET_TESTBED_PeerStartMessage *) message; | ||
468 | peer_id = ntohl (msg->peer_id); | ||
469 | if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) | ||
470 | { | ||
471 | GNUNET_break (0); | ||
472 | LOG (GNUNET_ERROR_TYPE_ERROR, | ||
473 | "Asked to start a non existent peer with id: %u\n", peer_id); | ||
474 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
475 | return; | ||
476 | } | ||
477 | peer = GST_peer_list[peer_id]; | ||
478 | if (GNUNET_YES == peer->is_remote) | ||
479 | { | ||
480 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
481 | GNUNET_SERVER_client_keep (client); | ||
482 | fopc->client = client; | ||
483 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
484 | fopc->type = OP_PEER_START; | ||
485 | fopc->opc = | ||
486 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
487 | slave->controller, | ||
488 | fopc->operation_id, &msg->header, | ||
489 | &GST_forwarded_operation_reply_relay, | ||
490 | fopc); | ||
491 | fopc->timeout_task = | ||
492 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
493 | fopc); | ||
494 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
495 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
496 | return; | ||
497 | } | ||
498 | if (GNUNET_OK != GNUNET_TESTING_peer_start (peer->details.local.peer)) | ||
499 | { | ||
500 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
501 | "Failed to start"); | ||
502 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
503 | return; | ||
504 | } | ||
505 | peer->details.local.is_running = GNUNET_YES; | ||
506 | reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
507 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); | ||
508 | reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
509 | reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_START); | ||
510 | reply->host_id = htonl (GST_context->host_id); | ||
511 | reply->peer_id = msg->peer_id; | ||
512 | reply->operation_id = msg->operation_id; | ||
513 | GST_queue_message (client, &reply->header); | ||
514 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
515 | } | ||
516 | |||
517 | |||
518 | /** | ||
519 | * Message handler for GNUNET_MESSAGE_TYPE_TESTBED_DESTROYPEER messages | ||
520 | * | ||
521 | * @param cls NULL | ||
522 | * @param client identification of the client | ||
523 | * @param message the actual message | ||
524 | */ | ||
525 | void | ||
526 | GST_handle_peer_stop (void *cls, struct GNUNET_SERVER_Client *client, | ||
527 | const struct GNUNET_MessageHeader *message) | ||
528 | { | ||
529 | const struct GNUNET_TESTBED_PeerStopMessage *msg; | ||
530 | struct GNUNET_TESTBED_PeerEventMessage *reply; | ||
531 | struct ForwardedOperationContext *fopc; | ||
532 | struct Peer *peer; | ||
533 | uint32_t peer_id; | ||
534 | |||
535 | msg = (const struct GNUNET_TESTBED_PeerStopMessage *) message; | ||
536 | peer_id = ntohl (msg->peer_id); | ||
537 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Received PEER_STOP for peer %u\n", peer_id); | ||
538 | if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) | ||
539 | { | ||
540 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
541 | "Peer not found"); | ||
542 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
543 | return; | ||
544 | } | ||
545 | peer = GST_peer_list[peer_id]; | ||
546 | if (GNUNET_YES == peer->is_remote) | ||
547 | { | ||
548 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Forwarding PEER_STOP for peer %u\n", | ||
549 | peer_id); | ||
550 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
551 | GNUNET_SERVER_client_keep (client); | ||
552 | fopc->client = client; | ||
553 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
554 | fopc->type = OP_PEER_STOP; | ||
555 | fopc->opc = | ||
556 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
557 | slave->controller, | ||
558 | fopc->operation_id, &msg->header, | ||
559 | &GST_forwarded_operation_reply_relay, | ||
560 | fopc); | ||
561 | fopc->timeout_task = | ||
562 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
563 | fopc); | ||
564 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
565 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
566 | return; | ||
567 | } | ||
568 | if (GNUNET_OK != GNUNET_TESTING_peer_kill (peer->details.local.peer)) | ||
569 | { | ||
570 | LOG (GNUNET_ERROR_TYPE_WARNING, "Stopping peer %u failed\n", peer_id); | ||
571 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
572 | "Peer not running"); | ||
573 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
574 | return; | ||
575 | } | ||
576 | LOG (GNUNET_ERROR_TYPE_DEBUG, "Peer %u successfully stopped\n", peer_id); | ||
577 | peer->details.local.is_running = GNUNET_NO; | ||
578 | reply = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
579 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT); | ||
580 | reply->header.size = htons (sizeof (struct GNUNET_TESTBED_PeerEventMessage)); | ||
581 | reply->event_type = htonl (GNUNET_TESTBED_ET_PEER_STOP); | ||
582 | reply->host_id = htonl (GST_context->host_id); | ||
583 | reply->peer_id = msg->peer_id; | ||
584 | reply->operation_id = msg->operation_id; | ||
585 | GST_queue_message (client, &reply->header); | ||
586 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
587 | GNUNET_TESTING_peer_wait (peer->details.local.peer); | ||
588 | } | ||
589 | |||
590 | |||
591 | /** | ||
592 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_GETPEERCONFIG messages | ||
593 | * | ||
594 | * @param cls NULL | ||
595 | * @param client identification of the client | ||
596 | * @param message the actual message | ||
597 | */ | ||
598 | void | ||
599 | GST_handle_peer_get_config (void *cls, struct GNUNET_SERVER_Client *client, | ||
600 | const struct GNUNET_MessageHeader *message) | ||
601 | { | ||
602 | const struct GNUNET_TESTBED_PeerGetConfigurationMessage *msg; | ||
603 | struct GNUNET_TESTBED_PeerConfigurationInformationMessage *reply; | ||
604 | struct Peer *peer; | ||
605 | char *config; | ||
606 | char *xconfig; | ||
607 | size_t c_size; | ||
608 | size_t xc_size; | ||
609 | uint32_t peer_id; | ||
610 | uint16_t msize; | ||
611 | |||
612 | msg = (const struct GNUNET_TESTBED_PeerGetConfigurationMessage *) message; | ||
613 | peer_id = ntohl (msg->peer_id); | ||
614 | if ((peer_id >= GST_peer_list_size) || (NULL == GST_peer_list[peer_id])) | ||
615 | { | ||
616 | GST_send_operation_fail_msg (client, GNUNET_ntohll (msg->operation_id), | ||
617 | "Peer not found"); | ||
618 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
619 | return; | ||
620 | } | ||
621 | peer = GST_peer_list[peer_id]; | ||
622 | if (GNUNET_YES == peer->is_remote) | ||
623 | { | ||
624 | struct ForwardedOperationContext *fopc; | ||
625 | |||
626 | LOG_DEBUG ("Forwarding PEER_GET_CONFIG for peer: %u\n", peer_id); | ||
627 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
628 | GNUNET_SERVER_client_keep (client); | ||
629 | fopc->client = client; | ||
630 | fopc->operation_id = GNUNET_ntohll (msg->operation_id); | ||
631 | fopc->type = OP_PEER_INFO; | ||
632 | fopc->opc = | ||
633 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
634 | slave->controller, | ||
635 | fopc->operation_id, &msg->header, | ||
636 | &GST_forwarded_operation_reply_relay, | ||
637 | fopc); | ||
638 | fopc->timeout_task = | ||
639 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
640 | fopc); | ||
641 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
642 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
643 | return; | ||
644 | } | ||
645 | LOG_DEBUG ("Received PEER_GET_CONFIG for peer: %u\n", peer_id); | ||
646 | config = | ||
647 | GNUNET_CONFIGURATION_serialize (GST_peer_list[peer_id]->details.local.cfg, | ||
648 | &c_size); | ||
649 | xc_size = GNUNET_TESTBED_compress_config_ (config, c_size, &xconfig); | ||
650 | GNUNET_free (config); | ||
651 | msize = | ||
652 | xc_size + | ||
653 | sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage); | ||
654 | reply = GNUNET_realloc (xconfig, msize); | ||
655 | (void) memmove (&reply[1], reply, xc_size); | ||
656 | reply->header.size = htons (msize); | ||
657 | reply->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION); | ||
658 | reply->peer_id = msg->peer_id; | ||
659 | reply->operation_id = msg->operation_id; | ||
660 | GNUNET_TESTING_peer_get_identity (GST_peer_list[peer_id]->details.local.peer, | ||
661 | &reply->peer_identity); | ||
662 | reply->config_size = htons ((uint16_t) c_size); | ||
663 | GST_queue_message (client, &reply->header); | ||
664 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
665 | } | ||
666 | |||
667 | |||
668 | /** | ||
669 | * Cleanup the context information created for managing a peer's service | ||
670 | * | ||
671 | * @param mctx the ManageServiceContext | ||
672 | */ | ||
673 | static void | ||
674 | cleanup_mctx (struct ManageServiceContext *mctx) | ||
675 | { | ||
676 | mctx->expired = GNUNET_YES; | ||
677 | GNUNET_CONTAINER_DLL_remove (mctx_head, mctx_tail, mctx); | ||
678 | GNUNET_SERVER_client_drop (mctx->client); | ||
679 | GNUNET_ARM_disconnect_and_free (mctx->ah); | ||
680 | GNUNET_assert (0 < mctx->peer->reference_cnt); | ||
681 | mctx->peer->reference_cnt--; | ||
682 | if ( (GNUNET_YES == mctx->peer->destroy_flag) | ||
683 | && (0 == mctx->peer->reference_cnt) ) | ||
684 | GST_destroy_peer (mctx->peer); | ||
685 | GNUNET_free (mctx); | ||
686 | } | ||
687 | |||
688 | |||
689 | /** | ||
690 | * Frees the ManageServiceContext queue | ||
691 | */ | ||
692 | void | ||
693 | GST_free_mctxq () | ||
694 | { | ||
695 | while (NULL != mctx_head) | ||
696 | cleanup_mctx (mctx_head); | ||
697 | } | ||
698 | |||
699 | |||
700 | /** | ||
701 | * Returns a string interpretation of 'rs' | ||
702 | * | ||
703 | * @param rs the request status from ARM | ||
704 | * @return a string interpretation of the request status | ||
705 | */ | ||
706 | static const char * | ||
707 | arm_req_string (enum GNUNET_ARM_RequestStatus rs) | ||
708 | { | ||
709 | switch (rs) | ||
710 | { | ||
711 | case GNUNET_ARM_REQUEST_SENT_OK: | ||
712 | return _("Message was sent successfully"); | ||
713 | case GNUNET_ARM_REQUEST_CONFIGURATION_ERROR: | ||
714 | return _("Misconfiguration (can't connect to the ARM service)"); | ||
715 | case GNUNET_ARM_REQUEST_DISCONNECTED: | ||
716 | return _("We disconnected from ARM before we could send a request"); | ||
717 | case GNUNET_ARM_REQUEST_BUSY: | ||
718 | return _("ARM API is busy"); | ||
719 | case GNUNET_ARM_REQUEST_TOO_LONG: | ||
720 | return _("Request doesn't fit into a message"); | ||
721 | case GNUNET_ARM_REQUEST_TIMEOUT: | ||
722 | return _("Request timed out"); | ||
723 | } | ||
724 | return _("Unknown request status"); | ||
725 | } | ||
726 | |||
727 | |||
728 | /** | ||
729 | * Returns a string interpretation of the 'result' | ||
730 | * | ||
731 | * @param result the arm result | ||
732 | * @return a string interpretation | ||
733 | */ | ||
734 | static const char * | ||
735 | arm_ret_string (enum GNUNET_ARM_Result result) | ||
736 | { | ||
737 | switch (result) | ||
738 | { | ||
739 | case GNUNET_ARM_RESULT_STOPPED: | ||
740 | return _("%s is stopped"); | ||
741 | case GNUNET_ARM_RESULT_STARTING: | ||
742 | return _("%s is starting"); | ||
743 | case GNUNET_ARM_RESULT_STOPPING: | ||
744 | return _("%s is stopping"); | ||
745 | case GNUNET_ARM_RESULT_IS_STARTING_ALREADY: | ||
746 | return _("%s is starting already"); | ||
747 | case GNUNET_ARM_RESULT_IS_STOPPING_ALREADY: | ||
748 | return _("%s is stopping already"); | ||
749 | case GNUNET_ARM_RESULT_IS_STARTED_ALREADY: | ||
750 | return _("%s is started already"); | ||
751 | case GNUNET_ARM_RESULT_IS_STOPPED_ALREADY: | ||
752 | return _("%s is stopped already"); | ||
753 | case GNUNET_ARM_RESULT_IS_NOT_KNOWN: | ||
754 | return _("%s service is not known to ARM"); | ||
755 | case GNUNET_ARM_RESULT_START_FAILED: | ||
756 | return _("%s service failed to start"); | ||
757 | case GNUNET_ARM_RESULT_IN_SHUTDOWN: | ||
758 | return _("%s service can't be started because ARM is shutting down"); | ||
759 | } | ||
760 | return _("%.s Unknown result code."); | ||
761 | } | ||
762 | |||
763 | |||
764 | /** | ||
765 | * Function called in response to a start/stop request. | ||
766 | * Will be called when request was not sent successfully, | ||
767 | * or when a reply comes. If the request was not sent successfully, | ||
768 | * 'rs' will indicate that, and 'service' and 'result' will be undefined. | ||
769 | * | ||
770 | * @param cls ManageServiceContext | ||
771 | * @param arm handle to the arm connection | ||
772 | * @param rs status of the request | ||
773 | * @param service service name | ||
774 | * @param result result of the operation | ||
775 | */ | ||
776 | static void | ||
777 | service_manage_result_cb (void *cls, struct GNUNET_ARM_Handle *arm, | ||
778 | enum GNUNET_ARM_RequestStatus rs, | ||
779 | const char *service, enum GNUNET_ARM_Result result) | ||
780 | { | ||
781 | struct ManageServiceContext *mctx = cls; | ||
782 | char *emsg; | ||
783 | |||
784 | emsg = NULL; | ||
785 | if (GNUNET_YES == mctx->expired) | ||
786 | return; | ||
787 | if (GNUNET_ARM_REQUEST_SENT_OK != rs) | ||
788 | { | ||
789 | GNUNET_asprintf (&emsg, "Error communicating with Peer %u's ARM: %s", | ||
790 | mctx->peer->id, arm_req_string (rs)); | ||
791 | goto ret; | ||
792 | } | ||
793 | if (1 == mctx->start) | ||
794 | goto service_start_check; | ||
795 | if (! ((GNUNET_ARM_RESULT_STOPPED == result) | ||
796 | || (GNUNET_ARM_RESULT_STOPPING == result) | ||
797 | || (GNUNET_ARM_RESULT_IS_STOPPING_ALREADY == result) | ||
798 | || (GNUNET_ARM_RESULT_IS_STOPPED_ALREADY == result)) ) | ||
799 | { | ||
800 | /* stopping a service failed */ | ||
801 | GNUNET_asprintf (&emsg, arm_ret_string (result), service); | ||
802 | goto ret; | ||
803 | } | ||
804 | /* service stopped successfully */ | ||
805 | goto ret; | ||
806 | |||
807 | service_start_check: | ||
808 | if (! ((GNUNET_ARM_RESULT_STARTING == result) | ||
809 | || (GNUNET_ARM_RESULT_IS_STARTING_ALREADY == result) | ||
810 | || (GNUNET_ARM_RESULT_IS_STARTED_ALREADY == result)) ) | ||
811 | { | ||
812 | /* starting a service failed */ | ||
813 | GNUNET_asprintf (&emsg, arm_ret_string (result), service); | ||
814 | goto ret; | ||
815 | } | ||
816 | /* service started successfully */ | ||
817 | |||
818 | ret: | ||
819 | if (NULL != emsg) | ||
820 | { | ||
821 | LOG_DEBUG ("%s\n", emsg); | ||
822 | GST_send_operation_fail_msg (mctx->client, mctx->op_id, emsg); | ||
823 | } | ||
824 | else | ||
825 | GST_send_operation_success_msg (mctx->client, mctx->op_id); | ||
826 | GNUNET_free_non_null (emsg); | ||
827 | cleanup_mctx (mctx); | ||
828 | } | ||
829 | |||
830 | |||
831 | /** | ||
832 | * Handler for GNUNET_TESTBED_ManagePeerServiceMessage message | ||
833 | * | ||
834 | * @param cls NULL | ||
835 | * @param client identification of client | ||
836 | * @param message the actual message | ||
837 | */ | ||
838 | void | ||
839 | GST_handle_manage_peer_service (void *cls, struct GNUNET_SERVER_Client *client, | ||
840 | const struct GNUNET_MessageHeader *message) | ||
841 | { | ||
842 | const struct GNUNET_TESTBED_ManagePeerServiceMessage *msg; | ||
843 | const char* service; | ||
844 | struct Peer *peer; | ||
845 | char *emsg; | ||
846 | struct GNUNET_ARM_Handle *ah; | ||
847 | struct ManageServiceContext *mctx; | ||
848 | struct ForwardedOperationContext *fopc; | ||
849 | uint64_t op_id; | ||
850 | uint32_t peer_id; | ||
851 | uint16_t msize; | ||
852 | |||
853 | |||
854 | msize = ntohs (message->size); | ||
855 | if (msize <= sizeof (struct GNUNET_TESTBED_ManagePeerServiceMessage)) | ||
856 | { | ||
857 | GNUNET_break_op (0); | ||
858 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
859 | return; | ||
860 | } | ||
861 | msg = (const struct GNUNET_TESTBED_ManagePeerServiceMessage *) message; | ||
862 | service = (const char *) &msg[1]; | ||
863 | if ('\0' != service[msize - sizeof | ||
864 | (struct GNUNET_TESTBED_ManagePeerServiceMessage) - 1]) | ||
865 | { | ||
866 | GNUNET_break_op (0); | ||
867 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
868 | return; | ||
869 | } | ||
870 | if (1 < msg->start) | ||
871 | { | ||
872 | GNUNET_break_op (0); | ||
873 | GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); | ||
874 | return; | ||
875 | } | ||
876 | peer_id = ntohl (msg->peer_id); | ||
877 | op_id = GNUNET_ntohll (msg->operation_id); | ||
878 | LOG_DEBUG ("Received request to manage service %s on peer %u\n", | ||
879 | service, (unsigned int) peer_id); | ||
880 | if ((GST_peer_list_size <= peer_id) | ||
881 | || (NULL == (peer = GST_peer_list[peer_id]))) | ||
882 | { | ||
883 | GNUNET_asprintf (&emsg, "Asked to manage service of a non existent peer " | ||
884 | "with id: %u", peer_id); | ||
885 | goto err_ret; | ||
886 | } | ||
887 | if (0 == strcasecmp ("arm", service)) | ||
888 | { | ||
889 | emsg = GNUNET_strdup ("Cannot start/stop peer's ARM service. " | ||
890 | "Use peer start/stop for that"); | ||
891 | goto err_ret; | ||
892 | } | ||
893 | if (GNUNET_YES == peer->is_remote) | ||
894 | { | ||
895 | /* Forward the destory message to sub controller */ | ||
896 | fopc = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
897 | GNUNET_SERVER_client_keep (client); | ||
898 | fopc->client = client; | ||
899 | fopc->cls = peer; | ||
900 | fopc->type = OP_MANAGE_SERVICE; | ||
901 | fopc->operation_id = op_id; | ||
902 | fopc->opc = | ||
903 | GNUNET_TESTBED_forward_operation_msg_ (peer->details.remote. | ||
904 | slave->controller, | ||
905 | fopc->operation_id, &msg->header, | ||
906 | &GST_forwarded_operation_reply_relay, | ||
907 | fopc); | ||
908 | fopc->timeout_task = | ||
909 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &GST_forwarded_operation_timeout, | ||
910 | fopc); | ||
911 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fopc); | ||
912 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
913 | return; | ||
914 | } | ||
915 | if ((0 != peer->reference_cnt) | ||
916 | && ( (0 == strcasecmp ("core", service)) | ||
917 | || (0 == strcasecmp ("transport", service)) ) ) | ||
918 | { | ||
919 | GNUNET_asprintf (&emsg, "Cannot stop %s service of peer with id: %u " | ||
920 | "since it is required by existing operations", | ||
921 | service, peer_id); | ||
922 | goto err_ret; | ||
923 | } | ||
924 | ah = GNUNET_ARM_connect (peer->details.local.cfg, NULL, NULL); | ||
925 | if (NULL == ah) | ||
926 | { | ||
927 | GNUNET_asprintf (&emsg, | ||
928 | "Cannot connect to ARM service of peer with id: %u", | ||
929 | peer_id); | ||
930 | goto err_ret; | ||
931 | } | ||
932 | mctx = GNUNET_malloc (sizeof (struct ManageServiceContext)); | ||
933 | mctx->peer = peer; | ||
934 | peer->reference_cnt++; | ||
935 | mctx->op_id = op_id; | ||
936 | mctx->ah = ah; | ||
937 | GNUNET_SERVER_client_keep (client); | ||
938 | mctx->client = client; | ||
939 | mctx->start = msg->start; | ||
940 | GNUNET_CONTAINER_DLL_insert_tail (mctx_head, mctx_tail, mctx); | ||
941 | if (1 == mctx->start) | ||
942 | GNUNET_ARM_request_service_start (mctx->ah, service, | ||
943 | GNUNET_OS_INHERIT_STD_ERR, | ||
944 | GST_timeout, | ||
945 | service_manage_result_cb, | ||
946 | mctx); | ||
947 | else | ||
948 | GNUNET_ARM_request_service_stop (mctx->ah, service, | ||
949 | GST_timeout, | ||
950 | service_manage_result_cb, | ||
951 | mctx); | ||
952 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
953 | return; | ||
954 | |||
955 | err_ret: | ||
956 | LOG (GNUNET_ERROR_TYPE_ERROR, "%s\n", emsg); | ||
957 | GST_send_operation_fail_msg (client, op_id, emsg); | ||
958 | GNUNET_free (emsg); | ||
959 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
960 | } | ||
961 | |||
962 | |||
963 | /** | ||
964 | * Stops and destroys all peers | ||
965 | */ | ||
966 | void | ||
967 | GST_destroy_peers () | ||
968 | { | ||
969 | struct Peer *peer; | ||
970 | unsigned int id; | ||
971 | |||
972 | if (NULL == GST_peer_list) | ||
973 | return; | ||
974 | for (id = 0; id < GST_peer_list_size; id++) | ||
975 | { | ||
976 | peer = GST_peer_list[id]; | ||
977 | if (NULL == peer) | ||
978 | continue; | ||
979 | /* If destroy flag is set it means that this peer should have been | ||
980 | * destroyed by a context which we destroy before */ | ||
981 | GNUNET_break (GNUNET_NO == peer->destroy_flag); | ||
982 | /* counter should be zero as we free all contexts before */ | ||
983 | GNUNET_break (0 == peer->reference_cnt); | ||
984 | if ((GNUNET_NO == peer->is_remote) && | ||
985 | (GNUNET_YES == peer->details.local.is_running)) | ||
986 | GNUNET_TESTING_peer_kill (peer->details.local.peer); | ||
987 | } | ||
988 | for (id = 0; id < GST_peer_list_size; id++) | ||
989 | { | ||
990 | peer = GST_peer_list[id]; | ||
991 | if (NULL == peer) | ||
992 | continue; | ||
993 | if (GNUNET_NO == peer->is_remote) | ||
994 | { | ||
995 | if (GNUNET_YES == peer->details.local.is_running) | ||
996 | GNUNET_TESTING_peer_wait (peer->details.local.peer); | ||
997 | GNUNET_TESTING_peer_destroy (peer->details.local.peer); | ||
998 | GNUNET_CONFIGURATION_destroy (peer->details.local.cfg); | ||
999 | } | ||
1000 | GNUNET_free (peer); | ||
1001 | } | ||
1002 | GNUNET_free_non_null (GST_peer_list); | ||
1003 | GST_peer_list = NULL; | ||
1004 | GST_peer_list_size = 0; | ||
1005 | } | ||
1006 | |||
1007 | |||
1008 | /** | ||
1009 | * Task run upon timeout of forwarded SHUTDOWN_PEERS operation | ||
1010 | * | ||
1011 | * @param cls the ForwardedOperationContext | ||
1012 | * @param tc the scheduler task context | ||
1013 | */ | ||
1014 | static void | ||
1015 | shutdown_peers_timeout_cb (void *cls, | ||
1016 | const struct GNUNET_SCHEDULER_TaskContext *tc) | ||
1017 | { | ||
1018 | struct ForwardedOperationContext *fo_ctxt = cls; | ||
1019 | struct HandlerContext_ShutdownPeers *hc; | ||
1020 | |||
1021 | fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1022 | hc = fo_ctxt->cls; | ||
1023 | hc->timeout = GNUNET_YES; | ||
1024 | GNUNET_assert (0 < hc->nslaves); | ||
1025 | hc->nslaves--; | ||
1026 | if (0 == hc->nslaves) | ||
1027 | GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, | ||
1028 | "Timeout at a slave controller"); | ||
1029 | GNUNET_TESTBED_forward_operation_msg_cancel_ (fo_ctxt->opc); | ||
1030 | GNUNET_SERVER_client_drop (fo_ctxt->client); | ||
1031 | GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); | ||
1032 | GNUNET_free (fo_ctxt); | ||
1033 | } | ||
1034 | |||
1035 | |||
1036 | /** | ||
1037 | * The reply msg handler forwarded SHUTDOWN_PEERS operation. Checks if a | ||
1038 | * success reply is received from all clients and then sends the success message | ||
1039 | * to the client | ||
1040 | * | ||
1041 | * @param cls ForwardedOperationContext | ||
1042 | * @param msg the message to relay | ||
1043 | */ | ||
1044 | static void | ||
1045 | shutdown_peers_reply_cb (void *cls, | ||
1046 | const struct GNUNET_MessageHeader *msg) | ||
1047 | { | ||
1048 | struct ForwardedOperationContext *fo_ctxt = cls; | ||
1049 | struct HandlerContext_ShutdownPeers *hc; | ||
1050 | |||
1051 | hc = fo_ctxt->cls; | ||
1052 | GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != fo_ctxt->timeout_task); | ||
1053 | GNUNET_SCHEDULER_cancel (fo_ctxt->timeout_task); | ||
1054 | fo_ctxt->timeout_task = GNUNET_SCHEDULER_NO_TASK; | ||
1055 | GNUNET_assert (0 < hc->nslaves); | ||
1056 | hc->nslaves--; | ||
1057 | if (GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS != | ||
1058 | ntohs (msg->type)) | ||
1059 | hc->timeout = GNUNET_YES; | ||
1060 | if (0 == hc->nslaves) | ||
1061 | { | ||
1062 | if (GNUNET_YES == hc->timeout) | ||
1063 | GST_send_operation_fail_msg (fo_ctxt->client, fo_ctxt->operation_id, | ||
1064 | "Timeout at a slave controller"); | ||
1065 | else | ||
1066 | GST_send_operation_success_msg (fo_ctxt->client, fo_ctxt->operation_id); | ||
1067 | } | ||
1068 | GNUNET_SERVER_client_drop (fo_ctxt->client); | ||
1069 | GNUNET_CONTAINER_DLL_remove (fopcq_head, fopcq_tail, fo_ctxt); | ||
1070 | GNUNET_free (fo_ctxt); | ||
1071 | } | ||
1072 | |||
1073 | |||
1074 | /** | ||
1075 | * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS messages | ||
1076 | * | ||
1077 | * @param cls NULL | ||
1078 | * @param client identification of the client | ||
1079 | * @param message the actual message | ||
1080 | */ | ||
1081 | void | ||
1082 | GST_handle_shutdown_peers (void *cls, struct GNUNET_SERVER_Client *client, | ||
1083 | const struct GNUNET_MessageHeader *message) | ||
1084 | { | ||
1085 | const struct GNUNET_TESTBED_ShutdownPeersMessage *msg; | ||
1086 | struct HandlerContext_ShutdownPeers *hc; | ||
1087 | struct Slave *slave; | ||
1088 | struct ForwardedOperationContext *fo_ctxt; | ||
1089 | uint64_t op_id; | ||
1090 | unsigned int cnt; | ||
1091 | |||
1092 | msg = (const struct GNUNET_TESTBED_ShutdownPeersMessage *) message; | ||
1093 | LOG_DEBUG ("Received SHUTDOWN_PEERS\n"); | ||
1094 | /* Stop and destroy all peers */ | ||
1095 | GST_free_mctxq (); | ||
1096 | GST_free_occq (); | ||
1097 | GST_free_roccq (); | ||
1098 | GST_clear_fopcq (); | ||
1099 | /* Forward to all slaves which we have started */ | ||
1100 | op_id = GNUNET_ntohll (msg->operation_id); | ||
1101 | hc = GNUNET_malloc (sizeof (struct HandlerContext_ShutdownPeers)); | ||
1102 | /* FIXME: have a better implementation where we track which slaves are | ||
1103 | started by this controller */ | ||
1104 | for (cnt = 0; cnt < GST_slave_list_size; cnt++) | ||
1105 | { | ||
1106 | slave = GST_slave_list[cnt]; | ||
1107 | if (NULL == slave) | ||
1108 | continue; | ||
1109 | if (NULL == slave->controller_proc) /* We didn't start the slave */ | ||
1110 | continue; | ||
1111 | LOG_DEBUG ("Forwarding SHUTDOWN_PEERS\n"); | ||
1112 | hc->nslaves++; | ||
1113 | fo_ctxt = GNUNET_malloc (sizeof (struct ForwardedOperationContext)); | ||
1114 | GNUNET_SERVER_client_keep (client); | ||
1115 | fo_ctxt->client = client; | ||
1116 | fo_ctxt->operation_id = op_id; | ||
1117 | fo_ctxt->cls = hc; | ||
1118 | fo_ctxt->type = OP_SHUTDOWN_PEERS; | ||
1119 | fo_ctxt->opc = | ||
1120 | GNUNET_TESTBED_forward_operation_msg_ (slave->controller, | ||
1121 | fo_ctxt->operation_id, | ||
1122 | &msg->header, | ||
1123 | shutdown_peers_reply_cb, | ||
1124 | fo_ctxt); | ||
1125 | fo_ctxt->timeout_task = | ||
1126 | GNUNET_SCHEDULER_add_delayed (GST_timeout, &shutdown_peers_timeout_cb, | ||
1127 | fo_ctxt); | ||
1128 | GNUNET_CONTAINER_DLL_insert_tail (fopcq_head, fopcq_tail, fo_ctxt); | ||
1129 | } | ||
1130 | LOG_DEBUG ("Shutting down peers\n"); | ||
1131 | GST_destroy_peers (); | ||
1132 | if (0 == hc->nslaves) | ||
1133 | { | ||
1134 | GST_send_operation_success_msg (client, op_id); | ||
1135 | GNUNET_free (hc); | ||
1136 | } | ||
1137 | GNUNET_SERVER_receive_done (client, GNUNET_OK); | ||
1138 | } | ||