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 * The message queue for sending messages to the controller service
75 * The message to be sent
77 struct GNUNET_MessageHeader *msg;
80 * next pointer for DLL
82 struct MessageQueue *next;
85 * prev pointer for DLL
87 struct MessageQueue *prev;
92 * Context data for forwarded Operation
94 struct ForwardedOperationData
98 * The callback to call when reply is available
100 GNUNET_CLIENT_MessageHandler cc;
103 * The closure for the above callback
111 * Context data for get slave config operations
113 struct GetSlaveConfigData
116 * The id of the slave controller
124 * Context data for controller link operations
126 struct ControllerLinkData
129 * The controller link message
131 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
134 * The id of the host which is hosting the controller to be linked
142 * Date context for OP_SHUTDOWN_PEERS operations
144 struct ShutdownPeersData
147 * The operation completion callback to call
149 GNUNET_TESTBED_OperationCompletionCallback cb;
152 * The closure for the above callback
159 * An entry in the stack for keeping operations which are about to expire
161 struct ExpireOperationEntry
164 * DLL head; new entries are to be inserted here
166 struct ExpireOperationEntry *next;
169 * DLL tail; entries are deleted from here
171 struct ExpireOperationEntry *prev;
174 * The operation. This will be a dangling pointer when the operation is freed
176 const struct GNUNET_TESTBED_Operation *op;
181 * DLL head for list of operations marked for expiry
183 static struct ExpireOperationEntry *exop_head;
186 * DLL tail for list of operation marked for expiry
188 static struct ExpireOperationEntry *exop_tail;
192 * Inserts an operation into the list of operations marked for expiry
194 * @param op the operation to insert
197 exop_insert (struct GNUNET_TESTBED_Operation *op)
199 struct ExpireOperationEntry *entry;
201 entry = GNUNET_new (struct ExpireOperationEntry);
203 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
208 * Checks if an operation is present in the list of operations marked for
209 * expiry. If the operation is found, it and the tail of operations after it
210 * are removed from the list.
212 * @param op the operation to check
213 * @return GNUNET_NO if the operation is not present in the list; GNUNET_YES if
214 * the operation is found in the list (the operation is then removed
215 * from the list -- calling this function again with the same
216 * paramenter will return GNUNET_NO)
219 exop_check (const struct GNUNET_TESTBED_Operation *const op)
221 struct ExpireOperationEntry *entry;
222 struct ExpireOperationEntry *entry2;
227 while (NULL != entry)
236 if (GNUNET_NO == found)
238 /* Truncate the tail */
239 while (NULL != entry)
241 entry2 = entry->next;
242 GNUNET_CONTAINER_DLL_remove (exop_head,
253 * Context information to be used while searching for operation contexts
258 * The result of the search
260 struct OperationContext *opc;
263 * The id of the operation context we are searching for
270 * Search iterator for searching an operation context
272 * @param cls the serach context
273 * @param key current key code
274 * @param value value in the hash map
275 * @return GNUNET_YES if we should continue to
280 opc_search_iterator (void *cls, uint32_t key, void *value)
282 struct SearchContext *sc = cls;
283 struct OperationContext *opc = value;
285 GNUNET_assert (NULL != opc);
286 GNUNET_assert (NULL == sc->opc);
287 if (opc->id != sc->id)
295 * Returns the operation context with the given id if found in the Operation
296 * context queues of the controller
298 * @param c the controller whose operation context map is searched
299 * @param id the id which has to be checked
300 * @return the matching operation context; NULL if no match found
302 static struct OperationContext *
303 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
305 struct SearchContext sc;
309 GNUNET_assert (NULL != c->opc_map);
311 GNUNET_CONTAINER_multihashmap32_get_multiple (c->opc_map, (uint32_t) id,
312 &opc_search_iterator, &sc))
319 * Inserts the given operation context into the operation context map of the
320 * given controller. Creates the operation context map if one does not exist
323 * @param c the controller
324 * @param opc the operation context to be inserted
327 GNUNET_TESTBED_insert_opc_ (struct GNUNET_TESTBED_Controller *c,
328 struct OperationContext *opc)
330 if (NULL == c->opc_map)
331 c->opc_map = GNUNET_CONTAINER_multihashmap32_create (256);
332 GNUNET_assert (GNUNET_OK ==
333 GNUNET_CONTAINER_multihashmap32_put (c->opc_map,
334 (uint32_t) opc->id, opc,
335 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
340 * Removes the given operation context from the operation context map of the
343 * @param c the controller
344 * @param opc the operation context to remove
347 GNUNET_TESTBED_remove_opc_ (const struct GNUNET_TESTBED_Controller *c,
348 struct OperationContext *opc)
350 GNUNET_assert (NULL != c->opc_map);
351 GNUNET_assert (GNUNET_YES ==
352 GNUNET_CONTAINER_multihashmap32_remove (c->opc_map,
355 if ( (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
356 && (NULL != c->opcq_empty_cb) )
357 c->opcq_empty_cb (c->opcq_empty_cls);
362 * Handler for forwarded operations
364 * @param c the controller handle
365 * @param opc the opearation context
366 * @param msg the message
369 handle_forwarded_operation_msg (void *cls,
370 struct OperationContext *opc,
371 const struct GNUNET_MessageHeader *msg)
373 struct GNUNET_TESTBED_Controller *c = cls;
374 struct ForwardedOperationData *fo_data;
377 if (NULL != fo_data->cc)
378 fo_data->cc (fo_data->cc_cls, msg);
379 GNUNET_TESTBED_remove_opc_ (c, opc);
380 GNUNET_free (fo_data);
386 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS message from
387 * controller (testbed service)
389 * @param c the controller handler
390 * @param msg message received
393 handle_opsuccess (void *cls,
394 const struct GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
396 struct GNUNET_TESTBED_Controller *c = cls;
397 struct OperationContext *opc;
398 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
399 void *op_comp_cb_cls;
400 struct GNUNET_TESTBED_EventInformation event;
403 op_id = GNUNET_ntohll (msg->operation_id);
404 LOG_DEBUG ("Operation %lu successful\n", op_id);
405 if (NULL == (opc = find_opc (c, op_id)))
407 LOG_DEBUG ("Operation not found\n");
410 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
412 event.op_cls = opc->op_cls;
413 event.details.operation_finished.emsg = NULL;
414 event.details.operation_finished.generic = NULL;
416 op_comp_cb_cls = NULL;
421 handle_forwarded_operation_msg (c, opc,
422 (const struct GNUNET_MessageHeader *) msg);
426 case OP_PEER_DESTROY:
428 struct GNUNET_TESTBED_Peer *peer;
431 GNUNET_TESTBED_peer_deregister_ (peer);
437 case OP_SHUTDOWN_PEERS:
439 struct ShutdownPeersData *data;
442 op_comp_cb = data->cb;
443 op_comp_cb_cls = data->cb_cls;
446 GNUNET_TESTBED_cleanup_peers_ ();
449 case OP_MANAGE_SERVICE:
451 struct ManageServiceData *data;
453 GNUNET_assert (NULL != (data = opc->data));
454 op_comp_cb = data->cb;
455 op_comp_cb_cls = data->cb_cls;
460 case OP_PEER_RECONFIGURE:
465 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
466 opc->state = OPC_STATE_FINISHED;
467 exop_insert (event.op);
468 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
471 c->cc (c->cc_cls, &event);
472 if (GNUNET_NO == exop_check (event.op))
476 LOG_DEBUG ("Not calling callback\n");
477 if (NULL != op_comp_cb)
478 op_comp_cb (op_comp_cb_cls, event.op, NULL);
479 /* You could have marked the operation as done by now */
480 GNUNET_break (GNUNET_NO == exop_check (event.op));
485 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS message from
486 * controller (testbed service)
488 * @param c the controller handle
489 * @param msg message received
492 handle_peer_create_success (void *cls,
493 const struct GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
495 struct GNUNET_TESTBED_Controller *c = cls;
496 struct OperationContext *opc;
497 struct PeerCreateData *data;
498 struct GNUNET_TESTBED_Peer *peer;
499 struct GNUNET_TESTBED_Operation *op;
500 GNUNET_TESTBED_PeerCreateCallback cb;
504 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
505 ntohs (msg->header.size));
506 op_id = GNUNET_ntohll (msg->operation_id);
507 if (NULL == (opc = find_opc (c, op_id)))
509 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
512 if (OP_FORWARDED == opc->type)
514 handle_forwarded_operation_msg (c, opc,
515 (const struct GNUNET_MessageHeader *) msg);
518 GNUNET_assert (OP_PEER_CREATE == opc->type);
519 GNUNET_assert (NULL != opc->data);
521 GNUNET_assert (NULL != data->peer);
523 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
524 peer->state = TESTBED_PS_CREATED;
525 GNUNET_TESTBED_peer_register_ (peer);
529 GNUNET_free (opc->data);
530 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
531 opc->state = OPC_STATE_FINISHED;
534 cb (cb_cls, peer, NULL);
535 /* You could have marked the operation as done by now */
536 GNUNET_break (GNUNET_NO == exop_check (op));
541 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT message from
542 * controller (testbed service)
544 * @param c the controller handler
545 * @param msg message received
548 handle_peer_event (void *cls,
549 const struct GNUNET_TESTBED_PeerEventMessage *msg)
551 struct GNUNET_TESTBED_Controller *c = cls;
552 struct OperationContext *opc;
553 struct GNUNET_TESTBED_Peer *peer;
554 struct PeerEventData *data;
555 GNUNET_TESTBED_PeerChurnCallback pcc;
557 struct GNUNET_TESTBED_EventInformation event;
561 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
562 ntohs (msg->header.size));
563 op_id = GNUNET_ntohll (msg->operation_id);
564 if (NULL == (opc = find_opc (c, op_id)))
566 LOG_DEBUG ("Operation not found\n");
569 if (OP_FORWARDED == opc->type)
571 handle_forwarded_operation_msg (c, opc,
572 (const struct GNUNET_MessageHeader *) msg);
575 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
577 GNUNET_assert (NULL != data);
579 GNUNET_assert (NULL != peer);
580 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
582 event.op_cls = opc->op_cls;
585 case GNUNET_TESTBED_ET_PEER_START:
586 peer->state = TESTBED_PS_STARTED;
587 event.details.peer_start.host = peer->host;
588 event.details.peer_start.peer = peer;
590 case GNUNET_TESTBED_ET_PEER_STOP:
591 peer->state = TESTBED_PS_STOPPED;
592 event.details.peer_stop.peer = peer;
595 GNUNET_assert (0); /* We should never reach this state */
598 pcc_cls = data->pcc_cls;
600 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
601 opc->state = OPC_STATE_FINISHED;
602 exop_insert (event.op);
603 mask = 1LL << GNUNET_TESTBED_ET_PEER_START;
604 mask |= 1LL << GNUNET_TESTBED_ET_PEER_STOP;
605 if (0 != (mask & c->event_mask))
608 c->cc (c->cc_cls, &event);
609 if (GNUNET_NO == exop_check (event.op))
614 /* You could have marked the operation as done by now */
615 GNUNET_break (GNUNET_NO == exop_check (event.op));
620 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT message from
621 * controller (testbed service)
623 * @param c the controller handler
624 * @param msg message received
627 handle_peer_conevent (void *cls,
628 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
630 struct GNUNET_TESTBED_Controller *c = cls;
631 struct OperationContext *opc;
632 struct OverlayConnectData *data;
633 GNUNET_TESTBED_OperationCompletionCallback cb;
635 struct GNUNET_TESTBED_EventInformation event;
639 op_id = GNUNET_ntohll (msg->operation_id);
640 if (NULL == (opc = find_opc (c, op_id)))
642 LOG_DEBUG ("Operation not found\n");
645 if (OP_FORWARDED == opc->type)
647 handle_forwarded_operation_msg (c, opc,
648 (const struct GNUNET_MessageHeader *) msg);
651 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
652 GNUNET_assert (NULL != (data = opc->data));
653 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
654 (ntohl (msg->peer2) == data->p2->unique_id));
655 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
657 event.op_cls = opc->op_cls;
660 case GNUNET_TESTBED_ET_CONNECT:
661 event.details.peer_connect.peer1 = data->p1;
662 event.details.peer_connect.peer2 = data->p2;
664 case GNUNET_TESTBED_ET_DISCONNECT:
665 GNUNET_assert (0); /* FIXME: implement */
668 GNUNET_assert (0); /* Should never reach here */
672 cb_cls = data->cb_cls;
673 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
674 opc->state = OPC_STATE_FINISHED;
675 exop_insert (event.op);
676 mask = 1LL << GNUNET_TESTBED_ET_CONNECT;
677 mask |= 1LL << GNUNET_TESTBED_ET_DISCONNECT;
678 if (0 != (mask & c->event_mask))
681 c->cc (c->cc_cls, &event);
682 if (GNUNET_NO == exop_check (event.op))
686 cb (cb_cls, opc->op, NULL);
687 /* You could have marked the operation as done by now */
688 GNUNET_break (GNUNET_NO == exop_check (event.op));
693 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION message from
694 * controller (testbed service)
696 * @param c the controller handler
697 * @param msg message received
700 handle_peer_config (void *cls,
702 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
704 struct GNUNET_TESTBED_Controller *c = cls;
705 struct OperationContext *opc;
706 struct GNUNET_TESTBED_Peer *peer;
707 struct PeerInfoData *data;
708 struct GNUNET_TESTBED_PeerInformation *pinfo;
709 GNUNET_TESTBED_PeerInfoCallback cb;
713 op_id = GNUNET_ntohll (msg->operation_id);
714 if (NULL == (opc = find_opc (c, op_id)))
716 LOG_DEBUG ("Operation not found\n");
719 if (OP_FORWARDED == opc->type)
721 handle_forwarded_operation_msg (c, opc,
722 (const struct GNUNET_MessageHeader *) msg);
726 GNUNET_assert (NULL != data);
728 GNUNET_assert (NULL != peer);
729 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
730 pinfo = GNUNET_new (struct GNUNET_TESTBED_PeerInformation);
731 pinfo->pit = data->pit;
733 cb_cls = data->cb_cls;
734 GNUNET_assert (NULL != cb);
739 case GNUNET_TESTBED_PIT_IDENTITY:
740 pinfo->result.id = GNUNET_new (struct GNUNET_PeerIdentity);
741 (void) memcpy (pinfo->result.id,
743 sizeof (struct GNUNET_PeerIdentity));
745 case GNUNET_TESTBED_PIT_CONFIGURATION:
746 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
747 GNUNET_TESTBED_extract_config_ (&msg->header);
749 case GNUNET_TESTBED_PIT_GENERIC:
750 GNUNET_assert (0); /* never reach here */
754 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
755 opc->state = OPC_STATE_FINISHED;
756 cb (cb_cls, opc->op, pinfo, NULL);
757 /* We dont check whether the operation is marked as done here as the
758 operation contains data (cfg/identify) which will be freed at a later point
764 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT message from
765 * controller (testbed service)
767 * @param c the controller handler
768 * @param msg message received
771 handle_op_fail_event (void *cls,
772 const struct GNUNET_TESTBED_OperationFailureEventMessage *msg)
774 struct GNUNET_TESTBED_Controller *c = cls;
775 struct OperationContext *opc;
779 struct GNUNET_TESTBED_EventInformation event;
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, opc,
790 (const struct GNUNET_MessageHeader *) msg);
793 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
794 opc->state = OPC_STATE_FINISHED;
795 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
797 emsg = "Unknown error";
798 if (OP_PEER_INFO == opc->type)
800 struct PeerInfoData *data;
803 if (NULL != data->cb)
804 data->cb (data->cb_cls, opc->op, NULL, emsg);
806 return; /* We do not call controller callback for peer info */
808 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
810 event.op_cls = opc->op_cls;
811 event.details.operation_finished.emsg = emsg;
812 event.details.operation_finished.generic = NULL;
813 mask = (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
814 if ((0 != (mask & c->event_mask)) && (NULL != c->cc))
816 exop_insert (event.op);
817 c->cc (c->cc_cls, &event);
818 if (GNUNET_NO == exop_check (event.op))
825 struct PeerCreateData *data;
828 GNUNET_free (data->peer);
829 if (NULL != data->cb)
830 data->cb (data->cls, NULL, emsg);
837 struct PeerEventData *data;
840 if (NULL != data->pcc)
841 data->pcc (data->pcc_cls, emsg);
845 case OP_PEER_DESTROY:
849 case OP_OVERLAY_CONNECT:
851 struct OverlayConnectData *data;
854 GNUNET_TESTBED_operation_mark_failed (opc->op);
855 if (NULL != data->cb)
856 data->cb (data->cb_cls, opc->op, emsg);
861 case OP_LINK_CONTROLLERS: /* No secondary callback */
863 case OP_SHUTDOWN_PEERS:
865 struct ShutdownPeersData *data;
868 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
872 case OP_MANAGE_SERVICE:
874 struct ManageServiceData *data = opc->data;
875 GNUNET_TESTBED_OperationCompletionCallback cb;
878 GNUNET_assert (NULL != data);
880 cb_cls = data->cb_cls;
883 exop_insert (event.op);
885 cb (cb_cls, opc->op, emsg);
886 /* You could have marked the operation as done by now */
887 GNUNET_break (GNUNET_NO == exop_check (event.op));
897 * Function to build GET_SLAVE_CONFIG message
899 * @param op_id the id this message should contain in its operation id field
900 * @param slave_id the id this message should contain in its slave id field
901 * @return newly allocated SlaveGetConfigurationMessage
903 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
904 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
906 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
909 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
910 msg = GNUNET_malloc (msize);
911 msg->header.size = htons (msize);
913 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
914 msg->operation_id = GNUNET_htonll (op_id);
915 msg->slave_id = htonl (slave_id);
921 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION message from controller
924 * @param c the controller handler
925 * @param msg message received
928 handle_slave_config (void *cls,
929 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
931 struct GNUNET_TESTBED_Controller *c = cls;
932 struct OperationContext *opc;
935 struct GNUNET_TESTBED_EventInformation event;
937 op_id = GNUNET_ntohll (msg->operation_id);
938 if (NULL == (opc = find_opc (c, op_id)))
940 LOG_DEBUG ("Operation not found\n");
943 if (OP_GET_SLAVE_CONFIG != opc->type)
948 opc->state = OPC_STATE_FINISHED;
949 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
950 mask = 1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED;
951 if ((0 != (mask & c->event_mask)) &&
954 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
955 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
957 event.op_cls = opc->op_cls;
958 event.details.operation_finished.generic = opc->data;
959 event.details.operation_finished.emsg = NULL;
960 c->cc (c->cc_cls, &event);
966 * Handler for #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT message from controller
969 * @param c the controller handler
970 * @param msg message received
973 handle_link_controllers_result (void *cls,
975 GNUNET_TESTBED_ControllerLinkResponse *msg)
977 struct GNUNET_TESTBED_Controller *c = cls;
978 struct OperationContext *opc;
979 struct ControllerLinkData *data;
980 struct GNUNET_CONFIGURATION_Handle *cfg;
981 struct GNUNET_TESTBED_Host *host;
984 struct GNUNET_TESTBED_EventInformation event;
986 op_id = GNUNET_ntohll (msg->operation_id);
987 if (NULL == (opc = find_opc (c, op_id)))
989 LOG_DEBUG ("Operation not found\n");
992 if (OP_FORWARDED == opc->type)
994 handle_forwarded_operation_msg (c, opc,
995 (const struct GNUNET_MessageHeader *) msg);
998 if (OP_LINK_CONTROLLERS != opc->type)
1003 GNUNET_assert (NULL != (data = opc->data));
1004 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
1005 GNUNET_assert (NULL != host);
1008 opc->state = OPC_STATE_FINISHED;
1009 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1010 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1012 event.op_cls = opc->op_cls;
1013 event.details.operation_finished.emsg = NULL;
1014 event.details.operation_finished.generic = NULL;
1017 if (GNUNET_NO == ntohs (msg->success))
1019 emsg = GNUNET_malloc (ntohs (msg->header.size)
1021 GNUNET_TESTBED_ControllerLinkResponse) + 1);
1022 memcpy (emsg, &msg[1], ntohs (msg->header.size)
1024 GNUNET_TESTBED_ControllerLinkResponse));
1025 event.details.operation_finished.emsg = emsg;
1029 if (0 != ntohs (msg->config_size))
1031 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
1032 GNUNET_assert (NULL != cfg);
1033 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
1036 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
1039 c->cc (c->cc_cls, &event);
1042 LOG_DEBUG ("Not calling callback\n");
1044 GNUNET_CONFIGURATION_destroy (cfg);
1045 GNUNET_free_non_null (emsg);
1050 * Handler for messages from controller (testbed service)
1052 * @param cls the controller handler
1053 * @param msg message received, NULL on timeout or fatal error
1056 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
1058 struct GNUNET_TESTBED_Controller *c = cls;
1062 c->in_receive = GNUNET_NO;
1063 /* FIXME: Add checks for message integrity */
1066 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
1069 msize = ntohs (msg->size);
1070 switch (ntohs (msg->type))
1072 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
1073 GNUNET_assert (msize >=
1074 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
1076 GNUNET_TESTBED_host_handle_addhostconfirm_
1077 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
1079 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
1080 GNUNET_assert (msize ==
1082 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
1083 handle_opsuccess (c,
1085 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
1087 status = GNUNET_YES;
1089 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
1090 GNUNET_assert (msize >=
1091 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
1092 handle_op_fail_event (c,
1094 GNUNET_TESTBED_OperationFailureEventMessage *)
1096 status = GNUNET_YES;
1098 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
1099 GNUNET_assert (msize ==
1101 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1102 handle_peer_create_success (c,
1104 GNUNET_TESTBED_PeerCreateSuccessEventMessage
1106 status = GNUNET_YES;
1108 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
1109 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1110 handle_peer_event (c,
1111 (const struct GNUNET_TESTBED_PeerEventMessage *)
1114 status = GNUNET_YES;
1116 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
1117 GNUNET_assert (msize >=
1119 GNUNET_TESTBED_PeerConfigurationInformationMessage));
1120 handle_peer_config (c,
1122 GNUNET_TESTBED_PeerConfigurationInformationMessage
1124 status = GNUNET_YES;
1127 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
1128 GNUNET_assert (msize ==
1129 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1130 handle_peer_conevent (c,
1132 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1133 status = GNUNET_YES;
1135 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1136 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1137 handle_slave_config (c,
1138 (const struct GNUNET_TESTBED_SlaveConfiguration *)
1140 status = GNUNET_YES;
1142 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1143 handle_link_controllers_result (c,
1145 GNUNET_TESTBED_ControllerLinkResponse
1147 status = GNUNET_YES;
1149 case GNUNET_MESSAGE_TYPE_TESTBED_BARRIER_STATUS:
1150 status = check_barrier_status_ (c,
1151 (const struct GNUNET_TESTBED_BarrierStatusMsg *) msg);
1152 if (GNUNET_OK == status)
1153 handle_barrier_status_ (c,
1155 GNUNET_TESTBED_BarrierStatusMsg *)
1161 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1163 c->in_receive = GNUNET_YES;
1164 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1165 GNUNET_TIME_UNIT_FOREVER_REL);
1171 * Function called to notify a client about the connection begin ready to queue
1172 * more data. "buf" will be NULL and "size" zero if the connection was closed
1173 * for writing in the meantime.
1175 * @param cls closure
1176 * @param size number of bytes available in buf
1177 * @param buf where the callee should write the message
1178 * @return number of bytes written to buf
1181 transmit_ready_notify (void *cls, size_t size, void *buf)
1183 struct GNUNET_TESTBED_Controller *c = cls;
1184 struct MessageQueue *mq_entry;
1187 mq_entry = c->mq_head;
1188 GNUNET_assert (NULL != mq_entry);
1189 if ((0 == size) && (NULL == buf)) /* Timeout */
1191 LOG_DEBUG ("Message sending timed out -- retrying\n");
1193 GNUNET_CLIENT_notify_transmit_ready (c->client,
1194 ntohs (mq_entry->msg->size),
1195 TIMEOUT_REL, GNUNET_YES,
1196 &transmit_ready_notify, c);
1199 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1200 size = ntohs (mq_entry->msg->size);
1201 memcpy (buf, mq_entry->msg, size);
1202 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1203 ntohs (mq_entry->msg->type), size);
1204 GNUNET_free (mq_entry->msg);
1205 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1206 GNUNET_free (mq_entry);
1207 mq_entry = c->mq_head;
1208 if (NULL != mq_entry)
1210 GNUNET_CLIENT_notify_transmit_ready (c->client,
1211 ntohs (mq_entry->msg->size),
1212 TIMEOUT_REL, GNUNET_YES,
1213 &transmit_ready_notify, c);
1214 if (GNUNET_NO == c->in_receive)
1216 c->in_receive = GNUNET_YES;
1217 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1218 GNUNET_TIME_UNIT_FOREVER_REL);
1225 * Queues a message in send queue for sending to the service
1227 * @param controller the handle to the controller
1228 * @param msg the message to queue
1231 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1232 struct GNUNET_MessageHeader *msg)
1234 struct MessageQueue *mq_entry;
1238 type = ntohs (msg->type);
1239 size = ntohs (msg->size);
1240 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1241 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1242 mq_entry = GNUNET_new (struct MessageQueue);
1243 mq_entry->msg = msg;
1244 LOG (GNUNET_ERROR_TYPE_DEBUG,
1245 "Queueing message of type %u, size %u for sending\n", type,
1247 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1249 if (NULL == controller->th)
1251 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1252 TIMEOUT_REL, GNUNET_YES,
1253 &transmit_ready_notify,
1259 * Sends the given message as an operation. The given callback is called when a
1260 * reply for the operation is available. Call
1261 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1262 * operation context if the cc hasn't been called
1264 * @param controller the controller to which the message has to be sent
1265 * @param operation_id the operation id of the message
1266 * @param msg the message to send
1267 * @param cc the callback to call when reply is available
1268 * @param cc_cls the closure for the above callback
1269 * @return the operation context which can be used to cancel the forwarded
1272 struct OperationContext *
1273 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1274 *controller, uint64_t operation_id,
1275 const struct GNUNET_MessageHeader *msg,
1276 GNUNET_CLIENT_MessageHandler cc,
1279 struct OperationContext *opc;
1280 struct ForwardedOperationData *data;
1281 struct GNUNET_MessageHeader *dup_msg;
1284 data = GNUNET_new (struct ForwardedOperationData);
1286 data->cc_cls = cc_cls;
1287 opc = GNUNET_new (struct OperationContext);
1288 opc->c = controller;
1289 opc->type = OP_FORWARDED;
1291 opc->id = operation_id;
1292 msize = ntohs (msg->size);
1293 dup_msg = GNUNET_malloc (msize);
1294 (void) memcpy (dup_msg, msg, msize);
1295 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1296 GNUNET_TESTBED_insert_opc_ (controller, opc);
1302 * Function to cancel an operation created by simply forwarding an operation
1305 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1308 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1310 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1311 GNUNET_free (opc->data);
1317 * Function to call to start a link-controllers type operation once all queues
1318 * the operation is part of declare that the operation can be activated.
1320 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1323 opstart_link_controllers (void *cls)
1325 struct OperationContext *opc = cls;
1326 struct ControllerLinkData *data;
1327 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1329 GNUNET_assert (NULL != opc->data);
1333 opc->state = OPC_STATE_STARTED;
1334 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1335 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1340 * Callback which will be called when link-controllers type operation is released
1342 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1345 oprelease_link_controllers (void *cls)
1347 struct OperationContext *opc = cls;
1348 struct ControllerLinkData *data;
1353 case OPC_STATE_INIT:
1354 GNUNET_free (data->msg);
1356 case OPC_STATE_STARTED:
1357 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1359 case OPC_STATE_FINISHED:
1362 GNUNET_free_non_null (data);
1368 * Function to be called when get slave config operation is ready
1370 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1373 opstart_get_slave_config (void *cls)
1375 struct OperationContext *opc = cls;
1376 struct GetSlaveConfigData *data = opc->data;
1377 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1379 GNUNET_assert (NULL != data);
1380 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1381 GNUNET_free (opc->data);
1384 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
1385 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1386 opc->state = OPC_STATE_STARTED;
1391 * Function to be called when get slave config operation is cancelled or finished
1393 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1396 oprelease_get_slave_config (void *cls)
1398 struct OperationContext *opc = cls;
1402 case OPC_STATE_INIT:
1403 GNUNET_free (opc->data);
1405 case OPC_STATE_STARTED:
1406 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
1408 case OPC_STATE_FINISHED:
1409 if (NULL != opc->data)
1410 GNUNET_CONFIGURATION_destroy (opc->data);
1418 * Start a controller process using the given configuration at the
1421 * @param host host to run the controller on; This should be the same host if
1422 * the controller was previously started with
1423 * GNUNET_TESTBED_controller_start()
1424 * @param event_mask bit mask with set of events to call 'cc' for;
1425 * or-ed values of "1LL" shifted by the
1426 * respective 'enum GNUNET_TESTBED_EventType'
1427 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1428 * @param cc controller callback to invoke on events
1429 * @param cc_cls closure for cc
1430 * @return handle to the controller
1432 struct GNUNET_TESTBED_Controller *
1433 GNUNET_TESTBED_controller_connect (struct GNUNET_TESTBED_Host *host,
1434 uint64_t event_mask,
1435 GNUNET_TESTBED_ControllerCallback cc,
1438 struct GNUNET_TESTBED_Controller *controller;
1439 struct GNUNET_TESTBED_InitMessage *msg;
1440 const struct GNUNET_CONFIGURATION_Handle *cfg;
1441 const char *controller_hostname;
1442 unsigned long long max_parallel_operations;
1443 unsigned long long max_parallel_service_connections;
1444 unsigned long long max_parallel_topology_config_operations;
1446 GNUNET_assert (NULL != (cfg = GNUNET_TESTBED_host_get_cfg_ (host)));
1448 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1449 "MAX_PARALLEL_OPERATIONS",
1450 &max_parallel_operations))
1456 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1457 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1458 &max_parallel_service_connections))
1464 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1465 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1466 &max_parallel_topology_config_operations))
1471 controller = GNUNET_new (struct GNUNET_TESTBED_Controller);
1472 controller->cc = cc;
1473 controller->cc_cls = cc_cls;
1474 controller->event_mask = event_mask;
1475 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1476 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1477 if (NULL == controller->client)
1479 GNUNET_TESTBED_controller_disconnect (controller);
1482 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1483 controller->host = host;
1484 controller->opq_parallel_operations =
1485 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1486 (unsigned int) max_parallel_operations);
1487 controller->opq_parallel_service_connections =
1488 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1490 max_parallel_service_connections);
1491 controller->opq_parallel_topology_config_operations =
1492 GNUNET_TESTBED_operation_queue_create_ (OPERATION_QUEUE_TYPE_FIXED,
1494 max_parallel_topology_config_operations);
1495 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1496 if (NULL == controller_hostname)
1497 controller_hostname = "127.0.0.1";
1499 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1500 strlen (controller_hostname) + 1);
1501 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1503 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1504 strlen (controller_hostname) + 1);
1505 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1506 msg->event_mask = GNUNET_htonll (controller->event_mask);
1507 strcpy ((char *) &msg[1], controller_hostname);
1508 GNUNET_TESTBED_queue_message_ (controller,
1509 (struct GNUNET_MessageHeader *) msg);
1515 * Iterator to free opc map entries
1517 * @param cls closure
1518 * @param key current key code
1519 * @param value value in the hash map
1520 * @return GNUNET_YES if we should continue to
1525 opc_free_iterator (void *cls, uint32_t key, void *value)
1527 struct GNUNET_CONTAINER_MultiHashMap32 *map = cls;
1528 struct OperationContext *opc = value;
1530 GNUNET_assert (NULL != opc);
1532 GNUNET_assert (GNUNET_YES ==
1533 GNUNET_CONTAINER_multihashmap32_remove (map, key, value));
1540 * Stop the given controller (also will terminate all peers and
1541 * controllers dependent on this controller). This function
1542 * blocks until the testbed has been fully terminated (!).
1544 * @param c handle to controller to stop
1547 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller *c)
1549 struct MessageQueue *mq_entry;
1552 GNUNET_CLIENT_notify_transmit_ready_cancel (c->th);
1553 /* Clear the message queue */
1554 while (NULL != (mq_entry = c->mq_head))
1556 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail,
1558 GNUNET_free (mq_entry->msg);
1559 GNUNET_free (mq_entry);
1561 if (NULL != c->client)
1562 GNUNET_CLIENT_disconnect (c->client);
1563 if (NULL != c->host)
1564 GNUNET_TESTBED_deregister_host_at_ (c->host, c);
1565 GNUNET_CONFIGURATION_destroy (c->cfg);
1566 GNUNET_TESTBED_operation_queue_destroy_ (c->opq_parallel_operations);
1567 GNUNET_TESTBED_operation_queue_destroy_
1568 (c->opq_parallel_service_connections);
1569 GNUNET_TESTBED_operation_queue_destroy_
1570 (c->opq_parallel_topology_config_operations);
1571 if (NULL != c->opc_map)
1573 GNUNET_assert (GNUNET_SYSERR !=
1574 GNUNET_CONTAINER_multihashmap32_iterate (c->opc_map,
1577 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (c->opc_map));
1578 GNUNET_CONTAINER_multihashmap32_destroy (c->opc_map);
1585 * Compresses given configuration using zlib compress
1587 * @param config the serialized configuration
1588 * @param size the size of config
1589 * @param xconfig will be set to the compressed configuration (memory is fresly
1591 * @return the size of the xconfig
1594 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1599 xsize = compressBound ((uLong) size);
1600 *xconfig = GNUNET_malloc (xsize);
1601 GNUNET_assert (Z_OK ==
1602 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1603 (const Bytef *) config, (uLongf) size,
1610 * Function to serialize and compress using zlib a configuration through a
1611 * configuration handle
1613 * @param cfg the configuration
1614 * @param size the size of configuration when serialize. Will be set on success.
1615 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1616 * @return the serialized and compressed configuration
1619 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1620 size_t *size, size_t *xsize)
1627 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1628 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1629 GNUNET_free (config);
1637 * Create a link from slave controller to delegated controller. Whenever the
1638 * master controller is asked to start a peer at the delegated controller the
1639 * request will be routed towards slave controller (if a route exists). The
1640 * slave controller will then route it to the delegated controller. The
1641 * configuration of the delegated controller is given and is used to either
1642 * create the delegated controller or to connect to an existing controller. Note
1643 * that while starting the delegated controller the configuration will be
1644 * modified to accommodate available free ports. the 'is_subordinate' specifies
1645 * if the given delegated controller should be started and managed by the slave
1646 * controller, or if the delegated controller already has a master and the slave
1647 * controller connects to it as a non master controller. The success or failure
1648 * of this operation will be signalled through the
1649 * GNUNET_TESTBED_ControllerCallback() with an event of type
1650 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1652 * @param op_cls the operation closure for the event which is generated to
1653 * signal success or failure of this operation
1654 * @param master handle to the master controller who creates the association
1655 * @param delegated_host requests to which host should be delegated; cannot be NULL
1656 * @param slave_host which host is used to run the slave controller; use NULL to
1657 * make the master controller connect to the delegated host
1658 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1659 * be started by the slave controller; GNUNET_NO if the slave
1660 * controller has to connect to the already started delegated
1661 * controller via TCP/IP
1662 * @return the operation handle
1664 struct GNUNET_TESTBED_Operation *
1665 GNUNET_TESTBED_controller_link (void *op_cls,
1666 struct GNUNET_TESTBED_Controller *master,
1667 struct GNUNET_TESTBED_Host *delegated_host,
1668 struct GNUNET_TESTBED_Host *slave_host,
1671 struct OperationContext *opc;
1672 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1673 struct ControllerLinkData *data;
1674 uint32_t slave_host_id;
1675 uint32_t delegated_host_id;
1678 GNUNET_assert (GNUNET_YES ==
1679 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1681 GNUNET_TESTBED_host_get_id_ ((NULL !=
1682 slave_host) ? slave_host : master->host);
1683 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1684 if ((NULL != slave_host) && (0 != slave_host_id))
1685 GNUNET_assert (GNUNET_YES ==
1686 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1687 msg_size = sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1688 msg = GNUNET_malloc (msg_size);
1689 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1690 msg->header.size = htons (msg_size);
1691 msg->delegated_host_id = htonl (delegated_host_id);
1692 msg->slave_host_id = htonl (slave_host_id);
1693 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1694 data = GNUNET_new (struct ControllerLinkData);
1696 data->host_id = delegated_host_id;
1697 opc = GNUNET_new (struct OperationContext);
1700 opc->type = OP_LINK_CONTROLLERS;
1701 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1702 opc->state = OPC_STATE_INIT;
1703 opc->op_cls = op_cls;
1704 msg->operation_id = GNUNET_htonll (opc->id);
1706 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1707 &oprelease_link_controllers);
1708 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1710 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1716 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1717 * check. Another difference is that this function takes the id of the slave
1720 * @param op_cls the closure for the operation
1721 * @param master the handle to master controller
1722 * @param slave_host_id id of the host where the slave controller is running to
1723 * the slave_host should remain valid until this operation is cancelled
1724 * or marked as finished
1725 * @return the operation handle;
1727 struct GNUNET_TESTBED_Operation *
1728 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1729 struct GNUNET_TESTBED_Controller *master,
1730 uint32_t slave_host_id)
1732 struct OperationContext *opc;
1733 struct GetSlaveConfigData *data;
1735 data = GNUNET_new (struct GetSlaveConfigData);
1736 data->slave_id = slave_host_id;
1737 opc = GNUNET_new (struct OperationContext);
1738 opc->state = OPC_STATE_INIT;
1740 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1741 opc->type = OP_GET_SLAVE_CONFIG;
1743 opc->op_cls = op_cls;
1745 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1746 &oprelease_get_slave_config);
1747 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1749 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1755 * Function to acquire the configuration of a running slave controller. The
1756 * completion of the operation is signalled through the controller_cb from
1757 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1758 * handle to the configuration is available in the generic pointer of
1759 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1761 * @param op_cls the closure for the operation
1762 * @param master the handle to master controller
1763 * @param slave_host the host where the slave controller is running; the handle
1764 * to the slave_host should remain valid until this operation is
1765 * cancelled or marked as finished
1766 * @return the operation handle; NULL if the slave_host is not registered at
1769 struct GNUNET_TESTBED_Operation *
1770 GNUNET_TESTBED_get_slave_config (void *op_cls,
1771 struct GNUNET_TESTBED_Controller *master,
1772 struct GNUNET_TESTBED_Host *slave_host)
1774 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1776 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1777 GNUNET_TESTBED_host_get_id_
1783 * Ask the testbed controller to write the current overlay topology to
1784 * a file. Naturally, the file will only contain a snapshot as the
1785 * topology may evolve all the time.
1787 * @param controller overlay controller to inspect
1788 * @param filename name of the file the topology should
1792 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1794 const char *filename)
1801 * Creates a helper initialization message. This function is here because we
1802 * want to use this in testing
1804 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1805 * HOST(all connections form this ip are permitted by the testbed) when
1806 * starting testbed controller at host. This can either be a single ip
1807 * address or a network address in CIDR notation.
1808 * @param hostname the hostname of the destination this message is intended for
1809 * @param cfg the configuration that has to used to start the testbed service
1811 * @return the initialization message
1813 struct GNUNET_TESTBED_HelperInit *
1814 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1815 const char *hostname,
1816 const struct GNUNET_CONFIGURATION_Handle
1819 struct GNUNET_TESTBED_HelperInit *msg;
1823 size_t xconfig_size;
1824 uint16_t trusted_ip_len;
1825 uint16_t hostname_len;
1828 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1829 GNUNET_assert (NULL != config);
1831 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1832 GNUNET_free (config);
1833 trusted_ip_len = strlen (trusted_ip);
1834 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1836 xconfig_size + trusted_ip_len + 1 +
1837 sizeof (struct GNUNET_TESTBED_HelperInit);
1838 msg_size += hostname_len;
1839 msg = GNUNET_realloc (xconfig, msg_size);
1840 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1842 msg->header.size = htons (msg_size);
1843 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1844 msg->trusted_ip_size = htons (trusted_ip_len);
1845 msg->hostname_size = htons (hostname_len);
1846 msg->config_size = htons (config_size);
1847 (void) strcpy ((char *) &msg[1], trusted_ip);
1848 if (0 != hostname_len)
1849 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1856 * This function is used to signal that the event information (struct
1857 * GNUNET_TESTBED_EventInformation) from an operation has been fully processed
1858 * i.e. if the event callback is ever called for this operation. If the event
1859 * callback for this operation has not yet been called, calling this function
1860 * cancels the operation, frees its resources and ensures the no event is
1861 * generated with respect to this operation. Note that however cancelling an
1862 * operation does NOT guarantee that the operation will be fully undone (or that
1863 * nothing ever happened).
1865 * This function MUST be called for every operation to fully remove the
1866 * operation from the operation queue. After calling this function, if
1867 * operation is completed and its event information is of type
1868 * GNUNET_TESTBED_ET_OPERATION_FINISHED, the 'op_result' becomes invalid (!).
1870 * If the operation is generated from GNUNET_TESTBED_service_connect() then
1871 * calling this function on such as operation calls the disconnect adapter if
1872 * the connect adapter was ever called.
1874 * @param operation operation to signal completion or cancellation
1877 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1879 (void) exop_check (operation);
1880 GNUNET_TESTBED_operation_release_ (operation);
1885 * Generates configuration by uncompressing configuration in given message. The
1886 * given message should be of the following types:
1887 * #GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION,
1888 * #GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1889 * #GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
1890 * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
1891 * #GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1893 * @param msg the message containing compressed configuration
1894 * @return handle to the parsed configuration; NULL upon error while parsing the message
1896 struct GNUNET_CONFIGURATION_Handle *
1897 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1899 struct GNUNET_CONFIGURATION_Handle *cfg;
1906 switch (ntohs (msg->type))
1908 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_INFORMATION:
1910 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1913 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1914 data_len = (uLong) ntohs (imsg->config_size);
1916 ntohs (imsg->header.size) -
1917 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1918 xdata = (const Bytef *) &imsg[1];
1921 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1923 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1925 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1926 data_len = (uLong) ntohs (imsg->config_size);
1928 ntohs (imsg->header.size) -
1929 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1930 xdata = (const Bytef *) &imsg[1];
1933 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1935 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1938 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1939 data_len = (uLong) ntohs (imsg->config_size);
1940 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1941 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1942 xdata_len = ntohs (imsg->header.size) - osize;
1943 xdata = (const Bytef *) ((const void *) imsg + osize);
1946 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1948 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
1950 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
1951 data_len = ntohs (imsg->config_size);
1952 xdata_len = ntohs (imsg->header.size) -
1953 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
1954 xdata = (const Bytef *) &imsg[1];
1957 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER:
1959 const struct GNUNET_TESTBED_PeerCreateMessage *imsg;
1961 imsg = (const struct GNUNET_TESTBED_PeerCreateMessage *) msg;
1962 data_len = ntohs (imsg->config_size);
1963 xdata_len = ntohs (imsg->header.size) -
1964 sizeof (struct GNUNET_TESTBED_PeerCreateMessage);
1965 xdata = (const Bytef *) &imsg[1];
1968 case GNUNET_MESSAGE_TYPE_TESTBED_RECONFIGURE_PEER:
1970 const struct GNUNET_TESTBED_PeerReconfigureMessage *imsg;
1972 imsg = (const struct GNUNET_TESTBED_PeerReconfigureMessage *) msg;
1973 data_len = ntohs (imsg->config_size);
1974 xdata_len = ntohs (imsg->header.size) -
1975 sizeof (struct GNUNET_TESTBED_PeerReconfigureMessage);
1976 xdata = (const Bytef *) &imsg[1];
1982 data = GNUNET_malloc (data_len);
1983 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1986 GNUNET_break_op (0); /* Un-compression failure */
1989 cfg = GNUNET_CONFIGURATION_create ();
1991 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
1996 GNUNET_break_op (0); /* De-serialization failure */
2005 * Checks the integrity of the OperationFailureEventMessage and if good returns
2006 * the error message it contains.
2008 * @param msg the OperationFailureEventMessage
2009 * @return the error message
2012 GNUNET_TESTBED_parse_error_string_ (const struct
2013 GNUNET_TESTBED_OperationFailureEventMessage
2019 msize = ntohs (msg->header.size);
2020 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2022 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2023 emsg = (const char *) &msg[1];
2024 if ('\0' != emsg[msize - 1])
2034 * Function to return the operation id for a controller. The operation id is
2035 * created from the controllers host id and its internal operation counter.
2037 * @param controller the handle to the controller whose operation id has to be incremented
2038 * @return the incremented operation id.
2041 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2045 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2046 op_id = op_id << 32;
2047 op_id |= (uint64_t) controller->operation_counter++;
2053 * Function called when a shutdown peers operation is ready
2055 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2058 opstart_shutdown_peers (void *cls)
2060 struct OperationContext *opc = cls;
2061 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2063 opc->state = OPC_STATE_STARTED;
2064 msg = GNUNET_new (struct GNUNET_TESTBED_ShutdownPeersMessage);
2066 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2067 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2068 msg->operation_id = GNUNET_htonll (opc->id);
2069 GNUNET_TESTBED_insert_opc_ (opc->c, opc);
2070 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
2075 * Callback which will be called when shutdown peers operation is released
2077 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2080 oprelease_shutdown_peers (void *cls)
2082 struct OperationContext *opc = cls;
2086 case OPC_STATE_STARTED:
2087 GNUNET_TESTBED_remove_opc_ (opc->c, opc);
2088 /* no break; continue */
2089 case OPC_STATE_INIT:
2090 GNUNET_free (opc->data);
2092 case OPC_STATE_FINISHED:
2100 * Stops and destroys all peers. Is equivalent of calling
2101 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2102 * except that the peer stop event and operation finished event corresponding to
2103 * the respective functions are not generated. This function should be called
2104 * when there are no other pending operations. If there are pending operations,
2105 * it will return NULL
2107 * @param c the controller to send this message to
2108 * @param op_cls closure for the operation
2109 * @param cb the callback to call when all peers are stopped and destroyed
2110 * @param cb_cls the closure for the callback
2111 * @return operation handle on success; NULL if any pending operations are
2114 struct GNUNET_TESTBED_Operation *
2115 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *c,
2117 GNUNET_TESTBED_OperationCompletionCallback cb,
2120 struct OperationContext *opc;
2121 struct ShutdownPeersData *data;
2123 if (0 != GNUNET_CONTAINER_multihashmap32_size (c->opc_map))
2125 data = GNUNET_new (struct ShutdownPeersData);
2127 data->cb_cls = cb_cls;
2128 opc = GNUNET_new (struct OperationContext);
2130 opc->op_cls = op_cls;
2132 opc->id = GNUNET_TESTBED_get_next_op_id (c);
2133 opc->type = OP_SHUTDOWN_PEERS;
2134 opc->state = OPC_STATE_INIT;
2135 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2136 &oprelease_shutdown_peers);
2137 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2139 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2145 * Return the index of the peer inside of the total peer array,
2146 * aka. the peer's "unique ID".
2148 * @param peer Peer handle.
2150 * @return The peer's unique ID.
2153 GNUNET_TESTBED_get_index (const struct GNUNET_TESTBED_Peer *peer)
2155 return peer->unique_id;
2158 /* end of testbed_api.c */