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_new (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 * Context information to be used while searching for operation contexts
258 * The result of the search
260 struct OperationContext *opc;
263 * The id of the operation context we are searching for
270 * Search iterator for searching an operation context
272 * @param cls the serach context
273 * @param key current key code
274 * @param value value in the hash map
275 * @return GNUNET_YES if we should continue to
280 opc_search_iterator (void *cls, uint32_t key, void *value)
282 struct SearchContext *sc = cls;
283 struct OperationContext *opc = value;
285 GNUNET_assert (NULL != opc);
286 GNUNET_assert (NULL == sc->opc);
287 if (opc->id != sc->id)
295 * Returns the operation context with the given id if found in the Operation
296 * context queues of the controller
298 * @param c the controller whose operation context map is searched
299 * @param id the id which has to be checked
300 * @return the matching operation context; NULL if no match found
302 static struct OperationContext *
303 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
305 struct SearchContext sc;
309 GNUNET_assert (NULL != c->opc_map);
311 GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id,
312 &opc_search_iterator, &sc))
319 * Inserts the given operation context into the operation context map of the
320 * given controller. Creates the operation context map if one does not exist
323 * @param c the controller
324 * @param opc the operation context to be inserted
327 GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
328 struct OperationContext *opc)
330 if (NULL == c->opc_map)
331 c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
332 GNUNET_assert (GNUNET_OK ==
333 GNUNET_CONTAINER_multihashmap32_put (c->opc_map,
334 (uint32_t) opc->id, opc,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
340 * Removes the given operation context from the operation context map of the
343 * @param c the controller
344 * @param opc the operation context to remove
347 GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
348 struct OperationContext *opc)
350 GNUNET_assert (NULL != c->opc_map);
351 GNUNET_assert (GNUNET_YES ==
352 GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
355 if ( (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
356 && (NULL != c->opcq_empty_cb) )
357 c->opcq_empty_cb (c->opcq_empty_cls);
362 * Handler for forwarded operations
364 * @param c the controller handle
365 * @param opc the opearation context
366 * @param msg the message
369 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
370 struct OperationContext *opc,
371 const struct GNUNET_MessageHeader *msg)
373 struct ForwardedOperationData *fo_data;
376 if (NULL != fo_data->cc)
377 fo_data->cc (fo_data->cc_cls, msg);
378 GNUNET_TESTBED_remove_opc_ (c, opc);
379 GNUNET_free (fo_data);
385 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
386 * controller (testbed service)
388 * @param c the controller handler
389 * @param msg message received
390 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
394 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
396 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
398 struct OperationContext *opc;
399 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
400 void *op_comp_cb_cls;
401 struct GNUNET_TESTBED_EventInformation event;
404 op_id = GNUNET_ntohll (msg->operation_id);
405 LOG_DEBUG ("Operation %lu successful\n", op_id);
406 if (NULL == (opc = find_opc (c, op_id)))
408 LOG_DEBUG ("Operation not found\n");
411 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
413 event.op_cls = opc->op_cls;
414 event.details.operation_finished.emsg = NULL;
415 event.details.operation_finished.generic = NULL;
417 op_comp_cb_cls = NULL;
422 handle_forwarded_operation_msg (c, opc,
423 (const struct GNUNET_MessageHeader *) msg);
427 case OP_PEER_DESTROY:
429 struct GNUNET_TESTBED_Peer *peer;
432 GNUNET_TESTBED_peer_deregister_ (peer);
438 case OP_SHUTDOWN_PEERS:
440 struct ShutdownPeersData *data;
443 op_comp_cb = data->cb;
444 op_comp_cb_cls = data->cb_cls;
447 GNUNET_TESTBED_cleanup_peers_ ();
450 case OP_MANAGE_SERVICE:
452 struct ManageServiceData *data;
454 GNUNET_assert (NULL != (data = opc->data));
455 op_comp_cb = data->cb;
456 op_comp_cb_cls = data->cb_cls;
461 case OP_PEER_RECONFIGURE:
466 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
467 opc->state = OPC_STATE_FINISHED;
468 exop_insert (event.op);
469 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
472 c->cc (c->cc_cls, &event);
473 if (GNUNET_NO == exop_check (event.op))
477 LOG_DEBUG ("Not calling callback\n");
478 if (NULL != op_comp_cb)
479 op_comp_cb (op_comp_cb_cls, event.op, NULL);
480 /* You could have marked the operation as done by now */
481 GNUNET_break (GNUNET_NO == exop_check (event.op));
487 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
488 * controller (testbed service)
490 * @param c the controller handle
491 * @param msg message received
492 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
496 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
498 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
500 struct OperationContext *opc;
501 struct PeerCreateData *data;
502 struct GNUNET_TESTBED_Peer *peer;
503 struct GNUNET_TESTBED_Operation *op;
504 GNUNET_TESTBED_PeerCreateCallback cb;
508 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
509 ntohs (msg->header.size));
510 op_id = GNUNET_ntohll (msg->operation_id);
511 if (NULL == (opc = find_opc (c, op_id)))
513 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
516 if (OP_FORWARDED == opc->type)
518 handle_forwarded_operation_msg (c, opc,
519 (const struct GNUNET_MessageHeader *) msg);
522 GNUNET_assert (OP_PEER_CREATE == opc->type);
523 GNUNET_assert (NULL != opc->data);
525 GNUNET_assert (NULL != data->peer);
527 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
528 peer->state = TESTBED_PS_CREATED;
529 GNUNET_TESTBED_peer_register_ (peer);
533 GNUNET_free (opc->data);
534 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
535 opc->state = OPC_STATE_FINISHED;
538 cb (cls, peer, NULL);
539 /* You could have marked the operation as done by now */
540 GNUNET_break (GNUNET_NO == exop_check (op));
546 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
547 * controller (testbed service)
549 * @param c the controller handler
550 * @param msg message received
551 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
555 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
556 const struct GNUNET_TESTBED_PeerEventMessage *msg)
558 struct OperationContext *opc;
559 struct GNUNET_TESTBED_Peer *peer;
560 struct PeerEventData *data;
561 GNUNET_TESTBED_PeerChurnCallback pcc;
563 struct GNUNET_TESTBED_EventInformation event;
567 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
568 ntohs (msg->header.size));
569 op_id = GNUNET_ntohll (msg->operation_id);
570 if (NULL == (opc = find_opc (c, op_id)))
572 LOG_DEBUG ("Operation not found\n");
575 if (OP_FORWARDED == opc->type)
577 handle_forwarded_operation_msg (c, opc,
578 (const struct GNUNET_MessageHeader *) msg);
581 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
583 GNUNET_assert (NULL != data);
585 GNUNET_assert (NULL != peer);
586 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
588 event.op_cls = opc->op_cls;
591 case GNUNET_TESTBED_ET_PEER_START:
592 peer->state = TESTBED_PS_STARTED;
593 event.details.peer_start.host = peer->host;
594 event.details.peer_start.peer = peer;
596 case GNUNET_TESTBED_ET_PEER_STOP:
597 peer->state = TESTBED_PS_STOPPED;
598 event.details.peer_stop.peer = peer;
601 GNUNET_assert (0); /* We should never reach this state */
604 pcc_cls = data->pcc_cls;
606 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
607 opc->state = OPC_STATE_FINISHED;
608 exop_insert (event.op);
609 mask = 1LL << GNUNET_TESTBED_ET_PEER_START;
610 mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP;
611 if (0 != (mask & c->event_mask))
614 c->cc (c->cc_cls, &event);
615 if (GNUNET_NO == exop_check (event.op))
620 /* You could have marked the operation as done by now */
621 GNUNET_break (GNUNET_NO == exop_check (event.op));
627 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
628 * controller (testbed service)
630 * @param c the controller handler
631 * @param msg message received
632 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
636 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
637 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
639 struct OperationContext *opc;
640 struct OverlayConnectData *data;
641 GNUNET_TESTBED_OperationCompletionCallback cb;
643 struct GNUNET_TESTBED_EventInformation event;
647 op_id = GNUNET_ntohll (msg->operation_id);
648 if (NULL == (opc = find_opc (c, op_id)))
650 LOG_DEBUG ("Operation not found\n");
653 if (OP_FORWARDED == opc->type)
655 handle_forwarded_operation_msg (c, opc,
656 (const struct GNUNET_MessageHeader *) msg);
659 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
660 GNUNET_assert (NULL != (data = opc->data));
661 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
662 (ntohl (msg->peer2) == data->p2->unique_id));
663 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
665 event.op_cls = opc->op_cls;
668 case GNUNET_TESTBED_ET_CONNECT:
669 event.details.peer_connect.peer1 = data->p1;
670 event.details.peer_connect.peer2 = data->p2;
672 case GNUNET_TESTBED_ET_DISCONNECT:
673 GNUNET_assert (0); /* FIXME: implement */
676 GNUNET_assert (0); /* Should never reach here */
680 cb_cls = data->cb_cls;
681 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
682 opc->state = OPC_STATE_FINISHED;
683 exop_insert (event.op);
684 mask = 1LL << GNUNET_TESTBED_ET_CONNECT;
685 mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT;
686 if (0 != (mask & c->event_mask))
689 c->cc (c->cc_cls, &event);
690 if (GNUNET_NO == exop_check (event.op))
694 cb (cb_cls, opc->op, NULL);
695 /* You could have marked the operation as done by now */
696 GNUNET_break (GNUNET_NO == exop_check (event.op));
702 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
703 * controller (testbed service)
705 * @param c the controller handler
706 * @param msg message received
707 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
711 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
713 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
715 struct OperationContext *opc;
716 struct GNUNET_TESTBED_Peer *peer;
717 struct PeerInfoData *data;
718 struct GNUNET_TESTBED_PeerInformation *pinfo;
719 GNUNET_TESTBED_PeerInfoCallback cb;
723 op_id = GNUNET_ntohll (msg->operation_id);
724 if (NULL == (opc = find_opc (c, op_id)))
726 LOG_DEBUG ("Operation not found\n");
729 if (OP_FORWARDED == opc->type)
731 handle_forwarded_operation_msg (c, opc,
732 (const struct GNUNET_MessageHeader *) msg);
736 GNUNET_assert (NULL != data);
738 GNUNET_assert (NULL != peer);
739 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
740 pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation);
741 pinfo->pit = data->pit;
743 cb_cls = data->cb_cls;
744 GNUNET_assert (NULL != cb);
749 case GNUNET_TESTBED_PIT_IDENTITY:
750 pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity);
751 (void) memcpy (pinfo->result.id, &msg->peer_identity,
752 sizeof (struct GNUNET_PeerIdentity));
754 case GNUNET_TESTBED_PIT_CONFIGURATION:
755 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
756 GNUNET_TESTBED_extract_config_ (&msg->header);
758 case GNUNET_TESTBED_PIT_GENERIC:
759 GNUNET_assert (0); /* never reach here */
763 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
764 opc->state = OPC_STATE_FINISHED;
765 cb (cb_cls, opc->op, pinfo, NULL);
766 /* We dont check whether the operation is marked as done here as the
767 operation contains data (cfg/identify) which will be freed at a later point
774 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
775 * controller (testbed service)
777 * @param c the controller handler
778 * @param msg message received
779 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
783 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
784 const struct GNUNET_TESTBED_OperationFailureEventMessage
787 struct OperationContext *opc;
791 struct GNUNET_TESTBED_EventInformation event;
793 op_id = GNUNET_ntohll (msg->operation_id);
794 if (NULL == (opc = find_opc (c, op_id)))
796 LOG_DEBUG ("Operation not found\n");
799 if (OP_FORWARDED == opc->type)
801 handle_forwarded_operation_msg (c, opc,
802 (const struct GNUNET_MessageHeader *) msg);
805 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
806 opc->state = OPC_STATE_FINISHED;
807 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
809 emsg = "Unknown error";
810 if (OP_PEER_INFO == opc->type)
812 struct PeerInfoData *data;
815 if (NULL != data->cb)
816 data->cb (data->cb_cls, opc->op, NULL, emsg);
818 return GNUNET_YES; /* We do not call controller callback for peer info */
820 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
822 event.op_cls = opc->op_cls;
823 event.details.operation_finished.emsg = emsg;
824 event.details.operation_finished.generic = NULL;
825 mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
826 if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
828 exop_insert (event.op);
829 c->cc (c->cc_cls, &event);
830 if (GNUNET_NO == exop_check (event.op))
837 struct PeerCreateData *data;
840 GNUNET_free (data->peer);
841 if (NULL != data->cb)
842 data->cb (data->cls, NULL, emsg);
849 struct PeerEventData *data;
852 if (NULL != data->pcc)
853 data->pcc (data->pcc_cls, emsg);
857 case OP_PEER_DESTROY:
861 case OP_OVERLAY_CONNECT:
863 struct OverlayConnectData *data;
866 GNUNET_TESTBED_operation_mark_failed (opc->op);
867 if (NULL != data->cb)
868 data->cb (data->cb_cls, opc->op, emsg);
873 case OP_LINK_CONTROLLERS: /* No secondary callback */
875 case OP_SHUTDOWN_PEERS:
877 struct ShutdownPeersData *data;
880 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
884 case OP_MANAGE_SERVICE:
886 struct ManageServiceData *data = opc->data;
887 GNUNET_TESTBED_OperationCompletionCallback cb;
890 GNUNET_assert (NULL != data);
892 cb_cls = data->cb_cls;
895 exop_insert (event.op);
897 cb (cb_cls, opc->op, emsg);
898 /* You could have marked the operation as done by now */
899 GNUNET_break (GNUNET_NO == exop_check (event.op));
910 * Function to build GET_SLAVE_CONFIG message
912 * @param op_id the id this message should contain in its operation id field
913 * @param slave_id the id this message should contain in its slave id field
914 * @return newly allocated SlaveGetConfigurationMessage
916 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
917 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
919 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
922 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
923 msg = GNUNET_malloc (msize);
924 msg->header.size = htons (msize);
926 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
927 msg->operation_id = GNUNET_htonll (op_id);
928 msg->slave_id = htonl (slave_id);
934 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
937 * @param c the controller handler
938 * @param msg message received
939 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
943 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
944 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
946 struct OperationContext *opc;
949 struct GNUNET_TESTBED_EventInformation event;
951 op_id = GNUNET_ntohll (msg->operation_id);
952 if (NULL == (opc = find_opc (c, op_id)))
954 LOG_DEBUG ("Operation not found\n");
957 if (OP_GET_SLAVE_CONFIG != opc->type)
962 opc->state = OPC_STATE_FINISHED;
963 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
964 mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
965 if ((0 != (mask & c->event_mask)) &&
968 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
969 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
971 event.op_cls = opc->op_cls;
972 event.details.operation_finished.generic = opc->data;
973 event.details.operation_finished.emsg = NULL;
974 c->cc (c->cc_cls, &event);
981 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
984 * @param c the controller handler
985 * @param msg message received
986 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
990 handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
992 GNUNET_TESTBED_ControllerLinkResponse *msg)
994 struct OperationContext *opc;
995 struct ControllerLinkData *data;
996 struct GNUNET_CONFIGURATION_Handle *cfg;
997 struct GNUNET_TESTBED_Host *host;
1000 struct GNUNET_TESTBED_EventInformation event;
1002 op_id = GNUNET_ntohll (msg->operation_id);
1003 if (NULL == (opc = find_opc (c, op_id)))
1005 LOG_DEBUG ("Operation not found\n");
1008 if (OP_FORWARDED == opc->type)
1010 handle_forwarded_operation_msg (c, opc,
1011 (const struct GNUNET_MessageHeader *) msg);
1014 if (OP_LINK_CONTROLLERS != opc->type)
1019 GNUNET_assert (NULL != (data = opc->data));
1020 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
1021 GNUNET_assert (NULL != host);
1024 opc->state = OPC_STATE_FINISHED;
1025 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1026 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1028 event.op_cls = opc->op_cls;
1029 event.details.operation_finished.emsg = NULL;
1030 event.details.operation_finished.generic = NULL;
1033 if (GNUNET_NO == ntohs (msg->success))
1035 emsg = GNUNET_malloc (ntohs (msg->header.size)
1037 GNUNET_TESTBED_ControllerLinkResponse) + 1);
1038 memcpy (emsg, &msg[1], ntohs (msg->header.size)
1040 GNUNET_TESTBED_ControllerLinkResponse));
1041 event.details.operation_finished.emsg = emsg;
1045 if (0 != ntohs (msg->config_size))
1047 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
1048 GNUNET_assert (NULL != cfg);
1049 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
1052 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
1055 c->cc (c->cc_cls, &event);
1058 LOG_DEBUG ("Not calling callback\n");
1060 GNUNET_CONFIGURATION_destroy (cfg);
1061 GNUNET_free_non_null (emsg);
1067 * Handler for messages from controller (testbed service)
1069 * @param cls the controller handler
1070 * @param msg message received, NULL on timeout or fatal error
1073 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
1075 struct GNUNET_TESTBED_Controller *c = cls;
1079 c->in_receive = GNUNET_NO;
1080 /* FIXME: Add checks for message integrity */
1083 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
1086 msize = ntohs (msg->size);
1087 switch (ntohs (msg->type))
1089 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
1090 GNUNET_assert (msize >=
1091 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
1093 GNUNET_TESTBED_host_handle_addhostconfirm_
1094 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
1096 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
1097 GNUNET_assert (msize ==
1099 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
1101 handle_opsuccess (c,
1103 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
1106 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
1107 GNUNET_assert (msize >=
1108 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
1110 handle_op_fail_event (c,
1112 GNUNET_TESTBED_OperationFailureEventMessage *)
1115 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
1116 GNUNET_assert (msize ==
1118 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1120 handle_peer_create_success (c,
1122 GNUNET_TESTBED_PeerCreateSuccessEventMessage
1125 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
1126 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1128 handle_peer_event (c,
1129 (const struct GNUNET_TESTBED_PeerEventMessage *)
1133 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
1134 GNUNET_assert (msize >=
1136 GNUNET_TESTBED_PeerConfigurationInformationMessage));
1138 handle_peer_config (c,
1140 GNUNET_TESTBED_PeerConfigurationInformationMessage
1143 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
1144 GNUNET_assert (msize ==
1145 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1147 handle_peer_conevent (c,
1149 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1151 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1152 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1154 handle_slave_config (c,
1155 (const struct GNUNET_TESTBED_SlaveConfiguration *)
1158 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1160 handle_link_controllers_result (c,
1162 GNUNET_TESTBED_ControllerLinkResponse
1165 case GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS:
1167 GNUNET_TESTBED_handle_barrier_status_ (c,
1169 GNUNET_TESTBED_BarrierStatusMsg *)
1175 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1177 c->in_receive = GNUNET_YES;
1178 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1179 GNUNET_TIME_UNIT_FOREVER_REL);
1185 * Function called to notify a client about the connection begin ready to queue
1186 * more data. "buf" will be NULL and "size" zero if the connection was closed
1187 * for writing in the meantime.
1189 * @param cls closure
1190 * @param size number of bytes available in buf
1191 * @param buf where the callee should write the message
1192 * @return number of bytes written to buf
1195 transmit_ready_notify (void *cls, size_t size, void *buf)
1197 struct GNUNET_TESTBED_Controller *c = cls;
1198 struct MessageQueue *mq_entry;
1201 mq_entry = c->mq_head;
1202 GNUNET_assert (NULL != mq_entry);
1203 if ((0 == size) && (NULL == buf)) /* Timeout */
1205 LOG_DEBUG ("Message sending timed out -- retrying\n");
1207 GNUNET_CLIENT_notify_transmit_ready (c->client,
1208 ntohs (mq_entry->msg->size),
1209 TIMEOUT_REL, GNUNET_YES,
1210 &transmit_ready_notify, c);
1213 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1214 size = ntohs (mq_entry->msg->size);
1215 memcpy (buf, mq_entry->msg, size);
1216 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1217 ntohs (mq_entry->msg->type), size);
1218 GNUNET_free (mq_entry->msg);
1219 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1220 GNUNET_free (mq_entry);
1221 mq_entry = c->mq_head;
1222 if (NULL != mq_entry)
1224 GNUNET_CLIENT_notify_transmit_ready (c->client,
1225 ntohs (mq_entry->msg->size),
1226 TIMEOUT_REL, GNUNET_YES,
1227 &transmit_ready_notify, c);
1228 if (GNUNET_NO == c->in_receive)
1230 c->in_receive = GNUNET_YES;
1231 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1232 GNUNET_TIME_UNIT_FOREVER_REL);
1239 * Queues a message in send queue for sending to the service
1241 * @param controller the handle to the controller
1242 * @param msg the message to queue
1245 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1246 struct GNUNET_MessageHeader *msg)
1248 struct MessageQueue *mq_entry;
1252 type = ntohs (msg->type);
1253 size = ntohs (msg->size);
1254 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1255 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1256 mq_entry = GNUNET_new (struct MessageQueue);
1257 mq_entry->msg = msg;
1258 LOG (GNUNET_ERROR_TYPE_DEBUG,
1259 "Queueing message of type %u, size %u for sending\n", type,
1261 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1263 if (NULL == controller->th)
1265 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1266 TIMEOUT_REL, GNUNET_YES,
1267 &transmit_ready_notify,
1273 * Sends the given message as an operation. The given callback is called when a
1274 * reply for the operation is available. Call
1275 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1276 * operation context if the cc hasn't been called
1278 * @param controller the controller to which the message has to be sent
1279 * @param operation_id the operation id of the message
1280 * @param msg the message to send
1281 * @param cc the callback to call when reply is available
1282 * @param cc_cls the closure for the above callback
1283 * @return the operation context which can be used to cancel the forwarded
1286 struct OperationContext *
1287 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1288 *controller, uint64_t operation_id,
1289 const struct GNUNET_MessageHeader *msg,
1290 GNUNET_CLIENT_MessageHandler cc,
1293 struct OperationContext *opc;
1294 struct ForwardedOperationData *data;
1295 struct GNUNET_MessageHeader *dup_msg;
1298 data = GNUNET_new (struct ForwardedOperationData);
1300 data->cc_cls = cc_cls;
1301 opc = GNUNET_new (struct OperationContext);
1302 opc->c = controller;
1303 opc->type = OP_FORWARDED;
1305 opc->id = operation_id;
1306 msize = ntohs (msg->size);
1307 dup_msg = GNUNET_malloc (msize);
1308 (void) memcpy (dup_msg, msg, msize);
1309 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1310 GNUNET_TESTBED_insert_opc_ (controller, opc);
1316 * Function to cancel an operation created by simply forwarding an operation
1319 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1322 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1324 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1325 GNUNET_free (opc->data);
1331 * Function to call to start a link-controllers type operation once all queues
1332 * the operation is part of declare that the operation can be activated.
1334 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1337 opstart_link_controllers (void *cls)
1339 struct OperationContext *opc = cls;
1340 struct ControllerLinkData *data;
1341 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1343 GNUNET_assert (NULL != opc->data);
1347 opc->state = OPC_STATE_STARTED;
1348 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1349 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1354 * Callback which will be called when link-controllers type operation is released
1356 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1359 oprelease_link_controllers (void *cls)
1361 struct OperationContext *opc = cls;
1362 struct ControllerLinkData *data;
1367 case OPC_STATE_INIT:
1368 GNUNET_free (data->msg);
1370 case OPC_STATE_STARTED:
1371 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1373 case OPC_STATE_FINISHED:
1376 GNUNET_free_non_null (data);
1382 * Function to be called when get slave config operation is ready
1384 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1387 opstart_get_slave_config (void *cls)
1389 struct OperationContext *opc = cls;
1390 struct GetSlaveConfigData *data = opc->data;
1391 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1393 GNUNET_assert (NULL != data);
1394 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1395 GNUNET_free (opc->data);
1398 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1399 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1400 opc->state = OPC_STATE_STARTED;
1405 * Function to be called when get slave config operation is cancelled or finished
1407 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1410 oprelease_get_slave_config (void *cls)
1412 struct OperationContext *opc = cls;
1416 case OPC_STATE_INIT:
1417 GNUNET_free (opc->data);
1419 case OPC_STATE_STARTED:
1420 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1422 case OPC_STATE_FINISHED:
1423 if (NULL != opc->data)
1424 GNUNET_CONFIGURATION_destroy (opc->data);
1432 * Start a controller process using the given configuration at the
1435 * @param host host to run the controller on; This should be the same host if
1436 * the controller was previously started with
1437 * GNUNET_TESTBED_controller_start()
1438 * @param event_mask bit mask with set of events to call 'cc' for;
1439 * or-ed values of "1LL" shifted by the
1440 * respective 'enum GNUNET_TESTBED_EventType'
1441 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1442 * @param cc controller callback to invoke on events
1443 * @param cc_cls closure for cc
1444 * @return handle to the controller
1446 struct GNUNET_TESTBED_Controller *
1447 GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1448 uint64_t event_mask,
1449 GNUNET_TESTBED_ControllerCallback cc,
1452 struct GNUNET_TESTBED_Controller *controller;
1453 struct GNUNET_TESTBED_InitMessage *msg;
1454 const struct GNUNET_CONFIGURATION_Handle *cfg;
1455 const char *controller_hostname;
1456 unsigned long long max_parallel_operations;
1457 unsigned long long max_parallel_service_connections;
1458 unsigned long long max_parallel_topology_config_operations;
1460 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
1462 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1463 "MAX_PARALLEL_OPERATIONS",
1464 &max_parallel_operations))
1470 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1471 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1472 &max_parallel_service_connections))
1478 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1479 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1480 &max_parallel_topology_config_operations))
1485 controller = GNUNET_new (struct GNUNET_TESTBED_Controller);
1486 controller->cc = cc;
1487 controller->cc_cls = cc_cls;
1488 controller->event_mask = event_mask;
1489 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1490 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1491 if (NULL == controller->client)
1493 GNUNET_TESTBED_controller_disconnect (controller);
1496 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1497 controller->host = host;
1498 controller->opq_parallel_operations =
1499 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1500 (unsigned int) max_parallel_operations);
1501 controller->opq_parallel_service_connections =
1502 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1504 max_parallel_service_connections);
1505 controller->opq_parallel_topology_config_operations =
1506 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1508 max_parallel_topology_config_operations);
1509 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1510 if (NULL == controller_hostname)
1511 controller_hostname = "127.0.0.1";
1513 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1514 strlen (controller_hostname) + 1);
1515 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1517 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1518 strlen (controller_hostname) + 1);
1519 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1520 msg->event_mask = GNUNET_htonll (controller->event_mask);
1521 strcpy ((char *) &msg[1], controller_hostname);
1522 GNUNET_TESTBED_queue_message_ (controller,
1523 (struct GNUNET_MessageHeader *) msg);
1529 * Iterator to free opc map entries
1531 * @param cls closure
1532 * @param key current key code
1533 * @param value value in the hash map
1534 * @return GNUNET_YES if we should continue to
1539 opc_free_iterator (void *cls, uint32_t key, void *value)
1541 struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
1542 struct OperationContext *opc = value;
1544 GNUNET_assert (NULL != opc);
1546 GNUNET_assert (GNUNET_YES ==
1547 GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
1554 * Stop the given controller (also will terminate all peers and
1555 * controllers dependent on this controller). This function
1556 * blocks until the testbed has been fully terminated (!).
1558 * @param c handle to controller to stop
1561 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1564 struct MessageQueue *mq_entry;
1567 GNUNET_CLIENT_notify_transmit_ready_cancel (c->th);
1568 /* Clear the message queue */
1569 while (NULL != (mq_entry = c->mq_head))
1571 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail,
1573 GNUNET_free (mq_entry->msg);
1574 GNUNET_free (mq_entry);
1576 if (NULL != c->client)
1577 GNUNET_CLIENT_disconnect (c->client);
1578 if (NULL != c->host)
1579 GNUNET_TESTBED_deregister_host_at_ (c->host, c);
1580 GNUNET_CONFIGURATION_destroy (c->cfg);
1581 GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
1582 GNUNET_TESTBED_operation_queue_destroy_
1583 (c->opq_parallel_service_connections);
1584 GNUNET_TESTBED_operation_queue_destroy_
1585 (c->opq_parallel_topology_config_operations);
1586 if (NULL != c->opc_map)
1588 GNUNET_assert (GNUNET_SYSERR !=
1589 GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
1592 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
1593 GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
1600 * Compresses given configuration using zlib compress
1602 * @param config the serialized configuration
1603 * @param size the size of config
1604 * @param xconfig will be set to the compressed configuration (memory is fresly
1606 * @return the size of the xconfig
1609 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1614 xsize = compressBound ((uLong) size);
1615 *xconfig = GNUNET_malloc (xsize);
1616 GNUNET_assert (Z_OK ==
1617 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1618 (const Bytef *) config, (uLongf) size,
1625 * Function to serialize and compress using zlib a configuration through a
1626 * configuration handle
1628 * @param cfg the configuration
1629 * @param size the size of configuration when serialize. Will be set on success.
1630 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1631 * @return the serialized and compressed configuration
1634 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1635 size_t *size, size_t *xsize)
1642 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1643 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1644 GNUNET_free (config);
1652 * Create a link from slave controller to delegated controller. Whenever the
1653 * master controller is asked to start a peer at the delegated controller the
1654 * request will be routed towards slave controller (if a route exists). The
1655 * slave controller will then route it to the delegated controller. The
1656 * configuration of the delegated controller is given and is used to either
1657 * create the delegated controller or to connect to an existing controller. Note
1658 * that while starting the delegated controller the configuration will be
1659 * modified to accommodate available free ports. the 'is_subordinate' specifies
1660 * if the given delegated controller should be started and managed by the slave
1661 * controller, or if the delegated controller already has a master and the slave
1662 * controller connects to it as a non master controller. The success or failure
1663 * of this operation will be signalled through the
1664 * GNUNET_TESTBED_ControllerCallback() with an event of type
1665 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1667 * @param op_cls the operation closure for the event which is generated to
1668 * signal success or failure of this operation
1669 * @param master handle to the master controller who creates the association
1670 * @param delegated_host requests to which host should be delegated; cannot be NULL
1671 * @param slave_host which host is used to run the slave controller; use NULL to
1672 * make the master controller connect to the delegated host
1673 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1674 * be started by the slave controller; GNUNET_NO if the slave
1675 * controller has to connect to the already started delegated
1676 * controller via TCP/IP
1677 * @return the operation handle
1679 struct GNUNET_TESTBED_Operation *
1680 GNUNET_TESTBED_controller_link (void *op_cls,
1681 struct GNUNET_TESTBED_Controller *master,
1682 struct GNUNET_TESTBED_Host *delegated_host,
1683 struct GNUNET_TESTBED_Host *slave_host,
1686 struct OperationContext *opc;
1687 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1688 struct ControllerLinkData *data;
1689 uint32_t slave_host_id;
1690 uint32_t delegated_host_id;
1693 GNUNET_assert (GNUNET_YES ==
1694 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1696 GNUNET_TESTBED_host_get_id_ ((NULL !=
1697 slave_host) ? slave_host : master->host);
1698 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1699 if ((NULL != slave_host) && (0 != slave_host_id))
1700 GNUNET_assert (GNUNET_YES ==
1701 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1702 msg_size = sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1703 msg = GNUNET_malloc (msg_size);
1704 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1705 msg->header.size = htons (msg_size);
1706 msg->delegated_host_id = htonl (delegated_host_id);
1707 msg->slave_host_id = htonl (slave_host_id);
1708 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1709 data = GNUNET_new (struct ControllerLinkData);
1711 data->host_id = delegated_host_id;
1712 opc = GNUNET_new (struct OperationContext);
1715 opc->type = OP_LINK_CONTROLLERS;
1716 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1717 opc->state = OPC_STATE_INIT;
1718 opc->op_cls = op_cls;
1719 msg->operation_id = GNUNET_htonll (opc->id);
1721 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1722 &oprelease_link_controllers);
1723 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1725 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1731 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1732 * check. Another difference is that this function takes the id of the slave
1735 * @param op_cls the closure for the operation
1736 * @param master the handle to master controller
1737 * @param slave_host_id id of the host where the slave controller is running to
1738 * the slave_host should remain valid until this operation is cancelled
1739 * or marked as finished
1740 * @return the operation handle;
1742 struct GNUNET_TESTBED_Operation *
1743 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1744 struct GNUNET_TESTBED_Controller *master,
1745 uint32_t slave_host_id)
1747 struct OperationContext *opc;
1748 struct GetSlaveConfigData *data;
1750 data = GNUNET_new (struct GetSlaveConfigData);
1751 data->slave_id = slave_host_id;
1752 opc = GNUNET_new (struct OperationContext);
1753 opc->state = OPC_STATE_INIT;
1755 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1756 opc->type = OP_GET_SLAVE_CONFIG;
1758 opc->op_cls = op_cls;
1760 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1761 &oprelease_get_slave_config);
1762 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1764 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1770 * Function to acquire the configuration of a running slave controller. The
1771 * completion of the operation is signalled through the controller_cb from
1772 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1773 * handle to the configuration is available in the generic pointer of
1774 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1776 * @param op_cls the closure for the operation
1777 * @param master the handle to master controller
1778 * @param slave_host the host where the slave controller is running; the handle
1779 * to the slave_host should remain valid until this operation is
1780 * cancelled or marked as finished
1781 * @return the operation handle; NULL if the slave_host is not registered at
1784 struct GNUNET_TESTBED_Operation *
1785 GNUNET_TESTBED_get_slave_config (void *op_cls,
1786 struct GNUNET_TESTBED_Controller *master,
1787 struct GNUNET_TESTBED_Host *slave_host)
1789 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1791 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1792 GNUNET_TESTBED_host_get_id_
1798 * Ask the testbed controller to write the current overlay topology to
1799 * a file. Naturally, the file will only contain a snapshot as the
1800 * topology may evolve all the time.
1802 * @param controller overlay controller to inspect
1803 * @param filename name of the file the topology should
1807 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1809 const char *filename)
1816 * Creates a helper initialization message. This function is here because we
1817 * want to use this in testing
1819 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1820 * HOST(all connections form this ip are permitted by the testbed) when
1821 * starting testbed controller at host. This can either be a single ip
1822 * address or a network address in CIDR notation.
1823 * @param hostname the hostname of the destination this message is intended for
1824 * @param cfg the configuration that has to used to start the testbed service
1826 * @return the initialization message
1828 struct GNUNET_TESTBED_HelperInit *
1829 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1830 const char *hostname,
1831 const struct GNUNET_CONFIGURATION_Handle
1834 struct GNUNET_TESTBED_HelperInit *msg;
1838 size_t xconfig_size;
1839 uint16_t trusted_ip_len;
1840 uint16_t hostname_len;
1843 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1844 GNUNET_assert (NULL != config);
1846 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1847 GNUNET_free (config);
1848 trusted_ip_len = strlen (trusted_ip);
1849 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1851 xconfig_size + trusted_ip_len + 1 +
1852 sizeof (struct GNUNET_TESTBED_HelperInit);
1853 msg_size += hostname_len;
1854 msg = GNUNET_realloc (xconfig, msg_size);
1855 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1857 msg->header.size = htons (msg_size);
1858 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1859 msg->trusted_ip_size = htons (trusted_ip_len);
1860 msg->hostname_size = htons (hostname_len);
1861 msg->config_size = htons (config_size);
1862 (void) strcpy ((char *) &msg[1], trusted_ip);
1863 if (0 != hostname_len)
1864 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1871 * This function is used to signal that the event information (struct
1872 * GNUNET_TESTBED_EventInformation) from an operation has been fully processed
1873 * i.e. if the event callback is ever called for this operation. If the event
1874 * callback for this operation has not yet been called, calling this function
1875 * cancels the operation, frees its resources and ensures the no event is
1876 * generated with respect to this operation. Note that however cancelling an
1877 * operation does NOT guarantee that the operation will be fully undone (or that
1878 * nothing ever happened).
1880 * This function MUST be called for every operation to fully remove the
1881 * operation from the operation queue. After calling this function, if
1882 * operation is completed and its event information is of type
1883 * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!).
1885 * If the operation is generated from GNUNET_TESTBED_service_connect() then
1886 * calling this function on such as operation calls the disconnect adapter if
1887 * the connect adapter was ever called.
1889 * @param operation operation to signal completion or cancellation
1892 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1894 (void) exop_check (operation);
1895 GNUNET_TESTBED_operation_release_ (operation);
1900 * Generates configuration by uncompressing configuration in given message. The
1901 * given message should be of the following types:
1902 * GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
1903 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1904 * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
1905 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
1906 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1908 * @param msg the message containing compressed configuration
1909 * @return handle to the parsed configuration; NULL upon error while parsing the message
1911 struct GNUNET_CONFIGURATION_Handle *
1912 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1914 struct GNUNET_CONFIGURATION_Handle *cfg;
1921 switch (ntohs (msg->type))
1923 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
1925 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1928 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1929 data_len = (uLong) ntohs (imsg->config_size);
1931 ntohs (imsg->header.size) -
1932 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1933 xdata = (const Bytef *) &imsg[1];
1936 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1938 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1940 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1941 data_len = (uLong) ntohs (imsg->config_size);
1943 ntohs (imsg->header.size) -
1944 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1945 xdata = (const Bytef *) &imsg[1];
1948 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1950 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1953 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1954 data_len = (uLong) ntohs (imsg->config_size);
1955 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1956 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1957 xdata_len = ntohs (imsg->header.size) - osize;
1958 xdata = (const Bytef *) ((const void *) imsg + osize);
1961 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1963 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
1965 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
1966 data_len = ntohs (imsg->config_size);
1967 xdata_len = ntohs (imsg->header.size) -
1968 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
1969 xdata = (const Bytef *) &imsg[1];
1972 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER:
1974 const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
1976 imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
1977 data_len = ntohs (imsg->config_size);
1978 xdata_len = ntohs (imsg->header.size) -
1979 sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1980 xdata = (const Bytef *) &imsg[1];
1983 case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER:
1985 const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
1987 imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
1988 data_len = ntohs (imsg->config_size);
1989 xdata_len = ntohs (imsg->header.size) -
1990 sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
1991 xdata = (const Bytef *) &imsg[1];
1997 data = GNUNET_malloc (data_len);
1998 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2001 GNUNET_break_op (0); /* Un-compression failure */
2004 cfg = GNUNET_CONFIGURATION_create ();
2006 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2011 GNUNET_break_op (0); /* De-serialization failure */
2020 * Checks the integrity of the OperationFailureEventMessage and if good returns
2021 * the error message it contains.
2023 * @param msg the OperationFailureEventMessage
2024 * @return the error message
2027 GNUNET_TESTBED_parse_error_string_ (const struct
2028 GNUNET_TESTBED_OperationFailureEventMessage
2034 msize = ntohs (msg->header.size);
2035 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2037 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2038 emsg = (const char *) &msg[1];
2039 if ('\0' != emsg[msize - 1])
2049 * Function to return the operation id for a controller. The operation id is
2050 * created from the controllers host id and its internal operation counter.
2052 * @param controller the handle to the controller whose operation id has to be incremented
2053 * @return the incremented operation id.
2056 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2060 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2061 op_id = op_id << 32;
2062 op_id |= (uint64_t) controller->operation_counter++;
2068 * Function called when a shutdown peers operation is ready
2070 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2073 opstart_shutdown_peers (void *cls)
2075 struct OperationContext *opc = cls;
2076 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2078 opc->state = OPC_STATE_STARTED;
2079 msg = GNUNET_new (struct GNUNET_TESTBED_ShutdownPeersMessage);
2081 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2082 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2083 msg->operation_id = GNUNET_htonll (opc->id);
2084 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
2085 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
2090 * Callback which will be called when shutdown peers operation is released
2092 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2095 oprelease_shutdown_peers (void *cls)
2097 struct OperationContext *opc = cls;
2101 case OPC_STATE_STARTED:
2102 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
2103 /* no break; continue */
2104 case OPC_STATE_INIT:
2105 GNUNET_free (opc->data);
2107 case OPC_STATE_FINISHED:
2115 * Stops and destroys all peers. Is equivalent of calling
2116 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2117 * except that the peer stop event and operation finished event corresponding to
2118 * the respective functions are not generated. This function should be called
2119 * when there are no other pending operations. If there are pending operations,
2120 * it will return NULL
2122 * @param c the controller to send this message to
2123 * @param op_cls closure for the operation
2124 * @param cb the callback to call when all peers are stopped and destroyed
2125 * @param cb_cls the closure for the callback
2126 * @return operation handle on success; NULL if any pending operations are
2129 struct GNUNET_TESTBED_Operation *
2130 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
2132 GNUNET_TESTBED_OperationCompletionCallback cb,
2135 struct OperationContext *opc;
2136 struct ShutdownPeersData *data;
2138 if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
2140 data = GNUNET_new (struct ShutdownPeersData);
2142 data->cb_cls = cb_cls;
2143 opc = GNUNET_new (struct OperationContext);
2145 opc->op_cls = op_cls;
2147 opc->id = GNUNET_TESTBED_get_next_op_id (c);
2148 opc->type = OP_SHUTDOWN_PEERS;
2149 opc->state = OPC_STATE_INIT;
2150 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2151 &oprelease_shutdown_peers);
2152 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2154 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2160 * Return the index of the peer inside of the total peer array,
2161 * aka. the peer's "unique ID".
2163 * @param peer Peer handle.
2165 * @return The peer's unique ID.
2168 GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer)
2170 return peer->unique_id;
2173 /* end of testbed_api.c */