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 /src/testbed/gnunet-service-testbed.c | |
parent | f2257ba6dd452dddb4a425689a1c137433b5f578 (diff) | |
download | gnunet-6f3ff8ff3db35d2a5c02e8cc88a912e9e0106d7c.tar.gz gnunet-6f3ff8ff3db35d2a5c02e8cc88a912e9e0106d7c.zip |
- restructure
Diffstat (limited to 'src/testbed/gnunet-service-testbed.c')
-rw-r--r-- | src/testbed/gnunet-service-testbed.c | 1112 |
1 files changed, 19 insertions, 1093 deletions
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 | }; |