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 it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your 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 Affero General Public License for more details.
17 * @file testbed/testbed_api.c
18 * @brief API for accessing the GNUnet testing service.
19 * This library is supposed to make it easier to write
20 * testcases and script large-scale benchmarks.
21 * @author Christian Grothoff
22 * @author Sree Harsha Totakura
25 #include "gnunet_testbed_service.h"
26 #include "gnunet_core_service.h"
27 #include "gnunet_constants.h"
28 #include "gnunet_transport_service.h"
29 #include "gnunet_hello_lib.h"
33 #include "testbed_api.h"
34 #include "testbed_api_hosts.h"
35 #include "testbed_api_peers.h"
36 #include "testbed_api_operations.h"
37 #include "testbed_api_sd.h"
40 * Generic logging shorthand
42 #define LOG(kind, ...) \
43 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
48 #define LOG_DEBUG(...) \
49 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
52 * Relative time seconds shorthand
54 #define TIME_REL_SECS(sec) \
55 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
59 * Default server message sending retry timeout
61 #define TIMEOUT_REL TIME_REL_SECS(1)
65 * Context data for forwarded Operation
67 struct ForwardedOperationData
71 * The callback to call when reply is available
73 GNUNET_MQ_MessageCallback cc;
76 * The closure for the above callback
84 * Context data for get slave config operations
86 struct GetSlaveConfigData
89 * The id of the slave controller
97 * Context data for controller link operations
99 struct ControllerLinkData
102 * The controller link message
104 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
107 * The id of the host which is hosting the controller to be linked
115 * Date context for OP_SHUTDOWN_PEERS operations
117 struct ShutdownPeersData
120 * The operation completion callback to call
122 GNUNET_TESTBED_OperationCompletionCallback cb;
125 * The closure for the above callback
132 * An entry in the stack for keeping operations which are about to expire
134 struct ExpireOperationEntry
137 * DLL head; new entries are to be inserted here
139 struct ExpireOperationEntry *next;
142 * DLL tail; entries are deleted from here
144 struct ExpireOperationEntry *prev;
147 * The operation. This will be a dangling pointer when the operation is freed
149 const struct GNUNET_TESTBED_Operation *op;
154 * DLL head for list of operations marked for expiry
156 static struct ExpireOperationEntry *exop_head;
159 * DLL tail for list of operation marked for expiry
161 static struct ExpireOperationEntry *exop_tail;
165 * Inserts an operation into the list of operations marked for expiry
167 * @param op the operation to insert
170 exop_insert (struct GNUNET_TESTBED_Operation *op)
172 struct ExpireOperationEntry *entry;
174 entry = GNUNET_new (struct ExpireOperationEntry);
176 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
181 * Checks if an operation is present in the list of operations marked for
182 * expiry. If the operation is found, it and the tail of operations after it
183 * are removed from the list.
185 * @param op the operation to check
186 * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
187 * the operation is found in the list (the operation is then removed
188 * from the list -- calling this function again with the same
189 * paramenter will return GNUNET_NO)
192 exop_check (const struct GNUNET_TESTBED_Operation *const op)
194 struct ExpireOperationEntry *entry;
195 struct ExpireOperationEntry *entry2;
200 while (NULL != entry)
209 if (GNUNET_NO == found)
211 /* Truncate the tail */
212 while (NULL != entry)
214 entry2 = entry->next;
215 GNUNET_CONTAINER_DLL_remove (exop_head,
226 * Context information to be used while searching for operation contexts
231 * The result of the search
233 struct OperationContext *opc;
236 * The id of the operation context we are searching for
243 * Search iterator for searching an operation context
245 * @param cls the serach context
246 * @param key current key code
247 * @param value value in the hash map
248 * @return #GNUNET_YES if we should continue to iterate,
252 opc_search_iterator (void *cls,
256 struct SearchContext *sc = cls;
257 struct OperationContext *opc = value;
259 GNUNET_assert (NULL != opc);
260 GNUNET_assert (NULL == sc->opc);
261 if (opc->id != sc->id)
269 * Returns the operation context with the given id if found in the Operation
270 * context queues of the controller
272 * @param c the controller whose operation context map is searched
273 * @param id the id which has to be checked
274 * @return the matching operation context; NULL if no match found
276 static struct OperationContext *
277 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
279 struct SearchContext sc;
283 GNUNET_assert (NULL != c->opc_map);
285 GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id,
286 &opc_search_iterator, &sc))
293 * Inserts the given operation context into the operation context map of the
294 * given controller. Creates the operation context map if one does not exist
297 * @param c the controller
298 * @param opc the operation context to be inserted
301 GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
302 struct OperationContext *opc)
304 if (NULL == c->opc_map)
305 c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
306 GNUNET_assert (GNUNET_OK ==
307 GNUNET_CONTAINER_multihashmap32_put (c->opc_map,
308 (uint32_t) opc->id, opc,
309 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
314 * Removes the given operation context from the operation context map of the
317 * @param c the controller
318 * @param opc the operation context to remove
321 GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
322 struct OperationContext *opc)
324 GNUNET_assert (NULL != c->opc_map);
325 GNUNET_assert (GNUNET_YES ==
326 GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
329 if ( (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
330 && (NULL != c->opcq_empty_cb) )
331 c->opcq_empty_cb (c->opcq_empty_cls);
337 * Check #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message is well-formed.
339 * @param cls the controller handler
340 * @param msg message received
341 * @return #GNUNET_OK if message is well-formed
344 check_add_host_confirm (void *cls,
345 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
350 msg_size = ntohs (msg->header.size) - sizeof (*msg);
353 /* We have an error message */
354 emsg = (const char *) &msg[1];
355 if ('\0' != emsg[msg_size - 1])
358 return GNUNET_SYSERR;
365 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
366 * controller (testbed service)
368 * @param cls the controller handler
369 * @param msg message received
372 handle_add_host_confirm (void *cls,
373 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
375 struct GNUNET_TESTBED_Controller *c = cls;
376 struct GNUNET_TESTBED_HostRegistrationHandle *rh = c->rh;
382 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
384 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
385 GNUNET_TESTBED_host_get_id_ (rh->host),
386 ntohl (msg->host_id));
390 msg_size = ntohs (msg->header.size) - sizeof (*msg);
393 LOG_DEBUG ("Host %u successfully registered\n",
394 ntohl (msg->host_id));
395 GNUNET_TESTBED_mark_host_registered_at_ (rh->host,
402 /* We have an error message */
403 emsg = (const char *) &msg[1];
404 LOG (GNUNET_ERROR_TYPE_ERROR,
405 _("Adding host %u failed with error: %s\n"),
406 ntohl (msg->host_id),
415 * Handler for forwarded operations
417 * @param c the controller handle
418 * @param opc the opearation context
419 * @param msg the message
422 handle_forwarded_operation_msg (void *cls,
423 struct OperationContext *opc,
424 const struct GNUNET_MessageHeader *msg)
426 struct GNUNET_TESTBED_Controller *c = cls;
427 struct ForwardedOperationData *fo_data;
430 if (NULL != fo_data->cc)
431 fo_data->cc (fo_data->cc_cls, msg);
432 GNUNET_TESTBED_remove_opc_ (c, opc);
433 GNUNET_free (fo_data);
439 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS message from
440 * controller (testbed service)
442 * @param c the controller handler
443 * @param msg message received
446 handle_opsuccess (void *cls,
447 const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
449 struct GNUNET_TESTBED_Controller *c = cls;
450 struct OperationContext *opc;
451 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
452 void *op_comp_cb_cls;
453 struct GNUNET_TESTBED_EventInformation event;
456 op_id = GNUNET_ntohll (msg->operation_id);
457 LOG_DEBUG ("Operation %lu successful\n", op_id);
458 if (NULL == (opc = find_opc (c, op_id)))
460 LOG_DEBUG ("Operation not found\n");
463 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
465 event.op_cls = opc->op_cls;
466 event.details.operation_finished.emsg = NULL;
467 event.details.operation_finished.generic = NULL;
469 op_comp_cb_cls = NULL;
474 handle_forwarded_operation_msg (c, opc,
475 (const struct GNUNET_MessageHeader *) msg);
479 case OP_PEER_DESTROY:
481 struct GNUNET_TESTBED_Peer *peer;
484 GNUNET_TESTBED_peer_deregister_ (peer);
490 case OP_SHUTDOWN_PEERS:
492 struct ShutdownPeersData *data;
495 op_comp_cb = data->cb;
496 op_comp_cb_cls = data->cb_cls;
499 GNUNET_TESTBED_cleanup_peers_ ();
502 case OP_MANAGE_SERVICE:
504 struct ManageServiceData *data;
506 GNUNET_assert (NULL != (data = opc->data));
507 op_comp_cb = data->cb;
508 op_comp_cb_cls = data->cb_cls;
513 case OP_PEER_RECONFIGURE:
518 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
519 opc->state = OPC_STATE_FINISHED;
520 exop_insert (event.op);
521 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
524 c->cc (c->cc_cls, &event);
525 if (GNUNET_NO == exop_check (event.op))
529 LOG_DEBUG ("Not calling callback\n");
530 if (NULL != op_comp_cb)
531 op_comp_cb (op_comp_cb_cls, event.op, NULL);
532 /* You could have marked the operation as done by now */
533 GNUNET_break (GNUNET_NO == exop_check (event.op));
538 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS message from
539 * controller (testbed service)
541 * @param c the controller handle
542 * @param msg message received
545 handle_peer_create_success (void *cls,
546 const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
548 struct GNUNET_TESTBED_Controller *c = cls;
549 struct OperationContext *opc;
550 struct PeerCreateData *data;
551 struct GNUNET_TESTBED_Peer *peer;
552 struct GNUNET_TESTBED_Operation *op;
553 GNUNET_TESTBED_PeerCreateCallback cb;
557 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
558 ntohs (msg->header.size));
559 op_id = GNUNET_ntohll (msg->operation_id);
560 if (NULL == (opc = find_opc (c, op_id)))
562 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
565 if (OP_FORWARDED == opc->type)
567 handle_forwarded_operation_msg (c, opc,
568 (const struct GNUNET_MessageHeader *) msg);
571 GNUNET_assert (OP_PEER_CREATE == opc->type);
572 GNUNET_assert (NULL != opc->data);
574 GNUNET_assert (NULL != data->peer);
576 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
577 peer->state = TESTBED_PS_CREATED;
578 GNUNET_TESTBED_peer_register_ (peer);
582 GNUNET_free (opc->data);
583 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
584 opc->state = OPC_STATE_FINISHED;
587 cb (cb_cls, peer, NULL);
588 /* You could have marked the operation as done by now */
589 GNUNET_break (GNUNET_NO == exop_check (op));
594 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT message from
595 * controller (testbed service)
597 * @param c the controller handler
598 * @param msg message received
601 handle_peer_event (void *cls,
602 const struct GNUNET_TESTBED_PeerEventMessage *msg)
604 struct GNUNET_TESTBED_Controller *c = cls;
605 struct OperationContext *opc;
606 struct GNUNET_TESTBED_Peer *peer;
607 struct PeerEventData *data;
608 GNUNET_TESTBED_PeerChurnCallback pcc;
610 struct GNUNET_TESTBED_EventInformation event;
614 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
615 ntohs (msg->header.size));
616 op_id = GNUNET_ntohll (msg->operation_id);
617 if (NULL == (opc = find_opc (c, op_id)))
619 LOG_DEBUG ("Operation not found\n");
622 if (OP_FORWARDED == opc->type)
624 handle_forwarded_operation_msg (c, opc,
625 (const struct GNUNET_MessageHeader *) msg);
628 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
630 GNUNET_assert (NULL != data);
632 GNUNET_assert (NULL != peer);
633 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
635 event.op_cls = opc->op_cls;
638 case GNUNET_TESTBED_ET_PEER_START:
639 peer->state = TESTBED_PS_STARTED;
640 event.details.peer_start.host = peer->host;
641 event.details.peer_start.peer = peer;
643 case GNUNET_TESTBED_ET_PEER_STOP:
644 peer->state = TESTBED_PS_STOPPED;
645 event.details.peer_stop.peer = peer;
648 GNUNET_assert (0); /* We should never reach this state */
651 pcc_cls = data->pcc_cls;
653 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
654 opc->state = OPC_STATE_FINISHED;
655 exop_insert (event.op);
656 mask = 1LL << GNUNET_TESTBED_ET_PEER_START;
657 mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP;
658 if (0 != (mask & c->event_mask))
661 c->cc (c->cc_cls, &event);
662 if (GNUNET_NO == exop_check (event.op))
667 /* You could have marked the operation as done by now */
668 GNUNET_break (GNUNET_NO == exop_check (event.op));
673 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT message from
674 * controller (testbed service)
676 * @param c the controller handler
677 * @param msg message received
680 handle_peer_conevent (void *cls,
681 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
683 struct GNUNET_TESTBED_Controller *c = cls;
684 struct OperationContext *opc;
685 struct OverlayConnectData *data;
686 GNUNET_TESTBED_OperationCompletionCallback cb;
688 struct GNUNET_TESTBED_EventInformation event;
692 op_id = GNUNET_ntohll (msg->operation_id);
693 if (NULL == (opc = find_opc (c, op_id)))
695 LOG_DEBUG ("Operation not found\n");
698 if (OP_FORWARDED == opc->type)
700 handle_forwarded_operation_msg (c, opc,
701 (const struct GNUNET_MessageHeader *) msg);
704 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
705 GNUNET_assert (NULL != (data = opc->data));
706 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
707 (ntohl (msg->peer2) == data->p2->unique_id));
708 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
710 event.op_cls = opc->op_cls;
713 case GNUNET_TESTBED_ET_CONNECT:
714 event.details.peer_connect.peer1 = data->p1;
715 event.details.peer_connect.peer2 = data->p2;
717 case GNUNET_TESTBED_ET_DISCONNECT:
718 GNUNET_assert (0); /* FIXME: implement */
721 GNUNET_assert (0); /* Should never reach here */
725 cb_cls = data->cb_cls;
726 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
727 opc->state = OPC_STATE_FINISHED;
728 exop_insert (event.op);
729 mask = 1LL << GNUNET_TESTBED_ET_CONNECT;
730 mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT;
731 if (0 != (mask & c->event_mask))
734 c->cc (c->cc_cls, &event);
735 if (GNUNET_NO == exop_check (event.op))
739 cb (cb_cls, opc->op, NULL);
740 /* You could have marked the operation as done by now */
741 GNUNET_break (GNUNET_NO == exop_check (event.op));
746 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
747 * controller (testbed service)
749 * @param c the controller handler
750 * @param msg message received
753 check_peer_config (void *cls,
754 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
762 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
763 * controller (testbed service)
765 * @param c the controller handler
766 * @param msg message received
769 handle_peer_config (void *cls,
770 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
772 struct GNUNET_TESTBED_Controller *c = cls;
773 struct OperationContext *opc;
774 struct GNUNET_TESTBED_Peer *peer;
775 struct PeerInfoData *data;
776 struct GNUNET_TESTBED_PeerInformation *pinfo;
777 GNUNET_TESTBED_PeerInfoCallback cb;
781 op_id = GNUNET_ntohll (msg->operation_id);
782 if (NULL == (opc = find_opc (c, op_id)))
784 LOG_DEBUG ("Operation not found\n");
787 if (OP_FORWARDED == opc->type)
789 handle_forwarded_operation_msg (c,
795 GNUNET_assert (NULL != data);
797 GNUNET_assert (NULL != peer);
798 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
799 pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation);
800 pinfo->pit = data->pit;
802 cb_cls = data->cb_cls;
803 GNUNET_assert (NULL != cb);
808 case GNUNET_TESTBED_PIT_IDENTITY:
809 pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity);
810 GNUNET_memcpy (pinfo->result.id,
812 sizeof (struct GNUNET_PeerIdentity));
814 case GNUNET_TESTBED_PIT_CONFIGURATION:
815 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
816 GNUNET_TESTBED_extract_config_ (&msg->header);
818 case GNUNET_TESTBED_PIT_GENERIC:
819 GNUNET_assert (0); /* never reach here */
823 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
824 opc->state = OPC_STATE_FINISHED;
825 cb (cb_cls, opc->op, pinfo, NULL);
826 /* We dont check whether the operation is marked as done here as the
827 operation contains data (cfg/identify) which will be freed at a later point
833 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
834 * controller (testbed service)
836 * @param c the controller handler
837 * @param msg message received
838 * @return #GNUNET_OK if message is well-formed
841 check_op_fail_event (void *cls,
842 const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
844 /* we accept anything as a valid error message */
850 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
851 * controller (testbed service)
853 * @param c the controller handler
854 * @param msg message received
857 handle_op_fail_event (void *cls,
858 const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
860 struct GNUNET_TESTBED_Controller *c = cls;
861 struct OperationContext *opc;
865 struct GNUNET_TESTBED_EventInformation event;
867 op_id = GNUNET_ntohll (msg->operation_id);
868 if (NULL == (opc = find_opc (c, op_id)))
870 LOG_DEBUG ("Operation not found\n");
873 if (OP_FORWARDED == opc->type)
875 handle_forwarded_operation_msg (c, opc,
876 (const struct GNUNET_MessageHeader *) msg);
879 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
880 opc->state = OPC_STATE_FINISHED;
881 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
883 emsg = "Unknown error";
884 if (OP_PEER_INFO == opc->type)
886 struct PeerInfoData *data;
889 if (NULL != data->cb)
890 data->cb (data->cb_cls, opc->op, NULL, emsg);
892 return; /* We do not call controller callback for peer info */
894 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
896 event.op_cls = opc->op_cls;
897 event.details.operation_finished.emsg = emsg;
898 event.details.operation_finished.generic = NULL;
899 mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
900 if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
902 exop_insert (event.op);
903 c->cc (c->cc_cls, &event);
904 if (GNUNET_NO == exop_check (event.op))
911 struct PeerCreateData *data;
914 GNUNET_free (data->peer);
915 if (NULL != data->cb)
916 data->cb (data->cls, NULL, emsg);
923 struct PeerEventData *data;
926 if (NULL != data->pcc)
927 data->pcc (data->pcc_cls, emsg);
931 case OP_PEER_DESTROY:
935 case OP_OVERLAY_CONNECT:
937 struct OverlayConnectData *data;
940 GNUNET_TESTBED_operation_mark_failed (opc->op);
941 if (NULL != data->cb)
942 data->cb (data->cb_cls, opc->op, emsg);
947 case OP_LINK_CONTROLLERS: /* No secondary callback */
949 case OP_SHUTDOWN_PEERS:
951 struct ShutdownPeersData *data;
954 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
958 case OP_MANAGE_SERVICE:
960 struct ManageServiceData *data = opc->data;
961 GNUNET_TESTBED_OperationCompletionCallback cb;
964 GNUNET_assert (NULL != data);
966 cb_cls = data->cb_cls;
969 exop_insert (event.op);
971 cb (cb_cls, opc->op, emsg);
972 /* You could have marked the operation as done by now */
973 GNUNET_break (GNUNET_NO == exop_check (event.op));
983 * Function to build GET_SLAVE_CONFIG message
985 * @param op_id the id this message should contain in its operation id field
986 * @param slave_id the id this message should contain in its slave id field
987 * @return newly allocated SlaveGetConfigurationMessage
989 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
990 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
992 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
995 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
996 msg = GNUNET_malloc (msize);
997 msg->header.size = htons (msize);
999 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
1000 msg->operation_id = GNUNET_htonll (op_id);
1001 msg->slave_id = htonl (slave_id);
1008 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_INFORMATION message from
1009 * controller (testbed service)
1011 * @param c the controller handler
1012 * @param msg message received
1015 check_slave_config (void *cls,
1016 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
1018 /* anything goes? */
1024 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION message from controller
1027 * @param c the controller handler
1028 * @param msg message received
1031 handle_slave_config (void *cls,
1032 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
1034 struct GNUNET_TESTBED_Controller *c = cls;
1035 struct OperationContext *opc;
1038 struct GNUNET_TESTBED_EventInformation event;
1040 op_id = GNUNET_ntohll (msg->operation_id);
1041 if (NULL == (opc = find_opc (c, op_id)))
1043 LOG_DEBUG ("Operation not found\n");
1046 if (OP_GET_SLAVE_CONFIG != opc->type)
1051 opc->state = OPC_STATE_FINISHED;
1052 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1053 mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
1054 if ((0 != (mask & c->event_mask)) &&
1057 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
1058 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1060 event.op_cls = opc->op_cls;
1061 event.details.operation_finished.generic = opc->data;
1062 event.details.operation_finished.emsg = NULL;
1063 c->cc (c->cc_cls, &event);
1069 * Check #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
1072 * @param c the controller handler
1073 * @param msg message received
1074 * @return #GNUNET_OK if @a msg is well-formed
1077 check_link_controllers_result (void *cls,
1078 const struct GNUNET_TESTBED_ControllerLinkResponse *msg)
1080 /* actual check to be implemented */
1086 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
1089 * @param c the controller handler
1090 * @param msg message received
1093 handle_link_controllers_result (void *cls,
1094 const struct GNUNET_TESTBED_ControllerLinkResponse *msg)
1096 struct GNUNET_TESTBED_Controller *c = cls;
1097 struct OperationContext *opc;
1098 struct ControllerLinkData *data;
1099 struct GNUNET_CONFIGURATION_Handle *cfg;
1100 struct GNUNET_TESTBED_Host *host;
1103 struct GNUNET_TESTBED_EventInformation event;
1105 op_id = GNUNET_ntohll (msg->operation_id);
1106 if (NULL == (opc = find_opc (c, op_id)))
1108 LOG_DEBUG ("Operation not found\n");
1111 if (OP_FORWARDED == opc->type)
1113 handle_forwarded_operation_msg (c, opc,
1114 (const struct GNUNET_MessageHeader *) msg);
1117 if (OP_LINK_CONTROLLERS != opc->type)
1122 GNUNET_assert (NULL != (data = opc->data));
1123 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
1124 GNUNET_assert (NULL != host);
1127 opc->state = OPC_STATE_FINISHED;
1128 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1129 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1131 event.op_cls = opc->op_cls;
1132 event.details.operation_finished.emsg = NULL;
1133 event.details.operation_finished.generic = NULL;
1136 if (GNUNET_NO == ntohs (msg->success))
1138 emsg = GNUNET_malloc (ntohs (msg->header.size)
1140 GNUNET_TESTBED_ControllerLinkResponse) + 1);
1141 GNUNET_memcpy (emsg,
1143 ntohs (msg->header.size)- sizeof (struct GNUNET_TESTBED_ControllerLinkResponse));
1144 event.details.operation_finished.emsg = emsg;
1148 if (0 != ntohs (msg->config_size))
1150 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
1151 GNUNET_assert (NULL != cfg);
1152 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
1155 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
1158 c->cc (c->cc_cls, &event);
1161 LOG_DEBUG ("Not calling callback\n");
1163 GNUNET_CONFIGURATION_destroy (cfg);
1164 GNUNET_free_non_null (emsg);
1169 * Validate #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS message.
1171 * @param cls the controller handle to determine the connection this message
1173 * @param msg the barrier status message
1174 * @return #GNUNET_OK if the message is valid; #GNUNET_SYSERR to tear it
1175 * down signalling an error (message malformed)
1178 check_barrier_status (void *cls,
1179 const struct GNUNET_TESTBED_BarrierStatusMsg *msg)
1187 msize = ntohs (msg->header.size);
1189 name_len = ntohs (msg->name_len);
1191 if (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len + 1 > msize)
1193 GNUNET_break_op (0);
1194 return GNUNET_SYSERR;
1196 if ('\0' != name[name_len])
1198 GNUNET_break_op (0);
1199 return GNUNET_SYSERR;
1201 status = ntohs (msg->status);
1202 if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
1204 emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg) + name_len
1208 GNUNET_break_op (0);
1209 return GNUNET_SYSERR;
1217 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS messages
1219 * @param cls the controller handle to determine the connection this message
1221 * @param msg the barrier status message
1224 handle_barrier_status (void *cls,
1225 const struct GNUNET_TESTBED_BarrierStatusMsg *msg)
1227 struct GNUNET_TESTBED_Controller *c = cls;
1228 struct GNUNET_TESTBED_Barrier *barrier;
1231 struct GNUNET_HashCode key;
1239 msize = ntohs (msg->header.size);
1240 if (msize <= sizeof (struct GNUNET_TESTBED_BarrierStatusMsg))
1242 GNUNET_break_op (0);
1246 name_len = ntohs (msg->name_len);
1247 if (name_len >= //name_len is strlen(barrier_name)
1248 (msize - ((sizeof msg->header) + sizeof (msg->status)) ) )
1250 GNUNET_break_op (0);
1253 if ('\0' != name[name_len])
1255 GNUNET_break_op (0);
1258 LOG_DEBUG ("Received BARRIER_STATUS msg\n");
1259 status = ntohs (msg->status);
1260 if (GNUNET_TESTBED_BARRIERSTATUS_ERROR == status)
1263 //unlike name_len, emsg_len includes the trailing zero
1264 emsg_len = msize - (sizeof (struct GNUNET_TESTBED_BarrierStatusMsg)
1268 GNUNET_break_op (0);
1271 if ('\0' != (msg->data[(name_len + 1) + (emsg_len - 1)]))
1273 GNUNET_break_op (0);
1276 emsg = GNUNET_malloc (emsg_len);
1277 GNUNET_memcpy (emsg,
1278 msg->data + name_len + 1,
1281 if (NULL == c->barrier_map)
1283 GNUNET_break_op (0);
1286 GNUNET_CRYPTO_hash (name, name_len, &key);
1287 barrier = GNUNET_CONTAINER_multihashmap_get (c->barrier_map, &key);
1288 if (NULL == barrier)
1290 GNUNET_break_op (0);
1293 GNUNET_assert (NULL != barrier->cb);
1294 if ((GNUNET_YES == barrier->echo) &&
1295 (GNUNET_TESTBED_BARRIERSTATUS_CROSSED == status))
1296 GNUNET_TESTBED_queue_message_ (c,
1297 GNUNET_copy_message (&msg->header));
1298 barrier->cb (barrier->cls,
1303 if (GNUNET_TESTBED_BARRIERSTATUS_INITIALISED == status)
1304 return; /* just initialised; skip cleanup */
1307 GNUNET_free_non_null (emsg);
1309 * Do not remove the barrier if we did not echo the status back; this is
1310 * required at the chained testbed controller setup to ensure the only the
1311 * test-driver echos the status and the controller hierarchy properly
1312 * propagates the status.
1314 if ((NULL != barrier) && (GNUNET_YES == barrier->echo))
1315 GNUNET_TESTBED_barrier_remove_ (barrier);
1320 * Queues a message in send queue for sending to the service
1322 * @param controller the handle to the controller
1323 * @param msg the message to queue
1326 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1327 struct GNUNET_MessageHeader *msg)
1329 struct GNUNET_MQ_Envelope *env;
1330 struct GNUNET_MessageHeader *m2;
1334 type = ntohs (msg->type);
1335 size = ntohs (msg->size);
1336 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1337 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1338 env = GNUNET_MQ_msg_extra (m2,
1339 size - sizeof (*m2),
1341 GNUNET_memcpy (m2, msg, size);
1343 GNUNET_MQ_send (controller->mq,
1349 * Sends the given message as an operation. The given callback is called when a
1350 * reply for the operation is available. Call
1351 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1352 * operation context if the cc hasn't been called
1354 * @param controller the controller to which the message has to be sent
1355 * @param operation_id the operation id of the message
1356 * @param msg the message to send
1357 * @param cc the callback to call when reply is available
1358 * @param cc_cls the closure for the above callback
1359 * @return the operation context which can be used to cancel the forwarded
1362 struct OperationContext *
1363 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller *controller,
1364 uint64_t operation_id,
1365 const struct GNUNET_MessageHeader *msg,
1366 GNUNET_MQ_MessageCallback cc,
1369 struct OperationContext *opc;
1370 struct ForwardedOperationData *data;
1371 struct GNUNET_MQ_Envelope *env;
1372 struct GNUNET_MessageHeader *m2;
1373 uint16_t type = ntohs (msg->type);
1374 uint16_t size = ntohs (msg->size);
1376 env = GNUNET_MQ_msg_extra (m2,
1377 size - sizeof (*m2),
1382 GNUNET_MQ_send (controller->mq,
1384 data = GNUNET_new (struct ForwardedOperationData);
1386 data->cc_cls = cc_cls;
1387 opc = GNUNET_new (struct OperationContext);
1388 opc->c = controller;
1389 opc->type = OP_FORWARDED;
1391 opc->id = operation_id;
1392 GNUNET_TESTBED_insert_opc_ (controller,
1399 * Function to cancel an operation created by simply forwarding an operation
1402 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1405 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1407 GNUNET_TESTBED_remove_opc_ (opc->c,
1409 GNUNET_free (opc->data);
1415 * Function to call to start a link-controllers type operation once all queues
1416 * the operation is part of declare that the operation can be activated.
1418 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1421 opstart_link_controllers (void *cls)
1423 struct OperationContext *opc = cls;
1424 struct ControllerLinkData *data;
1425 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1427 GNUNET_assert (NULL != opc->data);
1431 opc->state = OPC_STATE_STARTED;
1432 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1433 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1438 * Callback which will be called when link-controllers type operation is released
1440 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1443 oprelease_link_controllers (void *cls)
1445 struct OperationContext *opc = cls;
1446 struct ControllerLinkData *data;
1451 case OPC_STATE_INIT:
1452 GNUNET_free (data->msg);
1454 case OPC_STATE_STARTED:
1455 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1457 case OPC_STATE_FINISHED:
1460 GNUNET_free_non_null (data);
1466 * Function to be called when get slave config operation is ready
1468 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1471 opstart_get_slave_config (void *cls)
1473 struct OperationContext *opc = cls;
1474 struct GetSlaveConfigData *data = opc->data;
1475 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1477 GNUNET_assert (NULL != data);
1478 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1479 GNUNET_free (opc->data);
1482 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1483 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1484 opc->state = OPC_STATE_STARTED;
1489 * Function to be called when get slave config operation is cancelled or finished
1491 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1494 oprelease_get_slave_config (void *cls)
1496 struct OperationContext *opc = cls;
1500 case OPC_STATE_INIT:
1501 GNUNET_free (opc->data);
1503 case OPC_STATE_STARTED:
1504 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1506 case OPC_STATE_FINISHED:
1507 if (NULL != opc->data)
1508 GNUNET_CONFIGURATION_destroy (opc->data);
1516 * Generic error handler, called with the appropriate error code and
1517 * the same closure specified at the creation of the message queue.
1518 * Not every message queue implementation supports an error handler.
1520 * @param cls closure, a `struct GNUNET_TESTBED_Controller *`
1521 * @param error error code
1524 mq_error_handler (void *cls,
1525 enum GNUNET_MQ_Error error)
1527 /* struct GNUNET_TESTBED_Controller *c = cls; */
1529 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1530 "Encountered MQ error: %d\n",
1533 GNUNET_SCHEDULER_shutdown (); /* seems most reasonable */
1538 * Start a controller process using the given configuration at the
1541 * @param host host to run the controller on; This should be the same host if
1542 * the controller was previously started with
1543 * GNUNET_TESTBED_controller_start()
1544 * @param event_mask bit mask with set of events to call 'cc' for;
1545 * or-ed values of "1LL" shifted by the
1546 * respective 'enum GNUNET_TESTBED_EventType'
1547 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1548 * @param cc controller callback to invoke on events
1549 * @param cc_cls closure for cc
1550 * @return handle to the controller
1552 struct GNUNET_TESTBED_Controller *
1553 GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1554 uint64_t event_mask,
1555 GNUNET_TESTBED_ControllerCallback cc,
1558 struct GNUNET_TESTBED_Controller *controller
1559 = GNUNET_new (struct GNUNET_TESTBED_Controller);
1560 struct GNUNET_MQ_MessageHandler handlers[] = {
1561 GNUNET_MQ_hd_var_size (add_host_confirm,
1562 GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS,
1563 struct GNUNET_TESTBED_HostConfirmedMessage,
1565 GNUNET_MQ_hd_fixed_size (peer_conevent,
1566 GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT,
1567 struct GNUNET_TESTBED_ConnectionEventMessage,
1569 GNUNET_MQ_hd_fixed_size (opsuccess,
1570 GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS,
1571 struct GNUNET_TESTBED_GenericOperationSuccessEventMessage,
1573 GNUNET_MQ_hd_var_size (op_fail_event,
1574 GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT,
1575 struct GNUNET_TESTBED_OperationFailureEventMessage,
1577 GNUNET_MQ_hd_fixed_size (peer_create_success,
1578 GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS,
1579 struct GNUNET_TESTBED_PeerCreateSuccessEventMessage,
1581 GNUNET_MQ_hd_fixed_size (peer_event,
1582 GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT,
1583 struct GNUNET_TESTBED_PeerEventMessage,
1585 GNUNET_MQ_hd_var_size (peer_config,
1586 GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
1587 struct GNUNET_TESTBED_PeerConfigurationInformationMessage,
1589 GNUNET_MQ_hd_var_size (slave_config,
1590 GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1591 struct GNUNET_TESTBED_SlaveConfiguration,
1593 GNUNET_MQ_hd_var_size (link_controllers_result,
1594 GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1595 struct GNUNET_TESTBED_ControllerLinkResponse,
1597 GNUNET_MQ_hd_var_size (barrier_status,
1598 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS,
1599 struct GNUNET_TESTBED_BarrierStatusMsg,
1601 GNUNET_MQ_handler_end ()
1603 struct GNUNET_TESTBED_InitMessage *msg;
1604 struct GNUNET_MQ_Envelope *env;
1605 const struct GNUNET_CONFIGURATION_Handle *cfg;
1606 const char *controller_hostname;
1607 unsigned long long max_parallel_operations;
1608 unsigned long long max_parallel_service_connections;
1609 unsigned long long max_parallel_topology_config_operations;
1612 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
1614 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1615 "MAX_PARALLEL_OPERATIONS",
1616 &max_parallel_operations))
1619 GNUNET_free (controller);
1623 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1624 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1625 &max_parallel_service_connections))
1628 GNUNET_free (controller);
1632 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1633 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1634 &max_parallel_topology_config_operations))
1637 GNUNET_free (controller);
1640 controller->cc = cc;
1641 controller->cc_cls = cc_cls;
1642 controller->event_mask = event_mask;
1643 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1644 controller->mq = GNUNET_CLIENT_connect (controller->cfg,
1649 if (NULL == controller->mq)
1652 GNUNET_TESTBED_controller_disconnect (controller);
1655 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1656 controller->host = host;
1657 controller->opq_parallel_operations =
1658 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1659 (unsigned int) max_parallel_operations);
1660 controller->opq_parallel_service_connections =
1661 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1663 max_parallel_service_connections);
1664 controller->opq_parallel_topology_config_operations =
1665 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1667 max_parallel_topology_config_operations);
1668 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1669 if (NULL == controller_hostname)
1670 controller_hostname = "127.0.0.1";
1671 slen = strlen (controller_hostname) + 1;
1672 env = GNUNET_MQ_msg_extra (msg,
1674 GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1675 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1676 msg->event_mask = GNUNET_htonll (controller->event_mask);
1677 GNUNET_memcpy (&msg[1],
1678 controller_hostname,
1680 GNUNET_MQ_send (controller->mq,
1687 * Iterator to free opc map entries
1689 * @param cls closure
1690 * @param key current key code
1691 * @param value value in the hash map
1692 * @return #GNUNET_YES if we should continue to iterate,
1693 * #GNUNET_NO if not.
1696 opc_free_iterator (void *cls, uint32_t key, void *value)
1698 struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
1699 struct OperationContext *opc = value;
1701 GNUNET_assert (NULL != opc);
1703 GNUNET_assert (GNUNET_YES ==
1704 GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
1711 * Stop the given controller (also will terminate all peers and
1712 * controllers dependent on this controller). This function
1713 * blocks until the testbed has been fully terminated (!).
1715 * @param c handle to controller to stop
1718 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c)
1722 GNUNET_MQ_destroy (c->mq);
1725 if (NULL != c->host)
1726 GNUNET_TESTBED_deregister_host_at_ (c->host, c);
1727 GNUNET_CONFIGURATION_destroy (c->cfg);
1728 GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
1729 GNUNET_TESTBED_operation_queue_destroy_
1730 (c->opq_parallel_service_connections);
1731 GNUNET_TESTBED_operation_queue_destroy_
1732 (c->opq_parallel_topology_config_operations);
1733 if (NULL != c->opc_map)
1735 GNUNET_assert (GNUNET_SYSERR !=
1736 GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
1739 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
1740 GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
1747 * Compresses given configuration using zlib compress
1749 * @param config the serialized configuration
1750 * @param size the size of config
1751 * @param xconfig will be set to the compressed configuration (memory is fresly
1753 * @return the size of the xconfig
1756 GNUNET_TESTBED_compress_config_ (const char *config,
1762 xsize = compressBound ((uLong) size);
1763 *xconfig = GNUNET_malloc (xsize);
1764 GNUNET_assert (Z_OK ==
1765 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1766 (const Bytef *) config, (uLongf) size,
1773 * Function to serialize and compress using zlib a configuration through a
1774 * configuration handle
1776 * @param cfg the configuration
1777 * @param size the size of configuration when serialize. Will be set on success.
1778 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1779 * @return the serialized and compressed configuration
1782 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1783 size_t *size, size_t *xsize)
1790 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1791 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1792 GNUNET_free (config);
1800 * Create a link from slave controller to delegated controller. Whenever the
1801 * master controller is asked to start a peer at the delegated controller the
1802 * request will be routed towards slave controller (if a route exists). The
1803 * slave controller will then route it to the delegated controller. The
1804 * configuration of the delegated controller is given and is used to either
1805 * create the delegated controller or to connect to an existing controller. Note
1806 * that while starting the delegated controller the configuration will be
1807 * modified to accommodate available free ports. the 'is_subordinate' specifies
1808 * if the given delegated controller should be started and managed by the slave
1809 * controller, or if the delegated controller already has a master and the slave
1810 * controller connects to it as a non master controller. The success or failure
1811 * of this operation will be signalled through the
1812 * GNUNET_TESTBED_ControllerCallback() with an event of type
1813 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1815 * @param op_cls the operation closure for the event which is generated to
1816 * signal success or failure of this operation
1817 * @param master handle to the master controller who creates the association
1818 * @param delegated_host requests to which host should be delegated; cannot be NULL
1819 * @param slave_host which host is used to run the slave controller; use NULL to
1820 * make the master controller connect to the delegated host
1821 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1822 * be started by the slave controller; GNUNET_NO if the slave
1823 * controller has to connect to the already started delegated
1824 * controller via TCP/IP
1825 * @return the operation handle
1827 struct GNUNET_TESTBED_Operation *
1828 GNUNET_TESTBED_controller_link (void *op_cls,
1829 struct GNUNET_TESTBED_Controller *master,
1830 struct GNUNET_TESTBED_Host *delegated_host,
1831 struct GNUNET_TESTBED_Host *slave_host,
1834 struct OperationContext *opc;
1835 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1836 struct ControllerLinkData *data;
1837 uint32_t slave_host_id;
1838 uint32_t delegated_host_id;
1841 GNUNET_assert (GNUNET_YES ==
1842 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1844 GNUNET_TESTBED_host_get_id_ ((NULL !=
1845 slave_host) ? slave_host : master->host);
1846 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1847 if ((NULL != slave_host) && (0 != slave_host_id))
1848 GNUNET_assert (GNUNET_YES ==
1849 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1850 msg_size = sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1851 msg = GNUNET_malloc (msg_size);
1852 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1853 msg->header.size = htons (msg_size);
1854 msg->delegated_host_id = htonl (delegated_host_id);
1855 msg->slave_host_id = htonl (slave_host_id);
1856 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1857 data = GNUNET_new (struct ControllerLinkData);
1859 data->host_id = delegated_host_id;
1860 opc = GNUNET_new (struct OperationContext);
1863 opc->type = OP_LINK_CONTROLLERS;
1864 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1865 opc->state = OPC_STATE_INIT;
1866 opc->op_cls = op_cls;
1867 msg->operation_id = GNUNET_htonll (opc->id);
1869 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1870 &oprelease_link_controllers);
1871 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1873 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1879 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1880 * check. Another difference is that this function takes the id of the slave
1883 * @param op_cls the closure for the operation
1884 * @param master the handle to master controller
1885 * @param slave_host_id id of the host where the slave controller is running to
1886 * the slave_host should remain valid until this operation is cancelled
1887 * or marked as finished
1888 * @return the operation handle;
1890 struct GNUNET_TESTBED_Operation *
1891 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1892 struct GNUNET_TESTBED_Controller *master,
1893 uint32_t slave_host_id)
1895 struct OperationContext *opc;
1896 struct GetSlaveConfigData *data;
1898 data = GNUNET_new (struct GetSlaveConfigData);
1899 data->slave_id = slave_host_id;
1900 opc = GNUNET_new (struct OperationContext);
1901 opc->state = OPC_STATE_INIT;
1903 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1904 opc->type = OP_GET_SLAVE_CONFIG;
1906 opc->op_cls = op_cls;
1908 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1909 &oprelease_get_slave_config);
1910 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1912 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1918 * Function to acquire the configuration of a running slave controller. The
1919 * completion of the operation is signalled through the controller_cb from
1920 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1921 * handle to the configuration is available in the generic pointer of
1922 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1924 * @param op_cls the closure for the operation
1925 * @param master the handle to master controller
1926 * @param slave_host the host where the slave controller is running; the handle
1927 * to the slave_host should remain valid until this operation is
1928 * cancelled or marked as finished
1929 * @return the operation handle; NULL if the slave_host is not registered at
1932 struct GNUNET_TESTBED_Operation *
1933 GNUNET_TESTBED_get_slave_config (void *op_cls,
1934 struct GNUNET_TESTBED_Controller *master,
1935 struct GNUNET_TESTBED_Host *slave_host)
1937 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1939 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1940 GNUNET_TESTBED_host_get_id_
1946 * Ask the testbed controller to write the current overlay topology to
1947 * a file. Naturally, the file will only contain a snapshot as the
1948 * topology may evolve all the time.
1950 * @param controller overlay controller to inspect
1951 * @param filename name of the file the topology should
1955 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1957 const char *filename)
1964 * Creates a helper initialization message. This function is here because we
1965 * want to use this in testing
1967 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1968 * HOST(all connections form this ip are permitted by the testbed) when
1969 * starting testbed controller at host. This can either be a single ip
1970 * address or a network address in CIDR notation.
1971 * @param hostname the hostname of the destination this message is intended for
1972 * @param cfg the configuration that has to used to start the testbed service
1974 * @return the initialization message
1976 struct GNUNET_TESTBED_HelperInit *
1977 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1978 const char *hostname,
1979 const struct GNUNET_CONFIGURATION_Handle
1982 struct GNUNET_TESTBED_HelperInit *msg;
1986 size_t xconfig_size;
1987 uint16_t trusted_ip_len;
1988 uint16_t hostname_len;
1991 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1992 GNUNET_assert (NULL != config);
1994 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1995 GNUNET_free (config);
1996 trusted_ip_len = strlen (trusted_ip);
1997 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1999 xconfig_size + trusted_ip_len + 1 +
2000 sizeof (struct GNUNET_TESTBED_HelperInit);
2001 msg_size += hostname_len;
2002 msg = GNUNET_realloc (xconfig, msg_size);
2003 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
2005 msg->header.size = htons (msg_size);
2006 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2007 msg->trusted_ip_size = htons (trusted_ip_len);
2008 msg->hostname_size = htons (hostname_len);
2009 msg->config_size = htons (config_size);
2010 (void) strcpy ((char *) &msg[1], trusted_ip);
2011 if (0 != hostname_len)
2012 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
2019 * This function is used to signal that the event information (struct
2020 * GNUNET_TESTBED_EventInformation) from an operation has been fully processed
2021 * i.e. if the event callback is ever called for this operation. If the event
2022 * callback for this operation has not yet been called, calling this function
2023 * cancels the operation, frees its resources and ensures the no event is
2024 * generated with respect to this operation. Note that however cancelling an
2025 * operation does NOT guarantee that the operation will be fully undone (or that
2026 * nothing ever happened).
2028 * This function MUST be called for every operation to fully remove the
2029 * operation from the operation queue. After calling this function, if
2030 * operation is completed and its event information is of type
2031 * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!).
2033 * If the operation is generated from GNUNET_TESTBED_service_connect() then
2034 * calling this function on such as operation calls the disconnect adapter if
2035 * the connect adapter was ever called.
2037 * @param operation operation to signal completion or cancellation
2040 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2042 (void) exop_check (operation);
2043 GNUNET_TESTBED_operation_release_ (operation);
2048 * Generates configuration by uncompressing configuration in given message. The
2049 * given message should be of the following types:
2050 * #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
2051 * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
2052 * #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
2053 * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
2054 * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
2056 * FIXME: This API is incredibly ugly.
2058 * @param msg the message containing compressed configuration
2059 * @return handle to the parsed configuration; NULL upon error while parsing the message
2061 struct GNUNET_CONFIGURATION_Handle *
2062 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2064 struct GNUNET_CONFIGURATION_Handle *cfg;
2071 switch (ntohs (msg->type))
2073 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
2075 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2078 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
2079 data_len = (uLong) ntohs (imsg->config_size);
2081 ntohs (imsg->header.size) -
2082 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2083 xdata = (const Bytef *) &imsg[1];
2086 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
2088 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2090 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2091 data_len = (uLong) ntohs (imsg->config_size);
2093 ntohs (imsg->header.size) -
2094 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2095 xdata = (const Bytef *) &imsg[1];
2098 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
2100 const struct GNUNET_TESTBED_AddHostMessage *imsg;
2103 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
2104 data_len = (uLong) ntohs (imsg->config_size);
2105 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
2106 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
2107 xdata_len = ntohs (imsg->header.size) - osize;
2108 xdata = (const Bytef *) ((const void *) imsg + osize);
2111 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
2113 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
2115 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
2116 data_len = ntohs (imsg->config_size);
2117 xdata_len = ntohs (imsg->header.size) -
2118 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
2119 xdata = (const Bytef *) &imsg[1];
2122 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER:
2124 const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
2126 imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
2127 data_len = ntohs (imsg->config_size);
2128 xdata_len = ntohs (imsg->header.size) -
2129 sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
2130 xdata = (const Bytef *) &imsg[1];
2133 case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER:
2135 const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
2137 imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
2138 data_len = ntohs (imsg->config_size);
2139 xdata_len = ntohs (imsg->header.size) -
2140 sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
2141 xdata = (const Bytef *) &imsg[1];
2147 data = GNUNET_malloc (data_len);
2148 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2151 GNUNET_break_op (0); /* Un-compression failure */
2154 cfg = GNUNET_CONFIGURATION_create ();
2156 GNUNET_CONFIGURATION_deserialize (cfg,
2157 (const char *) data,
2162 GNUNET_break_op (0); /* De-serialization failure */
2171 * Checks the integrity of the OperationFailureEventMessage and if good returns
2172 * the error message it contains.
2174 * @param msg the OperationFailureEventMessage
2175 * @return the error message
2178 GNUNET_TESTBED_parse_error_string_ (const struct
2179 GNUNET_TESTBED_OperationFailureEventMessage
2185 msize = ntohs (msg->header.size);
2186 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2188 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2189 emsg = (const char *) &msg[1];
2190 if ('\0' != emsg[msize - 1])
2200 * Function to return the operation id for a controller. The operation id is
2201 * created from the controllers host id and its internal operation counter.
2203 * @param controller the handle to the controller whose operation id has to be incremented
2204 * @return the incremented operation id.
2207 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2211 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2212 op_id = op_id << 32;
2213 op_id |= (uint64_t) controller->operation_counter++;
2219 * Function called when a shutdown peers operation is ready
2221 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2224 opstart_shutdown_peers (void *cls)
2226 struct OperationContext *opc = cls;
2227 struct GNUNET_MQ_Envelope *env;
2228 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2230 opc->state = OPC_STATE_STARTED;
2231 env = GNUNET_MQ_msg (msg,
2232 GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2233 msg->operation_id = GNUNET_htonll (opc->id);
2234 GNUNET_TESTBED_insert_opc_ (opc->c,
2236 GNUNET_MQ_send (opc->c->mq,
2242 * Callback which will be called when shutdown peers operation is released
2244 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2247 oprelease_shutdown_peers (void *cls)
2249 struct OperationContext *opc = cls;
2253 case OPC_STATE_STARTED:
2254 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
2255 /* no break; continue */
2256 case OPC_STATE_INIT:
2257 GNUNET_free (opc->data);
2259 case OPC_STATE_FINISHED:
2267 * Stops and destroys all peers. Is equivalent of calling
2268 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2269 * except that the peer stop event and operation finished event corresponding to
2270 * the respective functions are not generated. This function should be called
2271 * when there are no other pending operations. If there are pending operations,
2272 * it will return NULL
2274 * @param c the controller to send this message to
2275 * @param op_cls closure for the operation
2276 * @param cb the callback to call when all peers are stopped and destroyed
2277 * @param cb_cls the closure for the callback
2278 * @return operation handle on success; NULL if any pending operations are
2281 struct GNUNET_TESTBED_Operation *
2282 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
2284 GNUNET_TESTBED_OperationCompletionCallback cb,
2287 struct OperationContext *opc;
2288 struct ShutdownPeersData *data;
2290 if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
2292 data = GNUNET_new (struct ShutdownPeersData);
2294 data->cb_cls = cb_cls;
2295 opc = GNUNET_new (struct OperationContext);
2297 opc->op_cls = op_cls;
2299 opc->id = GNUNET_TESTBED_get_next_op_id (c);
2300 opc->type = OP_SHUTDOWN_PEERS;
2301 opc->state = OPC_STATE_INIT;
2302 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2303 &oprelease_shutdown_peers);
2304 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2306 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2312 * Return the index of the peer inside of the total peer array,
2313 * aka. the peer's "unique ID".
2315 * @param peer Peer handle.
2317 * @return The peer's unique ID.
2320 GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer)
2322 return peer->unique_id;
2327 * Remove a barrier and it was the last one in the barrier hash map, destroy the
2330 * @param barrier the barrier to remove
2333 GNUNET_TESTBED_barrier_remove_ (struct GNUNET_TESTBED_Barrier *barrier)
2335 struct GNUNET_TESTBED_Controller *c = barrier->c;
2337 GNUNET_assert (NULL != c->barrier_map); /* No barriers present */
2338 GNUNET_assert (GNUNET_OK ==
2339 GNUNET_CONTAINER_multihashmap_remove (c->barrier_map,
2342 GNUNET_free (barrier->name);
2343 GNUNET_free (barrier);
2344 if (0 == GNUNET_CONTAINER_multihashmap_size (c->barrier_map))
2346 GNUNET_CONTAINER_multihashmap_destroy (c->barrier_map);
2347 c->barrier_map = NULL;
2353 * Initialise a barrier and call the given callback when the required percentage
2354 * of peers (quorum) reach the barrier OR upon error.
2356 * @param controller the handle to the controller
2357 * @param name identification name of the barrier
2358 * @param quorum the percentage of peers that is required to reach the barrier.
2359 * Peers signal reaching a barrier by calling
2360 * GNUNET_TESTBED_barrier_reached().
2361 * @param cb the callback to call when the barrier is reached or upon error.
2363 * @param cls closure for the above callback
2364 * @param echo GNUNET_YES to echo the barrier crossed status message back to the
2366 * @return barrier handle; NULL upon error
2368 struct GNUNET_TESTBED_Barrier *
2369 GNUNET_TESTBED_barrier_init_ (struct GNUNET_TESTBED_Controller *controller,
2371 unsigned int quorum,
2372 GNUNET_TESTBED_barrier_status_cb cb, void *cls,
2375 struct GNUNET_TESTBED_BarrierInit *msg;
2376 struct GNUNET_MQ_Envelope *env;
2377 struct GNUNET_TESTBED_Barrier *barrier;
2378 struct GNUNET_HashCode key;
2381 GNUNET_assert (quorum <= 100);
2382 GNUNET_assert (NULL != cb);
2383 name_len = strlen (name);
2384 GNUNET_assert (0 < name_len);
2385 GNUNET_CRYPTO_hash (name, name_len, &key);
2386 if (NULL == controller->barrier_map)
2387 controller->barrier_map = GNUNET_CONTAINER_multihashmap_create (3, GNUNET_YES);
2389 GNUNET_CONTAINER_multihashmap_contains (controller->barrier_map,
2395 LOG_DEBUG ("Initialising barrier `%s'\n", name);
2396 barrier = GNUNET_new (struct GNUNET_TESTBED_Barrier);
2397 barrier->c = controller;
2398 barrier->name = GNUNET_strdup (name);
2401 barrier->echo = echo;
2402 GNUNET_memcpy (&barrier->key, &key, sizeof (struct GNUNET_HashCode));
2403 GNUNET_assert (GNUNET_OK ==
2404 GNUNET_CONTAINER_multihashmap_put (controller->barrier_map,
2407 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST));
2409 env = GNUNET_MQ_msg_extra (msg,
2411 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_INIT);
2412 msg->quorum = (uint8_t) quorum;
2413 GNUNET_memcpy (msg->name,
2416 GNUNET_MQ_send (barrier->c->mq,
2423 * Initialise a barrier and call the given callback when the required percentage
2424 * of peers (quorum) reach the barrier OR upon error.
2426 * @param controller the handle to the controller
2427 * @param name identification name of the barrier
2428 * @param quorum the percentage of peers that is required to reach the barrier.
2429 * Peers signal reaching a barrier by calling
2430 * GNUNET_TESTBED_barrier_reached().
2431 * @param cb the callback to call when the barrier is reached or upon error.
2433 * @param cls closure for the above callback
2434 * @return barrier handle; NULL upon error
2436 struct GNUNET_TESTBED_Barrier *
2437 GNUNET_TESTBED_barrier_init (struct GNUNET_TESTBED_Controller *controller,
2439 unsigned int quorum,
2440 GNUNET_TESTBED_barrier_status_cb cb, void *cls)
2442 return GNUNET_TESTBED_barrier_init_ (controller,
2443 name, quorum, cb, cls, GNUNET_YES);
2450 * @param barrier the barrier handle
2453 GNUNET_TESTBED_barrier_cancel (struct GNUNET_TESTBED_Barrier *barrier)
2455 struct GNUNET_MQ_Envelope *env;
2456 struct GNUNET_TESTBED_BarrierCancel *msg;
2459 slen = strlen (barrier->name);
2460 env = GNUNET_MQ_msg_extra (msg,
2462 GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_CANCEL);
2463 GNUNET_memcpy (msg->name,
2466 GNUNET_MQ_send (barrier->c->mq,
2468 GNUNET_TESTBED_barrier_remove_ (barrier);
2472 /* end of testbed_api.c */