2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
47 * Generic logging shorthand
49 #define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
55 #define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
59 * Relative time seconds shorthand
61 #define TIME_REL_SECS(sec) \
62 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
66 * Default server message sending retry timeout
68 #define TIMEOUT_REL TIME_REL_SECS(1)
72 * The message queue for sending messages to the controller service
77 * The message to be sent
79 struct GNUNET_MessageHeader *msg;
82 * next pointer for DLL
84 struct MessageQueue *next;
87 * prev pointer for DLL
89 struct MessageQueue *prev;
94 * Context data for forwarded Operation
96 struct ForwardedOperationData
100 * The callback to call when reply is available
102 GNUNET_CLIENT_MessageHandler cc;
105 * The closure for the above callback
113 * Context data for get slave config operations
115 struct GetSlaveConfigData
118 * The id of the slave controller
126 * Context data for controller link operations
128 struct ControllerLinkData
131 * The controller link message
133 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
136 * The id of the host which is hosting the controller to be linked
144 * Date context for OP_SHUTDOWN_PEERS operations
146 struct ShutdownPeersData
149 * The operation completion callback to call
151 GNUNET_TESTBED_OperationCompletionCallback cb;
154 * The closure for the above callback
161 * An entry in the stack for keeping operations which are about to expire
163 struct ExpireOperationEntry
166 * DLL head; new entries are to be inserted here
168 struct ExpireOperationEntry *next;
171 * DLL tail; entries are deleted from here
173 struct ExpireOperationEntry *prev;
176 * The operation. This will be a dangling pointer when the operation is freed
178 const struct GNUNET_TESTBED_Operation *op;
181 static struct ExpireOperationEntry *exop_head;
183 static struct ExpireOperationEntry *exop_tail;
187 exop_insert (struct GNUNET_TESTBED_Operation *op)
189 struct ExpireOperationEntry *entry;
191 entry = GNUNET_malloc (sizeof (struct ExpireOperationEntry));
193 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
198 exop_check (const struct GNUNET_TESTBED_Operation *const op)
200 struct ExpireOperationEntry *entry;
201 struct ExpireOperationEntry *entry2;
206 while (NULL != entry)
215 if (GNUNET_NO == found)
217 /* Truncate the tail */
218 while (NULL != entry)
220 entry2 = entry->next;
221 GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry);
230 * Returns the operation context with the given id if found in the Operation
231 * context queues of the controller
233 * @param c the controller whose queues are searched
234 * @param id the id which has to be checked
235 * @return the matching operation context; NULL if no match found
237 static struct OperationContext *
238 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
240 struct OperationContext *opc;
242 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
252 * Handler for forwarded operations
254 * @param c the controller handle
255 * @param opc the opearation context
256 * @param msg the message
259 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
260 struct OperationContext *opc,
261 const struct GNUNET_MessageHeader *msg)
263 struct ForwardedOperationData *fo_data;
266 if (NULL != fo_data->cc)
267 fo_data->cc (fo_data->cc_cls, msg);
268 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
269 GNUNET_free (fo_data);
275 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
276 * controller (testbed service)
278 * @param c the controller handler
279 * @param msg message received
280 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
284 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
286 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
288 struct OperationContext *opc;
289 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
290 void *op_comp_cb_cls;
291 struct GNUNET_TESTBED_EventInformation event;
294 op_id = GNUNET_ntohll (msg->operation_id);
295 LOG_DEBUG ("Operation %lu successful\n", op_id);
296 if (NULL == (opc = find_opc (c, op_id)))
298 LOG_DEBUG ("Operation not found\n");
301 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
303 event.op_cls = opc->op_cls;
304 event.details.operation_finished.emsg = NULL;
305 event.details.operation_finished.generic = NULL;
307 op_comp_cb_cls = NULL;
312 handle_forwarded_operation_msg (c, opc,
313 (const struct GNUNET_MessageHeader *) msg);
317 case OP_PEER_DESTROY:
319 struct GNUNET_TESTBED_Peer *peer;
322 GNUNET_TESTBED_peer_deregister_ (peer);
328 case OP_SHUTDOWN_PEERS:
330 struct ShutdownPeersData *data;
333 op_comp_cb = data->cb;
334 op_comp_cb_cls = data->cb_cls;
337 GNUNET_TESTBED_cleanup_peers_ ();
343 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
344 opc->state = OPC_STATE_FINISHED;
345 exop_insert (event.op);
346 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
349 c->cc (c->cc_cls, &event);
350 if (GNUNET_NO == exop_check (event.op))
354 LOG_DEBUG ("Not calling callback\n");
355 if (NULL != op_comp_cb)
356 op_comp_cb (op_comp_cb_cls, event.op, NULL);
357 /* You could have marked the operation as done by now */
358 GNUNET_break (GNUNET_NO == exop_check (event.op));
364 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
365 * controller (testbed service)
367 * @param c the controller handle
368 * @param msg message received
369 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
373 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
375 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
377 struct OperationContext *opc;
378 struct PeerCreateData *data;
379 struct GNUNET_TESTBED_Peer *peer;
380 struct GNUNET_TESTBED_Operation *op;
381 GNUNET_TESTBED_PeerCreateCallback cb;
385 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
386 ntohs (msg->header.size));
387 op_id = GNUNET_ntohll (msg->operation_id);
388 if (NULL == (opc = find_opc (c, op_id)))
390 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
393 if (OP_FORWARDED == opc->type)
395 handle_forwarded_operation_msg (c, opc,
396 (const struct GNUNET_MessageHeader *) msg);
399 GNUNET_assert (OP_PEER_CREATE == opc->type);
400 GNUNET_assert (NULL != opc->data);
402 GNUNET_assert (NULL != data->peer);
404 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
405 peer->state = PS_CREATED;
406 GNUNET_TESTBED_peer_register_ (peer);
410 GNUNET_free (opc->data);
411 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
412 opc->state = OPC_STATE_FINISHED;
415 cb (cls, peer, NULL);
416 /* You could have marked the operation as done by now */
417 GNUNET_break (GNUNET_NO == exop_check (op));
423 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
424 * controller (testbed service)
426 * @param c the controller handler
427 * @param msg message received
428 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
432 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
433 const struct GNUNET_TESTBED_PeerEventMessage *msg)
435 struct OperationContext *opc;
436 struct GNUNET_TESTBED_Peer *peer;
437 struct PeerEventData *data;
438 GNUNET_TESTBED_PeerChurnCallback pcc;
440 struct GNUNET_TESTBED_EventInformation event;
443 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
444 ntohs (msg->header.size));
445 op_id = GNUNET_ntohll (msg->operation_id);
446 if (NULL == (opc = find_opc (c, op_id)))
448 LOG_DEBUG ("Operation not found\n");
451 if (OP_FORWARDED == opc->type)
453 handle_forwarded_operation_msg (c, opc,
454 (const struct GNUNET_MessageHeader *) msg);
457 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
459 GNUNET_assert (NULL != data);
461 GNUNET_assert (NULL != peer);
462 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
464 event.op_cls = opc->op_cls;
467 case GNUNET_TESTBED_ET_PEER_START:
468 peer->state = PS_STARTED;
469 event.details.peer_start.host = peer->host;
470 event.details.peer_start.peer = peer;
472 case GNUNET_TESTBED_ET_PEER_STOP:
473 peer->state = PS_STOPPED;
474 event.details.peer_stop.peer = peer;
477 GNUNET_assert (0); /* We should never reach this state */
480 pcc_cls = data->pcc_cls;
482 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
483 opc->state = OPC_STATE_FINISHED;
484 exop_insert (event.op);
486 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
490 c->cc (c->cc_cls, &event);
491 if (GNUNET_NO == exop_check (event.op))
496 /* You could have marked the operation as done by now */
497 GNUNET_break (GNUNET_NO == exop_check (event.op));
503 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
504 * controller (testbed service)
506 * @param c the controller handler
507 * @param msg message received
508 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
512 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
513 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
515 struct OperationContext *opc;
516 struct OverlayConnectData *data;
517 GNUNET_TESTBED_OperationCompletionCallback cb;
519 struct GNUNET_TESTBED_EventInformation event;
522 op_id = GNUNET_ntohll (msg->operation_id);
523 if (NULL == (opc = find_opc (c, op_id)))
525 LOG_DEBUG ("Operation not found\n");
528 if (OP_FORWARDED == opc->type)
530 handle_forwarded_operation_msg (c, opc,
531 (const struct GNUNET_MessageHeader *) msg);
534 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
536 GNUNET_assert (NULL != data);
537 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
538 (ntohl (msg->peer2) == data->p2->unique_id));
539 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
541 event.op_cls = opc->op_cls;
544 case GNUNET_TESTBED_ET_CONNECT:
545 event.details.peer_connect.peer1 = data->p1;
546 event.details.peer_connect.peer2 = data->p2;
548 case GNUNET_TESTBED_ET_DISCONNECT:
549 GNUNET_assert (0); /* FIXME: implement */
552 GNUNET_assert (0); /* Should never reach here */
556 cb_cls = data->cb_cls;
557 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
558 opc->state = OPC_STATE_FINISHED;
559 exop_insert (event.op);
561 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
565 c->cc (c->cc_cls, &event);
566 if (GNUNET_NO == exop_check (event.op))
570 cb (cb_cls, opc->op, NULL);
571 /* You could have marked the operation as done by now */
572 GNUNET_break (GNUNET_NO == exop_check (event.op));
578 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
579 * controller (testbed service)
581 * @param c the controller handler
582 * @param msg message received
583 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
587 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
589 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
591 struct OperationContext *opc;
592 struct GNUNET_TESTBED_Peer *peer;
593 struct PeerInfoData *data;
594 struct GNUNET_TESTBED_PeerInformation *pinfo;
595 GNUNET_TESTBED_PeerInfoCallback cb;
599 op_id = GNUNET_ntohll (msg->operation_id);
600 if (NULL == (opc = find_opc (c, op_id)))
602 LOG_DEBUG ("Operation not found\n");
605 if (OP_FORWARDED == opc->type)
607 handle_forwarded_operation_msg (c, opc,
608 (const struct GNUNET_MessageHeader *) msg);
612 GNUNET_assert (NULL != data);
614 GNUNET_assert (NULL != peer);
615 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
616 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
617 pinfo->pit = data->pit;
619 cb_cls = data->cb_cls;
620 GNUNET_assert (NULL != cb);
625 case GNUNET_TESTBED_PIT_IDENTITY:
626 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
627 (void) memcpy (pinfo->result.id, &msg->peer_identity,
628 sizeof (struct GNUNET_PeerIdentity));
630 case GNUNET_TESTBED_PIT_CONFIGURATION:
631 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
632 GNUNET_TESTBED_extract_config_ (&msg->header);
634 case GNUNET_TESTBED_PIT_GENERIC:
635 GNUNET_assert (0); /* never reach here */
639 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
640 opc->state = OPC_STATE_FINISHED;
641 cb (cb_cls, opc->op, pinfo, NULL);
642 /* We dont check whether the operation is marked as done here as the
643 operation contains data (cfg/identify) which will be freed at a later point
650 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
651 * controller (testbed service)
653 * @param c the controller handler
654 * @param msg message received
655 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
659 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
660 const struct GNUNET_TESTBED_OperationFailureEventMessage
663 struct OperationContext *opc;
666 struct GNUNET_TESTBED_EventInformation event;
668 op_id = GNUNET_ntohll (msg->operation_id);
669 if (NULL == (opc = find_opc (c, op_id)))
671 LOG_DEBUG ("Operation not found\n");
674 if (OP_FORWARDED == opc->type)
676 handle_forwarded_operation_msg (c, opc,
677 (const struct GNUNET_MessageHeader *) msg);
680 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
681 opc->state = OPC_STATE_FINISHED;
682 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
684 emsg = "Unknown error";
685 if (OP_PEER_INFO == opc->type)
687 struct PeerInfoData *data;
690 if (NULL != data->cb)
691 data->cb (data->cb_cls, opc->op, NULL, emsg);
693 return GNUNET_YES; /* We do not call controller callback for peer info */
695 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
698 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
700 event.op_cls = opc->op_cls;
701 event.details.operation_finished.emsg = emsg;
702 event.details.operation_finished.generic = NULL;
703 exop_insert (event.op);
704 c->cc (c->cc_cls, &event);
705 if (GNUNET_NO == exop_check (event.op))
712 struct PeerCreateData *data;
715 GNUNET_free (data->peer);
716 if (NULL != data->cb)
717 data->cb (data->cls, NULL, emsg);
724 struct PeerEventData *data;
727 if (NULL != data->pcc)
728 data->pcc (data->pcc_cls, emsg);
732 case OP_PEER_DESTROY:
736 case OP_OVERLAY_CONNECT:
738 struct OverlayConnectData *data;
741 data->failed = GNUNET_YES;
742 if (NULL != data->cb)
743 data->cb (data->cb_cls, opc->op, emsg);
748 case OP_LINK_CONTROLLERS: /* No secondary callback */
750 case OP_SHUTDOWN_PEERS:
752 struct ShutdownPeersData *data;
755 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
767 * Function to build GET_SLAVE_CONFIG message
769 * @param op_id the id this message should contain in its operation id field
770 * @param slave_id the id this message should contain in its slave id field
771 * @return newly allocated SlaveGetConfigurationMessage
773 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
774 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
776 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
779 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
780 msg = GNUNET_malloc (msize);
781 msg->header.size = htons (msize);
783 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
784 msg->operation_id = GNUNET_htonll (op_id);
785 msg->slave_id = htonl (slave_id);
791 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
794 * @param c the controller handler
795 * @param msg message received
796 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
800 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
801 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
803 struct OperationContext *opc;
805 struct GNUNET_TESTBED_EventInformation event;
807 op_id = GNUNET_ntohll (msg->operation_id);
808 if (NULL == (opc = find_opc (c, op_id)))
810 LOG_DEBUG ("Operation not found\n");
813 if (OP_GET_SLAVE_CONFIG != opc->type)
818 GNUNET_free (opc->data);
820 opc->state = OPC_STATE_FINISHED;
821 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
822 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
825 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
826 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
828 event.op_cls = opc->op_cls;
829 event.details.operation_finished.generic = opc->data;
830 event.details.operation_finished.emsg = NULL;
831 c->cc (c->cc_cls, &event);
838 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
841 * @param c the controller handler
842 * @param msg message received
843 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
847 handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
849 GNUNET_TESTBED_ControllerLinkResponse *msg)
851 struct OperationContext *opc;
852 struct ControllerLinkData *data;
853 struct GNUNET_CONFIGURATION_Handle *cfg;
854 struct GNUNET_TESTBED_Host *host;
857 struct GNUNET_TESTBED_EventInformation event;
859 op_id = GNUNET_ntohll (msg->operation_id);
860 if (NULL == (opc = find_opc (c, op_id)))
862 LOG_DEBUG ("Operation not found\n");
865 if (OP_FORWARDED == opc->type)
867 handle_forwarded_operation_msg (c, opc,
868 (const struct GNUNET_MessageHeader *) msg);
871 if (OP_LINK_CONTROLLERS != opc->type)
877 GNUNET_assert (NULL != data);
878 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
879 GNUNET_assert (NULL != host);
882 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
884 event.op_cls = opc->op_cls;
885 event.details.operation_finished.emsg = NULL;
886 event.details.operation_finished.generic = NULL;
889 if (GNUNET_NO == ntohs (msg->success))
891 emsg = GNUNET_malloc (ntohs (msg->header.size)
893 GNUNET_TESTBED_ControllerLinkResponse) + 1);
894 memcpy (emsg, &msg[1], ntohs (msg->header.size)
896 GNUNET_TESTBED_ControllerLinkResponse));
897 event.details.operation_finished.emsg = emsg;
901 if (0 != ntohs (msg->config_size))
903 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
904 GNUNET_assert (NULL != cfg);
905 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
908 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
909 opc->state = OPC_STATE_FINISHED;
910 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
913 c->cc (c->cc_cls, &event);
916 LOG_DEBUG ("Not calling callback\n");
918 GNUNET_CONFIGURATION_destroy (cfg);
919 GNUNET_free_non_null (emsg);
925 * Handler for messages from controller (testbed service)
927 * @param cls the controller handler
928 * @param msg message received, NULL on timeout or fatal error
931 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
933 struct GNUNET_TESTBED_Controller *c = cls;
937 c->in_receive = GNUNET_NO;
938 /* FIXME: Add checks for message integrity */
941 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
945 msize = ntohs (msg->size);
946 switch (ntohs (msg->type))
948 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
949 GNUNET_assert (msize >=
950 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
952 GNUNET_TESTBED_host_handle_addhostconfirm_
953 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
955 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
956 GNUNET_assert (msize ==
958 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
962 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
965 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
966 GNUNET_assert (msize >=
967 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
969 handle_op_fail_event (c,
971 GNUNET_TESTBED_OperationFailureEventMessage *)
974 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
975 GNUNET_assert (msize ==
977 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
979 handle_peer_create_success (c,
981 GNUNET_TESTBED_PeerCreateSuccessEventMessage
984 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
985 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
987 handle_peer_event (c,
988 (const struct GNUNET_TESTBED_PeerEventMessage *)
992 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
993 GNUNET_assert (msize >=
995 GNUNET_TESTBED_PeerConfigurationInformationMessage));
997 handle_peer_config (c,
999 GNUNET_TESTBED_PeerConfigurationInformationMessage
1002 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
1003 GNUNET_assert (msize ==
1004 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1006 handle_peer_conevent (c,
1008 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1010 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1011 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1013 handle_slave_config (c,
1014 (const struct GNUNET_TESTBED_SlaveConfiguration *)
1017 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1019 handle_link_controllers_result (c,
1021 GNUNET_TESTBED_ControllerLinkResponse
1027 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1029 c->in_receive = GNUNET_YES;
1030 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1031 GNUNET_TIME_UNIT_FOREVER_REL);
1037 * Function called to notify a client about the connection begin ready to queue
1038 * more data. "buf" will be NULL and "size" zero if the connection was closed
1039 * for writing in the meantime.
1041 * @param cls closure
1042 * @param size number of bytes available in buf
1043 * @param buf where the callee should write the message
1044 * @return number of bytes written to buf
1047 transmit_ready_notify (void *cls, size_t size, void *buf)
1049 struct GNUNET_TESTBED_Controller *c = cls;
1050 struct MessageQueue *mq_entry;
1053 mq_entry = c->mq_head;
1054 GNUNET_assert (NULL != mq_entry);
1055 if ((0 == size) && (NULL == buf)) /* Timeout */
1057 LOG_DEBUG ("Message sending timed out -- retrying\n");
1059 GNUNET_CLIENT_notify_transmit_ready (c->client,
1060 ntohs (mq_entry->msg->size),
1061 TIMEOUT_REL, GNUNET_YES,
1062 &transmit_ready_notify, c);
1065 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1066 size = ntohs (mq_entry->msg->size);
1067 memcpy (buf, mq_entry->msg, size);
1068 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1069 ntohs (mq_entry->msg->type), size);
1070 GNUNET_free (mq_entry->msg);
1071 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1072 GNUNET_free (mq_entry);
1073 mq_entry = c->mq_head;
1074 if (NULL != mq_entry)
1076 GNUNET_CLIENT_notify_transmit_ready (c->client,
1077 ntohs (mq_entry->msg->size),
1078 TIMEOUT_REL, GNUNET_YES,
1079 &transmit_ready_notify, c);
1080 if (GNUNET_NO == c->in_receive)
1082 c->in_receive = GNUNET_YES;
1083 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1084 GNUNET_TIME_UNIT_FOREVER_REL);
1091 * Queues a message in send queue for sending to the service
1093 * @param controller the handle to the controller
1094 * @param msg the message to queue
1097 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1098 struct GNUNET_MessageHeader *msg)
1100 struct MessageQueue *mq_entry;
1104 type = ntohs (msg->type);
1105 size = ntohs (msg->size);
1106 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1107 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1108 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1109 mq_entry->msg = msg;
1110 LOG (GNUNET_ERROR_TYPE_DEBUG,
1111 "Queueing message of type %u, size %u for sending\n", type,
1113 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1115 if (NULL == controller->th)
1117 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1118 TIMEOUT_REL, GNUNET_YES,
1119 &transmit_ready_notify,
1125 * Sends the given message as an operation. The given callback is called when a
1126 * reply for the operation is available. Call
1127 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1128 * operation context if the cc hasn't been called
1130 * @param controller the controller to which the message has to be sent
1131 * @param operation_id the operation id of the message
1132 * @param msg the message to send
1133 * @param cc the callback to call when reply is available
1134 * @param cc_cls the closure for the above callback
1135 * @return the operation context which can be used to cancel the forwarded
1138 struct OperationContext *
1139 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1140 *controller, uint64_t operation_id,
1141 const struct GNUNET_MessageHeader *msg,
1142 GNUNET_CLIENT_MessageHandler cc,
1145 struct OperationContext *opc;
1146 struct ForwardedOperationData *data;
1147 struct GNUNET_MessageHeader *dup_msg;
1150 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1152 data->cc_cls = cc_cls;
1153 opc = GNUNET_malloc (sizeof (struct OperationContext));
1154 opc->c = controller;
1155 opc->type = OP_FORWARDED;
1157 opc->id = operation_id;
1158 msize = ntohs (msg->size);
1159 dup_msg = GNUNET_malloc (msize);
1160 (void) memcpy (dup_msg, msg, msize);
1161 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1162 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1169 * Function to cancel an operation created by simply forwarding an operation
1172 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1175 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1177 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1178 GNUNET_free (opc->data);
1184 * Function to call to start a link-controllers type operation once all queues
1185 * the operation is part of declare that the operation can be activated.
1187 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1190 opstart_link_controllers (void *cls)
1192 struct OperationContext *opc = cls;
1193 struct ControllerLinkData *data;
1194 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1196 GNUNET_assert (NULL != opc->data);
1200 opc->state = OPC_STATE_STARTED;
1201 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1202 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1207 * Callback which will be called when link-controllers type operation is released
1209 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1212 oprelease_link_controllers (void *cls)
1214 struct OperationContext *opc = cls;
1215 struct ControllerLinkData *data;
1220 case OPC_STATE_INIT:
1221 GNUNET_free (data->msg);
1223 case OPC_STATE_STARTED:
1224 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1226 case OPC_STATE_FINISHED:
1229 GNUNET_free_non_null (data);
1235 * Function to be called when get slave config operation is ready
1237 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1240 opstart_get_slave_config (void *cls)
1242 struct OperationContext *opc = cls;
1243 struct GetSlaveConfigData *data;
1244 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1247 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1248 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1249 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1250 opc->state = OPC_STATE_STARTED;
1255 * Function to be called when get slave config operation is cancelled or finished
1257 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1260 oprelease_get_slave_config (void *cls)
1262 struct OperationContext *opc = cls;
1266 case OPC_STATE_INIT:
1267 GNUNET_free (opc->data);
1269 case OPC_STATE_STARTED:
1270 GNUNET_free (opc->data);
1271 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1273 case OPC_STATE_FINISHED:
1274 if (NULL != opc->data)
1275 GNUNET_CONFIGURATION_destroy (opc->data);
1283 * Start a controller process using the given configuration at the
1286 * @param cfg configuration to use
1287 * @param host host to run the controller on; This should be the same host if
1288 * the controller was previously started with
1289 * GNUNET_TESTBED_controller_start; NULL for localhost
1290 * @param event_mask bit mask with set of events to call 'cc' for;
1291 * or-ed values of "1LL" shifted by the
1292 * respective 'enum GNUNET_TESTBED_EventType'
1293 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1294 * @param cc controller callback to invoke on events
1295 * @param cc_cls closure for cc
1296 * @return handle to the controller
1298 struct GNUNET_TESTBED_Controller *
1299 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1300 *cfg, struct GNUNET_TESTBED_Host *host,
1301 uint64_t event_mask,
1302 GNUNET_TESTBED_ControllerCallback cc,
1305 struct GNUNET_TESTBED_Controller *controller;
1306 struct GNUNET_TESTBED_InitMessage *msg;
1307 const char *controller_hostname;
1308 unsigned long long max_parallel_operations;
1309 unsigned long long max_parallel_service_connections;
1310 unsigned long long max_parallel_topology_config_operations;
1313 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1314 "MAX_PARALLEL_OPERATIONS",
1315 &max_parallel_operations))
1321 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1322 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1323 &max_parallel_service_connections))
1329 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1330 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1331 &max_parallel_topology_config_operations))
1336 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1337 controller->cc = cc;
1338 controller->cc_cls = cc_cls;
1339 controller->event_mask = event_mask;
1340 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1341 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1342 if (NULL == controller->client)
1344 GNUNET_TESTBED_controller_disconnect (controller);
1349 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1350 if (NULL == host) /* If the above host create fails */
1352 LOG (GNUNET_ERROR_TYPE_WARNING,
1353 "Treating NULL host as localhost. Multiple references to localhost "
1354 "may break when localhost freed before calling disconnect \n");
1355 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1359 controller->aux_host = GNUNET_YES;
1362 GNUNET_assert (NULL != host);
1363 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1364 controller->host = host;
1365 controller->opq_parallel_operations =
1366 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1367 max_parallel_operations);
1368 controller->opq_parallel_service_connections =
1369 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1370 max_parallel_service_connections);
1371 controller->opq_parallel_topology_config_operations =
1372 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1373 max_parallel_topology_config_operations);
1374 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1375 if (NULL == controller_hostname)
1376 controller_hostname = "127.0.0.1";
1378 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1379 strlen (controller_hostname) + 1);
1380 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1382 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1383 strlen (controller_hostname) + 1);
1384 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1385 msg->event_mask = GNUNET_htonll (controller->event_mask);
1386 strcpy ((char *) &msg[1], controller_hostname);
1387 GNUNET_TESTBED_queue_message_ (controller,
1388 (struct GNUNET_MessageHeader *) msg);
1394 * Configure shared services at a controller. Using this function,
1395 * you can specify that certain services (such as "resolver")
1396 * should not be run for each peer but instead be shared
1397 * across N peers on the specified host. This function
1398 * must be called before any peers are created at the host.
1400 * @param controller controller to configure
1401 * @param service_name name of the service to share
1402 * @param num_peers number of peers that should share one instance
1403 * of the specified service (1 for no sharing is the default),
1404 * use 0 to disable the service
1407 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1409 const char *service_name,
1412 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1413 uint16_t service_name_size;
1416 service_name_size = strlen (service_name) + 1;
1418 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1420 msg = GNUNET_malloc (msg_size);
1421 msg->header.size = htons (msg_size);
1422 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1423 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1424 msg->num_peers = htonl (num_peers);
1425 memcpy (&msg[1], service_name, service_name_size);
1426 GNUNET_TESTBED_queue_message_ (controller,
1427 (struct GNUNET_MessageHeader *) msg);
1428 GNUNET_break (0); /* This function is not yet implemented on the
1429 * testbed service */
1434 * disconnects from the controller.
1436 * @param controller handle to controller to stop
1439 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1442 struct MessageQueue *mq_entry;
1444 if (NULL != controller->th)
1445 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1446 /* Clear the message queue */
1447 while (NULL != (mq_entry = controller->mq_head))
1449 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1451 GNUNET_free (mq_entry->msg);
1452 GNUNET_free (mq_entry);
1454 if (NULL != controller->client)
1455 GNUNET_CLIENT_disconnect (controller->client);
1456 GNUNET_CONFIGURATION_destroy (controller->cfg);
1457 if (GNUNET_YES == controller->aux_host)
1458 GNUNET_TESTBED_host_destroy (controller->host);
1459 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1460 GNUNET_TESTBED_operation_queue_destroy_
1461 (controller->opq_parallel_service_connections);
1462 GNUNET_TESTBED_operation_queue_destroy_
1463 (controller->opq_parallel_topology_config_operations);
1464 GNUNET_free (controller);
1469 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1472 * @param op_cls the operation closure for the event which is generated to
1473 * signal success or failure of this operation
1474 * @param master handle to the master controller who creates the association
1475 * @param delegated_host_id id of the host to which requests should be delegated
1476 * @param slave_host_id id of the host which is used to run the slave controller
1477 * @param sxcfg serialized and compressed configuration
1478 * @param sxcfg_size the size sxcfg
1479 * @param scfg_size the size of uncompressed serialized configuration
1480 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1481 * be started by the slave controller; GNUNET_NO if the slave
1482 * controller has to connect to the already started delegated
1483 * controller via TCP/IP
1484 * @return the operation handle
1486 struct GNUNET_TESTBED_Operation *
1487 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1488 struct GNUNET_TESTBED_Controller *master,
1489 uint32_t delegated_host_id,
1490 uint32_t slave_host_id, const char *sxcfg,
1491 size_t sxcfg_size, size_t scfg_size,
1494 struct OperationContext *opc;
1495 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1496 struct ControllerLinkData *data;
1499 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1500 msg = GNUNET_malloc (msg_size);
1501 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1502 msg->header.size = htons (msg_size);
1503 msg->delegated_host_id = htonl (delegated_host_id);
1504 msg->slave_host_id = htonl (slave_host_id);
1505 msg->config_size = htons ((uint16_t) scfg_size);
1506 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1507 memcpy (&msg[1], sxcfg, sxcfg_size);
1508 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1510 data->host_id = delegated_host_id;
1511 opc = GNUNET_malloc (sizeof (struct OperationContext));
1514 opc->type = OP_LINK_CONTROLLERS;
1515 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1516 opc->state = OPC_STATE_INIT;
1517 opc->op_cls = op_cls;
1518 msg->operation_id = GNUNET_htonll (opc->id);
1520 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1521 &oprelease_link_controllers);
1522 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1524 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1530 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1531 * serialized and compressed
1533 * @param op_cls the operation closure for the event which is generated to
1534 * signal success or failure of this operation
1535 * @param master handle to the master controller who creates the association
1536 * @param delegated_host requests to which host should be delegated; cannot be NULL
1537 * @param slave_host which host is used to run the slave controller; use NULL to
1538 * make the master controller connect to the delegated host
1539 * @param sxcfg serialized and compressed configuration
1540 * @param sxcfg_size the size sxcfg
1541 * @param scfg_size the size of uncompressed serialized configuration
1542 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1543 * be started by the slave controller; GNUNET_NO if the slave
1544 * controller has to connect to the already started delegated
1545 * controller via TCP/IP
1546 * @return the operation handle
1548 struct GNUNET_TESTBED_Operation *
1549 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1550 struct GNUNET_TESTBED_Controller *master,
1551 struct GNUNET_TESTBED_Host *delegated_host,
1552 struct GNUNET_TESTBED_Host *slave_host,
1553 const char *sxcfg, size_t sxcfg_size,
1554 size_t scfg_size, int is_subordinate)
1556 uint32_t delegated_host_id;
1557 uint32_t slave_host_id;
1559 GNUNET_assert (GNUNET_YES ==
1560 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1561 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1563 GNUNET_TESTBED_host_get_id_ ((NULL !=
1564 slave_host) ? slave_host : master->host);
1565 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1566 GNUNET_assert (GNUNET_YES ==
1567 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1569 return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1570 slave_host_id, sxcfg, sxcfg_size,
1571 scfg_size, is_subordinate);
1576 * Compresses given configuration using zlib compress
1578 * @param config the serialized configuration
1579 * @param size the size of config
1580 * @param xconfig will be set to the compressed configuration (memory is fresly
1582 * @return the size of the xconfig
1585 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1590 xsize = compressBound ((uLong) size);
1591 *xconfig = GNUNET_malloc (xsize);
1592 GNUNET_assert (Z_OK ==
1593 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1594 (const Bytef *) config, (uLongf) size,
1601 * Function to serialize and compress using zlib a configuration through a
1602 * configuration handle
1604 * @param cfg the configuration
1605 * @param size the size of configuration when serialize. Will be set on success.
1606 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1607 * @return the serialized and compressed configuration
1610 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1611 size_t *size, size_t *xsize)
1618 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1619 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1620 GNUNET_free (config);
1628 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1631 * @param op_cls the operation closure for the event which is generated to
1632 * signal success or failure of this operation
1633 * @param master handle to the master controller who creates the association
1634 * @param delegated_host_id id of the host to which requests should be
1635 * delegated; cannot be NULL
1636 * @param slave_host_id id of the host which should connect to controller
1637 * running on delegated host ; use NULL to make the master controller
1638 * connect to the delegated host
1639 * @param slave_cfg configuration to use for the slave controller
1640 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1641 * be started by the slave controller; GNUNET_NO if the slave
1642 * controller has to connect to the already started delegated
1643 * controller via TCP/IP
1644 * @return the operation handle
1646 struct GNUNET_TESTBED_Operation *
1647 GNUNET_TESTBED_controller_link_ (void *op_cls,
1648 struct GNUNET_TESTBED_Controller *master,
1649 uint32_t delegated_host_id,
1650 uint32_t slave_host_id,
1651 const struct GNUNET_CONFIGURATION_Handle
1652 *slave_cfg, int is_subordinate)
1654 struct GNUNET_TESTBED_Operation *op;
1660 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1661 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1662 GNUNET_free (config);
1663 /* Configuration doesn't fit in 1 message */
1664 GNUNET_assert ((UINT16_MAX -
1665 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)) >=
1667 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1668 slave_host_id, (const char *) cconfig,
1669 cc_size, config_size, is_subordinate);
1670 GNUNET_free (cconfig);
1676 * Create a link from slave controller to delegated controller. Whenever the
1677 * master controller is asked to start a peer at the delegated controller the
1678 * request will be routed towards slave controller (if a route exists). The
1679 * slave controller will then route it to the delegated controller. The
1680 * configuration of the delegated controller is given and is used to either
1681 * create the delegated controller or to connect to an existing controller. Note
1682 * that while starting the delegated controller the configuration will be
1683 * modified to accommodate available free ports. the 'is_subordinate' specifies
1684 * if the given delegated controller should be started and managed by the slave
1685 * controller, or if the delegated controller already has a master and the slave
1686 * controller connects to it as a non master controller. The success or failure
1687 * of this operation will be signalled through the
1688 * GNUNET_TESTBED_ControllerCallback() with an event of type
1689 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1691 * @param op_cls the operation closure for the event which is generated to
1692 * signal success or failure of this operation
1693 * @param master handle to the master controller who creates the association
1694 * @param delegated_host requests to which host should be delegated; cannot be NULL
1695 * @param slave_host which host is used to run the slave controller; use NULL to
1696 * make the master controller connect to the delegated host
1697 * @param slave_cfg configuration to use for the slave controller
1698 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1699 * be started by the slave controller; GNUNET_NO if the slave
1700 * controller has to connect to the already started delegated
1701 * controller via TCP/IP
1702 * @return the operation handle
1704 struct GNUNET_TESTBED_Operation *
1705 GNUNET_TESTBED_controller_link (void *op_cls,
1706 struct GNUNET_TESTBED_Controller *master,
1707 struct GNUNET_TESTBED_Host *delegated_host,
1708 struct GNUNET_TESTBED_Host *slave_host,
1709 const struct GNUNET_CONFIGURATION_Handle
1710 *slave_cfg, int is_subordinate)
1712 uint32_t slave_host_id;
1713 uint32_t delegated_host_id;
1716 GNUNET_assert (GNUNET_YES ==
1717 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1719 GNUNET_TESTBED_host_get_id_ ((NULL !=
1720 slave_host) ? slave_host : master->host);
1721 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1722 if ((NULL != slave_host) && (0 != slave_host_id))
1723 GNUNET_assert (GNUNET_YES ==
1724 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1725 return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
1727 GNUNET_TESTBED_host_get_cfg_ (delegated_host),
1734 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1735 * check. Another difference is that this function takes the id of the slave
1738 * @param op_cls the closure for the operation
1739 * @param master the handle to master controller
1740 * @param slave_host_id id of the host where the slave controller is running to
1741 * the slave_host should remain valid until this operation is cancelled
1742 * or marked as finished
1743 * @return the operation handle;
1745 struct GNUNET_TESTBED_Operation *
1746 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1747 struct GNUNET_TESTBED_Controller *master,
1748 uint32_t slave_host_id)
1750 struct OperationContext *opc;
1751 struct GetSlaveConfigData *data;
1753 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1754 data->slave_id = slave_host_id;
1755 opc = GNUNET_malloc (sizeof (struct OperationContext));
1756 opc->state = OPC_STATE_INIT;
1758 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1759 opc->type = OP_GET_SLAVE_CONFIG;
1761 opc->op_cls = op_cls;
1763 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1764 &oprelease_get_slave_config);
1765 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1767 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1773 * Function to acquire the configuration of a running slave controller. The
1774 * completion of the operation is signalled through the controller_cb from
1775 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1776 * handle to the configuration is available in the generic pointer of
1777 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1779 * @param op_cls the closure for the operation
1780 * @param master the handle to master controller
1781 * @param slave_host the host where the slave controller is running; the handle
1782 * to the slave_host should remain valid until this operation is
1783 * cancelled or marked as finished
1784 * @return the operation handle; NULL if the slave_host is not registered at
1787 struct GNUNET_TESTBED_Operation *
1788 GNUNET_TESTBED_get_slave_config (void *op_cls,
1789 struct GNUNET_TESTBED_Controller *master,
1790 struct GNUNET_TESTBED_Host *slave_host)
1792 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1794 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1795 GNUNET_TESTBED_host_get_id_
1801 * Ask the testbed controller to write the current overlay topology to
1802 * a file. Naturally, the file will only contain a snapshot as the
1803 * topology may evolve all the time.
1805 * @param controller overlay controller to inspect
1806 * @param filename name of the file the topology should
1810 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1812 const char *filename)
1819 * Creates a helper initialization message. This function is here because we
1820 * want to use this in testing
1822 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1823 * HOST(all connections form this ip are permitted by the testbed) when
1824 * starting testbed controller at host. This can either be a single ip
1825 * address or a network address in CIDR notation.
1826 * @param hostname the hostname of the destination this message is intended for
1827 * @param cfg the configuration that has to used to start the testbed service
1829 * @return the initialization message
1831 struct GNUNET_TESTBED_HelperInit *
1832 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1833 const char *hostname,
1834 const struct GNUNET_CONFIGURATION_Handle
1837 struct GNUNET_TESTBED_HelperInit *msg;
1841 size_t xconfig_size;
1842 uint16_t trusted_ip_len;
1843 uint16_t hostname_len;
1846 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1847 GNUNET_assert (NULL != config);
1849 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1850 GNUNET_free (config);
1851 trusted_ip_len = strlen (trusted_ip);
1852 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1854 xconfig_size + trusted_ip_len + 1 +
1855 sizeof (struct GNUNET_TESTBED_HelperInit);
1856 msg_size += hostname_len;
1857 msg = GNUNET_realloc (xconfig, msg_size);
1858 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1860 msg->header.size = htons (msg_size);
1861 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1862 msg->trusted_ip_size = htons (trusted_ip_len);
1863 msg->hostname_size = htons (hostname_len);
1864 msg->config_size = htons (config_size);
1865 (void) strcpy ((char *) &msg[1], trusted_ip);
1866 if (0 != hostname_len)
1867 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1874 * Signal that the information from an operation has been fully
1875 * processed. This function MUST be called for each event
1876 * of type 'operation_finished' to fully remove the operation
1877 * from the operation queue. After calling this function, the
1878 * 'op_result' becomes invalid (!).
1880 * @param operation operation to signal completion for
1883 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1885 (void) exop_check (operation);
1886 GNUNET_TESTBED_operation_release_ (operation);
1891 * Generates configuration by uncompressing configuration in given message. The
1892 * given message should be of the following types:
1893 * GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION,
1894 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1895 * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
1896 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
1897 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1899 * @param msg the message containing compressed configuration
1900 * @return handle to the parsed configuration; NULL upon error while parsing the message
1902 struct GNUNET_CONFIGURATION_Handle *
1903 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1905 struct GNUNET_CONFIGURATION_Handle *cfg;
1912 switch (ntohs (msg->type))
1914 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1916 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1919 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1920 data_len = (uLong) ntohs (imsg->config_size);
1922 ntohs (imsg->header.size) -
1923 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1924 xdata = (const Bytef *) &imsg[1];
1927 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1929 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1931 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1932 data_len = (uLong) ntohs (imsg->config_size);
1934 ntohs (imsg->header.size) -
1935 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1936 xdata = (const Bytef *) &imsg[1];
1939 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1941 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1944 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1945 data_len = (uLong) ntohs (imsg->config_size);
1946 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1947 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1948 xdata_len = ntohs (imsg->header.size) - osize;
1949 xdata = (const Bytef *) ((const void *) imsg + osize);
1952 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1954 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
1956 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
1957 data_len = ntohs (imsg->config_size);
1958 xdata_len = ntohs (imsg->header.size) -
1959 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
1960 xdata = (const Bytef *) &imsg[1];
1963 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS:
1965 const struct GNUNET_TESTBED_ControllerLinkRequest *imsg;
1966 imsg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) msg;
1967 data_len = ntohs (imsg->config_size);
1968 xdata_len = ntohs (imsg->header.size) - sizeof (const struct
1969 GNUNET_TESTBED_ControllerLinkRequest);
1970 xdata = (const Bytef *) &imsg[1];
1976 data = GNUNET_malloc (data_len);
1977 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1980 GNUNET_break_op (0);
1983 cfg = GNUNET_CONFIGURATION_create ();
1985 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
1990 GNUNET_break_op (0);
1999 * Checks the integrity of the OperationFailureEventMessage and if good returns
2000 * the error message it contains.
2002 * @param msg the OperationFailureEventMessage
2003 * @return the error message
2006 GNUNET_TESTBED_parse_error_string_ (const struct
2007 GNUNET_TESTBED_OperationFailureEventMessage
2013 msize = ntohs (msg->header.size);
2014 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2016 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2017 emsg = (const char *) &msg[1];
2018 if ('\0' != emsg[msize - 1])
2028 * Function to return the operation id for a controller. The operation id is
2029 * created from the controllers host id and its internal operation counter.
2031 * @param controller the handle to the controller whose operation id has to be incremented
2032 * @return the incremented operation id.
2035 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2039 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2040 op_id = op_id << 32;
2041 op_id |= (uint64_t) controller->operation_counter++;
2047 * Function called when a shutdown peers operation is ready
2049 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2052 opstart_shutdown_peers (void *cls)
2054 struct OperationContext *opc = cls;
2055 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2057 opc->state = OPC_STATE_STARTED;
2058 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2060 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2061 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2062 msg->operation_id = GNUNET_htonll (opc->id);
2063 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
2064 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
2069 * Callback which will be called when shutdown peers operation is released
2071 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2074 oprelease_shutdown_peers (void *cls)
2076 struct OperationContext *opc = cls;
2078 if (OPC_STATE_FINISHED != opc->state)
2080 GNUNET_free (opc->data);
2081 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
2088 * Stops and destroys all peers. Is equivalent of calling
2089 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2090 * except that the peer stop event and operation finished event corresponding to
2091 * the respective functions are not generated. This function should be called
2092 * when there are no other pending operations. If there are pending operations,
2093 * it will return NULL
2095 * @param controller the controller to send this message to
2096 * @param op_cls closure for the operation
2097 * @param cb the callback to call when all peers are stopped and destroyed
2098 * @param cb_cls the closure for the callback
2099 * @return operation handle on success; NULL if any pending operations are
2102 struct GNUNET_TESTBED_Operation *
2103 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *controller,
2105 GNUNET_TESTBED_OperationCompletionCallback cb,
2108 struct OperationContext *opc;
2109 struct ShutdownPeersData *data;
2111 if (NULL != controller->ocq_head)
2113 data = GNUNET_malloc (sizeof (struct ShutdownPeersData));
2115 data->cb_cls = cb_cls;
2116 opc = GNUNET_malloc (sizeof (struct OperationContext));
2117 opc->c = controller;
2118 opc->op_cls = op_cls;
2120 opc->id = GNUNET_TESTBED_get_next_op_id (controller);
2121 opc->type = OP_SHUTDOWN_PEERS;
2122 opc->state = OPC_STATE_INIT;
2123 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2124 &oprelease_shutdown_peers);
2125 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2127 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2132 /* end of testbed_api.c */