2 This file is part of GNUnet
3 (C) 2008--2012 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"
46 * Generic logging shorthand
48 #define LOG(kind, ...) \
49 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
54 #define LOG_DEBUG(...) \
55 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
58 * Relative time seconds shorthand
60 #define TIME_REL_SECS(sec) \
61 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
65 * Default server message sending retry timeout
67 #define TIMEOUT_REL TIME_REL_SECS(1)
71 * Handle for controller process
73 struct GNUNET_TESTBED_ControllerProc
78 struct GNUNET_HELPER_Handle *helper;
81 * The arguments used to start the helper
86 * The host where the helper is run
88 struct GNUNET_TESTBED_Host *host;
91 * The controller error callback
93 GNUNET_TESTBED_ControllerStatusCallback cb;
96 * The closure for the above callback
101 * The send handle for the helper
103 struct GNUNET_HELPER_SendHandle *shandle;
106 * The message corresponding to send handle
108 struct GNUNET_MessageHeader *msg;
111 * The configuration of the running testbed service
113 struct GNUNET_CONFIGURATION_Handle *cfg;
119 * The message queue for sending messages to the controller service
124 * The message to be sent
126 struct GNUNET_MessageHeader *msg;
129 * next pointer for DLL
131 struct MessageQueue *next;
134 * prev pointer for DLL
136 struct MessageQueue *prev;
141 * Structure for a controller link
143 struct ControllerLink
146 * The next ptr for DLL
148 struct ControllerLink *next;
151 * The prev ptr for DLL
153 struct ControllerLink *prev;
156 * The host which will be referred in the peer start request. This is the
157 * host where the peer should be started
159 struct GNUNET_TESTBED_Host *delegated_host;
162 * The host which will contacted to delegate the peer start request
164 struct GNUNET_TESTBED_Host *slave_host;
167 * The configuration to be used to connect to slave host
169 const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
172 * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
173 * if we are just allowed to use the slave via TCP/IP
180 * handle for host registration
182 struct GNUNET_TESTBED_HostRegistrationHandle
185 * The host being registered
187 struct GNUNET_TESTBED_Host *host;
190 * The controller at which this host is being registered
192 struct GNUNET_TESTBED_Controller *c;
195 * The Registartion completion callback
197 GNUNET_TESTBED_HostRegistrationCompletion cc;
200 * The closure for above callback
207 * Context data for forwarded Operation
209 struct ForwardedOperationData
213 * The callback to call when reply is available
215 GNUNET_CLIENT_MessageHandler cc;
218 * The closure for the above callback
226 * Context data for get slave config operations
228 struct GetSlaveConfigData
231 * The id of the slave controller
239 * Context data for controller link operations
241 struct ControllerLinkData
244 * The controller link message
246 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
256 struct SDEntry *next;
261 struct SDEntry *prev;
273 * DLL head for storing entries
275 struct SDEntry *head;
278 * DLL tail for storing entries
280 struct SDEntry *tail;
283 * Squared sum of data values
285 unsigned long long sqsum;
288 * Sum of the data values
293 * The average of data amounts
303 * Number of data values; also the length of DLL containing SDEntries
308 * max number of entries we can have in the DLL
310 unsigned int max_cnt;
320 static struct SDHandle *
321 SD_init (unsigned int max_cnt)
325 GNUNET_assert (1 < max_cnt);
326 h = GNUNET_malloc (sizeof (struct SDHandle));
327 h->max_cnt = max_cnt;
339 SD_destroy (struct SDHandle *h)
341 struct SDEntry *entry;
343 while (NULL != (entry = h->head))
345 GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry);
352 SD_add_data (struct SDHandle *h, unsigned int amount)
354 struct SDEntry *entry;
359 if (h->cnt == h->max_cnt)
362 GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry);
363 h->sum -= entry->amount;
364 h->sqsum -= ((unsigned long) entry->amount) *
365 ((unsigned long) entry->amount);
368 GNUNET_assert (h->cnt < h->max_cnt);
370 entry = GNUNET_malloc (sizeof (struct SDEntry));
371 entry->amount = amount;
372 GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, entry);
375 h->avg = ((float) h->sum) / ((float) h->cnt);
376 h->sqsum += ((unsigned long) amount) * ((unsigned long) amount);
377 sqsum_avg = ((double) h->sqsum) / ((double) h->cnt);
378 sqavg = ((double) h->avg) * ((double) h->avg);
379 h->vr = sqsum_avg - sqavg;
384 * Returns the factor by which the given amount differs from the standard deviation
386 * @param h the SDhandle
387 * @param amount the value for which the deviation is returned
388 * @return the deviation from the average; GNUNET_SYSERR if the deviation cannot
389 * be calculated; a maximum of 4 is returned for deviations equal to
393 SD_deviation_factor (struct SDHandle *h, unsigned int amount)
399 return GNUNET_SYSERR;
400 if (((float) amount) > h->avg)
401 diff = ((float) amount) - h->avg;
403 return 0; //diff = h->avg - ((float) amount);
405 for (n = 1; n < 4; n++)
406 if (diff < (((double) (n * n)) * h->vr))
413 * Returns the operation context with the given id if found in the Operation
414 * context queues of the controller
416 * @param c the controller whose queues are searched
417 * @param id the id which has to be checked
418 * @return the matching operation context; NULL if no match found
420 static struct OperationContext *
421 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
423 struct OperationContext *opc;
425 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
435 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
436 * controller (testbed service)
438 * @param c the controller handler
439 * @param msg message received
440 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
444 handle_addhostconfirm (struct GNUNET_TESTBED_Controller *c,
445 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
447 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
456 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
458 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
459 GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
463 msg_size = ntohs (msg->header.size);
464 if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
466 LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
467 GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
468 rh->cc (rh->cc_cls, NULL);
472 /* We have an error message */
473 emsg = (char *) &msg[1];
475 emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
481 LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
482 ntohl (msg->host_id), emsg);
483 rh->cc (rh->cc_cls, emsg);
490 * Handler for forwarded operations
492 * @param c the controller handle
493 * @param opc the opearation context
494 * @param msg the message
497 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
498 struct OperationContext *opc,
499 const struct GNUNET_MessageHeader *msg)
501 struct ForwardedOperationData *fo_data;
504 if (NULL != fo_data->cc)
505 fo_data->cc (fo_data->cc_cls, msg);
506 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
507 GNUNET_free (fo_data);
513 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
514 * controller (testbed service)
516 * @param c the controller handler
517 * @param msg message received
518 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
522 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
524 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
526 struct OperationContext *opc;
527 struct GNUNET_TESTBED_EventInformation event;
530 op_id = GNUNET_ntohll (msg->operation_id);
531 LOG_DEBUG ("Operation %lu successful\n", op_id);
532 if (NULL == (opc = find_opc (c, op_id)))
534 LOG_DEBUG ("Operation not found\n");
537 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
538 event.details.operation_finished.operation = opc->op;
539 event.details.operation_finished.op_cls = opc->op_cls;
540 event.details.operation_finished.emsg = NULL;
541 event.details.operation_finished.generic = NULL;
546 handle_forwarded_operation_msg
547 (c, opc, (const struct GNUNET_MessageHeader *) msg);
551 case OP_PEER_DESTROY:
553 struct GNUNET_TESTBED_Peer *peer;
561 case OP_LINK_CONTROLLERS:
563 struct ControllerLinkData *data;
566 GNUNET_assert (NULL != data);
574 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
575 opc->state = OPC_STATE_FINISHED;
576 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
579 c->cc (c->cc_cls, &event);
582 LOG_DEBUG ("Not calling callback\n");
588 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
589 * controller (testbed service)
591 * @param c the controller handle
592 * @param msg message received
593 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
597 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
599 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
601 struct OperationContext *opc;
602 struct PeerCreateData *data;
603 struct GNUNET_TESTBED_Peer *peer;
604 GNUNET_TESTBED_PeerCreateCallback cb;
608 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
609 ntohs (msg->header.size));
610 op_id = GNUNET_ntohll (msg->operation_id);
611 if (NULL == (opc = find_opc (c, op_id)))
613 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
616 if (OP_FORWARDED == opc->type)
618 handle_forwarded_operation_msg (c, opc,
619 (const struct GNUNET_MessageHeader *) msg);
622 GNUNET_assert (OP_PEER_CREATE == opc->type);
623 GNUNET_assert (NULL != opc->data);
625 GNUNET_assert (NULL != data->peer);
627 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
628 peer->state = PS_CREATED;
631 GNUNET_free (opc->data);
632 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
633 opc->state = OPC_STATE_FINISHED;
635 cb (cls, peer, NULL);
641 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
642 * controller (testbed service)
644 * @param c the controller handler
645 * @param msg message received
646 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
650 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
651 const struct GNUNET_TESTBED_PeerEventMessage *msg)
653 struct OperationContext *opc;
654 struct GNUNET_TESTBED_Peer *peer;
655 struct PeerEventData *data;
656 GNUNET_TESTBED_PeerChurnCallback pcc;
658 struct GNUNET_TESTBED_EventInformation event;
661 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
662 ntohs (msg->header.size));
663 op_id = GNUNET_ntohll (msg->operation_id);
664 if (NULL == (opc = find_opc (c, op_id)))
666 LOG_DEBUG ("Operation not found\n");
669 if (OP_FORWARDED == opc->type)
671 handle_forwarded_operation_msg (c, opc,
672 (const struct GNUNET_MessageHeader *) msg);
675 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
677 GNUNET_assert (NULL != data);
679 GNUNET_assert (NULL != peer);
680 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
683 case GNUNET_TESTBED_ET_PEER_START:
684 peer->state = PS_STARTED;
685 event.details.peer_start.host = peer->host;
686 event.details.peer_start.peer = peer;
688 case GNUNET_TESTBED_ET_PEER_STOP:
689 peer->state = PS_STOPPED;
690 event.details.peer_stop.peer = peer;
693 GNUNET_assert (0); /* We should never reach this state */
696 pcc_cls = data->pcc_cls;
698 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
699 opc->state = OPC_STATE_FINISHED;
701 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
705 c->cc (c->cc_cls, &event);
714 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
715 * controller (testbed service)
717 * @param c the controller handler
718 * @param msg message received
719 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
723 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
724 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
726 struct OperationContext *opc;
727 struct OverlayConnectData *data;
728 GNUNET_TESTBED_OperationCompletionCallback cb;
730 struct GNUNET_TESTBED_EventInformation event;
733 op_id = GNUNET_ntohll (msg->operation_id);
734 if (NULL == (opc = find_opc (c, op_id)))
736 LOG_DEBUG ("Operation not found\n");
739 if (OP_FORWARDED == opc->type)
741 handle_forwarded_operation_msg (c, opc,
742 (const struct GNUNET_MessageHeader *) msg);
745 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
747 GNUNET_assert (NULL != data);
748 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
749 (ntohl (msg->peer2) == data->p2->unique_id));
750 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
753 case GNUNET_TESTBED_ET_CONNECT:
754 event.details.peer_connect.peer1 = data->p1;
755 event.details.peer_connect.peer2 = data->p2;
757 case GNUNET_TESTBED_ET_DISCONNECT:
758 GNUNET_assert (0); /* FIXME: implement */
761 GNUNET_assert (0); /* Should never reach here */
765 cb_cls = data->cb_cls;
766 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
767 opc->state = OPC_STATE_FINISHED;
768 //GNUNET_free (data);
770 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
774 c->cc (c->cc_cls, &event);
777 cb (cb_cls, opc->op, NULL);
783 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
784 * controller (testbed service)
786 * @param c the controller handler
787 * @param msg message received
788 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
792 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
794 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
796 struct OperationContext *opc;
797 struct GNUNET_TESTBED_Peer *peer;
798 struct PeerInfoData *data;
799 struct GNUNET_TESTBED_PeerInformation *pinfo;
800 GNUNET_TESTBED_PeerInfoCallback cb;
804 op_id = GNUNET_ntohll (msg->operation_id);
805 if (NULL == (opc = find_opc (c, op_id)))
807 LOG_DEBUG ("Operation not found\n");
810 if (OP_FORWARDED == opc->type)
812 handle_forwarded_operation_msg (c, opc,
813 (const struct GNUNET_MessageHeader *) msg);
817 GNUNET_assert (NULL != data);
819 GNUNET_assert (NULL != peer);
820 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
821 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
822 pinfo->pit = data->pit;
824 cb_cls = data->cb_cls;
829 case GNUNET_TESTBED_PIT_IDENTITY:
830 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
831 (void) memcpy (pinfo->result.id, &msg->peer_identity,
832 sizeof (struct GNUNET_PeerIdentity));
834 case GNUNET_TESTBED_PIT_CONFIGURATION:
835 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
836 GNUNET_TESTBED_extract_config_ (&msg->header);
838 case GNUNET_TESTBED_PIT_GENERIC:
839 GNUNET_assert (0); /* never reach here */
843 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
844 opc->state = OPC_STATE_FINISHED;
846 cb (cb_cls, opc->op, pinfo, NULL);
852 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
853 * controller (testbed service)
855 * @param c the controller handler
856 * @param msg message received
857 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
861 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
862 const struct GNUNET_TESTBED_OperationFailureEventMessage
865 struct OperationContext *opc;
868 struct GNUNET_TESTBED_EventInformation event;
870 op_id = GNUNET_ntohll (msg->operation_id);
871 if (NULL == (opc = find_opc (c, op_id)))
873 LOG_DEBUG ("Operation not found\n");
876 if (OP_FORWARDED == opc->type)
878 handle_forwarded_operation_msg (c, opc,
879 (const struct GNUNET_MessageHeader *) msg);
882 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
883 opc->state = OPC_STATE_FINISHED;
884 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
886 emsg = "Unknown error";
887 if (OP_PEER_INFO == opc->type)
889 struct PeerInfoData *data;
891 if (NULL != data->cb)
892 data->cb (data->cb_cls, opc->op, NULL, emsg);
894 return GNUNET_YES; /* We do not call controller callback for peer info */
896 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
899 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
900 event.details.operation_finished.operation = opc->op;
901 event.details.operation_finished.op_cls = opc->op_cls;
902 event.details.operation_finished.emsg = emsg;
903 event.details.operation_finished.generic = NULL;
904 c->cc (c->cc_cls, &event);
910 struct PeerCreateData *data;
912 GNUNET_free (data->peer);
913 if (NULL != data->cb)
914 data->cb (data->cls, NULL, emsg);
921 struct PeerEventData *data;
923 if (NULL != data->pcc)
924 data->pcc (data->pcc_cls, emsg);
928 case OP_PEER_DESTROY:
932 case OP_OVERLAY_CONNECT:
934 struct OverlayConnectData *data;
936 if (NULL != data->cb)
937 data->cb (data->cb_cls, opc->op, emsg);
943 case OP_LINK_CONTROLLERS: /* No secondary callback */
953 * Function to build GET_SLAVE_CONFIG message
955 * @param op_id the id this message should contain in its operation id field
956 * @param slave_id the id this message should contain in its slave id field
957 * @return newly allocated SlaveGetConfigurationMessage
959 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
960 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
962 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
965 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
966 msg = GNUNET_malloc (msize);
967 msg->header.size = htons (msize);
968 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG);
969 msg->operation_id = GNUNET_htonll (op_id);
970 msg->slave_id = htonl (slave_id);
976 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
979 * @param c the controller handler
980 * @param msg message received
981 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
985 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
986 const struct GNUNET_TESTBED_SlaveConfiguration * msg)
988 struct OperationContext *opc;
990 struct GNUNET_TESTBED_EventInformation event;
992 op_id = GNUNET_ntohll (msg->operation_id);
993 if (NULL == (opc = find_opc (c, op_id)))
995 LOG_DEBUG ("Operation not found\n");
998 if (OP_GET_SLAVE_CONFIG != opc->type)
1003 GNUNET_free (opc->data);
1005 opc->state = OPC_STATE_FINISHED;
1006 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1007 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
1010 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
1011 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1012 event.details.operation_finished.generic = opc->data;
1013 event.details.operation_finished.operation = opc->op;
1014 event.details.operation_finished.op_cls = opc->op_cls;
1015 event.details.operation_finished.emsg = NULL;
1016 c->cc (c->cc_cls, &event);
1023 * Handler for messages from controller (testbed service)
1025 * @param cls the controller handler
1026 * @param msg message received, NULL on timeout or fatal error
1029 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
1031 struct GNUNET_TESTBED_Controller *c = cls;
1035 c->in_receive = GNUNET_NO;
1036 /* FIXME: Add checks for message integrity */
1039 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
1043 msize = ntohs (msg->size);
1044 switch (ntohs (msg->type))
1046 case GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM:
1047 GNUNET_assert (msize >=
1048 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
1050 handle_addhostconfirm (c,
1051 (const struct GNUNET_TESTBED_HostConfirmedMessage
1054 case GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS:
1055 GNUNET_assert (msize ==
1057 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
1059 handle_opsuccess (c,
1061 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
1064 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS:
1065 GNUNET_assert (msize ==
1067 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1069 handle_peer_create_success (c,
1071 GNUNET_TESTBED_PeerCreateSuccessEventMessage
1074 case GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT:
1075 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1077 handle_peer_event (c,
1078 (const struct GNUNET_TESTBED_PeerEventMessage *)
1082 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
1083 GNUNET_assert (msize >=
1085 GNUNET_TESTBED_PeerConfigurationInformationMessage));
1087 handle_peer_config (c,
1089 GNUNET_TESTBED_PeerConfigurationInformationMessage
1092 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT:
1093 GNUNET_assert (msize ==
1094 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1096 handle_peer_conevent (c,
1098 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1100 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT:
1101 GNUNET_assert (msize >=
1102 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
1104 handle_op_fail_event (c,
1106 GNUNET_TESTBED_OperationFailureEventMessage *)
1109 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG:
1110 GNUNET_assert (msize >
1111 sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1113 handle_slave_config (c, (const struct
1114 GNUNET_TESTBED_SlaveConfiguration *) msg);
1119 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1121 c->in_receive = GNUNET_YES;
1122 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1123 GNUNET_TIME_UNIT_FOREVER_REL);
1129 * Function called to notify a client about the connection begin ready to queue
1130 * more data. "buf" will be NULL and "size" zero if the connection was closed
1131 * for writing in the meantime.
1133 * @param cls closure
1134 * @param size number of bytes available in buf
1135 * @param buf where the callee should write the message
1136 * @return number of bytes written to buf
1139 transmit_ready_notify (void *cls, size_t size, void *buf)
1141 struct GNUNET_TESTBED_Controller *c = cls;
1142 struct MessageQueue *mq_entry;
1145 mq_entry = c->mq_head;
1146 GNUNET_assert (NULL != mq_entry);
1147 if ((0 == size) && (NULL == buf)) /* Timeout */
1149 LOG_DEBUG ("Message sending timed out -- retrying\n");
1151 GNUNET_CLIENT_notify_transmit_ready (c->client,
1152 ntohs (mq_entry->msg->size),
1153 TIMEOUT_REL, GNUNET_YES,
1154 &transmit_ready_notify, c);
1157 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1158 size = ntohs (mq_entry->msg->size);
1159 memcpy (buf, mq_entry->msg, size);
1160 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1161 ntohs (mq_entry->msg->type), size);
1162 GNUNET_free (mq_entry->msg);
1163 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1164 GNUNET_free (mq_entry);
1165 mq_entry = c->mq_head;
1166 if (NULL != mq_entry)
1168 GNUNET_CLIENT_notify_transmit_ready (c->client,
1169 ntohs (mq_entry->msg->size),
1170 TIMEOUT_REL, GNUNET_YES,
1171 &transmit_ready_notify, c);
1172 if (GNUNET_NO == c->in_receive)
1174 c->in_receive = GNUNET_YES;
1175 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1176 GNUNET_TIME_UNIT_FOREVER_REL);
1183 * Queues a message in send queue for sending to the service
1185 * @param controller the handle to the controller
1186 * @param msg the message to queue
1189 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1190 struct GNUNET_MessageHeader *msg)
1192 struct MessageQueue *mq_entry;
1196 type = ntohs (msg->type);
1197 size = ntohs (msg->size);
1198 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1199 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1200 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1201 mq_entry->msg = msg;
1202 LOG (GNUNET_ERROR_TYPE_DEBUG,
1203 "Queueing message of type %u, size %u for sending\n", type,
1205 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1207 if (NULL == controller->th)
1209 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1210 TIMEOUT_REL, GNUNET_YES,
1211 &transmit_ready_notify,
1217 * Sends the given message as an operation. The given callback is called when a
1218 * reply for the operation is available. Call
1219 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1220 * operation context if the cc hasn't been called
1222 * @param controller the controller to which the message has to be sent
1223 * @param operation_id the operation id of the message
1224 * @param msg the message to send
1225 * @param cc the callback to call when reply is available
1226 * @param cc_cls the closure for the above callback
1227 * @return the operation context which can be used to cancel the forwarded
1230 struct OperationContext *
1231 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1232 *controller, uint64_t operation_id,
1233 const struct GNUNET_MessageHeader *msg,
1234 GNUNET_CLIENT_MessageHandler cc,
1237 struct OperationContext *opc;
1238 struct ForwardedOperationData *data;
1239 struct GNUNET_MessageHeader *dup_msg;
1242 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1244 data->cc_cls = cc_cls;
1245 opc = GNUNET_malloc (sizeof (struct OperationContext));
1246 opc->c = controller;
1247 opc->type = OP_FORWARDED;
1249 opc->id = operation_id;
1250 msize = ntohs (msg->size);
1251 dup_msg = GNUNET_malloc (msize);
1252 (void) memcpy (dup_msg, msg, msize);
1253 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1254 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1261 * Function to cancel an operation created by simply forwarding an operation
1264 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1267 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1269 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1270 GNUNET_free (opc->data);
1276 * Functions with this signature are called whenever a
1277 * complete message is received by the tokenizer.
1279 * Do not call GNUNET_SERVER_mst_destroy in callback
1281 * @param cls closure
1282 * @param client identification of the client
1283 * @param message the actual message
1285 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1288 helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1290 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1291 const struct GNUNET_TESTBED_HelperReply *msg;
1292 const char *hostname;
1295 uLongf xconfig_size;
1297 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1298 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1299 ntohs (msg->header.size));
1300 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1301 ntohs (msg->header.type));
1302 config_size = (uLongf) ntohs (msg->config_size);
1304 (uLongf) (ntohs (msg->header.size) -
1305 sizeof (struct GNUNET_TESTBED_HelperReply));
1306 config = GNUNET_malloc (config_size);
1307 GNUNET_assert (Z_OK ==
1308 uncompress ((Bytef *) config, &config_size,
1309 (const Bytef *) &msg[1], xconfig_size));
1310 GNUNET_assert (NULL == cp->cfg);
1311 cp->cfg = GNUNET_CONFIGURATION_create ();
1312 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1313 (cp->cfg, config, config_size, GNUNET_NO));
1314 GNUNET_free (config);
1315 if ((NULL == cp->host) ||
1316 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
1317 hostname = "localhost";
1318 /* Change the hostname so that we can connect to it */
1319 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1321 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1327 * Continuation function from GNUNET_HELPER_send()
1329 * @param cls closure
1330 * @param result GNUNET_OK on success,
1331 * GNUNET_NO if helper process died
1332 * GNUNET_SYSERR during GNUNET_HELPER_stop
1335 clear_msg (void *cls, int result)
1337 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1339 GNUNET_assert (NULL != cp->shandle);
1341 GNUNET_free (cp->msg);
1346 * Callback that will be called when the helper process dies. This is not called
1347 * when the helper process is stoped using GNUNET_HELPER_stop()
1349 * @param cls the closure from GNUNET_HELPER_start()
1352 helper_exp_cb (void *cls)
1354 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1355 GNUNET_TESTBED_ControllerStatusCallback cb;
1361 GNUNET_TESTBED_controller_stop (cp);
1363 cb (cb_cls, NULL, GNUNET_SYSERR);
1368 * Function to call to start a link-controllers type operation once all queues
1369 * the operation is part of declare that the operation can be activated.
1371 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1374 opstart_link_controllers (void *cls)
1376 struct OperationContext *opc = cls;
1377 struct ControllerLinkData *data;
1378 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1380 GNUNET_assert (NULL != opc->data);
1384 opc->state = OPC_STATE_STARTED;
1385 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1386 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1391 * Callback which will be called when link-controllers type operation is released
1393 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1396 oprelease_link_controllers (void *cls)
1398 struct OperationContext *opc = cls;
1399 struct ControllerLinkData *data;
1404 case OPC_STATE_INIT:
1405 GNUNET_free (data->msg);
1407 case OPC_STATE_STARTED:
1408 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1410 case OPC_STATE_FINISHED:
1413 GNUNET_free_non_null (data);
1419 * Function to be called when get slave config operation is ready
1421 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1424 opstart_get_slave_config (void *cls)
1426 struct OperationContext *opc = cls;
1427 struct GetSlaveConfigData *data;
1428 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1431 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1432 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1433 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1434 opc->state = OPC_STATE_STARTED;
1439 * Function to be called when get slave config operation is cancelled or finished
1441 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1444 oprelease_get_slave_config (void *cls)
1446 struct OperationContext *opc = cls;
1450 case OPC_STATE_INIT:
1451 GNUNET_free (opc->data);
1453 case OPC_STATE_STARTED:
1454 GNUNET_free (opc->data);
1455 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1457 case OPC_STATE_FINISHED:
1458 if (NULL != opc->data)
1459 GNUNET_CONFIGURATION_destroy (opc->data);
1473 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (struct
1474 GNUNET_TESTBED_Controller *c,
1477 fprintf (stderr, "%d", npoc);
1478 GNUNET_free_non_null (c->tslots);
1479 c->tslots_filled = 0;
1480 c->num_parallel_connects = npoc;
1481 c->tslots = GNUNET_malloc (npoc * sizeof (struct TimeSlot));
1482 GNUNET_TESTBED_operation_queue_reset_max_active_
1483 (c->opq_parallel_overlay_connect_operations, npoc);
1488 * Function to copy NULL terminated list of arguments
1490 * @param argv the NULL terminated list of arguments. Cannot be NULL.
1491 * @return the copied NULL terminated arguments
1494 copy_argv (const char *const *argv)
1499 GNUNET_assert (NULL != argv);
1500 for (argp = 0; NULL != argv[argp]; argp++);
1501 argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
1502 for (argp = 0; NULL != argv[argp]; argp++)
1503 argv_dup[argp] = strdup (argv[argp]);
1509 * Frees the given NULL terminated arguments
1511 * @param argv the NULL terminated list of arguments
1514 free_argv (char **argv)
1518 for (argp = 0; NULL != argv[argp]; argp++)
1519 GNUNET_free (argv[argp]);
1525 * Starts a controller process at the given host
1527 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1528 * HOST(all connections form this ip are permitted by the testbed) when
1529 * starting testbed controller at host. This can either be a single ip
1530 * address or a network address in CIDR notation.
1531 * @param controller_ip the ip address of the controller. Will be set as TRUSTED
1532 * host when starting testbed controller at host
1533 * @param host the host where the controller has to be started; NULL for
1535 * @param cfg template configuration to use for the remote controller; the
1536 * remote controller will be started with a slightly modified
1537 * configuration (port numbers, unix domain sockets and service home
1538 * values are changed as per TESTING library on the remote host)
1539 * @param cb function called when the controller is successfully started or
1540 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1541 * called if cb is called with GNUNET_SYSERR as status. Will never be
1542 * called in the same task as 'GNUNET_TESTBED_controller_start'
1543 * (synchronous errors will be signalled by returning NULL). This
1544 * parameter cannot be NULL.
1545 * @param cls closure for above callbacks
1546 * @return the controller process handle, NULL on errors
1548 struct GNUNET_TESTBED_ControllerProc *
1549 GNUNET_TESTBED_controller_start (const char *trusted_ip,
1550 struct GNUNET_TESTBED_Host *host,
1551 const struct GNUNET_CONFIGURATION_Handle *cfg,
1552 GNUNET_TESTBED_ControllerStatusCallback cb,
1555 struct GNUNET_TESTBED_ControllerProc *cp;
1556 struct GNUNET_TESTBED_HelperInit *msg;
1557 const char *hostname;
1558 static char *const binary_argv[] = {
1559 HELPER_TESTBED_BINARY, NULL
1563 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1564 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1567 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1568 &helper_mst, &helper_exp_cb, cp);
1572 char *helper_binary_path;
1573 #define NUM_REMOTE_ARGS 12
1574 const char *remote_args[NUM_REMOTE_ARGS];
1575 const char *username;
1580 username = GNUNET_TESTBED_host_get_username_ (host);
1581 hostname = GNUNET_TESTBED_host_get_hostname (host);
1582 GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1583 if (NULL == username)
1584 GNUNET_asprintf (&dst, "%s", hostname);
1586 GNUNET_asprintf (&dst, "%s@%s", username, hostname);
1587 LOG_DEBUG ("Starting SSH to destination %s\n", dst);
1589 remote_args[argp++] = "ssh";
1590 remote_args[argp++] = "-p";
1591 remote_args[argp++] = port;
1592 remote_args[argp++] = "-o";
1593 remote_args[argp++] = "BatchMode=yes";
1594 remote_args[argp++] = "-o";
1595 remote_args[argp++] = "NoHostAuthenticationForLocalhost=yes";
1596 remote_args[argp++] = dst;
1597 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1598 "HELPER_BINARY_PATH",
1599 &helper_binary_path))
1600 helper_binary_path = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1601 remote_args[argp++] = "sh";
1602 remote_args[argp++] = "-lc";
1603 remote_args[argp++] = helper_binary_path;
1604 remote_args[argp++] = NULL;
1605 GNUNET_assert (NUM_REMOTE_ARGS == argp);
1606 cp->helper_argv = copy_argv (remote_args);
1610 GNUNET_HELPER_start (GNUNET_NO, "ssh", cp->helper_argv, &helper_mst,
1611 &helper_exp_cb, cp);
1612 GNUNET_free (helper_binary_path);
1614 if (NULL == cp->helper)
1616 if (NULL != cp->helper_argv)
1617 free_argv (cp->helper_argv);
1624 msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
1625 cp->msg = &msg->header;
1627 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1628 if (NULL == cp->shandle)
1631 GNUNET_TESTBED_controller_stop (cp);
1639 * Stop the controller process (also will terminate all peers and controllers
1640 * dependent on this controller). This function blocks until the testbed has
1641 * been fully terminated (!). The controller status cb from
1642 * GNUNET_TESTBED_controller_start() will not be called.
1644 * @param cproc the controller process handle
1647 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1649 if (NULL != cproc->shandle)
1650 GNUNET_HELPER_send_cancel (cproc->shandle);
1651 if (NULL != cproc->helper)
1652 GNUNET_HELPER_stop (cproc->helper);
1653 if (NULL != cproc->cfg)
1654 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1655 if (NULL != cproc->helper_argv)
1656 free_argv (cproc->helper_argv);
1657 GNUNET_free (cproc);
1662 * Start a controller process using the given configuration at the
1665 * @param cfg configuration to use
1666 * @param host host to run the controller on; This should be the same host if
1667 * the controller was previously started with
1668 * GNUNET_TESTBED_controller_start; NULL for localhost
1669 * @param event_mask bit mask with set of events to call 'cc' for;
1670 * or-ed values of "1LL" shifted by the
1671 * respective 'enum GNUNET_TESTBED_EventType'
1672 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1673 * @param cc controller callback to invoke on events
1674 * @param cc_cls closure for cc
1675 * @return handle to the controller
1677 struct GNUNET_TESTBED_Controller *
1678 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1679 *cfg, struct GNUNET_TESTBED_Host *host,
1680 uint64_t event_mask,
1681 GNUNET_TESTBED_ControllerCallback cc,
1684 struct GNUNET_TESTBED_Controller *controller;
1685 struct GNUNET_TESTBED_InitMessage *msg;
1686 const char *controller_hostname;
1687 unsigned long long max_parallel_operations;
1688 unsigned long long max_parallel_service_connections;
1689 unsigned long long max_parallel_topology_config_operations;
1692 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1693 "MAX_PARALLEL_OPERATIONS",
1694 &max_parallel_operations))
1700 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1701 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1702 &max_parallel_service_connections))
1708 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1709 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1710 &max_parallel_topology_config_operations))
1715 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1716 controller->cc = cc;
1717 controller->cc_cls = cc_cls;
1718 controller->event_mask = event_mask;
1719 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1720 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1721 if (NULL == controller->client)
1723 GNUNET_TESTBED_controller_disconnect (controller);
1728 host = GNUNET_TESTBED_host_create_by_id_ (0);
1729 if (NULL == host) /* If the above host create fails */
1731 LOG (GNUNET_ERROR_TYPE_WARNING,
1732 "Treating NULL host as localhost. Multiple references to localhost "
1733 "may break when localhost freed before calling disconnect \n");
1734 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1738 controller->aux_host = GNUNET_YES;
1741 GNUNET_assert (NULL != host);
1742 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1743 controller->host = host;
1744 controller->opq_parallel_operations =
1745 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1746 max_parallel_operations);
1747 controller->opq_parallel_service_connections =
1748 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1749 max_parallel_service_connections);
1750 controller->opq_parallel_topology_config_operations=
1751 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1752 max_parallel_topology_config_operations);
1753 controller->opq_parallel_overlay_connect_operations=
1754 GNUNET_TESTBED_operation_queue_create_ (0);
1755 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (controller, 1);
1756 controller->poc_sd = SD_init (10);
1757 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1758 if (NULL == controller_hostname)
1759 controller_hostname = "127.0.0.1";
1761 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1762 strlen (controller_hostname) + 1);
1763 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1765 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1766 strlen (controller_hostname) + 1);
1767 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1768 msg->event_mask = GNUNET_htonll (controller->event_mask);
1769 strcpy ((char *) &msg[1], controller_hostname);
1770 GNUNET_TESTBED_queue_message_ (controller,
1771 (struct GNUNET_MessageHeader *) msg);
1777 * Configure shared services at a controller. Using this function,
1778 * you can specify that certain services (such as "resolver")
1779 * should not be run for each peer but instead be shared
1780 * across N peers on the specified host. This function
1781 * must be called before any peers are created at the host.
1783 * @param controller controller to configure
1784 * @param service_name name of the service to share
1785 * @param num_peers number of peers that should share one instance
1786 * of the specified service (1 for no sharing is the default),
1787 * use 0 to disable the service
1790 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1792 const char *service_name,
1795 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1796 uint16_t service_name_size;
1799 service_name_size = strlen (service_name) + 1;
1801 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1803 msg = GNUNET_malloc (msg_size);
1804 msg->header.size = htons (msg_size);
1805 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE);
1806 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1807 msg->num_peers = htonl (num_peers);
1808 memcpy (&msg[1], service_name, service_name_size);
1809 GNUNET_TESTBED_queue_message_ (controller,
1810 (struct GNUNET_MessageHeader *) msg);
1811 GNUNET_break (0); /* This function is not yet implemented on the
1817 * disconnects from the controller.
1819 * @param controller handle to controller to stop
1822 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1825 struct MessageQueue *mq_entry;
1827 if (NULL != controller->th)
1828 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1829 /* Clear the message queue */
1830 while (NULL != (mq_entry = controller->mq_head))
1832 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1834 GNUNET_free (mq_entry->msg);
1835 GNUNET_free (mq_entry);
1837 if (NULL != controller->client)
1838 GNUNET_CLIENT_disconnect (controller->client);
1839 GNUNET_CONFIGURATION_destroy (controller->cfg);
1840 if (GNUNET_YES == controller->aux_host)
1841 GNUNET_TESTBED_host_destroy (controller->host);
1842 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1843 GNUNET_TESTBED_operation_queue_destroy_
1844 (controller->opq_parallel_service_connections);
1845 GNUNET_TESTBED_operation_queue_destroy_
1846 (controller->opq_parallel_topology_config_operations);
1847 GNUNET_TESTBED_operation_queue_destroy_
1848 (controller->opq_parallel_overlay_connect_operations);
1849 SD_destroy (controller->poc_sd);
1850 GNUNET_free_non_null (controller->tslots);
1851 GNUNET_free (controller);
1856 * Register a host with the controller
1858 * @param controller the controller handle
1859 * @param host the host to register
1860 * @param cc the completion callback to call to inform the status of
1861 * registration. After calling this callback the registration handle
1862 * will be invalid. Cannot be NULL.
1863 * @param cc_cls the closure for the cc
1864 * @return handle to the host registration which can be used to cancel the
1867 struct GNUNET_TESTBED_HostRegistrationHandle *
1868 GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller,
1869 struct GNUNET_TESTBED_Host *host,
1870 GNUNET_TESTBED_HostRegistrationCompletion cc,
1873 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
1874 struct GNUNET_TESTBED_AddHostMessage *msg;
1875 const char *username;
1876 const char *hostname;
1878 uint16_t user_name_length;
1880 if (NULL != controller->rh)
1882 hostname = GNUNET_TESTBED_host_get_hostname (host);
1883 if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller))
1885 LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n",
1886 (NULL == hostname) ? "localhost" : hostname);
1889 rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
1892 GNUNET_assert (NULL != cc);
1894 rh->cc_cls = cc_cls;
1895 controller->rh = rh;
1896 username = GNUNET_TESTBED_host_get_username_ (host);
1897 msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage));
1898 user_name_length = 0;
1899 if (NULL != username)
1901 user_name_length = strlen (username) + 1;
1902 msg_size += user_name_length;
1904 /* FIXME: what happens when hostname is NULL? localhost */
1905 GNUNET_assert (NULL != hostname);
1906 msg_size += strlen (hostname) + 1;
1907 msg = GNUNET_malloc (msg_size);
1908 msg->header.size = htons (msg_size);
1909 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST);
1910 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1911 msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host));
1912 if (NULL != username)
1914 msg->user_name_length = htons (user_name_length - 1);
1915 memcpy (&msg[1], username, user_name_length);
1918 msg->user_name_length = htons (user_name_length);
1919 strcpy (((void *) &msg[1]) + user_name_length, hostname);
1920 GNUNET_TESTBED_queue_message_ (controller,
1921 (struct GNUNET_MessageHeader *) msg);
1927 * Cancel the pending registration. Note that if the registration message is
1928 * already sent to the service the cancellation has only the effect that the
1929 * registration completion callback for the registration is never called.
1931 * @param handle the registration handle to cancel
1934 GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle
1937 if (handle != handle->c->rh)
1942 handle->c->rh = NULL;
1943 GNUNET_free (handle);
1948 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1951 * @param op_cls the operation closure for the event which is generated to
1952 * signal success or failure of this operation
1953 * @param master handle to the master controller who creates the association
1954 * @param delegated_host_id id of the host to which requests should be delegated
1955 * @param slave_host_id id of the host which is used to run the slave controller
1956 * @param sxcfg serialized and compressed configuration
1957 * @param sxcfg_size the size sxcfg
1958 * @param scfg_size the size of uncompressed serialized configuration
1959 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1960 * be started by the slave controller; GNUNET_NO if the slave
1961 * controller has to connect to the already started delegated
1962 * controller via TCP/IP
1963 * @return the operation handle
1965 struct GNUNET_TESTBED_Operation *
1966 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1967 struct GNUNET_TESTBED_Controller *master,
1968 uint32_t delegated_host_id,
1969 uint32_t slave_host_id,
1970 const char *sxcfg, size_t sxcfg_size,
1971 size_t scfg_size, int is_subordinate)
1973 struct OperationContext *opc;
1974 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1975 struct ControllerLinkData *data;
1978 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1979 msg = GNUNET_malloc (msg_size);
1980 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS);
1981 msg->header.size = htons (msg_size);
1982 msg->delegated_host_id = htonl (delegated_host_id);
1983 msg->slave_host_id = htonl (slave_host_id);
1984 msg->config_size = htons ((uint16_t) scfg_size);
1985 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1986 memcpy (&msg[1], sxcfg, sxcfg_size);
1987 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1989 opc = GNUNET_malloc (sizeof (struct OperationContext));
1992 opc->type = OP_LINK_CONTROLLERS;
1993 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1994 opc->state = OPC_STATE_INIT;
1995 opc->op_cls = op_cls;
1996 msg->operation_id = GNUNET_htonll (opc->id);
1998 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1999 &oprelease_link_controllers);
2000 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2002 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2008 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
2009 * serialized and compressed
2011 * @param op_cls the operation closure for the event which is generated to
2012 * signal success or failure of this operation
2013 * @param master handle to the master controller who creates the association
2014 * @param delegated_host requests to which host should be delegated; cannot be NULL
2015 * @param slave_host which host is used to run the slave controller; use NULL to
2016 * make the master controller connect to the delegated host
2017 * @param sxcfg serialized and compressed configuration
2018 * @param sxcfg_size the size sxcfg
2019 * @param scfg_size the size of uncompressed serialized configuration
2020 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2021 * be started by the slave controller; GNUNET_NO if the slave
2022 * controller has to connect to the already started delegated
2023 * controller via TCP/IP
2024 * @return the operation handle
2026 struct GNUNET_TESTBED_Operation *
2027 GNUNET_TESTBED_controller_link_2 (void *op_cls,
2028 struct GNUNET_TESTBED_Controller *master,
2029 struct GNUNET_TESTBED_Host *delegated_host,
2030 struct GNUNET_TESTBED_Host *slave_host,
2031 const char *sxcfg, size_t sxcfg_size,
2032 size_t scfg_size, int is_subordinate)
2034 uint32_t delegated_host_id;
2035 uint32_t slave_host_id;
2037 GNUNET_assert (GNUNET_YES ==
2038 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
2039 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
2041 GNUNET_TESTBED_host_get_id_ ((NULL != slave_host)
2042 ? slave_host : master->host);
2043 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
2044 GNUNET_assert (GNUNET_YES ==
2045 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
2047 return GNUNET_TESTBED_controller_link_2_ (op_cls,
2052 scfg_size, is_subordinate);
2057 * Compresses given configuration using zlib compress
2059 * @param config the serialized configuration
2060 * @param size the size of config
2061 * @param xconfig will be set to the compressed configuration (memory is fresly
2063 * @return the size of the xconfig
2066 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
2071 xsize = compressBound ((uLong) size);
2072 *xconfig = GNUNET_malloc (xsize);
2073 GNUNET_assert (Z_OK ==
2074 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
2075 (const Bytef *) config, (uLongf) size,
2082 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
2085 * @param op_cls the operation closure for the event which is generated to
2086 * signal success or failure of this operation
2087 * @param master handle to the master controller who creates the association
2088 * @param delegated_host_id id of the host to which requests should be
2089 * delegated; cannot be NULL
2090 * @param slave_host_id id of the host which should connect to controller
2091 * running on delegated host ; use NULL to make the master controller
2092 * connect to the delegated host
2093 * @param slave_cfg configuration to use for the slave controller
2094 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2095 * be started by the slave controller; GNUNET_NO if the slave
2096 * controller has to connect to the already started delegated
2097 * controller via TCP/IP
2098 * @return the operation handle
2100 struct GNUNET_TESTBED_Operation *
2101 GNUNET_TESTBED_controller_link_ (void *op_cls,
2102 struct GNUNET_TESTBED_Controller *master,
2103 uint32_t delegated_host_id,
2104 uint32_t slave_host_id,
2105 const struct GNUNET_CONFIGURATION_Handle
2109 struct GNUNET_TESTBED_Operation *op;
2115 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
2116 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
2117 GNUNET_free (config);
2118 /* Configuration doesn't fit in 1 message */
2119 GNUNET_assert ((UINT16_MAX -
2120 sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
2122 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
2123 slave_host_id, (const char *) cconfig,
2124 cc_size, config_size, is_subordinate);
2125 GNUNET_free (cconfig);
2131 * Create a link from slave controller to delegated controller. Whenever the
2132 * master controller is asked to start a peer at the delegated controller the
2133 * request will be routed towards slave controller (if a route exists). The
2134 * slave controller will then route it to the delegated controller. The
2135 * configuration of the delegated controller is given and is used to either
2136 * create the delegated controller or to connect to an existing controller. Note
2137 * that while starting the delegated controller the configuration will be
2138 * modified to accommodate available free ports. the 'is_subordinate' specifies
2139 * if the given delegated controller should be started and managed by the slave
2140 * controller, or if the delegated controller already has a master and the slave
2141 * controller connects to it as a non master controller. The success or failure
2142 * of this operation will be signalled through the
2143 * GNUNET_TESTBED_ControllerCallback() with an event of type
2144 * GNUNET_TESTBED_ET_OPERATION_FINISHED
2146 * @param op_cls the operation closure for the event which is generated to
2147 * signal success or failure of this operation
2148 * @param master handle to the master controller who creates the association
2149 * @param delegated_host requests to which host should be delegated; cannot be NULL
2150 * @param slave_host which host is used to run the slave controller; use NULL to
2151 * make the master controller connect to the delegated host
2152 * @param slave_cfg configuration to use for the slave controller
2153 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2154 * be started by the slave controller; GNUNET_NO if the slave
2155 * controller has to connect to the already started delegated
2156 * controller via TCP/IP
2157 * @return the operation handle
2159 struct GNUNET_TESTBED_Operation *
2160 GNUNET_TESTBED_controller_link (void *op_cls,
2161 struct GNUNET_TESTBED_Controller *master,
2162 struct GNUNET_TESTBED_Host *delegated_host,
2163 struct GNUNET_TESTBED_Host *slave_host,
2164 const struct GNUNET_CONFIGURATION_Handle
2165 *slave_cfg, int is_subordinate)
2167 uint32_t slave_host_id;
2168 uint32_t delegated_host_id;
2170 GNUNET_assert (GNUNET_YES ==
2171 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
2173 GNUNET_TESTBED_host_get_id_ ((NULL != slave_host)
2174 ? slave_host : master->host);
2175 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
2176 if ((NULL != slave_host) && (0 != slave_host_id))
2177 GNUNET_assert (GNUNET_YES ==
2178 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
2179 return GNUNET_TESTBED_controller_link_ (op_cls, master,
2189 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
2190 * check. Another difference is that this function takes the id of the slave
2193 * @param op_cls the closure for the operation
2194 * @param master the handle to master controller
2195 * @param slave_host_id id of the host where the slave controller is running to
2196 * the slave_host should remain valid until this operation is cancelled
2197 * or marked as finished
2198 * @return the operation handle;
2200 struct GNUNET_TESTBED_Operation *
2201 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
2202 struct GNUNET_TESTBED_Controller *master,
2203 uint32_t slave_host_id)
2205 struct OperationContext *opc;
2206 struct GetSlaveConfigData *data;
2208 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
2209 data->slave_id = slave_host_id;
2210 opc = GNUNET_malloc (sizeof (struct OperationContext));
2211 opc->state = OPC_STATE_INIT;
2213 opc->id = GNUNET_TESTBED_get_next_op_id (master);
2214 opc->type = OP_GET_SLAVE_CONFIG;
2216 opc->op_cls = op_cls;
2218 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
2219 &oprelease_get_slave_config);
2220 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2222 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2228 * Function to acquire the configuration of a running slave controller. The
2229 * completion of the operation is signalled through the controller_cb from
2230 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
2231 * handle to the configuration is available in the generic pointer of
2232 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
2234 * @param op_cls the closure for the operation
2235 * @param master the handle to master controller
2236 * @param slave_host the host where the slave controller is running; the handle
2237 * to the slave_host should remain valid until this operation is
2238 * cancelled or marked as finished
2239 * @return the operation handle; NULL if the slave_host is not registered at
2242 struct GNUNET_TESTBED_Operation *
2243 GNUNET_TESTBED_get_slave_config (void *op_cls,
2244 struct GNUNET_TESTBED_Controller *master,
2245 struct GNUNET_TESTBED_Host *slave_host)
2247 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
2249 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
2250 GNUNET_TESTBED_host_get_id_ (slave_host));
2255 * Ask the testbed controller to write the current overlay topology to
2256 * a file. Naturally, the file will only contain a snapshot as the
2257 * topology may evolve all the time.
2259 * @param controller overlay controller to inspect
2260 * @param filename name of the file the topology should
2264 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
2266 const char *filename)
2273 * Creates a helper initialization message. This function is here because we
2274 * want to use this in testing
2276 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
2277 * HOST(all connections form this ip are permitted by the testbed) when
2278 * starting testbed controller at host. This can either be a single ip
2279 * address or a network address in CIDR notation.
2280 * @param hostname the hostname of the destination this message is intended for
2281 * @param cfg the configuration that has to used to start the testbed service
2283 * @return the initialization message
2285 struct GNUNET_TESTBED_HelperInit *
2286 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
2287 const char *hostname,
2288 const struct GNUNET_CONFIGURATION_Handle
2291 struct GNUNET_TESTBED_HelperInit *msg;
2295 size_t xconfig_size;
2296 uint16_t trusted_ip_len;
2297 uint16_t hostname_len;
2300 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
2301 GNUNET_assert (NULL != config);
2303 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
2304 GNUNET_free (config);
2305 trusted_ip_len = strlen (trusted_ip);
2306 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2308 xconfig_size + trusted_ip_len + 1 + sizeof (struct GNUNET_TESTBED_HelperInit);
2309 msg_size += hostname_len;
2310 msg = GNUNET_realloc (xconfig, msg_size);
2311 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len,
2314 msg->header.size = htons (msg_size);
2315 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2316 msg->trusted_ip_size = htons (trusted_ip_len);
2317 msg->hostname_size = htons (hostname_len);
2318 msg->config_size = htons (config_size);
2319 (void) strcpy ((char *) &msg[1], trusted_ip);
2320 if (0 != hostname_len)
2321 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname, hostname_len);
2327 * Cancel a pending operation. Releases all resources
2328 * of the operation and will ensure that no event
2329 * is generated for the operation. Does NOT guarantee
2330 * that the operation will be fully undone (or that
2331 * nothing ever happened).
2333 * @param operation operation to cancel
2336 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
2338 GNUNET_TESTBED_operation_done (operation);
2343 * Signal that the information from an operation has been fully
2344 * processed. This function MUST be called for each event
2345 * of type 'operation_finished' to fully remove the operation
2346 * from the operation queue. After calling this function, the
2347 * 'op_result' becomes invalid (!).
2349 * @param operation operation to signal completion for
2352 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2354 GNUNET_TESTBED_operation_release_ (operation);
2359 * Generates configuration by uncompressing configuration in given message. The
2360 * given message should be of the following types:
2361 * GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG,
2362 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG
2364 * @param msg the message containing compressed configuration
2365 * @return handle to the parsed configuration
2367 struct GNUNET_CONFIGURATION_Handle *
2368 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2370 struct GNUNET_CONFIGURATION_Handle *cfg;
2377 switch (ntohs (msg->type))
2379 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
2381 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2383 imsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2385 data_len = (uLong) ntohs (imsg->config_size);
2386 xdata_len = ntohs (imsg->header.size)
2387 - sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2388 xdata = (const Bytef *) &imsg[1];
2391 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG:
2393 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2395 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2396 data_len = (uLong) ntohs (imsg->config_size);
2397 xdata_len = ntohs (imsg->header.size)
2398 - sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2399 xdata = (const Bytef *) &imsg[1];
2405 data = GNUNET_malloc (data_len);
2408 uncompress (data, &data_len, xdata, xdata_len)))
2410 cfg = GNUNET_CONFIGURATION_create ();
2411 GNUNET_assert (GNUNET_OK ==
2412 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2421 * Checks the integrity of the OperationFailureEventMessage and if good returns
2422 * the error message it contains.
2424 * @param msg the OperationFailureEventMessage
2425 * @return the error message
2428 GNUNET_TESTBED_parse_error_string_ (const struct
2429 GNUNET_TESTBED_OperationFailureEventMessage
2435 msize = ntohs (msg->header.size);
2436 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2438 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2439 emsg = (const char *) &msg[1];
2440 if ('\0' != emsg[msize - 1])
2450 * Function to return the operation id for a controller. The operation id is
2451 * created from the controllers host id and its internal operation counter.
2453 * @param controller the handle to the controller whose operation id has to be incremented
2454 * @return the incremented operation id.
2457 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller)
2461 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2462 op_id = op_id << 32;
2463 op_id |= (uint64_t) controller->operation_counter++;
2469 * Returns a timing slot which will be exclusively locked
2471 * @param c the controller handle
2472 * @return the time slot index in the array of time slots in the controller
2476 GNUNET_TESTBED_get_tslot_ (struct GNUNET_TESTBED_Controller *c, void *key)
2480 GNUNET_assert (NULL != c->tslots);
2481 GNUNET_assert (NULL != key);
2482 for (slot = 0; slot < c->num_parallel_connects; slot++)
2483 if (NULL == c->tslots[slot].key)
2485 c->tslots[slot].key = key;
2488 GNUNET_assert (0); /* We should always find a free tslot */
2493 decide_npoc (struct GNUNET_TESTBED_Controller *c)
2495 struct GNUNET_TIME_Relative avg;
2499 if (c->tslots_filled != c->num_parallel_connects)
2501 avg = GNUNET_TIME_UNIT_ZERO;
2502 for (slot = 0; slot < c->num_parallel_connects; slot++)
2503 avg = GNUNET_TIME_relative_add (avg, c->tslots[slot].time);
2504 avg = GNUNET_TIME_relative_divide (avg, c->num_parallel_connects);
2505 GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value != avg.rel_value);
2506 sd = SD_deviation_factor (c->poc_sd, (unsigned int) avg.rel_value);
2507 if (GNUNET_SYSERR == sd)
2509 SD_add_data (c->poc_sd, (unsigned int) avg.rel_value);
2510 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (c, c->num_parallel_connects);
2513 GNUNET_assert (0 <= sd);
2516 SD_add_data (c->poc_sd, (unsigned int) avg.rel_value);
2517 GNUNET_TESTBED_set_num_parallel_overlay_connects_
2518 (c, c->num_parallel_connects * 2);
2521 if (1 == c->num_parallel_connects)
2523 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (c, 1);
2526 GNUNET_TESTBED_set_num_parallel_overlay_connects_
2527 (c, c->num_parallel_connects / 2);
2532 GNUNET_TESTBED_release_time_slot_ (struct GNUNET_TESTBED_Controller *c,
2536 struct TimeSlot *slot;
2538 GNUNET_assert (NULL != key);
2539 if (index >= c->num_parallel_connects)
2541 slot = &c->tslots[index];
2542 if (key != slot->key)
2550 * Function to update a time slot
2552 * @param c the controller handle
2553 * @param index the index of the time slot to update
2554 * @param time the new time
2557 GNUNET_TESTBED_update_time_slot_ (struct GNUNET_TESTBED_Controller *c,
2560 struct GNUNET_TIME_Relative time)
2562 struct GNUNET_TIME_Relative avg;
2563 struct TimeSlot *slot;
2565 if (GNUNET_NO == GNUNET_TESTBED_release_time_slot_ (c, index, key))
2567 slot = &c->tslots[index];
2568 if (GNUNET_TIME_UNIT_ZERO.rel_value == slot->time.rel_value)
2575 avg = GNUNET_TIME_relative_add (slot->time, time);
2576 avg = GNUNET_TIME_relative_divide (avg, 2);
2581 /* end of testbed_api.c */