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;
315 * Initialize standard deviation calculation handle
317 * @param max_cnt the maximum number of readings to keep
318 * @return the initialized handle
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;
333 * Frees the memory allocated to the SD handle
335 * @param h the SD handle
338 SD_destroy (struct SDHandle *h)
340 struct SDEntry *entry;
342 while (NULL != (entry = h->head))
344 GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry);
352 * Add a reading to SD
354 * @param h the SD handle
355 * @param amount the reading value
358 SD_add_data (struct SDHandle *h, unsigned int amount)
360 struct SDEntry *entry;
365 if (h->cnt == h->max_cnt)
368 GNUNET_CONTAINER_DLL_remove (h->head, h->tail, entry);
369 h->sum -= entry->amount;
370 h->sqsum -= ((unsigned long) entry->amount) *
371 ((unsigned long) entry->amount);
374 GNUNET_assert (h->cnt < h->max_cnt);
376 entry = GNUNET_malloc (sizeof (struct SDEntry));
377 entry->amount = amount;
378 GNUNET_CONTAINER_DLL_insert_tail (h->head, h->tail, entry);
381 h->avg = ((float) h->sum) / ((float) h->cnt);
382 h->sqsum += ((unsigned long) amount) * ((unsigned long) amount);
383 sqsum_avg = ((double) h->sqsum) / ((double) h->cnt);
384 sqavg = ((double) h->avg) * ((double) h->avg);
385 h->vr = sqsum_avg - sqavg;
390 * Returns the factor by which the given amount differs from the standard deviation
392 * @param h the SDhandle
393 * @param amount the value for which the deviation is returned
395 * @return the deviation from the average; GNUNET_SYSERR if the deviation cannot
396 * be calculated OR 0 if the deviation is less than the average; a
397 * maximum of 4 is returned for deviations equal to or larger than 4
400 SD_deviation_factor (struct SDHandle *h, unsigned int amount)
406 return GNUNET_SYSERR;
407 if (((float) amount) > h->avg)
408 diff = ((float) amount) - h->avg;
410 return 0; //diff = h->avg - ((float) amount);
412 for (n = 1; n < 4; n++)
413 if (diff < (((double) (n * n)) * h->vr))
420 * Returns the operation context with the given id if found in the Operation
421 * context queues of the controller
423 * @param c the controller whose queues are searched
424 * @param id the id which has to be checked
425 * @return the matching operation context; NULL if no match found
427 static struct OperationContext *
428 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
430 struct OperationContext *opc;
432 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
442 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
443 * controller (testbed service)
445 * @param c the controller handler
446 * @param msg message received
447 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
451 handle_addhostconfirm (struct GNUNET_TESTBED_Controller *c,
452 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
454 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
463 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
465 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
466 GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
470 msg_size = ntohs (msg->header.size);
471 if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
473 LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
474 GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
475 rh->cc (rh->cc_cls, NULL);
479 /* We have an error message */
480 emsg = (char *) &msg[1];
482 emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
488 LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
489 ntohl (msg->host_id), emsg);
490 rh->cc (rh->cc_cls, emsg);
497 * Handler for forwarded operations
499 * @param c the controller handle
500 * @param opc the opearation context
501 * @param msg the message
504 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
505 struct OperationContext *opc,
506 const struct GNUNET_MessageHeader *msg)
508 struct ForwardedOperationData *fo_data;
511 if (NULL != fo_data->cc)
512 fo_data->cc (fo_data->cc_cls, msg);
513 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
514 GNUNET_free (fo_data);
520 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
521 * controller (testbed service)
523 * @param c the controller handler
524 * @param msg message received
525 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
529 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
531 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
533 struct OperationContext *opc;
534 struct GNUNET_TESTBED_EventInformation event;
537 op_id = GNUNET_ntohll (msg->operation_id);
538 LOG_DEBUG ("Operation %lu successful\n", op_id);
539 if (NULL == (opc = find_opc (c, op_id)))
541 LOG_DEBUG ("Operation not found\n");
544 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
545 event.details.operation_finished.operation = opc->op;
546 event.details.operation_finished.op_cls = opc->op_cls;
547 event.details.operation_finished.emsg = NULL;
548 event.details.operation_finished.generic = NULL;
553 handle_forwarded_operation_msg
554 (c, opc, (const struct GNUNET_MessageHeader *) msg);
558 case OP_PEER_DESTROY:
560 struct GNUNET_TESTBED_Peer *peer;
568 case OP_LINK_CONTROLLERS:
570 struct ControllerLinkData *data;
573 GNUNET_assert (NULL != data);
581 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
582 opc->state = OPC_STATE_FINISHED;
583 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
586 c->cc (c->cc_cls, &event);
589 LOG_DEBUG ("Not calling callback\n");
595 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
596 * controller (testbed service)
598 * @param c the controller handle
599 * @param msg message received
600 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
604 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
606 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
608 struct OperationContext *opc;
609 struct PeerCreateData *data;
610 struct GNUNET_TESTBED_Peer *peer;
611 GNUNET_TESTBED_PeerCreateCallback cb;
615 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
616 ntohs (msg->header.size));
617 op_id = GNUNET_ntohll (msg->operation_id);
618 if (NULL == (opc = find_opc (c, op_id)))
620 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
623 if (OP_FORWARDED == opc->type)
625 handle_forwarded_operation_msg (c, opc,
626 (const struct GNUNET_MessageHeader *) msg);
629 GNUNET_assert (OP_PEER_CREATE == opc->type);
630 GNUNET_assert (NULL != opc->data);
632 GNUNET_assert (NULL != data->peer);
634 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
635 peer->state = PS_CREATED;
638 GNUNET_free (opc->data);
639 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
640 opc->state = OPC_STATE_FINISHED;
642 cb (cls, peer, NULL);
648 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
649 * controller (testbed service)
651 * @param c the controller handler
652 * @param msg message received
653 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
657 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
658 const struct GNUNET_TESTBED_PeerEventMessage *msg)
660 struct OperationContext *opc;
661 struct GNUNET_TESTBED_Peer *peer;
662 struct PeerEventData *data;
663 GNUNET_TESTBED_PeerChurnCallback pcc;
665 struct GNUNET_TESTBED_EventInformation event;
668 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
669 ntohs (msg->header.size));
670 op_id = GNUNET_ntohll (msg->operation_id);
671 if (NULL == (opc = find_opc (c, op_id)))
673 LOG_DEBUG ("Operation not found\n");
676 if (OP_FORWARDED == opc->type)
678 handle_forwarded_operation_msg (c, opc,
679 (const struct GNUNET_MessageHeader *) msg);
682 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
684 GNUNET_assert (NULL != data);
686 GNUNET_assert (NULL != peer);
687 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
690 case GNUNET_TESTBED_ET_PEER_START:
691 peer->state = PS_STARTED;
692 event.details.peer_start.host = peer->host;
693 event.details.peer_start.peer = peer;
695 case GNUNET_TESTBED_ET_PEER_STOP:
696 peer->state = PS_STOPPED;
697 event.details.peer_stop.peer = peer;
700 GNUNET_assert (0); /* We should never reach this state */
703 pcc_cls = data->pcc_cls;
705 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
706 opc->state = OPC_STATE_FINISHED;
708 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
712 c->cc (c->cc_cls, &event);
721 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
722 * controller (testbed service)
724 * @param c the controller handler
725 * @param msg message received
726 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
730 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
731 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
733 struct OperationContext *opc;
734 struct OverlayConnectData *data;
735 GNUNET_TESTBED_OperationCompletionCallback cb;
737 struct GNUNET_TESTBED_EventInformation event;
740 op_id = GNUNET_ntohll (msg->operation_id);
741 if (NULL == (opc = find_opc (c, op_id)))
743 LOG_DEBUG ("Operation not found\n");
746 if (OP_FORWARDED == opc->type)
748 handle_forwarded_operation_msg (c, opc,
749 (const struct GNUNET_MessageHeader *) msg);
752 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
754 GNUNET_assert (NULL != data);
755 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
756 (ntohl (msg->peer2) == data->p2->unique_id));
757 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
760 case GNUNET_TESTBED_ET_CONNECT:
761 event.details.peer_connect.peer1 = data->p1;
762 event.details.peer_connect.peer2 = data->p2;
764 case GNUNET_TESTBED_ET_DISCONNECT:
765 GNUNET_assert (0); /* FIXME: implement */
768 GNUNET_assert (0); /* Should never reach here */
772 cb_cls = data->cb_cls;
773 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
774 opc->state = OPC_STATE_FINISHED;
776 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
780 c->cc (c->cc_cls, &event);
783 cb (cb_cls, opc->op, NULL);
789 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
790 * controller (testbed service)
792 * @param c the controller handler
793 * @param msg message received
794 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
798 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
800 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
802 struct OperationContext *opc;
803 struct GNUNET_TESTBED_Peer *peer;
804 struct PeerInfoData *data;
805 struct GNUNET_TESTBED_PeerInformation *pinfo;
806 GNUNET_TESTBED_PeerInfoCallback cb;
810 op_id = GNUNET_ntohll (msg->operation_id);
811 if (NULL == (opc = find_opc (c, op_id)))
813 LOG_DEBUG ("Operation not found\n");
816 if (OP_FORWARDED == opc->type)
818 handle_forwarded_operation_msg (c, opc,
819 (const struct GNUNET_MessageHeader *) msg);
823 GNUNET_assert (NULL != data);
825 GNUNET_assert (NULL != peer);
826 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
827 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
828 pinfo->pit = data->pit;
830 cb_cls = data->cb_cls;
835 case GNUNET_TESTBED_PIT_IDENTITY:
836 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
837 (void) memcpy (pinfo->result.id, &msg->peer_identity,
838 sizeof (struct GNUNET_PeerIdentity));
840 case GNUNET_TESTBED_PIT_CONFIGURATION:
841 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
842 GNUNET_TESTBED_extract_config_ (&msg->header);
844 case GNUNET_TESTBED_PIT_GENERIC:
845 GNUNET_assert (0); /* never reach here */
849 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
850 opc->state = OPC_STATE_FINISHED;
852 cb (cb_cls, opc->op, pinfo, NULL);
858 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
859 * controller (testbed service)
861 * @param c the controller handler
862 * @param msg message received
863 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
867 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
868 const struct GNUNET_TESTBED_OperationFailureEventMessage
871 struct OperationContext *opc;
874 struct GNUNET_TESTBED_EventInformation event;
876 op_id = GNUNET_ntohll (msg->operation_id);
877 if (NULL == (opc = find_opc (c, op_id)))
879 LOG_DEBUG ("Operation not found\n");
882 if (OP_FORWARDED == opc->type)
884 handle_forwarded_operation_msg (c, opc,
885 (const struct GNUNET_MessageHeader *) msg);
888 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
889 opc->state = OPC_STATE_FINISHED;
890 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
892 emsg = "Unknown error";
893 if (OP_PEER_INFO == opc->type)
895 struct PeerInfoData *data;
897 if (NULL != data->cb)
898 data->cb (data->cb_cls, opc->op, NULL, emsg);
900 return GNUNET_YES; /* We do not call controller callback for peer info */
902 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
905 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
906 event.details.operation_finished.operation = opc->op;
907 event.details.operation_finished.op_cls = opc->op_cls;
908 event.details.operation_finished.emsg = emsg;
909 event.details.operation_finished.generic = NULL;
910 c->cc (c->cc_cls, &event);
916 struct PeerCreateData *data;
918 GNUNET_free (data->peer);
919 if (NULL != data->cb)
920 data->cb (data->cls, NULL, emsg);
927 struct PeerEventData *data;
929 if (NULL != data->pcc)
930 data->pcc (data->pcc_cls, emsg);
934 case OP_PEER_DESTROY:
938 case OP_OVERLAY_CONNECT:
940 struct OverlayConnectData *data;
942 if (NULL != data->cb)
943 data->cb (data->cb_cls, opc->op, emsg);
948 case OP_LINK_CONTROLLERS: /* No secondary callback */
958 * Function to build GET_SLAVE_CONFIG message
960 * @param op_id the id this message should contain in its operation id field
961 * @param slave_id the id this message should contain in its slave id field
962 * @return newly allocated SlaveGetConfigurationMessage
964 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
965 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
967 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
970 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
971 msg = GNUNET_malloc (msize);
972 msg->header.size = htons (msize);
973 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG);
974 msg->operation_id = GNUNET_htonll (op_id);
975 msg->slave_id = htonl (slave_id);
981 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
984 * @param c the controller handler
985 * @param msg message received
986 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
990 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
991 const struct GNUNET_TESTBED_SlaveConfiguration * msg)
993 struct OperationContext *opc;
995 struct GNUNET_TESTBED_EventInformation event;
997 op_id = GNUNET_ntohll (msg->operation_id);
998 if (NULL == (opc = find_opc (c, op_id)))
1000 LOG_DEBUG ("Operation not found\n");
1003 if (OP_GET_SLAVE_CONFIG != opc->type)
1008 GNUNET_free (opc->data);
1010 opc->state = OPC_STATE_FINISHED;
1011 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1012 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
1015 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
1016 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
1017 event.details.operation_finished.generic = opc->data;
1018 event.details.operation_finished.operation = opc->op;
1019 event.details.operation_finished.op_cls = opc->op_cls;
1020 event.details.operation_finished.emsg = NULL;
1021 c->cc (c->cc_cls, &event);
1028 * Handler for messages from controller (testbed service)
1030 * @param cls the controller handler
1031 * @param msg message received, NULL on timeout or fatal error
1034 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
1036 struct GNUNET_TESTBED_Controller *c = cls;
1040 c->in_receive = GNUNET_NO;
1041 /* FIXME: Add checks for message integrity */
1044 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
1048 msize = ntohs (msg->size);
1049 switch (ntohs (msg->type))
1051 case GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM:
1052 GNUNET_assert (msize >=
1053 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
1055 handle_addhostconfirm (c,
1056 (const struct GNUNET_TESTBED_HostConfirmedMessage
1059 case GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS:
1060 GNUNET_assert (msize ==
1062 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
1064 handle_opsuccess (c,
1066 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
1069 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS:
1070 GNUNET_assert (msize ==
1072 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
1074 handle_peer_create_success (c,
1076 GNUNET_TESTBED_PeerCreateSuccessEventMessage
1079 case GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT:
1080 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
1082 handle_peer_event (c,
1083 (const struct GNUNET_TESTBED_PeerEventMessage *)
1087 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
1088 GNUNET_assert (msize >=
1090 GNUNET_TESTBED_PeerConfigurationInformationMessage));
1092 handle_peer_config (c,
1094 GNUNET_TESTBED_PeerConfigurationInformationMessage
1097 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT:
1098 GNUNET_assert (msize ==
1099 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1101 handle_peer_conevent (c,
1103 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1105 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT:
1106 GNUNET_assert (msize >=
1107 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
1109 handle_op_fail_event (c,
1111 GNUNET_TESTBED_OperationFailureEventMessage *)
1114 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG:
1115 GNUNET_assert (msize >
1116 sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1118 handle_slave_config (c, (const struct
1119 GNUNET_TESTBED_SlaveConfiguration *) msg);
1124 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1126 c->in_receive = GNUNET_YES;
1127 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1128 GNUNET_TIME_UNIT_FOREVER_REL);
1134 * Function called to notify a client about the connection begin ready to queue
1135 * more data. "buf" will be NULL and "size" zero if the connection was closed
1136 * for writing in the meantime.
1138 * @param cls closure
1139 * @param size number of bytes available in buf
1140 * @param buf where the callee should write the message
1141 * @return number of bytes written to buf
1144 transmit_ready_notify (void *cls, size_t size, void *buf)
1146 struct GNUNET_TESTBED_Controller *c = cls;
1147 struct MessageQueue *mq_entry;
1150 mq_entry = c->mq_head;
1151 GNUNET_assert (NULL != mq_entry);
1152 if ((0 == size) && (NULL == buf)) /* Timeout */
1154 LOG_DEBUG ("Message sending timed out -- retrying\n");
1156 GNUNET_CLIENT_notify_transmit_ready (c->client,
1157 ntohs (mq_entry->msg->size),
1158 TIMEOUT_REL, GNUNET_YES,
1159 &transmit_ready_notify, c);
1162 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1163 size = ntohs (mq_entry->msg->size);
1164 memcpy (buf, mq_entry->msg, size);
1165 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1166 ntohs (mq_entry->msg->type), size);
1167 GNUNET_free (mq_entry->msg);
1168 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1169 GNUNET_free (mq_entry);
1170 mq_entry = c->mq_head;
1171 if (NULL != mq_entry)
1173 GNUNET_CLIENT_notify_transmit_ready (c->client,
1174 ntohs (mq_entry->msg->size),
1175 TIMEOUT_REL, GNUNET_YES,
1176 &transmit_ready_notify, c);
1177 if (GNUNET_NO == c->in_receive)
1179 c->in_receive = GNUNET_YES;
1180 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1181 GNUNET_TIME_UNIT_FOREVER_REL);
1188 * Queues a message in send queue for sending to the service
1190 * @param controller the handle to the controller
1191 * @param msg the message to queue
1194 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1195 struct GNUNET_MessageHeader *msg)
1197 struct MessageQueue *mq_entry;
1201 type = ntohs (msg->type);
1202 size = ntohs (msg->size);
1203 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1204 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1205 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1206 mq_entry->msg = msg;
1207 LOG (GNUNET_ERROR_TYPE_DEBUG,
1208 "Queueing message of type %u, size %u for sending\n", type,
1210 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1212 if (NULL == controller->th)
1214 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1215 TIMEOUT_REL, GNUNET_YES,
1216 &transmit_ready_notify,
1222 * Sends the given message as an operation. The given callback is called when a
1223 * reply for the operation is available. Call
1224 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1225 * operation context if the cc hasn't been called
1227 * @param controller the controller to which the message has to be sent
1228 * @param operation_id the operation id of the message
1229 * @param msg the message to send
1230 * @param cc the callback to call when reply is available
1231 * @param cc_cls the closure for the above callback
1232 * @return the operation context which can be used to cancel the forwarded
1235 struct OperationContext *
1236 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1237 *controller, uint64_t operation_id,
1238 const struct GNUNET_MessageHeader *msg,
1239 GNUNET_CLIENT_MessageHandler cc,
1242 struct OperationContext *opc;
1243 struct ForwardedOperationData *data;
1244 struct GNUNET_MessageHeader *dup_msg;
1247 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1249 data->cc_cls = cc_cls;
1250 opc = GNUNET_malloc (sizeof (struct OperationContext));
1251 opc->c = controller;
1252 opc->type = OP_FORWARDED;
1254 opc->id = operation_id;
1255 msize = ntohs (msg->size);
1256 dup_msg = GNUNET_malloc (msize);
1257 (void) memcpy (dup_msg, msg, msize);
1258 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1259 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1266 * Function to cancel an operation created by simply forwarding an operation
1269 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1272 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1274 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1275 GNUNET_free (opc->data);
1281 * Functions with this signature are called whenever a
1282 * complete message is received by the tokenizer.
1284 * Do not call GNUNET_SERVER_mst_destroy in callback
1286 * @param cls closure
1287 * @param client identification of the client
1288 * @param message the actual message
1290 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1293 helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1295 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1296 const struct GNUNET_TESTBED_HelperReply *msg;
1297 const char *hostname;
1300 uLongf xconfig_size;
1302 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1303 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1304 ntohs (msg->header.size));
1305 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1306 ntohs (msg->header.type));
1307 config_size = (uLongf) ntohs (msg->config_size);
1309 (uLongf) (ntohs (msg->header.size) -
1310 sizeof (struct GNUNET_TESTBED_HelperReply));
1311 config = GNUNET_malloc (config_size);
1312 GNUNET_assert (Z_OK ==
1313 uncompress ((Bytef *) config, &config_size,
1314 (const Bytef *) &msg[1], xconfig_size));
1315 GNUNET_assert (NULL == cp->cfg);
1316 cp->cfg = GNUNET_CONFIGURATION_create ();
1317 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1318 (cp->cfg, config, config_size, GNUNET_NO));
1319 GNUNET_free (config);
1320 if ((NULL == cp->host) ||
1321 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
1322 hostname = "localhost";
1323 /* Change the hostname so that we can connect to it */
1324 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1326 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1332 * Continuation function from GNUNET_HELPER_send()
1334 * @param cls closure
1335 * @param result GNUNET_OK on success,
1336 * GNUNET_NO if helper process died
1337 * GNUNET_SYSERR during GNUNET_HELPER_stop
1340 clear_msg (void *cls, int result)
1342 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1344 GNUNET_assert (NULL != cp->shandle);
1346 GNUNET_free (cp->msg);
1351 * Callback that will be called when the helper process dies. This is not called
1352 * when the helper process is stoped using GNUNET_HELPER_stop()
1354 * @param cls the closure from GNUNET_HELPER_start()
1357 helper_exp_cb (void *cls)
1359 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1360 GNUNET_TESTBED_ControllerStatusCallback cb;
1366 GNUNET_TESTBED_controller_stop (cp);
1368 cb (cb_cls, NULL, GNUNET_SYSERR);
1373 * Function to call to start a link-controllers type operation once all queues
1374 * the operation is part of declare that the operation can be activated.
1376 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1379 opstart_link_controllers (void *cls)
1381 struct OperationContext *opc = cls;
1382 struct ControllerLinkData *data;
1383 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1385 GNUNET_assert (NULL != opc->data);
1389 opc->state = OPC_STATE_STARTED;
1390 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1391 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1396 * Callback which will be called when link-controllers type operation is released
1398 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1401 oprelease_link_controllers (void *cls)
1403 struct OperationContext *opc = cls;
1404 struct ControllerLinkData *data;
1409 case OPC_STATE_INIT:
1410 GNUNET_free (data->msg);
1412 case OPC_STATE_STARTED:
1413 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1415 case OPC_STATE_FINISHED:
1418 GNUNET_free_non_null (data);
1424 * Function to be called when get slave config operation is ready
1426 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1429 opstart_get_slave_config (void *cls)
1431 struct OperationContext *opc = cls;
1432 struct GetSlaveConfigData *data;
1433 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1436 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1437 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1438 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1439 opc->state = OPC_STATE_STARTED;
1444 * Function to be called when get slave config operation is cancelled or finished
1446 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1449 oprelease_get_slave_config (void *cls)
1451 struct OperationContext *opc = cls;
1455 case OPC_STATE_INIT:
1456 GNUNET_free (opc->data);
1458 case OPC_STATE_STARTED:
1459 GNUNET_free (opc->data);
1460 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1462 case OPC_STATE_FINISHED:
1463 if (NULL != opc->data)
1464 GNUNET_CONFIGURATION_destroy (opc->data);
1472 * Initializes the operation queue for parallel overlay connects
1474 * @param c the controller handle
1475 * @param npoc the number of parallel overlay connects - the queue size
1478 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (struct
1479 GNUNET_TESTBED_Controller *c,
1482 fprintf (stderr, "%d", npoc);
1483 GNUNET_free_non_null (c->tslots);
1484 c->tslots_filled = 0;
1485 c->num_parallel_connects = npoc;
1486 c->tslots = GNUNET_malloc (npoc * sizeof (struct TimeSlot));
1487 GNUNET_TESTBED_operation_queue_reset_max_active_
1488 (c->opq_parallel_overlay_connect_operations, npoc);
1493 * Function to copy NULL terminated list of arguments
1495 * @param argv the NULL terminated list of arguments. Cannot be NULL.
1496 * @return the copied NULL terminated arguments
1499 copy_argv (const char *const *argv)
1504 GNUNET_assert (NULL != argv);
1505 for (argp = 0; NULL != argv[argp]; argp++);
1506 argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
1507 for (argp = 0; NULL != argv[argp]; argp++)
1508 argv_dup[argp] = strdup (argv[argp]);
1514 * Frees the given NULL terminated arguments
1516 * @param argv the NULL terminated list of arguments
1519 free_argv (char **argv)
1523 for (argp = 0; NULL != argv[argp]; argp++)
1524 GNUNET_free (argv[argp]);
1530 * Starts a controller process at the given host
1532 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1533 * HOST(all connections form this ip are permitted by the testbed) when
1534 * starting testbed controller at host. This can either be a single ip
1535 * address or a network address in CIDR notation.
1536 * @param host the host where the controller has to be started; NULL for
1538 * @param cfg template configuration to use for the remote controller; the
1539 * remote controller will be started with a slightly modified
1540 * configuration (port numbers, unix domain sockets and service home
1541 * values are changed as per TESTING library on the remote host)
1542 * @param cb function called when the controller is successfully started or
1543 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1544 * called if cb is called with GNUNET_SYSERR as status. Will never be
1545 * called in the same task as 'GNUNET_TESTBED_controller_start'
1546 * (synchronous errors will be signalled by returning NULL). This
1547 * parameter cannot be NULL.
1548 * @param cls closure for above callbacks
1549 * @return the controller process handle, NULL on errors
1551 struct GNUNET_TESTBED_ControllerProc *
1552 GNUNET_TESTBED_controller_start (const char *trusted_ip,
1553 struct GNUNET_TESTBED_Host *host,
1554 const struct GNUNET_CONFIGURATION_Handle *cfg,
1555 GNUNET_TESTBED_ControllerStatusCallback cb,
1558 struct GNUNET_TESTBED_ControllerProc *cp;
1559 struct GNUNET_TESTBED_HelperInit *msg;
1560 const char *hostname;
1561 static char *const binary_argv[] = {
1562 HELPER_TESTBED_BINARY, NULL
1566 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1567 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1570 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1571 &helper_mst, &helper_exp_cb, cp);
1575 char *helper_binary_path;
1576 #define NUM_REMOTE_ARGS 12
1577 const char *remote_args[NUM_REMOTE_ARGS];
1578 const char *username;
1583 username = GNUNET_TESTBED_host_get_username_ (host);
1584 hostname = GNUNET_TESTBED_host_get_hostname (host);
1585 GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1586 if (NULL == username)
1587 GNUNET_asprintf (&dst, "%s", hostname);
1589 GNUNET_asprintf (&dst, "%s@%s", username, hostname);
1590 LOG_DEBUG ("Starting SSH to destination %s\n", dst);
1592 remote_args[argp++] = "ssh";
1593 remote_args[argp++] = "-p";
1594 remote_args[argp++] = port;
1595 remote_args[argp++] = "-o";
1596 remote_args[argp++] = "BatchMode=yes";
1597 remote_args[argp++] = "-o";
1598 remote_args[argp++] = "NoHostAuthenticationForLocalhost=yes";
1599 remote_args[argp++] = dst;
1600 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1601 "HELPER_BINARY_PATH",
1602 &helper_binary_path))
1603 helper_binary_path = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1604 remote_args[argp++] = "sh";
1605 remote_args[argp++] = "-lc";
1606 remote_args[argp++] = helper_binary_path;
1607 remote_args[argp++] = NULL;
1608 GNUNET_assert (NUM_REMOTE_ARGS == argp);
1609 cp->helper_argv = copy_argv (remote_args);
1613 GNUNET_HELPER_start (GNUNET_NO, "ssh", cp->helper_argv, &helper_mst,
1614 &helper_exp_cb, cp);
1615 GNUNET_free (helper_binary_path);
1617 if (NULL == cp->helper)
1619 if (NULL != cp->helper_argv)
1620 free_argv (cp->helper_argv);
1627 msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
1628 cp->msg = &msg->header;
1630 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1631 if (NULL == cp->shandle)
1634 GNUNET_TESTBED_controller_stop (cp);
1642 * Stop the controller process (also will terminate all peers and controllers
1643 * dependent on this controller). This function blocks until the testbed has
1644 * been fully terminated (!). The controller status cb from
1645 * GNUNET_TESTBED_controller_start() will not be called.
1647 * @param cproc the controller process handle
1650 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1652 if (NULL != cproc->shandle)
1653 GNUNET_HELPER_send_cancel (cproc->shandle);
1654 if (NULL != cproc->helper)
1655 GNUNET_HELPER_stop (cproc->helper);
1656 if (NULL != cproc->cfg)
1657 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1658 if (NULL != cproc->helper_argv)
1659 free_argv (cproc->helper_argv);
1660 GNUNET_free (cproc);
1665 * Start a controller process using the given configuration at the
1668 * @param cfg configuration to use
1669 * @param host host to run the controller on; This should be the same host if
1670 * the controller was previously started with
1671 * GNUNET_TESTBED_controller_start; NULL for localhost
1672 * @param event_mask bit mask with set of events to call 'cc' for;
1673 * or-ed values of "1LL" shifted by the
1674 * respective 'enum GNUNET_TESTBED_EventType'
1675 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1676 * @param cc controller callback to invoke on events
1677 * @param cc_cls closure for cc
1678 * @return handle to the controller
1680 struct GNUNET_TESTBED_Controller *
1681 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1682 *cfg, struct GNUNET_TESTBED_Host *host,
1683 uint64_t event_mask,
1684 GNUNET_TESTBED_ControllerCallback cc,
1687 struct GNUNET_TESTBED_Controller *controller;
1688 struct GNUNET_TESTBED_InitMessage *msg;
1689 const char *controller_hostname;
1690 unsigned long long max_parallel_operations;
1691 unsigned long long max_parallel_service_connections;
1692 unsigned long long max_parallel_topology_config_operations;
1695 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1696 "MAX_PARALLEL_OPERATIONS",
1697 &max_parallel_operations))
1703 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1704 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1705 &max_parallel_service_connections))
1711 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1712 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1713 &max_parallel_topology_config_operations))
1718 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1719 controller->cc = cc;
1720 controller->cc_cls = cc_cls;
1721 controller->event_mask = event_mask;
1722 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1723 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1724 if (NULL == controller->client)
1726 GNUNET_TESTBED_controller_disconnect (controller);
1731 host = GNUNET_TESTBED_host_create_by_id_ (0);
1732 if (NULL == host) /* If the above host create fails */
1734 LOG (GNUNET_ERROR_TYPE_WARNING,
1735 "Treating NULL host as localhost. Multiple references to localhost "
1736 "may break when localhost freed before calling disconnect \n");
1737 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1741 controller->aux_host = GNUNET_YES;
1744 GNUNET_assert (NULL != host);
1745 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1746 controller->host = host;
1747 controller->opq_parallel_operations =
1748 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1749 max_parallel_operations);
1750 controller->opq_parallel_service_connections =
1751 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1752 max_parallel_service_connections);
1753 controller->opq_parallel_topology_config_operations=
1754 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1755 max_parallel_topology_config_operations);
1756 controller->opq_parallel_overlay_connect_operations=
1757 GNUNET_TESTBED_operation_queue_create_ (0);
1758 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (controller, 1);
1759 controller->poc_sd = SD_init (10);
1760 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1761 if (NULL == controller_hostname)
1762 controller_hostname = "127.0.0.1";
1764 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1765 strlen (controller_hostname) + 1);
1766 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1768 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1769 strlen (controller_hostname) + 1);
1770 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1771 msg->event_mask = GNUNET_htonll (controller->event_mask);
1772 strcpy ((char *) &msg[1], controller_hostname);
1773 GNUNET_TESTBED_queue_message_ (controller,
1774 (struct GNUNET_MessageHeader *) msg);
1780 * Configure shared services at a controller. Using this function,
1781 * you can specify that certain services (such as "resolver")
1782 * should not be run for each peer but instead be shared
1783 * across N peers on the specified host. This function
1784 * must be called before any peers are created at the host.
1786 * @param controller controller to configure
1787 * @param service_name name of the service to share
1788 * @param num_peers number of peers that should share one instance
1789 * of the specified service (1 for no sharing is the default),
1790 * use 0 to disable the service
1793 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1795 const char *service_name,
1798 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1799 uint16_t service_name_size;
1802 service_name_size = strlen (service_name) + 1;
1804 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1806 msg = GNUNET_malloc (msg_size);
1807 msg->header.size = htons (msg_size);
1808 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE);
1809 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1810 msg->num_peers = htonl (num_peers);
1811 memcpy (&msg[1], service_name, service_name_size);
1812 GNUNET_TESTBED_queue_message_ (controller,
1813 (struct GNUNET_MessageHeader *) msg);
1814 GNUNET_break (0); /* This function is not yet implemented on the
1820 * disconnects from the controller.
1822 * @param controller handle to controller to stop
1825 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1828 struct MessageQueue *mq_entry;
1830 if (NULL != controller->th)
1831 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1832 /* Clear the message queue */
1833 while (NULL != (mq_entry = controller->mq_head))
1835 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1837 GNUNET_free (mq_entry->msg);
1838 GNUNET_free (mq_entry);
1840 if (NULL != controller->client)
1841 GNUNET_CLIENT_disconnect (controller->client);
1842 GNUNET_CONFIGURATION_destroy (controller->cfg);
1843 if (GNUNET_YES == controller->aux_host)
1844 GNUNET_TESTBED_host_destroy (controller->host);
1845 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1846 GNUNET_TESTBED_operation_queue_destroy_
1847 (controller->opq_parallel_service_connections);
1848 GNUNET_TESTBED_operation_queue_destroy_
1849 (controller->opq_parallel_topology_config_operations);
1850 GNUNET_TESTBED_operation_queue_destroy_
1851 (controller->opq_parallel_overlay_connect_operations);
1852 SD_destroy (controller->poc_sd);
1853 GNUNET_free_non_null (controller->tslots);
1854 GNUNET_free (controller);
1859 * Register a host with the controller
1861 * @param controller the controller handle
1862 * @param host the host to register
1863 * @param cc the completion callback to call to inform the status of
1864 * registration. After calling this callback the registration handle
1865 * will be invalid. Cannot be NULL.
1866 * @param cc_cls the closure for the cc
1867 * @return handle to the host registration which can be used to cancel the
1870 struct GNUNET_TESTBED_HostRegistrationHandle *
1871 GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller,
1872 struct GNUNET_TESTBED_Host *host,
1873 GNUNET_TESTBED_HostRegistrationCompletion cc,
1876 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
1877 struct GNUNET_TESTBED_AddHostMessage *msg;
1878 const char *username;
1879 const char *hostname;
1881 uint16_t user_name_length;
1883 if (NULL != controller->rh)
1885 hostname = GNUNET_TESTBED_host_get_hostname (host);
1886 if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller))
1888 LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n",
1889 (NULL == hostname) ? "localhost" : hostname);
1892 rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
1895 GNUNET_assert (NULL != cc);
1897 rh->cc_cls = cc_cls;
1898 controller->rh = rh;
1899 username = GNUNET_TESTBED_host_get_username_ (host);
1900 msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage));
1901 user_name_length = 0;
1902 if (NULL != username)
1904 user_name_length = strlen (username) + 1;
1905 msg_size += user_name_length;
1907 /* FIXME: what happens when hostname is NULL? localhost */
1908 GNUNET_assert (NULL != hostname);
1909 msg_size += strlen (hostname) + 1;
1910 msg = GNUNET_malloc (msg_size);
1911 msg->header.size = htons (msg_size);
1912 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST);
1913 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1914 msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host));
1915 if (NULL != username)
1917 msg->user_name_length = htons (user_name_length - 1);
1918 memcpy (&msg[1], username, user_name_length);
1921 msg->user_name_length = htons (user_name_length);
1922 strcpy (((void *) &msg[1]) + user_name_length, hostname);
1923 GNUNET_TESTBED_queue_message_ (controller,
1924 (struct GNUNET_MessageHeader *) msg);
1930 * Cancel the pending registration. Note that if the registration message is
1931 * already sent to the service the cancellation has only the effect that the
1932 * registration completion callback for the registration is never called.
1934 * @param handle the registration handle to cancel
1937 GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle
1940 if (handle != handle->c->rh)
1945 handle->c->rh = NULL;
1946 GNUNET_free (handle);
1951 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1954 * @param op_cls the operation closure for the event which is generated to
1955 * signal success or failure of this operation
1956 * @param master handle to the master controller who creates the association
1957 * @param delegated_host_id id of the host to which requests should be delegated
1958 * @param slave_host_id id of the host which is used to run the slave controller
1959 * @param sxcfg serialized and compressed configuration
1960 * @param sxcfg_size the size sxcfg
1961 * @param scfg_size the size of uncompressed serialized configuration
1962 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1963 * be started by the slave controller; GNUNET_NO if the slave
1964 * controller has to connect to the already started delegated
1965 * controller via TCP/IP
1966 * @return the operation handle
1968 struct GNUNET_TESTBED_Operation *
1969 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1970 struct GNUNET_TESTBED_Controller *master,
1971 uint32_t delegated_host_id,
1972 uint32_t slave_host_id,
1973 const char *sxcfg, size_t sxcfg_size,
1974 size_t scfg_size, int is_subordinate)
1976 struct OperationContext *opc;
1977 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1978 struct ControllerLinkData *data;
1981 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1982 msg = GNUNET_malloc (msg_size);
1983 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS);
1984 msg->header.size = htons (msg_size);
1985 msg->delegated_host_id = htonl (delegated_host_id);
1986 msg->slave_host_id = htonl (slave_host_id);
1987 msg->config_size = htons ((uint16_t) scfg_size);
1988 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1989 memcpy (&msg[1], sxcfg, sxcfg_size);
1990 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1992 opc = GNUNET_malloc (sizeof (struct OperationContext));
1995 opc->type = OP_LINK_CONTROLLERS;
1996 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1997 opc->state = OPC_STATE_INIT;
1998 opc->op_cls = op_cls;
1999 msg->operation_id = GNUNET_htonll (opc->id);
2001 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
2002 &oprelease_link_controllers);
2003 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2005 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2011 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
2012 * serialized and compressed
2014 * @param op_cls the operation closure for the event which is generated to
2015 * signal success or failure of this operation
2016 * @param master handle to the master controller who creates the association
2017 * @param delegated_host requests to which host should be delegated; cannot be NULL
2018 * @param slave_host which host is used to run the slave controller; use NULL to
2019 * make the master controller connect to the delegated host
2020 * @param sxcfg serialized and compressed configuration
2021 * @param sxcfg_size the size sxcfg
2022 * @param scfg_size the size of uncompressed serialized configuration
2023 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2024 * be started by the slave controller; GNUNET_NO if the slave
2025 * controller has to connect to the already started delegated
2026 * controller via TCP/IP
2027 * @return the operation handle
2029 struct GNUNET_TESTBED_Operation *
2030 GNUNET_TESTBED_controller_link_2 (void *op_cls,
2031 struct GNUNET_TESTBED_Controller *master,
2032 struct GNUNET_TESTBED_Host *delegated_host,
2033 struct GNUNET_TESTBED_Host *slave_host,
2034 const char *sxcfg, size_t sxcfg_size,
2035 size_t scfg_size, int is_subordinate)
2037 uint32_t delegated_host_id;
2038 uint32_t slave_host_id;
2040 GNUNET_assert (GNUNET_YES ==
2041 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
2042 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
2044 GNUNET_TESTBED_host_get_id_ ((NULL != slave_host)
2045 ? slave_host : master->host);
2046 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
2047 GNUNET_assert (GNUNET_YES ==
2048 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
2050 return GNUNET_TESTBED_controller_link_2_ (op_cls,
2055 scfg_size, is_subordinate);
2060 * Compresses given configuration using zlib compress
2062 * @param config the serialized configuration
2063 * @param size the size of config
2064 * @param xconfig will be set to the compressed configuration (memory is fresly
2066 * @return the size of the xconfig
2069 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
2074 xsize = compressBound ((uLong) size);
2075 *xconfig = GNUNET_malloc (xsize);
2076 GNUNET_assert (Z_OK ==
2077 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
2078 (const Bytef *) config, (uLongf) size,
2085 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
2088 * @param op_cls the operation closure for the event which is generated to
2089 * signal success or failure of this operation
2090 * @param master handle to the master controller who creates the association
2091 * @param delegated_host_id id of the host to which requests should be
2092 * delegated; cannot be NULL
2093 * @param slave_host_id id of the host which should connect to controller
2094 * running on delegated host ; use NULL to make the master controller
2095 * connect to the delegated host
2096 * @param slave_cfg configuration to use for the slave controller
2097 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2098 * be started by the slave controller; GNUNET_NO if the slave
2099 * controller has to connect to the already started delegated
2100 * controller via TCP/IP
2101 * @return the operation handle
2103 struct GNUNET_TESTBED_Operation *
2104 GNUNET_TESTBED_controller_link_ (void *op_cls,
2105 struct GNUNET_TESTBED_Controller *master,
2106 uint32_t delegated_host_id,
2107 uint32_t slave_host_id,
2108 const struct GNUNET_CONFIGURATION_Handle
2112 struct GNUNET_TESTBED_Operation *op;
2118 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
2119 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
2120 GNUNET_free (config);
2121 /* Configuration doesn't fit in 1 message */
2122 GNUNET_assert ((UINT16_MAX -
2123 sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
2125 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
2126 slave_host_id, (const char *) cconfig,
2127 cc_size, config_size, is_subordinate);
2128 GNUNET_free (cconfig);
2134 * Create a link from slave controller to delegated controller. Whenever the
2135 * master controller is asked to start a peer at the delegated controller the
2136 * request will be routed towards slave controller (if a route exists). The
2137 * slave controller will then route it to the delegated controller. The
2138 * configuration of the delegated controller is given and is used to either
2139 * create the delegated controller or to connect to an existing controller. Note
2140 * that while starting the delegated controller the configuration will be
2141 * modified to accommodate available free ports. the 'is_subordinate' specifies
2142 * if the given delegated controller should be started and managed by the slave
2143 * controller, or if the delegated controller already has a master and the slave
2144 * controller connects to it as a non master controller. The success or failure
2145 * of this operation will be signalled through the
2146 * GNUNET_TESTBED_ControllerCallback() with an event of type
2147 * GNUNET_TESTBED_ET_OPERATION_FINISHED
2149 * @param op_cls the operation closure for the event which is generated to
2150 * signal success or failure of this operation
2151 * @param master handle to the master controller who creates the association
2152 * @param delegated_host requests to which host should be delegated; cannot be NULL
2153 * @param slave_host which host is used to run the slave controller; use NULL to
2154 * make the master controller connect to the delegated host
2155 * @param slave_cfg configuration to use for the slave controller
2156 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2157 * be started by the slave controller; GNUNET_NO if the slave
2158 * controller has to connect to the already started delegated
2159 * controller via TCP/IP
2160 * @return the operation handle
2162 struct GNUNET_TESTBED_Operation *
2163 GNUNET_TESTBED_controller_link (void *op_cls,
2164 struct GNUNET_TESTBED_Controller *master,
2165 struct GNUNET_TESTBED_Host *delegated_host,
2166 struct GNUNET_TESTBED_Host *slave_host,
2167 const struct GNUNET_CONFIGURATION_Handle
2168 *slave_cfg, int is_subordinate)
2170 uint32_t slave_host_id;
2171 uint32_t delegated_host_id;
2173 GNUNET_assert (GNUNET_YES ==
2174 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
2176 GNUNET_TESTBED_host_get_id_ ((NULL != slave_host)
2177 ? slave_host : master->host);
2178 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
2179 if ((NULL != slave_host) && (0 != slave_host_id))
2180 GNUNET_assert (GNUNET_YES ==
2181 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
2182 return GNUNET_TESTBED_controller_link_ (op_cls, master,
2192 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
2193 * check. Another difference is that this function takes the id of the slave
2196 * @param op_cls the closure for the operation
2197 * @param master the handle to master controller
2198 * @param slave_host_id id of the host where the slave controller is running to
2199 * the slave_host should remain valid until this operation is cancelled
2200 * or marked as finished
2201 * @return the operation handle;
2203 struct GNUNET_TESTBED_Operation *
2204 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
2205 struct GNUNET_TESTBED_Controller *master,
2206 uint32_t slave_host_id)
2208 struct OperationContext *opc;
2209 struct GetSlaveConfigData *data;
2211 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
2212 data->slave_id = slave_host_id;
2213 opc = GNUNET_malloc (sizeof (struct OperationContext));
2214 opc->state = OPC_STATE_INIT;
2216 opc->id = GNUNET_TESTBED_get_next_op_id (master);
2217 opc->type = OP_GET_SLAVE_CONFIG;
2219 opc->op_cls = op_cls;
2221 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
2222 &oprelease_get_slave_config);
2223 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2225 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2231 * Function to acquire the configuration of a running slave controller. The
2232 * completion of the operation is signalled through the controller_cb from
2233 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
2234 * handle to the configuration is available in the generic pointer of
2235 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
2237 * @param op_cls the closure for the operation
2238 * @param master the handle to master controller
2239 * @param slave_host the host where the slave controller is running; the handle
2240 * to the slave_host should remain valid until this operation is
2241 * cancelled or marked as finished
2242 * @return the operation handle; NULL if the slave_host is not registered at
2245 struct GNUNET_TESTBED_Operation *
2246 GNUNET_TESTBED_get_slave_config (void *op_cls,
2247 struct GNUNET_TESTBED_Controller *master,
2248 struct GNUNET_TESTBED_Host *slave_host)
2250 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
2252 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
2253 GNUNET_TESTBED_host_get_id_ (slave_host));
2258 * Ask the testbed controller to write the current overlay topology to
2259 * a file. Naturally, the file will only contain a snapshot as the
2260 * topology may evolve all the time.
2262 * @param controller overlay controller to inspect
2263 * @param filename name of the file the topology should
2267 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
2269 const char *filename)
2276 * Creates a helper initialization message. This function is here because we
2277 * want to use this in testing
2279 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
2280 * HOST(all connections form this ip are permitted by the testbed) when
2281 * starting testbed controller at host. This can either be a single ip
2282 * address or a network address in CIDR notation.
2283 * @param hostname the hostname of the destination this message is intended for
2284 * @param cfg the configuration that has to used to start the testbed service
2286 * @return the initialization message
2288 struct GNUNET_TESTBED_HelperInit *
2289 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
2290 const char *hostname,
2291 const struct GNUNET_CONFIGURATION_Handle
2294 struct GNUNET_TESTBED_HelperInit *msg;
2298 size_t xconfig_size;
2299 uint16_t trusted_ip_len;
2300 uint16_t hostname_len;
2303 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
2304 GNUNET_assert (NULL != config);
2306 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
2307 GNUNET_free (config);
2308 trusted_ip_len = strlen (trusted_ip);
2309 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2311 xconfig_size + trusted_ip_len + 1 + sizeof (struct GNUNET_TESTBED_HelperInit);
2312 msg_size += hostname_len;
2313 msg = GNUNET_realloc (xconfig, msg_size);
2314 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len,
2317 msg->header.size = htons (msg_size);
2318 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2319 msg->trusted_ip_size = htons (trusted_ip_len);
2320 msg->hostname_size = htons (hostname_len);
2321 msg->config_size = htons (config_size);
2322 (void) strcpy ((char *) &msg[1], trusted_ip);
2323 if (0 != hostname_len)
2324 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname, hostname_len);
2330 * Cancel a pending operation. Releases all resources
2331 * of the operation and will ensure that no event
2332 * is generated for the operation. Does NOT guarantee
2333 * that the operation will be fully undone (or that
2334 * nothing ever happened).
2336 * @param operation operation to cancel
2339 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
2341 GNUNET_TESTBED_operation_done (operation);
2346 * Signal that the information from an operation has been fully
2347 * processed. This function MUST be called for each event
2348 * of type 'operation_finished' to fully remove the operation
2349 * from the operation queue. After calling this function, the
2350 * 'op_result' becomes invalid (!).
2352 * @param operation operation to signal completion for
2355 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2357 GNUNET_TESTBED_operation_release_ (operation);
2362 * Generates configuration by uncompressing configuration in given message. The
2363 * given message should be of the following types:
2364 * GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG,
2365 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG
2367 * @param msg the message containing compressed configuration
2368 * @return handle to the parsed configuration
2370 struct GNUNET_CONFIGURATION_Handle *
2371 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2373 struct GNUNET_CONFIGURATION_Handle *cfg;
2380 switch (ntohs (msg->type))
2382 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
2384 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2386 imsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2388 data_len = (uLong) ntohs (imsg->config_size);
2389 xdata_len = ntohs (imsg->header.size)
2390 - sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2391 xdata = (const Bytef *) &imsg[1];
2394 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG:
2396 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2398 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2399 data_len = (uLong) ntohs (imsg->config_size);
2400 xdata_len = ntohs (imsg->header.size)
2401 - sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2402 xdata = (const Bytef *) &imsg[1];
2408 data = GNUNET_malloc (data_len);
2411 uncompress (data, &data_len, xdata, xdata_len)))
2413 cfg = GNUNET_CONFIGURATION_create ();
2414 GNUNET_assert (GNUNET_OK ==
2415 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2424 * Checks the integrity of the OperationFailureEventMessage and if good returns
2425 * the error message it contains.
2427 * @param msg the OperationFailureEventMessage
2428 * @return the error message
2431 GNUNET_TESTBED_parse_error_string_ (const struct
2432 GNUNET_TESTBED_OperationFailureEventMessage
2438 msize = ntohs (msg->header.size);
2439 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2441 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2442 emsg = (const char *) &msg[1];
2443 if ('\0' != emsg[msize - 1])
2453 * Function to return the operation id for a controller. The operation id is
2454 * created from the controllers host id and its internal operation counter.
2456 * @param controller the handle to the controller whose operation id has to be incremented
2457 * @return the incremented operation id.
2460 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller)
2464 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2465 op_id = op_id << 32;
2466 op_id |= (uint64_t) controller->operation_counter++;
2472 * Returns a timing slot which will be exclusively locked
2474 * @param c the controller handle
2475 * @param key a pointer which is associated to the returned slot; should not be
2476 * NULL. It serves as a key to determine the correct owner of the slot
2477 * @return the time slot index in the array of time slots in the controller
2481 GNUNET_TESTBED_get_tslot_ (struct GNUNET_TESTBED_Controller *c, void *key)
2485 GNUNET_assert (NULL != c->tslots);
2486 GNUNET_assert (NULL != key);
2487 for (slot = 0; slot < c->num_parallel_connects; slot++)
2488 if (NULL == c->tslots[slot].key)
2490 c->tslots[slot].key = key;
2493 GNUNET_assert (0); /* We should always find a free tslot */
2498 * Decides whether any change in the number of parallel overlay connects is
2499 * necessary to adapt to the load on the system
2501 * @param c the controller handle
2504 decide_npoc (struct GNUNET_TESTBED_Controller *c)
2506 struct GNUNET_TIME_Relative avg;
2510 if (c->tslots_filled != c->num_parallel_connects)
2512 avg = GNUNET_TIME_UNIT_ZERO;
2513 for (slot = 0; slot < c->num_parallel_connects; slot++)
2514 avg = GNUNET_TIME_relative_add (avg, c->tslots[slot].time);
2515 avg = GNUNET_TIME_relative_divide (avg, c->num_parallel_connects);
2516 GNUNET_assert (GNUNET_TIME_UNIT_FOREVER_REL.rel_value != avg.rel_value);
2517 sd = SD_deviation_factor (c->poc_sd, (unsigned int) avg.rel_value);
2518 if (GNUNET_SYSERR == sd)
2520 SD_add_data (c->poc_sd, (unsigned int) avg.rel_value);
2521 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (c, c->num_parallel_connects);
2524 GNUNET_assert (0 <= sd);
2527 SD_add_data (c->poc_sd, (unsigned int) avg.rel_value);
2528 GNUNET_TESTBED_set_num_parallel_overlay_connects_
2529 (c, c->num_parallel_connects * 2);
2532 if (1 == c->num_parallel_connects)
2534 GNUNET_TESTBED_set_num_parallel_overlay_connects_ (c, 1);
2537 GNUNET_TESTBED_set_num_parallel_overlay_connects_
2538 (c, c->num_parallel_connects / 2);
2543 * Releases a time slot thus making it available for be used again
2545 * @param c the controller handle
2546 * @param index the index of the the time slot
2547 * @param key the key to prove ownership of the timeslot
2548 * @return GNUNET_YES if the time slot is successfully removed; GNUNET_NO if the
2549 * time slot cannot be removed - this could be because of the index
2550 * greater than existing number of time slots or `key' being different
2553 GNUNET_TESTBED_release_time_slot_ (struct GNUNET_TESTBED_Controller *c,
2557 struct TimeSlot *slot;
2559 GNUNET_assert (NULL != key);
2560 if (index >= c->num_parallel_connects)
2562 slot = &c->tslots[index];
2563 if (key != slot->key)
2571 * Function to update a time slot
2573 * @param c the controller handle
2574 * @param index the index of the time slot to update
2575 * @param key the key to identify ownership of the slot
2576 * @param time the new time
2579 GNUNET_TESTBED_update_time_slot_ (struct GNUNET_TESTBED_Controller *c,
2582 struct GNUNET_TIME_Relative time)
2584 struct GNUNET_TIME_Relative avg;
2585 struct TimeSlot *slot;
2587 if (GNUNET_NO == GNUNET_TESTBED_release_time_slot_ (c, index, key))
2589 slot = &c->tslots[index];
2590 if (GNUNET_TIME_UNIT_ZERO.rel_value == slot->time.rel_value)
2597 avg = GNUNET_TIME_relative_add (slot->time, time);
2598 avg = GNUNET_TIME_relative_divide (avg, 2);
2603 /* end of testbed_api.c */