2 This file is part of GNUnet
3 Copyright (C) 2008--2013 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, 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
30 #include "gnunet_testbed_service.h"
31 #include "gnunet_core_service.h"
32 #include "gnunet_constants.h"
33 #include "gnunet_transport_service.h"
34 #include "gnunet_hello_lib.h"
38 #include "testbed_api.h"
39 #include "testbed_api_hosts.h"
40 #include "testbed_api_peers.h"
41 #include "testbed_api_operations.h"
42 #include "testbed_api_sd.h"
45 * Generic logging shorthand
47 #define LOG(kind, ...) \
48 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
53 #define LOG_DEBUG(...) \
54 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
57 * Relative time seconds shorthand
59 #define TIME_REL_SECS(sec) \
60 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
64 * Default server message sending retry timeout
66 #define TIMEOUT_REL TIME_REL_SECS(1)
70 * Context data for forwarded Operation
72 struct ForwardedOperationData
76 * The callback to call when reply is available
78 GNUNET_MQ_MessageCallback cc;
81 * The closure for the above callback
89 * Context data for get slave config operations
91 struct GetSlaveConfigData
94 * The id of the slave controller
102 * Context data for controller link operations
104 struct ControllerLinkData
107 * The controller link message
109 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
112 * The id of the host which is hosting the controller to be linked
120 * Date context for OP_SHUTDOWN_PEERS operations
122 struct ShutdownPeersData
125 * The operation completion callback to call
127 GNUNET_TESTBED_OperationCompletionCallback cb;
130 * The closure for the above callback
137 * An entry in the stack for keeping operations which are about to expire
139 struct ExpireOperationEntry
142 * DLL head; new entries are to be inserted here
144 struct ExpireOperationEntry *next;
147 * DLL tail; entries are deleted from here
149 struct ExpireOperationEntry *prev;
152 * The operation. This will be a dangling pointer when the operation is freed
154 const struct GNUNET_TESTBED_Operation *op;
159 * DLL head for list of operations marked for expiry
161 static struct ExpireOperationEntry *exop_head;
164 * DLL tail for list of operation marked for expiry
166 static struct ExpireOperationEntry *exop_tail;
170 * Inserts an operation into the list of operations marked for expiry
172 * @param op the operation to insert
175 exop_insert (struct GNUNET_TESTBED_Operation *op)
177 struct ExpireOperationEntry *entry;
179 entry = GNUNET_new (struct ExpireOperationEntry);
181 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
186 * Checks if an operation is present in the list of operations marked for
187 * expiry. If the operation is found, it and the tail of operations after it
188 * are removed from the list.
190 * @param op the operation to check
191 * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
192 * the operation is found in the list (the operation is then removed
193 * from the list -- calling this function again with the same
194 * paramenter will return GNUNET_NO)
197 exop_check (const struct GNUNET_TESTBED_Operation *const op)
199 struct ExpireOperationEntry *entry;
200 struct ExpireOperationEntry *entry2;
205 while (NULL != entry)
214 if (GNUNET_NO == found)
216 /* Truncate the tail */
217 while (NULL != entry)
219 entry2 = entry->next;
220 GNUNET_CONTAINER_DLL_remove (exop_head,
231 * Context information to be used while searching for operation contexts
236 * The result of the search
238 struct OperationContext *opc;
241 * The id of the operation context we are searching for
248 * Search iterator for searching an operation context
250 * @param cls the serach context
251 * @param key current key code
252 * @param value value in the hash map
253 * @return #GNUNET_YES if we should continue to iterate,
257 opc_search_iterator (void *cls,
261 struct SearchContext *sc = cls;
262 struct OperationContext *opc = value;
264 GNUNET_assert (NULL != opc);
265 GNUNET_assert (NULL == sc->opc);
266 if (opc->id != sc->id)
274 * Returns the operation context with the given id if found in the Operation
275 * context queues of the controller
277 * @param c the controller whose operation context map is searched
278 * @param id the id which has to be checked
279 * @return the matching operation context; NULL if no match found
281 static struct OperationContext *
282 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
284 struct SearchContext sc;
288 GNUNET_assert (NULL != c->opc_map);
290 GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id,
291 &opc_search_iterator, &sc))
298 * Inserts the given operation context into the operation context map of the
299 * given controller. Creates the operation context map if one does not exist
302 * @param c the controller
303 * @param opc the operation context to be inserted
306 GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
307 struct OperationContext *opc)
309 if (NULL == c->opc_map)
310 c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
311 GNUNET_assert (GNUNET_OK ==
312 GNUNET_CONTAINER_multihashmap32_put (c->opc_map,
313 (uint32_t) opc->id, opc,
314 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
319 * Removes the given operation context from the operation context map of the
322 * @param c the controller
323 * @param opc the operation context to remove
326 GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
327 struct OperationContext *opc)
329 GNUNET_assert (NULL != c->opc_map);
330 GNUNET_assert (GNUNET_YES ==
331 GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
334 if ( (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
335 && (NULL != c->opcq_empty_cb) )
336 c->opcq_empty_cb (c->opcq_empty_cls);
342 * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message is well-formed.
344 * @param cls the controller handler
345 * @param msg message received
346 * @return #GNUNET_OK if message is well-formed
349 check_add_host_confirm (void *cls,
350 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
355 msg_size = ntohs (msg->header.size) - sizeof (*msg);
358 /* We have an error message */
359 emsg = (const char *) &msg[1];
360 if ('\0' != emsg[msg_size - 1])
363 return GNUNET_SYSERR;
370 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
371 * controller (testbed service)
373 * @param cls the controller handler
374 * @param msg message received
377 handle_add_host_confirm (void *cls,
378 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
380 struct GNUNET_TESTBED_Controller *c = cls;
381 struct GNUNET_TESTBED_HostRegistrationHandle *rh = c->rh;
387 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
389 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
390 GNUNET_TESTBED_host_get_id_ (rh->host),
391 ntohl (msg->host_id));
395 msg_size = ntohs (msg->header.size) - sizeof (*msg);
398 LOG_DEBUG ("Host %u successfully registered\n",
399 ntohl (msg->host_id));
400 GNUNET_TESTBED_mark_host_registered_at_ (rh->host,
407 /* We have an error message */
408 emsg = (const char *) &msg[1];
409 LOG (GNUNET_ERROR_TYPE_ERROR,
410 _("Adding host %u failed with error: %s\n"),
411 ntohl (msg->host_id),
420 * Handler for forwarded operations
422 * @param c the controller handle
423 * @param opc the opearation context
424 * @param msg the message
427 handle_forwarded_operation_msg (void *cls,
428 struct OperationContext *opc,
429 const struct GNUNET_MessageHeader *msg)
431 struct GNUNET_TESTBED_Controller *c = cls;
432 struct ForwardedOperationData *fo_data;
435 if (NULL != fo_data->cc)
436 fo_data->cc (fo_data->cc_cls, msg);
437 GNUNET_TESTBED_remove_opc_ (c, opc);
438 GNUNET_free (fo_data);
444 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS message from
445 * controller (testbed service)
447 * @param c the controller handler
448 * @param msg message received
451 handle_opsuccess (void *cls,
452 const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
454 struct GNUNET_TESTBED_Controller *c = cls;
455 struct OperationContext *opc;
456 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
457 void *op_comp_cb_cls;
458 struct GNUNET_TESTBED_EventInformation event;
461 op_id = GNUNET_ntohll (msg->operation_id);
462 LOG_DEBUG ("Operation %lu successful\n", op_id);
463 if (NULL == (opc = find_opc (c, op_id)))
465 LOG_DEBUG ("Operation not found\n");
468 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
470 event.op_cls = opc->op_cls;
471 event.details.operation_finished.emsg = NULL;
472 event.details.operation_finished.generic = NULL;
474 op_comp_cb_cls = NULL;
479 handle_forwarded_operation_msg (c, opc,
480 (const struct GNUNET_MessageHeader *) msg);
484 case OP_PEER_DESTROY:
486 struct GNUNET_TESTBED_Peer *peer;
489 GNUNET_TESTBED_peer_deregister_ (peer);
495 case OP_SHUTDOWN_PEERS:
497 struct ShutdownPeersData *data;
500 op_comp_cb = data->cb;
501 op_comp_cb_cls = data->cb_cls;
504 GNUNET_TESTBED_cleanup_peers_ ();
507 case OP_MANAGE_SERVICE:
509 struct ManageServiceData *data;
511 GNUNET_assert (NULL != (data = opc->data));
512 op_comp_cb = data->cb;
513 op_comp_cb_cls = data->cb_cls;
518 case OP_PEER_RECONFIGURE:
523 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
524 opc->state = OPC_STATE_FINISHED;
525 exop_insert (event.op);
526 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
529 c->cc (c->cc_cls, &event);
530 if (GNUNET_NO == exop_check (event.op))
534 LOG_DEBUG ("Not calling callback\n");
535 if (NULL != op_comp_cb)
536 op_comp_cb (op_comp_cb_cls, event.op, NULL);
537 /* You could have marked the operation as done by now */
538 GNUNET_break (GNUNET_NO == exop_check (event.op));
543 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS message from
544 * controller (testbed service)
546 * @param c the controller handle
547 * @param msg message received
550 handle_peer_create_success (void *cls,
551 const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
553 struct GNUNET_TESTBED_Controller *c = cls;
554 struct OperationContext *opc;
555 struct PeerCreateData *data;
556 struct GNUNET_TESTBED_Peer *peer;
557 struct GNUNET_TESTBED_Operation *op;
558 GNUNET_TESTBED_PeerCreateCallback cb;
562 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
563 ntohs (msg->header.size));
564 op_id = GNUNET_ntohll (msg->operation_id);
565 if (NULL == (opc = find_opc (c, op_id)))
567 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
570 if (OP_FORWARDED == opc->type)
572 handle_forwarded_operation_msg (c, opc,
573 (const struct GNUNET_MessageHeader *) msg);
576 GNUNET_assert (OP_PEER_CREATE == opc->type);
577 GNUNET_assert (NULL != opc->data);
579 GNUNET_assert (NULL != data->peer);
581 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
582 peer->state = TESTBED_PS_CREATED;
583 GNUNET_TESTBED_peer_register_ (peer);
587 GNUNET_free (opc->data);
588 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
589 opc->state = OPC_STATE_FINISHED;
592 cb (cb_cls, peer, NULL);
593 /* You could have marked the operation as done by now */
594 GNUNET_break (GNUNET_NO == exop_check (op));
599 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT message from
600 * controller (testbed service)
602 * @param c the controller handler
603 * @param msg message received
606 handle_peer_event (void *cls,
607 const struct GNUNET_TESTBED_PeerEventMessage *msg)
609 struct GNUNET_TESTBED_Controller *c = cls;
610 struct OperationContext *opc;
611 struct GNUNET_TESTBED_Peer *peer;
612 struct PeerEventData *data;
613 GNUNET_TESTBED_PeerChurnCallback pcc;
615 struct GNUNET_TESTBED_EventInformation event;
619 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
620 ntohs (msg->header.size));
621 op_id = GNUNET_ntohll (msg->operation_id);
622 if (NULL == (opc = find_opc (c, op_id)))
624 LOG_DEBUG ("Operation not found\n");
627 if (OP_FORWARDED == opc->type)
629 handle_forwarded_operation_msg (c, opc,
630 (const struct GNUNET_MessageHeader *) msg);
633 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
635 GNUNET_assert (NULL != data);
637 GNUNET_assert (NULL != peer);
638 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
640 event.op_cls = opc->op_cls;
643 case GNUNET_TESTBED_ET_PEER_START:
644 peer->state = TESTBED_PS_STARTED;
645 event.details.peer_start.host = peer->host;
646 event.details.peer_start.peer = peer;
648 case GNUNET_TESTBED_ET_PEER_STOP:
649 peer->state = TESTBED_PS_STOPPED;
650 event.details.peer_stop.peer = peer;
653 GNUNET_assert (0); /* We should never reach this state */
656 pcc_cls = data->pcc_cls;
658 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
659 opc->state = OPC_STATE_FINISHED;
660 exop_insert (event.op);
661 mask = 1LL << GNUNET_TESTBED_ET_PEER_START;
662 mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP;
663 if (0 != (mask & c->event_mask))
666 c->cc (c->cc_cls, &event);
667 if (GNUNET_NO == exop_check (event.op))
672 /* You could have marked the operation as done by now */
673 GNUNET_break (GNUNET_NO == exop_check (event.op));
678 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT message from
679 * controller (testbed service)
681 * @param c the controller handler
682 * @param msg message received
685 handle_peer_conevent (void *cls,
686 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
688 struct GNUNET_TESTBED_Controller *c = cls;
689 struct OperationContext *opc;
690 struct OverlayConnectData *data;
691 GNUNET_TESTBED_OperationCompletionCallback cb;
693 struct GNUNET_TESTBED_EventInformation event;
697 op_id = GNUNET_ntohll (msg->operation_id);
698 if (NULL == (opc = find_opc (c, op_id)))
700 LOG_DEBUG ("Operation not found\n");
703 if (OP_FORWARDED == opc->type)
705 handle_forwarded_operation_msg (c, opc,
706 (const struct GNUNET_MessageHeader *) msg);
709 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
710 GNUNET_assert (NULL != (data = opc->data));
711 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
712 (ntohl (msg->peer2) == data->p2->unique_id));
713 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
715 event.op_cls = opc->op_cls;
718 case GNUNET_TESTBED_ET_CONNECT:
719 event.details.peer_connect.peer1 = data->p1;
720 event.details.peer_connect.peer2 = data->p2;
722 case GNUNET_TESTBED_ET_DISCONNECT:
723 GNUNET_assert (0); /* FIXME: implement */
726 GNUNET_assert (0); /* Should never reach here */
730 cb_cls = data->cb_cls;
731 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
732 opc->state = OPC_STATE_FINISHED;
733 exop_insert (event.op);
734 mask = 1LL << GNUNET_TESTBED_ET_CONNECT;
735 mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT;
736 if (0 != (mask & c->event_mask))
739 c->cc (c->cc_cls, &event);
740 if (GNUNET_NO == exop_check (event.op))
744 cb (cb_cls, opc->op, NULL);
745 /* You could have marked the operation as done by now */
746 GNUNET_break (GNUNET_NO == exop_check (event.op));
751 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
752 * controller (testbed service)
754 * @param c the controller handler
755 * @param msg message received
758 check_peer_config (void *cls,
759 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
767 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
768 * controller (testbed service)
770 * @param c the controller handler
771 * @param msg message received
774 handle_peer_config (void *cls,
775 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
777 struct GNUNET_TESTBED_Controller *c = cls;
778 struct OperationContext *opc;
779 struct GNUNET_TESTBED_Peer *peer;
780 struct PeerInfoData *data;
781 struct GNUNET_TESTBED_PeerInformation *pinfo;
782 GNUNET_TESTBED_PeerInfoCallback cb;
786 op_id = GNUNET_ntohll (msg->operation_id);
787 if (NULL == (opc = find_opc (c, op_id)))
789 LOG_DEBUG ("Operation not found\n");
792 if (OP_FORWARDED == opc->type)
794 handle_forwarded_operation_msg (c,
800 GNUNET_assert (NULL != data);
802 GNUNET_assert (NULL != peer);
803 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
804 pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation);
805 pinfo->pit = data->pit;
807 cb_cls = data->cb_cls;
808 GNUNET_assert (NULL != cb);
813 case GNUNET_TESTBED_PIT_IDENTITY:
814 pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity);
815 GNUNET_memcpy (pinfo->result.id,
817 sizeof (struct GNUNET_PeerIdentity));
819 case GNUNET_TESTBED_PIT_CONFIGURATION:
820 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
821 GNUNET_TESTBED_extract_config_ (&msg->header);
823 case GNUNET_TESTBED_PIT_GENERIC:
824 GNUNET_assert (0); /* never reach here */
828 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
829 opc->state = OPC_STATE_FINISHED;
830 cb (cb_cls, opc->op, pinfo, NULL);
831 /* We dont check whether the operation is marked as done here as the
832 operation contains data (cfg/identify) which will be freed at a later point
838 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
839 * controller (testbed service)
841 * @param c the controller handler
842 * @param msg message received
843 * @return #GNUNET_OK if message is well-formed
846 check_op_fail_event (void *cls,
847 const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
849 /* we accept anything as a valid error message */
855 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
856 * controller (testbed service)
858 * @param c the controller handler
859 * @param msg message received
862 handle_op_fail_event (void *cls,
863 const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
865 struct GNUNET_TESTBED_Controller *c = cls;
866 struct OperationContext *opc;
870 struct GNUNET_TESTBED_EventInformation event;
872 op_id = GNUNET_ntohll (msg->operation_id);
873 if (NULL == (opc = find_opc (c, op_id)))
875 LOG_DEBUG ("Operation not found\n");
878 if (OP_FORWARDED == opc->type)
880 handle_forwarded_operation_msg (c, opc,
881 (const struct GNUNET_MessageHeader *) msg);
884 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
885 opc->state = OPC_STATE_FINISHED;
886 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
888 emsg = "Unknown error";
889 if (OP_PEER_INFO == opc->type)
891 struct PeerInfoData *data;
894 if (NULL != data->cb)
895 data->cb (data->cb_cls, opc->op, NULL, emsg);
897 return; /* We do not call controller callback for peer info */
899 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
901 event.op_cls = opc->op_cls;
902 event.details.operation_finished.emsg = emsg;
903 event.details.operation_finished.generic = NULL;
904 mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
905 if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
907 exop_insert (event.op);
908 c->cc (c->cc_cls, &event);
909 if (GNUNET_NO == exop_check (event.op))
916 struct PeerCreateData *data;
919 GNUNET_free (data->peer);
920 if (NULL != data->cb)
921 data->cb (data->cls, NULL, emsg);
928 struct PeerEventData *data;
931 if (NULL != data->pcc)
932 data->pcc (data->pcc_cls, emsg);
936 case OP_PEER_DESTROY:
940 case OP_OVERLAY_CONNECT:
942 struct OverlayConnectData *data;
945 GNUNET_TESTBED_operation_mark_failed (opc->op);
946 if (NULL != data->cb)
947 data->cb (data->cb_cls, opc->op, emsg);
952 case OP_LINK_CONTROLLERS: /* No secondary callback */
954 case OP_SHUTDOWN_PEERS:
956 struct ShutdownPeersData *data;
959 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
963 case OP_MANAGE_SERVICE:
965 struct ManageServiceData *data = opc->data;
966 GNUNET_TESTBED_OperationCompletionCallback cb;
969 GNUNET_assert (NULL != data);
971 cb_cls = data->cb_cls;
974 exop_insert (event.op);
976 cb (cb_cls, opc->op, emsg);
977 /* You could have marked the operation as done by now */
978 GNUNET_break (GNUNET_NO == exop_check (event.op));
988 * Function to build GET_SLAVE_CONFIG message
990 * @param op_id the id this message should contain in its operation id field
991 * @param slave_id the id this message should contain in its slave id field
992 * @return newly allocated SlaveGetConfigurationMessage
994 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
995 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
997 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1000 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
1001 msg = GNUNET_malloc (msize);
1002 msg->header.size = htons (msize);
1004 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
1005 msg->operation_id = GNUNET_htonll (op_id);
1006 msg->slave_id = htonl (slave_id);
1013 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_INFORMATION message from
1014 * controller (testbed service)
1016 * @param c the controller handler
1017 * @param msg message received
1020 check_slave_config (void *cls,
1021 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
1023 /* anything goes? */
1029 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION message from controller
1032 * @param c the controller handler
1033 * @param msg message received
1036 handle_slave_config (void *cls,
1037 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
1039 struct GNUNET_TESTBED_Controller *c = cls;
1040 struct OperationContext *opc;
1043 struct GNUNET_TESTBED_EventInformation event;
1045 op_id = GNUNET_ntohll (msg->operation_id);
1046 if (NULL == (opc = find_opc (c, op_id)))
1048 LOG_DEBUG ("Operation not found\n");
1051 if (OP_GET_SLAVE_CONFIG != opc->type)
1056 opc->state = OPC_STATE_FINISHED;
1057 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1058 mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
1059 if ((0 != (mask & c->event_mask)) &&
1062 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
1063 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1065 event.op_cls = opc->op_cls;
1066 event.details.operation_finished.generic = opc->data;
1067 event.details.operation_finished.emsg = NULL;
1068 c->cc (c->cc_cls, &event);
1074 * Check #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
1077 * @param c the controller handler
1078 * @param msg message received
1079 * @return #GNUNET_OK if @a msg is well-formed
1082 check_link_controllers_result (void *cls,
1083 const struct GNUNET_TESTBED_ControllerLinkResponse *msg)
1085 /* actual check to be implemented */
1091 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
1094 * @param c the controller handler
1095 * @param msg message received
1098 handle_link_controllers_result (void *cls,
1099 const struct GNUNET_TESTBED_ControllerLinkResponse *msg)
1101 struct GNUNET_TESTBED_Controller *c = cls;
1102 struct OperationContext *opc;
1103 struct ControllerLinkData *data;
1104 struct GNUNET_CONFIGURATION_Handle *cfg;
1105 struct GNUNET_TESTBED_Host *host;
1108 struct GNUNET_TESTBED_EventInformation event;
1110 op_id = GNUNET_ntohll (msg->operation_id);
1111 if (NULL == (opc = find_opc (c, op_id)))
1113 LOG_DEBUG ("Operation not found\n");
1116 if (OP_FORWARDED == opc->type)
1118 handle_forwarded_operation_msg (c, opc,
1119 (const struct GNUNET_MessageHeader *) msg);
1122 if (OP_LINK_CONTROLLERS != opc->type)
1127 GNUNET_assert (NULL != (data = opc->data));
1128 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
1129 GNUNET_assert (NULL != host);
1132 opc->state = OPC_STATE_FINISHED;
1133 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1134 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1136 event.op_cls = opc->op_cls;
1137 event.details.operation_finished.emsg = NULL;
1138 event.details.operation_finished.generic = NULL;
1141 if (GNUNET_NO == ntohs (msg->success))
1143 emsg = GNUNET_malloc (ntohs (msg->header.size)
1145 GNUNET_TESTBED_ControllerLinkResponse) + 1);
1146 GNUNET_memcpy (emsg,
1148 ntohs (msg->header.size)- sizeof (struct GNUNET_TESTBED_ControllerLinkResponse));
1149 event.details.operation_finished.emsg = emsg;
1153 if (0 != ntohs (msg->config_size))
1155 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
1156 GNUNET_assert (NULL != cfg);
1157 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
1160 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
1163 c->cc (c->cc_cls, &event);
1166 LOG_DEBUG ("Not calling callback\n");
1168 GNUNET_CONFIGURATION_destroy (cfg);
1169 GNUNET_free_non_null (emsg);
1174 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS message.
1176 * @param cls the controller handle to determine the connection this message
1178 * @param msg the barrier status message
1179 * @return #GNUNET_OK if the message is valid; #GNUNET_SYSERR to tear it
1180 * down signalling an error (message malformed)
1183 check_barrier_status (void *cls,
1184 const struct GNUNET_TESTBED_BarrierStatusMsg *msg)
1192 msize = ntohs (msg->header.size);
1194 name_len = ntohs (msg->name_len);
1196 if (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize)
1198 GNUNET_break_op (0);
1199 return GNUNET_SYSERR;
1201 if ('\0' != name[name_len])
1203 GNUNET_break_op (0);
1204 return GNUNET_SYSERR;
1206 status = ntohs (msg->status);
1207 if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
1209 emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len
1213 GNUNET_break_op (0);
1214 return GNUNET_SYSERR;
1222 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages
1224 * @param cls the controller handle to determine the connection this message
1226 * @param msg the barrier status message
1229 handle_barrier_status (void *cls,
1230 const struct GNUNET_TESTBED_BarrierStatusMsg *msg)
1232 struct GNUNET_TESTBED_Controller *c = cls;
1233 struct GNUNET_TESTBED_Barrier *barrier;
1236 struct GNUNET_HashCode key;
1244 msize = ntohs (msg->header.size);
1245 if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg))
1247 GNUNET_break_op (0);
1251 name_len = ntohs (msg->name_len);
1252 if (name_len >= //name_len is strlen(barrier_name)
1253 (msize - ((sizeof msg->header) + sizeof (msg->status)) ) )
1255 GNUNET_break_op (0);
1258 if ('\0' != name[name_len])
1260 GNUNET_break_op (0);
1263 LOG_DEBUG ("Received BARRIER_STATUS msg\n");
1264 status = ntohs (msg->status);
1265 if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
1268 //unlike name_len, emsg_len includes the trailing zero
1269 emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)
1273 GNUNET_break_op (0);
1276 if ('\0' != (msg->data[(name_len + 1) + (emsg_len - 1)]))
1278 GNUNET_break_op (0);
1281 emsg = GNUNET_malloc (emsg_len);
1282 GNUNET_memcpy (emsg,
1283 msg->data + name_len + 1,
1286 if (NULL == c->barrier_map)
1288 GNUNET_break_op (0);
1291 GNUNET_CRYPTO_hash (name, name_len, &key);
1292 barrier = GNUNET_CONTAINER_multihashmap_get (c->barrier_map, &key);
1293 if (NULL == barrier)
1295 GNUNET_break_op (0);
1298 GNUNET_assert (NULL != barrier->cb);
1299 if ((GNUNET_YES == barrier->echo) &&
1300 (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status))
1301 GNUNET_TESTBED_queue_message_ (c,
1302 GNUNET_copy_message (&msg->header));
1303 barrier->cb (barrier->cls,
1308 if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status)
1309 return; /* just initialised; skip cleanup */
1312 GNUNET_free_non_null (emsg);
1314 * Do not remove the barrier if we did not echo the status back; this is
1315 * required at the chained testbed controller setup to ensure the only the
1316 * test-driver echos the status and the controller hierarchy properly
1317 * propagates the status.
1319 if ((NULL != barrier) && (GNUNET_YES == barrier->echo))
1320 GNUNET_TESTBED_barrier_remove_ (barrier);
1325 * Queues a message in send queue for sending to the service
1327 * @param controller the handle to the controller
1328 * @param msg the message to queue
1331 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1332 struct GNUNET_MessageHeader *msg)
1334 struct GNUNET_MQ_Envelope *env;
1335 struct GNUNET_MessageHeader *m2;
1339 type = ntohs (msg->type);
1340 size = ntohs (msg->size);
1341 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1342 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1343 env = GNUNET_MQ_msg_extra (m2,
1344 size - sizeof (*m2),
1346 GNUNET_memcpy (m2, msg, size);
1348 GNUNET_MQ_send (controller->mq,
1354 * Sends the given message as an operation. The given callback is called when a
1355 * reply for the operation is available. Call
1356 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1357 * operation context if the cc hasn't been called
1359 * @param controller the controller to which the message has to be sent
1360 * @param operation_id the operation id of the message
1361 * @param msg the message to send
1362 * @param cc the callback to call when reply is available
1363 * @param cc_cls the closure for the above callback
1364 * @return the operation context which can be used to cancel the forwarded
1367 struct OperationContext *
1368 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller *controller,
1369 uint64_t operation_id,
1370 const struct GNUNET_MessageHeader *msg,
1371 GNUNET_MQ_MessageCallback cc,
1374 struct OperationContext *opc;
1375 struct ForwardedOperationData *data;
1376 struct GNUNET_MQ_Envelope *env;
1377 struct GNUNET_MessageHeader *m2;
1378 uint16_t type = ntohs (msg->type);
1379 uint16_t size = ntohs (msg->size);
1381 env = GNUNET_MQ_msg_extra (m2,
1382 size - sizeof (*m2),
1387 GNUNET_MQ_send (controller->mq,
1389 data = GNUNET_new (struct ForwardedOperationData);
1391 data->cc_cls = cc_cls;
1392 opc = GNUNET_new (struct OperationContext);
1393 opc->c = controller;
1394 opc->type = OP_FORWARDED;
1396 opc->id = operation_id;
1397 GNUNET_TESTBED_insert_opc_ (controller,
1404 * Function to cancel an operation created by simply forwarding an operation
1407 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1410 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1412 GNUNET_TESTBED_remove_opc_ (opc->c,
1414 GNUNET_free (opc->data);
1420 * Function to call to start a link-controllers type operation once all queues
1421 * the operation is part of declare that the operation can be activated.
1423 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1426 opstart_link_controllers (void *cls)
1428 struct OperationContext *opc = cls;
1429 struct ControllerLinkData *data;
1430 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1432 GNUNET_assert (NULL != opc->data);
1436 opc->state = OPC_STATE_STARTED;
1437 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1438 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1443 * Callback which will be called when link-controllers type operation is released
1445 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1448 oprelease_link_controllers (void *cls)
1450 struct OperationContext *opc = cls;
1451 struct ControllerLinkData *data;
1456 case OPC_STATE_INIT:
1457 GNUNET_free (data->msg);
1459 case OPC_STATE_STARTED:
1460 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1462 case OPC_STATE_FINISHED:
1465 GNUNET_free_non_null (data);
1471 * Function to be called when get slave config operation is ready
1473 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1476 opstart_get_slave_config (void *cls)
1478 struct OperationContext *opc = cls;
1479 struct GetSlaveConfigData *data = opc->data;
1480 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1482 GNUNET_assert (NULL != data);
1483 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1484 GNUNET_free (opc->data);
1487 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1488 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1489 opc->state = OPC_STATE_STARTED;
1494 * Function to be called when get slave config operation is cancelled or finished
1496 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1499 oprelease_get_slave_config (void *cls)
1501 struct OperationContext *opc = cls;
1505 case OPC_STATE_INIT:
1506 GNUNET_free (opc->data);
1508 case OPC_STATE_STARTED:
1509 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1511 case OPC_STATE_FINISHED:
1512 if (NULL != opc->data)
1513 GNUNET_CONFIGURATION_destroy (opc->data);
1521 * Generic error handler, called with the appropriate error code and
1522 * the same closure specified at the creation of the message queue.
1523 * Not every message queue implementation supports an error handler.
1525 * @param cls closure, a `struct GNUNET_TESTBED_Controller *`
1526 * @param error error code
1529 mq_error_handler (void *cls,
1530 enum GNUNET_MQ_Error error)
1532 /* struct GNUNET_TESTBED_Controller *c = cls; */
1534 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1535 "Encountered MQ error: %d\n",
1538 GNUNET_SCHEDULER_shutdown (); /* seems most reasonable */
1543 * Start a controller process using the given configuration at the
1546 * @param host host to run the controller on; This should be the same host if
1547 * the controller was previously started with
1548 * GNUNET_TESTBED_controller_start()
1549 * @param event_mask bit mask with set of events to call 'cc' for;
1550 * or-ed values of "1LL" shifted by the
1551 * respective 'enum GNUNET_TESTBED_EventType'
1552 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1553 * @param cc controller callback to invoke on events
1554 * @param cc_cls closure for cc
1555 * @return handle to the controller
1557 struct GNUNET_TESTBED_Controller *
1558 GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1559 uint64_t event_mask,
1560 GNUNET_TESTBED_ControllerCallback cc,
1563 struct GNUNET_TESTBED_Controller *controller
1564 = GNUNET_new (struct GNUNET_TESTBED_Controller);
1565 struct GNUNET_MQ_MessageHandler handlers[] = {
1566 GNUNET_MQ_hd_var_size (add_host_confirm,
1567 GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS,
1568 struct GNUNET_TESTBED_HostConfirmedMessage,
1570 GNUNET_MQ_hd_fixed_size (peer_conevent,
1571 GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT,
1572 struct GNUNET_TESTBED_ConnectionEventMessage,
1574 GNUNET_MQ_hd_fixed_size (opsuccess,
1575 GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS,
1576 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage,
1578 GNUNET_MQ_hd_var_size (op_fail_event,
1579 GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT,
1580 struct GNUNET_TESTBED_OperationFailureEventMessage,
1582 GNUNET_MQ_hd_fixed_size (peer_create_success,
1583 GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS,
1584 struct GNUNET_TESTBED_PeerCreateSuccessEventMessage,
1586 GNUNET_MQ_hd_fixed_size (peer_event,
1587 GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT,
1588 struct GNUNET_TESTBED_PeerEventMessage,
1590 GNUNET_MQ_hd_var_size (peer_config,
1591 GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
1592 struct GNUNET_TESTBED_PeerConfigurationInformationMessage,
1594 GNUNET_MQ_hd_var_size (slave_config,
1595 GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1596 struct GNUNET_TESTBED_SlaveConfiguration,
1598 GNUNET_MQ_hd_var_size (link_controllers_result,
1599 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1600 struct GNUNET_TESTBED_ControllerLinkResponse,
1602 GNUNET_MQ_hd_var_size (barrier_status,
1603 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS,
1604 struct GNUNET_TESTBED_BarrierStatusMsg,
1606 GNUNET_MQ_handler_end ()
1608 struct GNUNET_TESTBED_InitMessage *msg;
1609 struct GNUNET_MQ_Envelope *env;
1610 const struct GNUNET_CONFIGURATION_Handle *cfg;
1611 const char *controller_hostname;
1612 unsigned long long max_parallel_operations;
1613 unsigned long long max_parallel_service_connections;
1614 unsigned long long max_parallel_topology_config_operations;
1617 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
1619 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1620 "MAX_PARALLEL_OPERATIONS",
1621 &max_parallel_operations))
1624 GNUNET_free (controller);
1628 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1629 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1630 &max_parallel_service_connections))
1633 GNUNET_free (controller);
1637 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1638 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1639 &max_parallel_topology_config_operations))
1642 GNUNET_free (controller);
1645 controller->cc = cc;
1646 controller->cc_cls = cc_cls;
1647 controller->event_mask = event_mask;
1648 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1649 controller->mq = GNUNET_CLIENT_connect (controller->cfg,
1654 if (NULL == controller->mq)
1657 GNUNET_TESTBED_controller_disconnect (controller);
1660 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1661 controller->host = host;
1662 controller->opq_parallel_operations =
1663 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1664 (unsigned int) max_parallel_operations);
1665 controller->opq_parallel_service_connections =
1666 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1668 max_parallel_service_connections);
1669 controller->opq_parallel_topology_config_operations =
1670 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1672 max_parallel_topology_config_operations);
1673 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1674 if (NULL == controller_hostname)
1675 controller_hostname = "127.0.0.1";
1676 slen = strlen (controller_hostname) + 1;
1677 env = GNUNET_MQ_msg_extra (msg,
1679 GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1680 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1681 msg->event_mask = GNUNET_htonll (controller->event_mask);
1682 GNUNET_memcpy (&msg[1],
1683 controller_hostname,
1685 GNUNET_MQ_send (controller->mq,
1692 * Iterator to free opc map entries
1694 * @param cls closure
1695 * @param key current key code
1696 * @param value value in the hash map
1697 * @return #GNUNET_YES if we should continue to iterate,
1698 * #GNUNET_NO if not.
1701 opc_free_iterator (void *cls, uint32_t key, void *value)
1703 struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
1704 struct OperationContext *opc = value;
1706 GNUNET_assert (NULL != opc);
1708 GNUNET_assert (GNUNET_YES ==
1709 GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
1716 * Stop the given controller (also will terminate all peers and
1717 * controllers dependent on this controller). This function
1718 * blocks until the testbed has been fully terminated (!).
1720 * @param c handle to controller to stop
1723 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c)
1727 GNUNET_MQ_destroy (c->mq);
1730 if (NULL != c->host)
1731 GNUNET_TESTBED_deregister_host_at_ (c->host, c);
1732 GNUNET_CONFIGURATION_destroy (c->cfg);
1733 GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
1734 GNUNET_TESTBED_operation_queue_destroy_
1735 (c->opq_parallel_service_connections);
1736 GNUNET_TESTBED_operation_queue_destroy_
1737 (c->opq_parallel_topology_config_operations);
1738 if (NULL != c->opc_map)
1740 GNUNET_assert (GNUNET_SYSERR !=
1741 GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
1744 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
1745 GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
1752 * Compresses given configuration using zlib compress
1754 * @param config the serialized configuration
1755 * @param size the size of config
1756 * @param xconfig will be set to the compressed configuration (memory is fresly
1758 * @return the size of the xconfig
1761 GNUNET_TESTBED_compress_config_ (const char *config,
1767 xsize = compressBound ((uLong) size);
1768 *xconfig = GNUNET_malloc (xsize);
1769 GNUNET_assert (Z_OK ==
1770 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1771 (const Bytef *) config, (uLongf) size,
1778 * Function to serialize and compress using zlib a configuration through a
1779 * configuration handle
1781 * @param cfg the configuration
1782 * @param size the size of configuration when serialize. Will be set on success.
1783 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1784 * @return the serialized and compressed configuration
1787 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1788 size_t *size, size_t *xsize)
1795 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1796 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1797 GNUNET_free (config);
1805 * Create a link from slave controller to delegated controller. Whenever the
1806 * master controller is asked to start a peer at the delegated controller the
1807 * request will be routed towards slave controller (if a route exists). The
1808 * slave controller will then route it to the delegated controller. The
1809 * configuration of the delegated controller is given and is used to either
1810 * create the delegated controller or to connect to an existing controller. Note
1811 * that while starting the delegated controller the configuration will be
1812 * modified to accommodate available free ports. the 'is_subordinate' specifies
1813 * if the given delegated controller should be started and managed by the slave
1814 * controller, or if the delegated controller already has a master and the slave
1815 * controller connects to it as a non master controller. The success or failure
1816 * of this operation will be signalled through the
1817 * GNUNET_TESTBED_ControllerCallback() with an event of type
1818 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1820 * @param op_cls the operation closure for the event which is generated to
1821 * signal success or failure of this operation
1822 * @param master handle to the master controller who creates the association
1823 * @param delegated_host requests to which host should be delegated; cannot be NULL
1824 * @param slave_host which host is used to run the slave controller; use NULL to
1825 * make the master controller connect to the delegated host
1826 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1827 * be started by the slave controller; GNUNET_NO if the slave
1828 * controller has to connect to the already started delegated
1829 * controller via TCP/IP
1830 * @return the operation handle
1832 struct GNUNET_TESTBED_Operation *
1833 GNUNET_TESTBED_controller_link (void *op_cls,
1834 struct GNUNET_TESTBED_Controller *master,
1835 struct GNUNET_TESTBED_Host *delegated_host,
1836 struct GNUNET_TESTBED_Host *slave_host,
1839 struct OperationContext *opc;
1840 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1841 struct ControllerLinkData *data;
1842 uint32_t slave_host_id;
1843 uint32_t delegated_host_id;
1846 GNUNET_assert (GNUNET_YES ==
1847 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1849 GNUNET_TESTBED_host_get_id_ ((NULL !=
1850 slave_host) ? slave_host : master->host);
1851 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1852 if ((NULL != slave_host) && (0 != slave_host_id))
1853 GNUNET_assert (GNUNET_YES ==
1854 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1855 msg_size = sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1856 msg = GNUNET_malloc (msg_size);
1857 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1858 msg->header.size = htons (msg_size);
1859 msg->delegated_host_id = htonl (delegated_host_id);
1860 msg->slave_host_id = htonl (slave_host_id);
1861 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1862 data = GNUNET_new (struct ControllerLinkData);
1864 data->host_id = delegated_host_id;
1865 opc = GNUNET_new (struct OperationContext);
1868 opc->type = OP_LINK_CONTROLLERS;
1869 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1870 opc->state = OPC_STATE_INIT;
1871 opc->op_cls = op_cls;
1872 msg->operation_id = GNUNET_htonll (opc->id);
1874 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1875 &oprelease_link_controllers);
1876 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1878 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1884 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1885 * check. Another difference is that this function takes the id of the slave
1888 * @param op_cls the closure for the operation
1889 * @param master the handle to master controller
1890 * @param slave_host_id id of the host where the slave controller is running to
1891 * the slave_host should remain valid until this operation is cancelled
1892 * or marked as finished
1893 * @return the operation handle;
1895 struct GNUNET_TESTBED_Operation *
1896 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1897 struct GNUNET_TESTBED_Controller *master,
1898 uint32_t slave_host_id)
1900 struct OperationContext *opc;
1901 struct GetSlaveConfigData *data;
1903 data = GNUNET_new (struct GetSlaveConfigData);
1904 data->slave_id = slave_host_id;
1905 opc = GNUNET_new (struct OperationContext);
1906 opc->state = OPC_STATE_INIT;
1908 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1909 opc->type = OP_GET_SLAVE_CONFIG;
1911 opc->op_cls = op_cls;
1913 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1914 &oprelease_get_slave_config);
1915 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1917 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1923 * Function to acquire the configuration of a running slave controller. The
1924 * completion of the operation is signalled through the controller_cb from
1925 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1926 * handle to the configuration is available in the generic pointer of
1927 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1929 * @param op_cls the closure for the operation
1930 * @param master the handle to master controller
1931 * @param slave_host the host where the slave controller is running; the handle
1932 * to the slave_host should remain valid until this operation is
1933 * cancelled or marked as finished
1934 * @return the operation handle; NULL if the slave_host is not registered at
1937 struct GNUNET_TESTBED_Operation *
1938 GNUNET_TESTBED_get_slave_config (void *op_cls,
1939 struct GNUNET_TESTBED_Controller *master,
1940 struct GNUNET_TESTBED_Host *slave_host)
1942 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1944 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1945 GNUNET_TESTBED_host_get_id_
1951 * Ask the testbed controller to write the current overlay topology to
1952 * a file. Naturally, the file will only contain a snapshot as the
1953 * topology may evolve all the time.
1955 * @param controller overlay controller to inspect
1956 * @param filename name of the file the topology should
1960 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1962 const char *filename)
1969 * Creates a helper initialization message. This function is here because we
1970 * want to use this in testing
1972 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1973 * HOST(all connections form this ip are permitted by the testbed) when
1974 * starting testbed controller at host. This can either be a single ip
1975 * address or a network address in CIDR notation.
1976 * @param hostname the hostname of the destination this message is intended for
1977 * @param cfg the configuration that has to used to start the testbed service
1979 * @return the initialization message
1981 struct GNUNET_TESTBED_HelperInit *
1982 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1983 const char *hostname,
1984 const struct GNUNET_CONFIGURATION_Handle
1987 struct GNUNET_TESTBED_HelperInit *msg;
1991 size_t xconfig_size;
1992 uint16_t trusted_ip_len;
1993 uint16_t hostname_len;
1996 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1997 GNUNET_assert (NULL != config);
1999 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
2000 GNUNET_free (config);
2001 trusted_ip_len = strlen (trusted_ip);
2002 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2004 xconfig_size + trusted_ip_len + 1 +
2005 sizeof (struct GNUNET_TESTBED_HelperInit);
2006 msg_size += hostname_len;
2007 msg = GNUNET_realloc (xconfig, msg_size);
2008 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
2010 msg->header.size = htons (msg_size);
2011 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2012 msg->trusted_ip_size = htons (trusted_ip_len);
2013 msg->hostname_size = htons (hostname_len);
2014 msg->config_size = htons (config_size);
2015 (void) strcpy ((char *) &msg[1], trusted_ip);
2016 if (0 != hostname_len)
2017 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
2024 * This function is used to signal that the event information (struct
2025 * GNUNET_TESTBED_EventInformation) from an operation has been fully processed
2026 * i.e. if the event callback is ever called for this operation. If the event
2027 * callback for this operation has not yet been called, calling this function
2028 * cancels the operation, frees its resources and ensures the no event is
2029 * generated with respect to this operation. Note that however cancelling an
2030 * operation does NOT guarantee that the operation will be fully undone (or that
2031 * nothing ever happened).
2033 * This function MUST be called for every operation to fully remove the
2034 * operation from the operation queue. After calling this function, if
2035 * operation is completed and its event information is of type
2036 * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!).
2038 * If the operation is generated from GNUNET_TESTBED_service_connect() then
2039 * calling this function on such as operation calls the disconnect adapter if
2040 * the connect adapter was ever called.
2042 * @param operation operation to signal completion or cancellation
2045 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2047 (void) exop_check (operation);
2048 GNUNET_TESTBED_operation_release_ (operation);
2053 * Generates configuration by uncompressing configuration in given message. The
2054 * given message should be of the following types:
2055 * #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
2056 * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
2057 * #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
2058 * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
2059 * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
2061 * FIXME: This API is incredibly ugly.
2063 * @param msg the message containing compressed configuration
2064 * @return handle to the parsed configuration; NULL upon error while parsing the message
2066 struct GNUNET_CONFIGURATION_Handle *
2067 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2069 struct GNUNET_CONFIGURATION_Handle *cfg;
2076 switch (ntohs (msg->type))
2078 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
2080 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2083 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
2084 data_len = (uLong) ntohs (imsg->config_size);
2086 ntohs (imsg->header.size) -
2087 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2088 xdata = (const Bytef *) &imsg[1];
2091 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
2093 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2095 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2096 data_len = (uLong) ntohs (imsg->config_size);
2098 ntohs (imsg->header.size) -
2099 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2100 xdata = (const Bytef *) &imsg[1];
2103 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
2105 const struct GNUNET_TESTBED_AddHostMessage *imsg;
2108 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
2109 data_len = (uLong) ntohs (imsg->config_size);
2110 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
2111 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
2112 xdata_len = ntohs (imsg->header.size) - osize;
2113 xdata = (const Bytef *) ((const void *) imsg + osize);
2116 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
2118 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
2120 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
2121 data_len = ntohs (imsg->config_size);
2122 xdata_len = ntohs (imsg->header.size) -
2123 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
2124 xdata = (const Bytef *) &imsg[1];
2127 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER:
2129 const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
2131 imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
2132 data_len = ntohs (imsg->config_size);
2133 xdata_len = ntohs (imsg->header.size) -
2134 sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
2135 xdata = (const Bytef *) &imsg[1];
2138 case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER:
2140 const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
2142 imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
2143 data_len = ntohs (imsg->config_size);
2144 xdata_len = ntohs (imsg->header.size) -
2145 sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
2146 xdata = (const Bytef *) &imsg[1];
2152 data = GNUNET_malloc (data_len);
2153 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2156 GNUNET_break_op (0); /* Un-compression failure */
2159 cfg = GNUNET_CONFIGURATION_create ();
2161 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2166 GNUNET_break_op (0); /* De-serialization failure */
2175 * Checks the integrity of the OperationFailureEventMessage and if good returns
2176 * the error message it contains.
2178 * @param msg the OperationFailureEventMessage
2179 * @return the error message
2182 GNUNET_TESTBED_parse_error_string_ (const struct
2183 GNUNET_TESTBED_OperationFailureEventMessage
2189 msize = ntohs (msg->header.size);
2190 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2192 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2193 emsg = (const char *) &msg[1];
2194 if ('\0' != emsg[msize - 1])
2204 * Function to return the operation id for a controller. The operation id is
2205 * created from the controllers host id and its internal operation counter.
2207 * @param controller the handle to the controller whose operation id has to be incremented
2208 * @return the incremented operation id.
2211 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2215 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2216 op_id = op_id << 32;
2217 op_id |= (uint64_t) controller->operation_counter++;
2223 * Function called when a shutdown peers operation is ready
2225 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2228 opstart_shutdown_peers (void *cls)
2230 struct OperationContext *opc = cls;
2231 struct GNUNET_MQ_Envelope *env;
2232 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2234 opc->state = OPC_STATE_STARTED;
2235 env = GNUNET_MQ_msg (msg,
2236 GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2237 msg->operation_id = GNUNET_htonll (opc->id);
2238 GNUNET_TESTBED_insert_opc_ (opc->c,
2240 GNUNET_MQ_send (opc->c->mq,
2246 * Callback which will be called when shutdown peers operation is released
2248 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2251 oprelease_shutdown_peers (void *cls)
2253 struct OperationContext *opc = cls;
2257 case OPC_STATE_STARTED:
2258 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
2259 /* no break; continue */
2260 case OPC_STATE_INIT:
2261 GNUNET_free (opc->data);
2263 case OPC_STATE_FINISHED:
2271 * Stops and destroys all peers. Is equivalent of calling
2272 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2273 * except that the peer stop event and operation finished event corresponding to
2274 * the respective functions are not generated. This function should be called
2275 * when there are no other pending operations. If there are pending operations,
2276 * it will return NULL
2278 * @param c the controller to send this message to
2279 * @param op_cls closure for the operation
2280 * @param cb the callback to call when all peers are stopped and destroyed
2281 * @param cb_cls the closure for the callback
2282 * @return operation handle on success; NULL if any pending operations are
2285 struct GNUNET_TESTBED_Operation *
2286 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
2288 GNUNET_TESTBED_OperationCompletionCallback cb,
2291 struct OperationContext *opc;
2292 struct ShutdownPeersData *data;
2294 if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
2296 data = GNUNET_new (struct ShutdownPeersData);
2298 data->cb_cls = cb_cls;
2299 opc = GNUNET_new (struct OperationContext);
2301 opc->op_cls = op_cls;
2303 opc->id = GNUNET_TESTBED_get_next_op_id (c);
2304 opc->type = OP_SHUTDOWN_PEERS;
2305 opc->state = OPC_STATE_INIT;
2306 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2307 &oprelease_shutdown_peers);
2308 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2310 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2316 * Return the index of the peer inside of the total peer array,
2317 * aka. the peer's "unique ID".
2319 * @param peer Peer handle.
2321 * @return The peer's unique ID.
2324 GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer)
2326 return peer->unique_id;
2331 * Remove a barrier and it was the last one in the barrier hash map, destroy the
2334 * @param barrier the barrier to remove
2337 GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier)
2339 struct GNUNET_TESTBED_Controller *c = barrier->c;
2341 GNUNET_assert (NULL != c->barrier_map); /* No barriers present */
2342 GNUNET_assert (GNUNET_OK ==
2343 GNUNET_CONTAINER_multihashmap_remove (c->barrier_map,
2346 GNUNET_free (barrier->name);
2347 GNUNET_free (barrier);
2348 if (0 == GNUNET_CONTAINER_multihashmap_size (c->barrier_map))
2350 GNUNET_CONTAINER_multihashmap_destroy (c->barrier_map);
2351 c->barrier_map = NULL;
2357 * Initialise a barrier and call the given callback when the required percentage
2358 * of peers (quorum) reach the barrier OR upon error.
2360 * @param controller the handle to the controller
2361 * @param name identification name of the barrier
2362 * @param quorum the percentage of peers that is required to reach the barrier.
2363 * Peers signal reaching a barrier by calling
2364 * GNUNET_TESTBED_barrier_reached().
2365 * @param cb the callback to call when the barrier is reached or upon error.
2367 * @param cls closure for the above callback
2368 * @param echo GNUNET_YES to echo the barrier crossed status message back to the
2370 * @return barrier handle; NULL upon error
2372 struct GNUNET_TESTBED_Barrier *
2373 GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller,
2375 unsigned int quorum,
2376 GNUNET_TESTBED_barrier_status_cb cb, void *cls,
2379 struct GNUNET_TESTBED_BarrierInit *msg;
2380 struct GNUNET_MQ_Envelope *env;
2381 struct GNUNET_TESTBED_Barrier *barrier;
2382 struct GNUNET_HashCode key;
2385 GNUNET_assert (quorum <= 100);
2386 GNUNET_assert (NULL != cb);
2387 name_len = strlen (name);
2388 GNUNET_assert (0 < name_len);
2389 GNUNET_CRYPTO_hash (name, name_len, &key);
2390 if (NULL == controller->barrier_map)
2391 controller->barrier_map = GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES);
2393 GNUNET_CONTAINER_multihashmap_contains (controller->barrier_map,
2399 LOG_DEBUG ("Initialising barrier `%s'\n", name);
2400 barrier = GNUNET_new (struct GNUNET_TESTBED_Barrier);
2401 barrier->c = controller;
2402 barrier->name = GNUNET_strdup (name);
2405 barrier->echo = echo;
2406 GNUNET_memcpy (&barrier->key, &key, sizeof (struct GNUNET_HashCode));
2407 GNUNET_assert (GNUNET_OK ==
2408 GNUNET_CONTAINER_multihashmap_put (controller->barrier_map,
2411 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
2413 env = GNUNET_MQ_msg_extra (msg,
2415 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT);
2416 msg->quorum = (uint8_t) quorum;
2417 GNUNET_memcpy (msg->name,
2420 GNUNET_MQ_send (barrier->c->mq,
2427 * Initialise a barrier and call the given callback when the required percentage
2428 * of peers (quorum) reach the barrier OR upon error.
2430 * @param controller the handle to the controller
2431 * @param name identification name of the barrier
2432 * @param quorum the percentage of peers that is required to reach the barrier.
2433 * Peers signal reaching a barrier by calling
2434 * GNUNET_TESTBED_barrier_reached().
2435 * @param cb the callback to call when the barrier is reached or upon error.
2437 * @param cls closure for the above callback
2438 * @return barrier handle; NULL upon error
2440 struct GNUNET_TESTBED_Barrier *
2441 GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller,
2443 unsigned int quorum,
2444 GNUNET_TESTBED_barrier_status_cb cb, void *cls)
2446 return GNUNET_TESTBED_barrier_init_ (controller,
2447 name, quorum, cb, cls, GNUNET_YES);
2454 * @param barrier the barrier handle
2457 GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier)
2459 struct GNUNET_MQ_Envelope *env;
2460 struct GNUNET_TESTBED_BarrierCancel *msg;
2463 slen = strlen (barrier->name);
2464 env = GNUNET_MQ_msg_extra (msg,
2466 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL);
2467 GNUNET_memcpy (msg->name,
2470 GNUNET_MQ_send (barrier->c->mq,
2472 GNUNET_TESTBED_barrier_remove_ (barrier);
2476 /* end of testbed_api.c */