2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
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 3, or (at your
8 option) any later version.
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.
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.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
47 * Generic logging shorthand
49 #define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
55 #define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
59 * Relative time seconds shorthand
61 #define TIME_REL_SECS(sec) \
62 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
66 * Default server message sending retry timeout
68 #define TIMEOUT_REL TIME_REL_SECS(1)
72 * The message queue for sending messages to the controller service
77 * The message to be sent
79 struct GNUNET_MessageHeader *msg;
82 * next pointer for DLL
84 struct MessageQueue *next;
87 * prev pointer for DLL
89 struct MessageQueue *prev;
94 * Context data for forwarded Operation
96 struct ForwardedOperationData
100 * The callback to call when reply is available
102 GNUNET_CLIENT_MessageHandler cc;
105 * The closure for the above callback
113 * Context data for get slave config operations
115 struct GetSlaveConfigData
118 * The id of the slave controller
126 * Context data for controller link operations
128 struct ControllerLinkData
131 * The controller link message
133 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
136 * The id of the host which is hosting the controller to be linked
144 * Date context for OP_SHUTDOWN_PEERS operations
146 struct ShutdownPeersData
149 * The operation completion callback to call
151 GNUNET_TESTBED_OperationCompletionCallback cb;
154 * The closure for the above callback
161 * An entry in the stack for keeping operations which are about to expire
163 struct ExpireOperationEntry
166 * DLL head; new entries are to be inserted here
168 struct ExpireOperationEntry *next;
171 * DLL tail; entries are deleted from here
173 struct ExpireOperationEntry *prev;
176 * The operation. This will be a dangling pointer when the operation is freed
178 const struct GNUNET_TESTBED_Operation *op;
183 * DLL head for list of operations marked for expiry
185 static struct ExpireOperationEntry *exop_head;
188 * DLL tail for list of operation marked for expiry
190 static struct ExpireOperationEntry *exop_tail;
194 * Inserts an operation into the list of operations marked for expiry
196 * @param op the operation to insert
199 exop_insert (struct GNUNET_TESTBED_Operation *op)
201 struct ExpireOperationEntry *entry;
203 entry = GNUNET_malloc (sizeof (struct ExpireOperationEntry));
205 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
210 * Checks if an operation is present in the list of operations marked for
211 * expiry. If the operation is found, it and the tail of operations after it
212 * are removed from the list.
214 * @param op the operation to check
215 * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
216 * the operation is found in the list (the operation is then removed
217 * from the list -- calling this function again with the same
218 * paramenter will return GNUNET_NO)
221 exop_check (const struct GNUNET_TESTBED_Operation *const op)
223 struct ExpireOperationEntry *entry;
224 struct ExpireOperationEntry *entry2;
229 while (NULL != entry)
238 if (GNUNET_NO == found)
240 /* Truncate the tail */
241 while (NULL != entry)
243 entry2 = entry->next;
244 GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry);
253 * Returns the operation context with the given id if found in the Operation
254 * context queues of the controller
256 * @param c the controller whose queues are searched
257 * @param id the id which has to be checked
258 * @return the matching operation context; NULL if no match found
260 static struct OperationContext *
261 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
263 struct OperationContext *opc;
265 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
275 * Handler for forwarded operations
277 * @param c the controller handle
278 * @param opc the opearation context
279 * @param msg the message
282 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
283 struct OperationContext *opc,
284 const struct GNUNET_MessageHeader *msg)
286 struct ForwardedOperationData *fo_data;
289 if (NULL != fo_data->cc)
290 fo_data->cc (fo_data->cc_cls, msg);
291 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
292 GNUNET_free (fo_data);
298 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
299 * controller (testbed service)
301 * @param c the controller handler
302 * @param msg message received
303 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
307 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
309 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
311 struct OperationContext *opc;
312 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
313 void *op_comp_cb_cls;
314 struct GNUNET_TESTBED_EventInformation event;
317 op_id = GNUNET_ntohll (msg->operation_id);
318 LOG_DEBUG ("Operation %lu successful\n", op_id);
319 if (NULL == (opc = find_opc (c, op_id)))
321 LOG_DEBUG ("Operation not found\n");
324 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
326 event.op_cls = opc->op_cls;
327 event.details.operation_finished.emsg = NULL;
328 event.details.operation_finished.generic = NULL;
330 op_comp_cb_cls = NULL;
335 handle_forwarded_operation_msg (c, opc,
336 (const struct GNUNET_MessageHeader *) msg);
340 case OP_PEER_DESTROY:
342 struct GNUNET_TESTBED_Peer *peer;
345 GNUNET_TESTBED_peer_deregister_ (peer);
351 case OP_SHUTDOWN_PEERS:
353 struct ShutdownPeersData *data;
356 op_comp_cb = data->cb;
357 op_comp_cb_cls = data->cb_cls;
360 GNUNET_TESTBED_cleanup_peers_ ();
363 case OP_MANAGE_SERVICE:
365 struct ManageServiceData *data;
367 GNUNET_assert (NULL != (data = opc->data));
368 op_comp_cb = data->cb;
369 op_comp_cb_cls = data->cb_cls;
377 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
378 opc->state = OPC_STATE_FINISHED;
379 exop_insert (event.op);
380 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
383 c->cc (c->cc_cls, &event);
384 if (GNUNET_NO == exop_check (event.op))
388 LOG_DEBUG ("Not calling callback\n");
389 if (NULL != op_comp_cb)
390 op_comp_cb (op_comp_cb_cls, event.op, NULL);
391 /* You could have marked the operation as done by now */
392 GNUNET_break (GNUNET_NO == exop_check (event.op));
398 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
399 * controller (testbed service)
401 * @param c the controller handle
402 * @param msg message received
403 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
407 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
409 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
411 struct OperationContext *opc;
412 struct PeerCreateData *data;
413 struct GNUNET_TESTBED_Peer *peer;
414 struct GNUNET_TESTBED_Operation *op;
415 GNUNET_TESTBED_PeerCreateCallback cb;
419 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
420 ntohs (msg->header.size));
421 op_id = GNUNET_ntohll (msg->operation_id);
422 if (NULL == (opc = find_opc (c, op_id)))
424 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
427 if (OP_FORWARDED == opc->type)
429 handle_forwarded_operation_msg (c, opc,
430 (const struct GNUNET_MessageHeader *) msg);
433 GNUNET_assert (OP_PEER_CREATE == opc->type);
434 GNUNET_assert (NULL != opc->data);
436 GNUNET_assert (NULL != data->peer);
438 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
439 peer->state = PS_CREATED;
440 GNUNET_TESTBED_peer_register_ (peer);
444 GNUNET_free (opc->data);
445 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
446 opc->state = OPC_STATE_FINISHED;
449 cb (cls, peer, NULL);
450 /* You could have marked the operation as done by now */
451 GNUNET_break (GNUNET_NO == exop_check (op));
457 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
458 * controller (testbed service)
460 * @param c the controller handler
461 * @param msg message received
462 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
466 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
467 const struct GNUNET_TESTBED_PeerEventMessage *msg)
469 struct OperationContext *opc;
470 struct GNUNET_TESTBED_Peer *peer;
471 struct PeerEventData *data;
472 GNUNET_TESTBED_PeerChurnCallback pcc;
474 struct GNUNET_TESTBED_EventInformation event;
477 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
478 ntohs (msg->header.size));
479 op_id = GNUNET_ntohll (msg->operation_id);
480 if (NULL == (opc = find_opc (c, op_id)))
482 LOG_DEBUG ("Operation not found\n");
485 if (OP_FORWARDED == opc->type)
487 handle_forwarded_operation_msg (c, opc,
488 (const struct GNUNET_MessageHeader *) msg);
491 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
493 GNUNET_assert (NULL != data);
495 GNUNET_assert (NULL != peer);
496 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
498 event.op_cls = opc->op_cls;
501 case GNUNET_TESTBED_ET_PEER_START:
502 peer->state = PS_STARTED;
503 event.details.peer_start.host = peer->host;
504 event.details.peer_start.peer = peer;
506 case GNUNET_TESTBED_ET_PEER_STOP:
507 peer->state = PS_STOPPED;
508 event.details.peer_stop.peer = peer;
511 GNUNET_assert (0); /* We should never reach this state */
514 pcc_cls = data->pcc_cls;
516 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
517 opc->state = OPC_STATE_FINISHED;
518 exop_insert (event.op);
520 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
524 c->cc (c->cc_cls, &event);
525 if (GNUNET_NO == exop_check (event.op))
530 /* You could have marked the operation as done by now */
531 GNUNET_break (GNUNET_NO == exop_check (event.op));
537 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
538 * controller (testbed service)
540 * @param c the controller handler
541 * @param msg message received
542 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
546 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
547 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
549 struct OperationContext *opc;
550 struct OverlayConnectData *data;
551 GNUNET_TESTBED_OperationCompletionCallback cb;
553 struct GNUNET_TESTBED_EventInformation event;
556 op_id = GNUNET_ntohll (msg->operation_id);
557 if (NULL == (opc = find_opc (c, op_id)))
559 LOG_DEBUG ("Operation not found\n");
562 if (OP_FORWARDED == opc->type)
564 handle_forwarded_operation_msg (c, opc,
565 (const struct GNUNET_MessageHeader *) msg);
568 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
569 GNUNET_assert (NULL != (data = opc->data));
570 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
571 (ntohl (msg->peer2) == data->p2->unique_id));
572 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
574 event.op_cls = opc->op_cls;
577 case GNUNET_TESTBED_ET_CONNECT:
578 event.details.peer_connect.peer1 = data->p1;
579 event.details.peer_connect.peer2 = data->p2;
581 case GNUNET_TESTBED_ET_DISCONNECT:
582 GNUNET_assert (0); /* FIXME: implement */
585 GNUNET_assert (0); /* Should never reach here */
589 cb_cls = data->cb_cls;
590 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
591 opc->state = OPC_STATE_FINISHED;
592 exop_insert (event.op);
594 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
598 c->cc (c->cc_cls, &event);
599 if (GNUNET_NO == exop_check (event.op))
603 cb (cb_cls, opc->op, NULL);
604 /* You could have marked the operation as done by now */
605 GNUNET_break (GNUNET_NO == exop_check (event.op));
611 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
612 * controller (testbed service)
614 * @param c the controller handler
615 * @param msg message received
616 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
620 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
622 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
624 struct OperationContext *opc;
625 struct GNUNET_TESTBED_Peer *peer;
626 struct PeerInfoData *data;
627 struct GNUNET_TESTBED_PeerInformation *pinfo;
628 GNUNET_TESTBED_PeerInfoCallback cb;
632 op_id = GNUNET_ntohll (msg->operation_id);
633 if (NULL == (opc = find_opc (c, op_id)))
635 LOG_DEBUG ("Operation not found\n");
638 if (OP_FORWARDED == opc->type)
640 handle_forwarded_operation_msg (c, opc,
641 (const struct GNUNET_MessageHeader *) msg);
645 GNUNET_assert (NULL != data);
647 GNUNET_assert (NULL != peer);
648 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
649 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
650 pinfo->pit = data->pit;
652 cb_cls = data->cb_cls;
653 GNUNET_assert (NULL != cb);
658 case GNUNET_TESTBED_PIT_IDENTITY:
659 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
660 (void) memcpy (pinfo->result.id, &msg->peer_identity,
661 sizeof (struct GNUNET_PeerIdentity));
663 case GNUNET_TESTBED_PIT_CONFIGURATION:
664 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
665 GNUNET_TESTBED_extract_config_ (&msg->header);
667 case GNUNET_TESTBED_PIT_GENERIC:
668 GNUNET_assert (0); /* never reach here */
672 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
673 opc->state = OPC_STATE_FINISHED;
674 cb (cb_cls, opc->op, pinfo, NULL);
675 /* We dont check whether the operation is marked as done here as the
676 operation contains data (cfg/identify) which will be freed at a later point
683 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
684 * controller (testbed service)
686 * @param c the controller handler
687 * @param msg message received
688 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
692 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
693 const struct GNUNET_TESTBED_OperationFailureEventMessage
696 struct OperationContext *opc;
699 struct GNUNET_TESTBED_EventInformation event;
701 op_id = GNUNET_ntohll (msg->operation_id);
702 if (NULL == (opc = find_opc (c, op_id)))
704 LOG_DEBUG ("Operation not found\n");
707 if (OP_FORWARDED == opc->type)
709 handle_forwarded_operation_msg (c, opc,
710 (const struct GNUNET_MessageHeader *) msg);
713 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
714 opc->state = OPC_STATE_FINISHED;
715 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
717 emsg = "Unknown error";
718 if (OP_PEER_INFO == opc->type)
720 struct PeerInfoData *data;
723 if (NULL != data->cb)
724 data->cb (data->cb_cls, opc->op, NULL, emsg);
726 return GNUNET_YES; /* We do not call controller callback for peer info */
728 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
730 event.op_cls = opc->op_cls;
731 event.details.operation_finished.emsg = emsg;
732 event.details.operation_finished.generic = NULL;
733 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
736 exop_insert (event.op);
737 c->cc (c->cc_cls, &event);
738 if (GNUNET_NO == exop_check (event.op))
745 struct PeerCreateData *data;
748 GNUNET_free (data->peer);
749 if (NULL != data->cb)
750 data->cb (data->cls, NULL, emsg);
757 struct PeerEventData *data;
760 if (NULL != data->pcc)
761 data->pcc (data->pcc_cls, emsg);
765 case OP_PEER_DESTROY:
769 case OP_OVERLAY_CONNECT:
771 struct OverlayConnectData *data;
774 data->failed = GNUNET_YES;
775 if (NULL != data->cb)
776 data->cb (data->cb_cls, opc->op, emsg);
781 case OP_LINK_CONTROLLERS: /* No secondary callback */
783 case OP_SHUTDOWN_PEERS:
785 struct ShutdownPeersData *data;
788 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
792 case OP_MANAGE_SERVICE:
794 struct ManageServiceData *data = opc->data;
795 GNUNET_TESTBED_OperationCompletionCallback cb;
798 GNUNET_assert (NULL != data);
800 cb_cls = data->cb_cls;
803 exop_insert (event.op);
805 cb (cb_cls, opc->op, emsg);
806 /* You could have marked the operation as done by now */
807 GNUNET_break (GNUNET_NO == exop_check (event.op));
818 * Function to build GET_SLAVE_CONFIG message
820 * @param op_id the id this message should contain in its operation id field
821 * @param slave_id the id this message should contain in its slave id field
822 * @return newly allocated SlaveGetConfigurationMessage
824 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
825 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
827 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
830 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
831 msg = GNUNET_malloc (msize);
832 msg->header.size = htons (msize);
834 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
835 msg->operation_id = GNUNET_htonll (op_id);
836 msg->slave_id = htonl (slave_id);
842 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
845 * @param c the controller handler
846 * @param msg message received
847 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
851 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
852 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
854 struct OperationContext *opc;
856 struct GNUNET_TESTBED_EventInformation event;
858 op_id = GNUNET_ntohll (msg->operation_id);
859 if (NULL == (opc = find_opc (c, op_id)))
861 LOG_DEBUG ("Operation not found\n");
864 if (OP_GET_SLAVE_CONFIG != opc->type)
869 opc->state = OPC_STATE_FINISHED;
870 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
871 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
874 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
875 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
877 event.op_cls = opc->op_cls;
878 event.details.operation_finished.generic = opc->data;
879 event.details.operation_finished.emsg = NULL;
880 c->cc (c->cc_cls, &event);
887 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
890 * @param c the controller handler
891 * @param msg message received
892 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
896 handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
898 GNUNET_TESTBED_ControllerLinkResponse *msg)
900 struct OperationContext *opc;
901 struct ControllerLinkData *data;
902 struct GNUNET_CONFIGURATION_Handle *cfg;
903 struct GNUNET_TESTBED_Host *host;
906 struct GNUNET_TESTBED_EventInformation event;
908 op_id = GNUNET_ntohll (msg->operation_id);
909 if (NULL == (opc = find_opc (c, op_id)))
911 LOG_DEBUG ("Operation not found\n");
914 if (OP_FORWARDED == opc->type)
916 handle_forwarded_operation_msg (c, opc,
917 (const struct GNUNET_MessageHeader *) msg);
920 if (OP_LINK_CONTROLLERS != opc->type)
925 GNUNET_assert (NULL != (data = opc->data));
926 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
927 GNUNET_assert (NULL != host);
930 opc->state = OPC_STATE_FINISHED;
931 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
932 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
934 event.op_cls = opc->op_cls;
935 event.details.operation_finished.emsg = NULL;
936 event.details.operation_finished.generic = NULL;
939 if (GNUNET_NO == ntohs (msg->success))
941 emsg = GNUNET_malloc (ntohs (msg->header.size)
943 GNUNET_TESTBED_ControllerLinkResponse) + 1);
944 memcpy (emsg, &msg[1], ntohs (msg->header.size)
946 GNUNET_TESTBED_ControllerLinkResponse));
947 event.details.operation_finished.emsg = emsg;
951 if (0 != ntohs (msg->config_size))
953 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
954 GNUNET_assert (NULL != cfg);
955 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
958 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
961 c->cc (c->cc_cls, &event);
964 LOG_DEBUG ("Not calling callback\n");
966 GNUNET_CONFIGURATION_destroy (cfg);
967 GNUNET_free_non_null (emsg);
973 * Handler for messages from controller (testbed service)
975 * @param cls the controller handler
976 * @param msg message received, NULL on timeout or fatal error
979 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
981 struct GNUNET_TESTBED_Controller *c = cls;
985 c->in_receive = GNUNET_NO;
986 /* FIXME: Add checks for message integrity */
989 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
993 msize = ntohs (msg->size);
994 switch (ntohs (msg->type))
996 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
997 GNUNET_assert (msize >=
998 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
1000 GNUNET_TESTBED_host_handle_addhostconfirm_
1001 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
1003 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
1004 GNUNET_assert (msize ==
1006 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
1008 handle_opsuccess (c,
1010 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
1013 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
1014 GNUNET_assert (msize >=
1015 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
1017 handle_op_fail_event (c,
1019 GNUNET_TESTBED_OperationFailureEventMessage *)
1022 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
1023 GNUNET_assert (msize ==
1025 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1027 handle_peer_create_success (c,
1029 GNUNET_TESTBED_PeerCreateSuccessEventMessage
1032 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
1033 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1035 handle_peer_event (c,
1036 (const struct GNUNET_TESTBED_PeerEventMessage *)
1040 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1041 GNUNET_assert (msize >=
1043 GNUNET_TESTBED_PeerConfigurationInformationMessage));
1045 handle_peer_config (c,
1047 GNUNET_TESTBED_PeerConfigurationInformationMessage
1050 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
1051 GNUNET_assert (msize ==
1052 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1054 handle_peer_conevent (c,
1056 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1058 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1059 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1061 handle_slave_config (c,
1062 (const struct GNUNET_TESTBED_SlaveConfiguration *)
1065 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1067 handle_link_controllers_result (c,
1069 GNUNET_TESTBED_ControllerLinkResponse
1075 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1077 c->in_receive = GNUNET_YES;
1078 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1079 GNUNET_TIME_UNIT_FOREVER_REL);
1085 * Function called to notify a client about the connection begin ready to queue
1086 * more data. "buf" will be NULL and "size" zero if the connection was closed
1087 * for writing in the meantime.
1089 * @param cls closure
1090 * @param size number of bytes available in buf
1091 * @param buf where the callee should write the message
1092 * @return number of bytes written to buf
1095 transmit_ready_notify (void *cls, size_t size, void *buf)
1097 struct GNUNET_TESTBED_Controller *c = cls;
1098 struct MessageQueue *mq_entry;
1101 mq_entry = c->mq_head;
1102 GNUNET_assert (NULL != mq_entry);
1103 if ((0 == size) && (NULL == buf)) /* Timeout */
1105 LOG_DEBUG ("Message sending timed out -- retrying\n");
1107 GNUNET_CLIENT_notify_transmit_ready (c->client,
1108 ntohs (mq_entry->msg->size),
1109 TIMEOUT_REL, GNUNET_YES,
1110 &transmit_ready_notify, c);
1113 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1114 size = ntohs (mq_entry->msg->size);
1115 memcpy (buf, mq_entry->msg, size);
1116 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1117 ntohs (mq_entry->msg->type), size);
1118 GNUNET_free (mq_entry->msg);
1119 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1120 GNUNET_free (mq_entry);
1121 mq_entry = c->mq_head;
1122 if (NULL != mq_entry)
1124 GNUNET_CLIENT_notify_transmit_ready (c->client,
1125 ntohs (mq_entry->msg->size),
1126 TIMEOUT_REL, GNUNET_YES,
1127 &transmit_ready_notify, c);
1128 if (GNUNET_NO == c->in_receive)
1130 c->in_receive = GNUNET_YES;
1131 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1132 GNUNET_TIME_UNIT_FOREVER_REL);
1139 * Queues a message in send queue for sending to the service
1141 * @param controller the handle to the controller
1142 * @param msg the message to queue
1145 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1146 struct GNUNET_MessageHeader *msg)
1148 struct MessageQueue *mq_entry;
1152 type = ntohs (msg->type);
1153 size = ntohs (msg->size);
1154 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1155 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1156 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1157 mq_entry->msg = msg;
1158 LOG (GNUNET_ERROR_TYPE_DEBUG,
1159 "Queueing message of type %u, size %u for sending\n", type,
1161 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1163 if (NULL == controller->th)
1165 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1166 TIMEOUT_REL, GNUNET_YES,
1167 &transmit_ready_notify,
1173 * Sends the given message as an operation. The given callback is called when a
1174 * reply for the operation is available. Call
1175 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1176 * operation context if the cc hasn't been called
1178 * @param controller the controller to which the message has to be sent
1179 * @param operation_id the operation id of the message
1180 * @param msg the message to send
1181 * @param cc the callback to call when reply is available
1182 * @param cc_cls the closure for the above callback
1183 * @return the operation context which can be used to cancel the forwarded
1186 struct OperationContext *
1187 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1188 *controller, uint64_t operation_id,
1189 const struct GNUNET_MessageHeader *msg,
1190 GNUNET_CLIENT_MessageHandler cc,
1193 struct OperationContext *opc;
1194 struct ForwardedOperationData *data;
1195 struct GNUNET_MessageHeader *dup_msg;
1198 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1200 data->cc_cls = cc_cls;
1201 opc = GNUNET_malloc (sizeof (struct OperationContext));
1202 opc->c = controller;
1203 opc->type = OP_FORWARDED;
1205 opc->id = operation_id;
1206 msize = ntohs (msg->size);
1207 dup_msg = GNUNET_malloc (msize);
1208 (void) memcpy (dup_msg, msg, msize);
1209 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1210 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1217 * Function to cancel an operation created by simply forwarding an operation
1220 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1223 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1225 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1226 GNUNET_free (opc->data);
1232 * Function to call to start a link-controllers type operation once all queues
1233 * the operation is part of declare that the operation can be activated.
1235 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1238 opstart_link_controllers (void *cls)
1240 struct OperationContext *opc = cls;
1241 struct ControllerLinkData *data;
1242 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1244 GNUNET_assert (NULL != opc->data);
1248 opc->state = OPC_STATE_STARTED;
1249 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1250 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1255 * Callback which will be called when link-controllers type operation is released
1257 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1260 oprelease_link_controllers (void *cls)
1262 struct OperationContext *opc = cls;
1263 struct ControllerLinkData *data;
1268 case OPC_STATE_INIT:
1269 GNUNET_free (data->msg);
1271 case OPC_STATE_STARTED:
1272 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1274 case OPC_STATE_FINISHED:
1277 GNUNET_free_non_null (data);
1283 * Function to be called when get slave config operation is ready
1285 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1288 opstart_get_slave_config (void *cls)
1290 struct OperationContext *opc = cls;
1291 struct GetSlaveConfigData *data = opc->data;
1292 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1294 GNUNET_assert (NULL != data);
1295 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1296 GNUNET_free (opc->data);
1299 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1300 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1301 opc->state = OPC_STATE_STARTED;
1306 * Function to be called when get slave config operation is cancelled or finished
1308 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1311 oprelease_get_slave_config (void *cls)
1313 struct OperationContext *opc = cls;
1317 case OPC_STATE_INIT:
1318 GNUNET_free (opc->data);
1320 case OPC_STATE_STARTED:
1321 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1323 case OPC_STATE_FINISHED:
1324 if (NULL != opc->data)
1325 GNUNET_CONFIGURATION_destroy (opc->data);
1333 * Start a controller process using the given configuration at the
1336 * @param host host to run the controller on; This should be the same host if
1337 * the controller was previously started with
1338 * GNUNET_TESTBED_controller_start; NULL for localhost
1339 * @param event_mask bit mask with set of events to call 'cc' for;
1340 * or-ed values of "1LL" shifted by the
1341 * respective 'enum GNUNET_TESTBED_EventType'
1342 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1343 * @param cc controller callback to invoke on events
1344 * @param cc_cls closure for cc
1345 * @return handle to the controller
1347 struct GNUNET_TESTBED_Controller *
1348 GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1349 uint64_t event_mask,
1350 GNUNET_TESTBED_ControllerCallback cc,
1353 struct GNUNET_TESTBED_Controller *controller;
1354 struct GNUNET_TESTBED_InitMessage *msg;
1355 const struct GNUNET_CONFIGURATION_Handle *cfg;
1356 const char *controller_hostname;
1357 unsigned long long max_parallel_operations;
1358 unsigned long long max_parallel_service_connections;
1359 unsigned long long max_parallel_topology_config_operations;
1361 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
1363 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1364 "MAX_PARALLEL_OPERATIONS",
1365 &max_parallel_operations))
1371 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1372 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1373 &max_parallel_service_connections))
1379 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1380 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1381 &max_parallel_topology_config_operations))
1386 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1387 controller->cc = cc;
1388 controller->cc_cls = cc_cls;
1389 controller->event_mask = event_mask;
1390 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1391 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1392 if (NULL == controller->client)
1394 GNUNET_TESTBED_controller_disconnect (controller);
1399 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1400 if (NULL == host) /* If the above host create fails */
1402 LOG (GNUNET_ERROR_TYPE_WARNING,
1403 "Treating NULL host as localhost. Multiple references to localhost "
1404 "may break when localhost freed before calling disconnect \n");
1405 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1409 controller->aux_host = GNUNET_YES;
1412 GNUNET_assert (NULL != host);
1413 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1414 controller->host = host;
1415 controller->opq_parallel_operations =
1416 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1417 max_parallel_operations);
1418 controller->opq_parallel_service_connections =
1419 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1420 max_parallel_service_connections);
1421 controller->opq_parallel_topology_config_operations =
1422 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1423 max_parallel_topology_config_operations);
1424 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1425 if (NULL == controller_hostname)
1426 controller_hostname = "127.0.0.1";
1428 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1429 strlen (controller_hostname) + 1);
1430 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1432 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1433 strlen (controller_hostname) + 1);
1434 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1435 msg->event_mask = GNUNET_htonll (controller->event_mask);
1436 strcpy ((char *) &msg[1], controller_hostname);
1437 GNUNET_TESTBED_queue_message_ (controller,
1438 (struct GNUNET_MessageHeader *) msg);
1444 * Configure shared services at a controller. Using this function,
1445 * you can specify that certain services (such as "resolver")
1446 * should not be run for each peer but instead be shared
1447 * across N peers on the specified host. This function
1448 * must be called before any peers are created at the host.
1450 * @param controller controller to configure
1451 * @param service_name name of the service to share
1452 * @param num_peers number of peers that should share one instance
1453 * of the specified service (1 for no sharing is the default),
1454 * use 0 to disable the service
1457 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1459 const char *service_name,
1462 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1463 uint16_t service_name_size;
1466 service_name_size = strlen (service_name) + 1;
1468 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1470 msg = GNUNET_malloc (msg_size);
1471 msg->header.size = htons (msg_size);
1472 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1473 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1474 msg->num_peers = htonl (num_peers);
1475 memcpy (&msg[1], service_name, service_name_size);
1476 GNUNET_TESTBED_queue_message_ (controller,
1477 (struct GNUNET_MessageHeader *) msg);
1478 GNUNET_break (0); /* This function is not yet implemented on the
1479 * testbed service */
1484 * disconnects from the controller.
1486 * @param controller handle to controller to stop
1489 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1492 struct MessageQueue *mq_entry;
1494 if (NULL != controller->th)
1495 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1496 /* Clear the message queue */
1497 while (NULL != (mq_entry = controller->mq_head))
1499 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1501 GNUNET_free (mq_entry->msg);
1502 GNUNET_free (mq_entry);
1504 if (NULL != controller->client)
1505 GNUNET_CLIENT_disconnect (controller->client);
1506 GNUNET_CONFIGURATION_destroy (controller->cfg);
1507 if (GNUNET_YES == controller->aux_host)
1508 GNUNET_TESTBED_host_destroy (controller->host);
1509 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1510 GNUNET_TESTBED_operation_queue_destroy_
1511 (controller->opq_parallel_service_connections);
1512 GNUNET_TESTBED_operation_queue_destroy_
1513 (controller->opq_parallel_topology_config_operations);
1514 GNUNET_free (controller);
1519 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1522 * @param op_cls the operation closure for the event which is generated to
1523 * signal success or failure of this operation
1524 * @param master handle to the master controller who creates the association
1525 * @param delegated_host_id id of the host to which requests should be delegated
1526 * @param slave_host_id id of the host which is used to run the slave controller
1527 * @param sxcfg serialized and compressed configuration
1528 * @param sxcfg_size the size sxcfg
1529 * @param scfg_size the size of uncompressed serialized configuration
1530 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1531 * be started by the slave controller; GNUNET_NO if the slave
1532 * controller has to connect to the already started delegated
1533 * controller via TCP/IP
1534 * @return the operation handle
1536 struct GNUNET_TESTBED_Operation *
1537 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1538 struct GNUNET_TESTBED_Controller *master,
1539 uint32_t delegated_host_id,
1540 uint32_t slave_host_id, const char *sxcfg,
1541 size_t sxcfg_size, size_t scfg_size,
1544 struct OperationContext *opc;
1545 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1546 struct ControllerLinkData *data;
1549 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1550 msg = GNUNET_malloc (msg_size);
1551 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1552 msg->header.size = htons (msg_size);
1553 msg->delegated_host_id = htonl (delegated_host_id);
1554 msg->slave_host_id = htonl (slave_host_id);
1555 msg->config_size = htons ((uint16_t) scfg_size);
1556 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1557 memcpy (&msg[1], sxcfg, sxcfg_size);
1558 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1560 data->host_id = delegated_host_id;
1561 opc = GNUNET_malloc (sizeof (struct OperationContext));
1564 opc->type = OP_LINK_CONTROLLERS;
1565 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1566 opc->state = OPC_STATE_INIT;
1567 opc->op_cls = op_cls;
1568 msg->operation_id = GNUNET_htonll (opc->id);
1570 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1571 &oprelease_link_controllers);
1572 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1574 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1580 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1581 * serialized and compressed
1583 * @param op_cls the operation closure for the event which is generated to
1584 * signal success or failure of this operation
1585 * @param master handle to the master controller who creates the association
1586 * @param delegated_host requests to which host should be delegated; cannot be NULL
1587 * @param slave_host which host is used to run the slave controller; use NULL to
1588 * make the master controller connect to the delegated host
1589 * @param sxcfg serialized and compressed configuration
1590 * @param sxcfg_size the size sxcfg
1591 * @param scfg_size the size of uncompressed serialized configuration
1592 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1593 * be started by the slave controller; GNUNET_NO if the slave
1594 * controller has to connect to the already started delegated
1595 * controller via TCP/IP
1596 * @return the operation handle
1598 struct GNUNET_TESTBED_Operation *
1599 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1600 struct GNUNET_TESTBED_Controller *master,
1601 struct GNUNET_TESTBED_Host *delegated_host,
1602 struct GNUNET_TESTBED_Host *slave_host,
1603 const char *sxcfg, size_t sxcfg_size,
1604 size_t scfg_size, int is_subordinate)
1606 uint32_t delegated_host_id;
1607 uint32_t slave_host_id;
1609 GNUNET_assert (GNUNET_YES ==
1610 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1611 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1613 GNUNET_TESTBED_host_get_id_ ((NULL !=
1614 slave_host) ? slave_host : master->host);
1615 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1616 GNUNET_assert (GNUNET_YES ==
1617 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1619 return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1620 slave_host_id, sxcfg, sxcfg_size,
1621 scfg_size, is_subordinate);
1626 * Compresses given configuration using zlib compress
1628 * @param config the serialized configuration
1629 * @param size the size of config
1630 * @param xconfig will be set to the compressed configuration (memory is fresly
1632 * @return the size of the xconfig
1635 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1640 xsize = compressBound ((uLong) size);
1641 *xconfig = GNUNET_malloc (xsize);
1642 GNUNET_assert (Z_OK ==
1643 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1644 (const Bytef *) config, (uLongf) size,
1651 * Function to serialize and compress using zlib a configuration through a
1652 * configuration handle
1654 * @param cfg the configuration
1655 * @param size the size of configuration when serialize. Will be set on success.
1656 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1657 * @return the serialized and compressed configuration
1660 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1661 size_t *size, size_t *xsize)
1668 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1669 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1670 GNUNET_free (config);
1678 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1681 * @param op_cls the operation closure for the event which is generated to
1682 * signal success or failure of this operation
1683 * @param master handle to the master controller who creates the association
1684 * @param delegated_host_id id of the host to which requests should be
1685 * delegated; cannot be NULL
1686 * @param slave_host_id id of the host which should connect to controller
1687 * running on delegated host ; use NULL to make the master controller
1688 * connect to the delegated host
1689 * @param slave_cfg configuration to use for the slave controller
1690 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1691 * be started by the slave controller; GNUNET_NO if the slave
1692 * controller has to connect to the already started delegated
1693 * controller via TCP/IP
1694 * @return the operation handle
1696 struct GNUNET_TESTBED_Operation *
1697 GNUNET_TESTBED_controller_link_ (void *op_cls,
1698 struct GNUNET_TESTBED_Controller *master,
1699 uint32_t delegated_host_id,
1700 uint32_t slave_host_id,
1701 const struct GNUNET_CONFIGURATION_Handle
1702 *slave_cfg, int is_subordinate)
1704 struct GNUNET_TESTBED_Operation *op;
1710 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1711 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1712 GNUNET_free (config);
1713 /* Configuration doesn't fit in 1 message */
1714 GNUNET_assert ((UINT16_MAX -
1715 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)) >=
1717 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1718 slave_host_id, (const char *) cconfig,
1719 cc_size, config_size, is_subordinate);
1720 GNUNET_free (cconfig);
1726 * Create a link from slave controller to delegated controller. Whenever the
1727 * master controller is asked to start a peer at the delegated controller the
1728 * request will be routed towards slave controller (if a route exists). The
1729 * slave controller will then route it to the delegated controller. The
1730 * configuration of the delegated controller is given and is used to either
1731 * create the delegated controller or to connect to an existing controller. Note
1732 * that while starting the delegated controller the configuration will be
1733 * modified to accommodate available free ports. the 'is_subordinate' specifies
1734 * if the given delegated controller should be started and managed by the slave
1735 * controller, or if the delegated controller already has a master and the slave
1736 * controller connects to it as a non master controller. The success or failure
1737 * of this operation will be signalled through the
1738 * GNUNET_TESTBED_ControllerCallback() with an event of type
1739 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1741 * @param op_cls the operation closure for the event which is generated to
1742 * signal success or failure of this operation
1743 * @param master handle to the master controller who creates the association
1744 * @param delegated_host requests to which host should be delegated; cannot be NULL
1745 * @param slave_host which host is used to run the slave controller; use NULL to
1746 * make the master controller connect to the delegated host
1747 * @param slave_cfg configuration to use for the slave controller
1748 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1749 * be started by the slave controller; GNUNET_NO if the slave
1750 * controller has to connect to the already started delegated
1751 * controller via TCP/IP
1752 * @return the operation handle
1754 struct GNUNET_TESTBED_Operation *
1755 GNUNET_TESTBED_controller_link (void *op_cls,
1756 struct GNUNET_TESTBED_Controller *master,
1757 struct GNUNET_TESTBED_Host *delegated_host,
1758 struct GNUNET_TESTBED_Host *slave_host,
1759 const struct GNUNET_CONFIGURATION_Handle
1760 *slave_cfg, int is_subordinate)
1762 uint32_t slave_host_id;
1763 uint32_t delegated_host_id;
1765 GNUNET_assert (GNUNET_YES ==
1766 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1768 GNUNET_TESTBED_host_get_id_ ((NULL !=
1769 slave_host) ? slave_host : master->host);
1770 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1771 if ((NULL != slave_host) && (0 != slave_host_id))
1772 GNUNET_assert (GNUNET_YES ==
1773 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1774 return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
1776 GNUNET_TESTBED_host_get_cfg_ (delegated_host),
1783 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1784 * check. Another difference is that this function takes the id of the slave
1787 * @param op_cls the closure for the operation
1788 * @param master the handle to master controller
1789 * @param slave_host_id id of the host where the slave controller is running to
1790 * the slave_host should remain valid until this operation is cancelled
1791 * or marked as finished
1792 * @return the operation handle;
1794 struct GNUNET_TESTBED_Operation *
1795 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1796 struct GNUNET_TESTBED_Controller *master,
1797 uint32_t slave_host_id)
1799 struct OperationContext *opc;
1800 struct GetSlaveConfigData *data;
1802 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1803 data->slave_id = slave_host_id;
1804 opc = GNUNET_malloc (sizeof (struct OperationContext));
1805 opc->state = OPC_STATE_INIT;
1807 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1808 opc->type = OP_GET_SLAVE_CONFIG;
1810 opc->op_cls = op_cls;
1812 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1813 &oprelease_get_slave_config);
1814 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1816 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1822 * Function to acquire the configuration of a running slave controller. The
1823 * completion of the operation is signalled through the controller_cb from
1824 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1825 * handle to the configuration is available in the generic pointer of
1826 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1828 * @param op_cls the closure for the operation
1829 * @param master the handle to master controller
1830 * @param slave_host the host where the slave controller is running; the handle
1831 * to the slave_host should remain valid until this operation is
1832 * cancelled or marked as finished
1833 * @return the operation handle; NULL if the slave_host is not registered at
1836 struct GNUNET_TESTBED_Operation *
1837 GNUNET_TESTBED_get_slave_config (void *op_cls,
1838 struct GNUNET_TESTBED_Controller *master,
1839 struct GNUNET_TESTBED_Host *slave_host)
1841 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1843 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1844 GNUNET_TESTBED_host_get_id_
1850 * Ask the testbed controller to write the current overlay topology to
1851 * a file. Naturally, the file will only contain a snapshot as the
1852 * topology may evolve all the time.
1854 * @param controller overlay controller to inspect
1855 * @param filename name of the file the topology should
1859 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1861 const char *filename)
1868 * Creates a helper initialization message. This function is here because we
1869 * want to use this in testing
1871 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1872 * HOST(all connections form this ip are permitted by the testbed) when
1873 * starting testbed controller at host. This can either be a single ip
1874 * address or a network address in CIDR notation.
1875 * @param hostname the hostname of the destination this message is intended for
1876 * @param cfg the configuration that has to used to start the testbed service
1878 * @return the initialization message
1880 struct GNUNET_TESTBED_HelperInit *
1881 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1882 const char *hostname,
1883 const struct GNUNET_CONFIGURATION_Handle
1886 struct GNUNET_TESTBED_HelperInit *msg;
1890 size_t xconfig_size;
1891 uint16_t trusted_ip_len;
1892 uint16_t hostname_len;
1895 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1896 GNUNET_assert (NULL != config);
1898 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1899 GNUNET_free (config);
1900 trusted_ip_len = strlen (trusted_ip);
1901 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1903 xconfig_size + trusted_ip_len + 1 +
1904 sizeof (struct GNUNET_TESTBED_HelperInit);
1905 msg_size += hostname_len;
1906 msg = GNUNET_realloc (xconfig, msg_size);
1907 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1909 msg->header.size = htons (msg_size);
1910 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1911 msg->trusted_ip_size = htons (trusted_ip_len);
1912 msg->hostname_size = htons (hostname_len);
1913 msg->config_size = htons (config_size);
1914 (void) strcpy ((char *) &msg[1], trusted_ip);
1915 if (0 != hostname_len)
1916 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1923 * Signal that the information from an operation has been fully
1924 * processed. This function MUST be called for each event
1925 * of type 'operation_finished' to fully remove the operation
1926 * from the operation queue. After calling this function, the
1927 * 'op_result' becomes invalid (!).
1929 * @param operation operation to signal completion for
1932 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1934 (void) exop_check (operation);
1935 GNUNET_TESTBED_operation_release_ (operation);
1940 * Generates configuration by uncompressing configuration in given message. The
1941 * given message should be of the following types:
1942 * GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION,
1943 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1944 * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
1945 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
1946 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1948 * @param msg the message containing compressed configuration
1949 * @return handle to the parsed configuration; NULL upon error while parsing the message
1951 struct GNUNET_CONFIGURATION_Handle *
1952 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1954 struct GNUNET_CONFIGURATION_Handle *cfg;
1961 switch (ntohs (msg->type))
1963 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1965 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1968 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1969 data_len = (uLong) ntohs (imsg->config_size);
1971 ntohs (imsg->header.size) -
1972 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1973 xdata = (const Bytef *) &imsg[1];
1976 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1978 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1980 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1981 data_len = (uLong) ntohs (imsg->config_size);
1983 ntohs (imsg->header.size) -
1984 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1985 xdata = (const Bytef *) &imsg[1];
1988 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1990 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1993 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1994 data_len = (uLong) ntohs (imsg->config_size);
1995 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1996 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1997 xdata_len = ntohs (imsg->header.size) - osize;
1998 xdata = (const Bytef *) ((const void *) imsg + osize);
2001 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
2003 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
2005 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
2006 data_len = ntohs (imsg->config_size);
2007 xdata_len = ntohs (imsg->header.size) -
2008 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
2009 xdata = (const Bytef *) &imsg[1];
2012 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS:
2014 const struct GNUNET_TESTBED_ControllerLinkRequest *imsg;
2015 imsg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) msg;
2016 data_len = ntohs (imsg->config_size);
2017 xdata_len = ntohs (imsg->header.size) - sizeof (const struct
2018 GNUNET_TESTBED_ControllerLinkRequest);
2019 xdata = (const Bytef *) &imsg[1];
2025 data = GNUNET_malloc (data_len);
2026 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2029 GNUNET_break_op (0);
2032 cfg = GNUNET_CONFIGURATION_create ();
2034 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2039 GNUNET_break_op (0);
2048 * Checks the integrity of the OperationFailureEventMessage and if good returns
2049 * the error message it contains.
2051 * @param msg the OperationFailureEventMessage
2052 * @return the error message
2055 GNUNET_TESTBED_parse_error_string_ (const struct
2056 GNUNET_TESTBED_OperationFailureEventMessage
2062 msize = ntohs (msg->header.size);
2063 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2065 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2066 emsg = (const char *) &msg[1];
2067 if ('\0' != emsg[msize - 1])
2077 * Function to return the operation id for a controller. The operation id is
2078 * created from the controllers host id and its internal operation counter.
2080 * @param controller the handle to the controller whose operation id has to be incremented
2081 * @return the incremented operation id.
2084 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2088 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2089 op_id = op_id << 32;
2090 op_id |= (uint64_t) controller->operation_counter++;
2096 * Function called when a shutdown peers operation is ready
2098 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2101 opstart_shutdown_peers (void *cls)
2103 struct OperationContext *opc = cls;
2104 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2106 opc->state = OPC_STATE_STARTED;
2107 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2109 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2110 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2111 msg->operation_id = GNUNET_htonll (opc->id);
2112 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
2113 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
2118 * Callback which will be called when shutdown peers operation is released
2120 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2123 oprelease_shutdown_peers (void *cls)
2125 struct OperationContext *opc = cls;
2129 case OPC_STATE_STARTED:
2130 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
2131 /* no break; continue */
2132 case OPC_STATE_INIT:
2133 GNUNET_free (opc->data);
2135 case OPC_STATE_FINISHED:
2143 * Stops and destroys all peers. Is equivalent of calling
2144 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2145 * except that the peer stop event and operation finished event corresponding to
2146 * the respective functions are not generated. This function should be called
2147 * when there are no other pending operations. If there are pending operations,
2148 * it will return NULL
2150 * @param controller the controller to send this message to
2151 * @param op_cls closure for the operation
2152 * @param cb the callback to call when all peers are stopped and destroyed
2153 * @param cb_cls the closure for the callback
2154 * @return operation handle on success; NULL if any pending operations are
2157 struct GNUNET_TESTBED_Operation *
2158 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *controller,
2160 GNUNET_TESTBED_OperationCompletionCallback cb,
2163 struct OperationContext *opc;
2164 struct ShutdownPeersData *data;
2166 if (NULL != controller->ocq_head)
2168 data = GNUNET_malloc (sizeof (struct ShutdownPeersData));
2170 data->cb_cls = cb_cls;
2171 opc = GNUNET_malloc (sizeof (struct OperationContext));
2172 opc->c = controller;
2173 opc->op_cls = op_cls;
2175 opc->id = GNUNET_TESTBED_get_next_op_id (controller);
2176 opc->type = OP_SHUTDOWN_PEERS;
2177 opc->state = OPC_STATE_INIT;
2178 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2179 &oprelease_shutdown_peers);
2180 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2182 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2187 /* end of testbed_api.c */