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"
44 #include "testbed_api_sd.h"
47 * Generic logging shorthand
49 #define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
55 #define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
59 * Relative time seconds shorthand
61 #define TIME_REL_SECS(sec) \
62 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
66 * Default server message sending retry timeout
68 #define TIMEOUT_REL TIME_REL_SECS(1)
72 * Handle for controller process
74 struct GNUNET_TESTBED_ControllerProc
79 struct GNUNET_HELPER_Handle *helper;
82 * The arguments used to start the helper
87 * The host where the helper is run
89 struct GNUNET_TESTBED_Host *host;
92 * The controller error callback
94 GNUNET_TESTBED_ControllerStatusCallback cb;
97 * The closure for the above callback
102 * The send handle for the helper
104 struct GNUNET_HELPER_SendHandle *shandle;
107 * The message corresponding to send handle
109 struct GNUNET_MessageHeader *msg;
112 * The configuration of the running testbed service
114 struct GNUNET_CONFIGURATION_Handle *cfg;
120 * The message queue for sending messages to the controller service
125 * The message to be sent
127 struct GNUNET_MessageHeader *msg;
130 * next pointer for DLL
132 struct MessageQueue *next;
135 * prev pointer for DLL
137 struct MessageQueue *prev;
142 * Structure for a controller link
144 struct ControllerLink
147 * The next ptr for DLL
149 struct ControllerLink *next;
152 * The prev ptr for DLL
154 struct ControllerLink *prev;
157 * The host which will be referred in the peer start request. This is the
158 * host where the peer should be started
160 struct GNUNET_TESTBED_Host *delegated_host;
163 * The host which will contacted to delegate the peer start request
165 struct GNUNET_TESTBED_Host *slave_host;
168 * The configuration to be used to connect to slave host
170 const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
173 * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
174 * if we are just allowed to use the slave via TCP/IP
181 * handle for host registration
183 struct GNUNET_TESTBED_HostRegistrationHandle
186 * The host being registered
188 struct GNUNET_TESTBED_Host *host;
191 * The controller at which this host is being registered
193 struct GNUNET_TESTBED_Controller *c;
196 * The Registartion completion callback
198 GNUNET_TESTBED_HostRegistrationCompletion cc;
201 * The closure for above callback
208 * Context data for forwarded Operation
210 struct ForwardedOperationData
214 * The callback to call when reply is available
216 GNUNET_CLIENT_MessageHandler cc;
219 * The closure for the above callback
227 * Context data for get slave config operations
229 struct GetSlaveConfigData
232 * The id of the slave controller
240 * Context data for controller link operations
242 struct ControllerLinkData
245 * The controller link message
247 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
253 * This variable is set to the operation that has been last marked as done. It
254 * is used to verify whether the state associated with an operation is valid
255 * after the first notify callback is called. Such checks are necessary for
256 * certain operations where we have 2 notify callbacks. Examples are
257 * OP_PEER_CREATE, OP_PEER_START/STOP, OP_OVERLAY_CONNECT.
259 * This variable should ONLY be used to compare; it is a dangling pointer!!
261 static const struct GNUNET_TESTBED_Operation *last_finished_operation;
265 * Returns the operation context with the given id if found in the Operation
266 * context queues of the controller
268 * @param c the controller whose queues are searched
269 * @param id the id which has to be checked
270 * @return the matching operation context; NULL if no match found
272 static struct OperationContext *
273 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
275 struct OperationContext *opc;
277 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
287 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
288 * controller (testbed service)
290 * @param c the controller handler
291 * @param msg message received
292 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
296 handle_addhostconfirm (struct GNUNET_TESTBED_Controller *c,
297 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
299 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
308 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
310 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
311 GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
315 msg_size = ntohs (msg->header.size);
316 if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
318 LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
319 GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
320 rh->cc (rh->cc_cls, NULL);
324 /* We have an error message */
325 emsg = (char *) &msg[1];
327 emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
333 LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
334 ntohl (msg->host_id), emsg);
335 rh->cc (rh->cc_cls, emsg);
342 * Handler for forwarded operations
344 * @param c the controller handle
345 * @param opc the opearation context
346 * @param msg the message
349 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
350 struct OperationContext *opc,
351 const struct GNUNET_MessageHeader *msg)
353 struct ForwardedOperationData *fo_data;
356 if (NULL != fo_data->cc)
357 fo_data->cc (fo_data->cc_cls, msg);
358 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
359 GNUNET_free (fo_data);
365 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
366 * controller (testbed service)
368 * @param c the controller handler
369 * @param msg message received
370 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
374 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
376 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
378 struct OperationContext *opc;
379 struct GNUNET_TESTBED_EventInformation event;
382 op_id = GNUNET_ntohll (msg->operation_id);
383 LOG_DEBUG ("Operation %lu successful\n", op_id);
384 if (NULL == (opc = find_opc (c, op_id)))
386 LOG_DEBUG ("Operation not found\n");
389 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
390 event.details.operation_finished.operation = opc->op;
391 event.details.operation_finished.op_cls = opc->op_cls;
392 event.details.operation_finished.emsg = NULL;
393 event.details.operation_finished.generic = NULL;
398 handle_forwarded_operation_msg (c, opc,
399 (const struct GNUNET_MessageHeader *) msg);
403 case OP_PEER_DESTROY:
405 struct GNUNET_TESTBED_Peer *peer;
413 case OP_LINK_CONTROLLERS:
415 struct ControllerLinkData *data;
418 GNUNET_assert (NULL != data);
426 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
427 opc->state = OPC_STATE_FINISHED;
428 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
431 c->cc (c->cc_cls, &event);
434 LOG_DEBUG ("Not calling callback\n");
440 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
441 * controller (testbed service)
443 * @param c the controller handle
444 * @param msg message received
445 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
449 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
451 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
453 struct OperationContext *opc;
454 struct PeerCreateData *data;
455 struct GNUNET_TESTBED_Peer *peer;
456 GNUNET_TESTBED_PeerCreateCallback cb;
460 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
461 ntohs (msg->header.size));
462 op_id = GNUNET_ntohll (msg->operation_id);
463 if (NULL == (opc = find_opc (c, op_id)))
465 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
468 if (OP_FORWARDED == opc->type)
470 handle_forwarded_operation_msg (c, opc,
471 (const struct GNUNET_MessageHeader *) msg);
474 GNUNET_assert (OP_PEER_CREATE == opc->type);
475 GNUNET_assert (NULL != opc->data);
477 GNUNET_assert (NULL != data->peer);
479 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
480 peer->state = PS_CREATED;
483 GNUNET_free (opc->data);
484 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
485 opc->state = OPC_STATE_FINISHED;
487 cb (cls, peer, NULL);
493 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
494 * controller (testbed service)
496 * @param c the controller handler
497 * @param msg message received
498 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
502 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
503 const struct GNUNET_TESTBED_PeerEventMessage *msg)
505 struct OperationContext *opc;
506 struct GNUNET_TESTBED_Peer *peer;
507 struct PeerEventData *data;
508 GNUNET_TESTBED_PeerChurnCallback pcc;
510 struct GNUNET_TESTBED_EventInformation event;
513 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
514 ntohs (msg->header.size));
515 op_id = GNUNET_ntohll (msg->operation_id);
516 if (NULL == (opc = find_opc (c, op_id)))
518 LOG_DEBUG ("Operation not found\n");
521 if (OP_FORWARDED == opc->type)
523 handle_forwarded_operation_msg (c, opc,
524 (const struct GNUNET_MessageHeader *) msg);
527 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
529 GNUNET_assert (NULL != data);
531 GNUNET_assert (NULL != peer);
532 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
535 case GNUNET_TESTBED_ET_PEER_START:
536 peer->state = PS_STARTED;
537 event.details.peer_start.host = peer->host;
538 event.details.peer_start.peer = peer;
540 case GNUNET_TESTBED_ET_PEER_STOP:
541 peer->state = PS_STOPPED;
542 event.details.peer_stop.peer = peer;
545 GNUNET_assert (0); /* We should never reach this state */
548 pcc_cls = data->pcc_cls;
550 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
551 opc->state = OPC_STATE_FINISHED;
553 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
557 c->cc (c->cc_cls, &event);
566 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
567 * controller (testbed service)
569 * @param c the controller handler
570 * @param msg message received
571 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
575 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
576 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
578 struct OperationContext *opc;
579 struct OverlayConnectData *data;
580 GNUNET_TESTBED_OperationCompletionCallback cb;
582 struct GNUNET_TESTBED_EventInformation event;
585 op_id = GNUNET_ntohll (msg->operation_id);
586 if (NULL == (opc = find_opc (c, op_id)))
588 LOG_DEBUG ("Operation not found\n");
591 if (OP_FORWARDED == opc->type)
593 handle_forwarded_operation_msg (c, opc,
594 (const struct GNUNET_MessageHeader *) msg);
597 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
599 GNUNET_assert (NULL != data);
600 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
601 (ntohl (msg->peer2) == data->p2->unique_id));
602 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
605 case GNUNET_TESTBED_ET_CONNECT:
606 event.details.peer_connect.peer1 = data->p1;
607 event.details.peer_connect.peer2 = data->p2;
609 case GNUNET_TESTBED_ET_DISCONNECT:
610 GNUNET_assert (0); /* FIXME: implement */
613 GNUNET_assert (0); /* Should never reach here */
617 cb_cls = data->cb_cls;
618 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
619 opc->state = OPC_STATE_FINISHED;
621 cb (cb_cls, opc->op, NULL);
623 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
627 c->cc (c->cc_cls, &event);
634 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
635 * controller (testbed service)
637 * @param c the controller handler
638 * @param msg message received
639 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
643 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
645 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
647 struct OperationContext *opc;
648 struct GNUNET_TESTBED_Peer *peer;
649 struct PeerInfoData *data;
650 struct GNUNET_TESTBED_PeerInformation *pinfo;
651 GNUNET_TESTBED_PeerInfoCallback cb;
655 op_id = GNUNET_ntohll (msg->operation_id);
656 if (NULL == (opc = find_opc (c, op_id)))
658 LOG_DEBUG ("Operation not found\n");
661 if (OP_FORWARDED == opc->type)
663 handle_forwarded_operation_msg (c, opc,
664 (const struct GNUNET_MessageHeader *) msg);
668 GNUNET_assert (NULL != data);
670 GNUNET_assert (NULL != peer);
671 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
672 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
673 pinfo->pit = data->pit;
675 cb_cls = data->cb_cls;
680 case GNUNET_TESTBED_PIT_IDENTITY:
681 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
682 (void) memcpy (pinfo->result.id, &msg->peer_identity,
683 sizeof (struct GNUNET_PeerIdentity));
685 case GNUNET_TESTBED_PIT_CONFIGURATION:
686 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
687 GNUNET_TESTBED_extract_config_ (&msg->header);
689 case GNUNET_TESTBED_PIT_GENERIC:
690 GNUNET_assert (0); /* never reach here */
694 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
695 opc->state = OPC_STATE_FINISHED;
697 cb (cb_cls, opc->op, pinfo, NULL);
703 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
704 * controller (testbed service)
706 * @param c the controller handler
707 * @param msg message received
708 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
712 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
713 const struct GNUNET_TESTBED_OperationFailureEventMessage
716 struct OperationContext *opc;
719 struct GNUNET_TESTBED_EventInformation event;
721 op_id = GNUNET_ntohll (msg->operation_id);
722 if (NULL == (opc = find_opc (c, op_id)))
724 LOG_DEBUG ("Operation not found\n");
727 if (OP_FORWARDED == opc->type)
729 handle_forwarded_operation_msg (c, opc,
730 (const struct GNUNET_MessageHeader *) msg);
733 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
734 opc->state = OPC_STATE_FINISHED;
735 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
737 emsg = "Unknown error";
738 if (OP_PEER_INFO == opc->type)
740 struct PeerInfoData *data;
743 if (NULL != data->cb)
744 data->cb (data->cb_cls, opc->op, NULL, emsg);
746 return GNUNET_YES; /* We do not call controller callback for peer info */
748 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
751 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
752 event.details.operation_finished.operation = opc->op;
753 event.details.operation_finished.op_cls = opc->op_cls;
754 event.details.operation_finished.emsg = emsg;
755 event.details.operation_finished.generic = NULL;
756 c->cc (c->cc_cls, &event);
757 if (event.details.operation_finished.operation == last_finished_operation)
764 struct PeerCreateData *data;
767 GNUNET_free (data->peer);
768 if (NULL != data->cb)
769 data->cb (data->cls, NULL, emsg);
776 struct PeerEventData *data;
779 if (NULL != data->pcc)
780 data->pcc (data->pcc_cls, emsg);
784 case OP_PEER_DESTROY:
788 case OP_OVERLAY_CONNECT:
790 struct OverlayConnectData *data;
793 data->failed = GNUNET_YES;
794 if (NULL != data->cb)
795 data->cb (data->cb_cls, opc->op, emsg);
800 case OP_LINK_CONTROLLERS: /* No secondary callback */
810 * Function to build GET_SLAVE_CONFIG message
812 * @param op_id the id this message should contain in its operation id field
813 * @param slave_id the id this message should contain in its slave id field
814 * @return newly allocated SlaveGetConfigurationMessage
816 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
817 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
819 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
822 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
823 msg = GNUNET_malloc (msize);
824 msg->header.size = htons (msize);
826 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
827 msg->operation_id = GNUNET_htonll (op_id);
828 msg->slave_id = htonl (slave_id);
834 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
837 * @param c the controller handler
838 * @param msg message received
839 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
843 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
844 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
846 struct OperationContext *opc;
848 struct GNUNET_TESTBED_EventInformation event;
850 op_id = GNUNET_ntohll (msg->operation_id);
851 if (NULL == (opc = find_opc (c, op_id)))
853 LOG_DEBUG ("Operation not found\n");
856 if (OP_GET_SLAVE_CONFIG != opc->type)
861 GNUNET_free (opc->data);
863 opc->state = OPC_STATE_FINISHED;
864 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
865 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
868 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
869 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
870 event.details.operation_finished.generic = opc->data;
871 event.details.operation_finished.operation = opc->op;
872 event.details.operation_finished.op_cls = opc->op_cls;
873 event.details.operation_finished.emsg = NULL;
874 c->cc (c->cc_cls, &event);
881 * Handler for messages from controller (testbed service)
883 * @param cls the controller handler
884 * @param msg message received, NULL on timeout or fatal error
887 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
889 struct GNUNET_TESTBED_Controller *c = cls;
893 c->in_receive = GNUNET_NO;
894 /* FIXME: Add checks for message integrity */
897 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
901 msize = ntohs (msg->size);
902 switch (ntohs (msg->type))
904 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
905 GNUNET_assert (msize >=
906 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
908 handle_addhostconfirm (c,
909 (const struct GNUNET_TESTBED_HostConfirmedMessage
912 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
913 GNUNET_assert (msize ==
915 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
919 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
922 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
923 GNUNET_assert (msize ==
925 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
927 handle_peer_create_success (c,
929 GNUNET_TESTBED_PeerCreateSuccessEventMessage
932 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
933 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
935 handle_peer_event (c,
936 (const struct GNUNET_TESTBED_PeerEventMessage *)
940 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
941 GNUNET_assert (msize >=
943 GNUNET_TESTBED_PeerConfigurationInformationMessage));
945 handle_peer_config (c,
947 GNUNET_TESTBED_PeerConfigurationInformationMessage
950 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
951 GNUNET_assert (msize ==
952 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
954 handle_peer_conevent (c,
956 GNUNET_TESTBED_ConnectionEventMessage *) msg);
958 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
959 GNUNET_assert (msize >=
960 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
962 handle_op_fail_event (c,
964 GNUNET_TESTBED_OperationFailureEventMessage *)
967 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
968 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
970 handle_slave_config (c,
971 (const struct GNUNET_TESTBED_SlaveConfiguration *)
977 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
979 c->in_receive = GNUNET_YES;
980 GNUNET_CLIENT_receive (c->client, &message_handler, c,
981 GNUNET_TIME_UNIT_FOREVER_REL);
987 * Function called to notify a client about the connection begin ready to queue
988 * more data. "buf" will be NULL and "size" zero if the connection was closed
989 * for writing in the meantime.
992 * @param size number of bytes available in buf
993 * @param buf where the callee should write the message
994 * @return number of bytes written to buf
997 transmit_ready_notify (void *cls, size_t size, void *buf)
999 struct GNUNET_TESTBED_Controller *c = cls;
1000 struct MessageQueue *mq_entry;
1003 mq_entry = c->mq_head;
1004 GNUNET_assert (NULL != mq_entry);
1005 if ((0 == size) && (NULL == buf)) /* Timeout */
1007 LOG_DEBUG ("Message sending timed out -- retrying\n");
1009 GNUNET_CLIENT_notify_transmit_ready (c->client,
1010 ntohs (mq_entry->msg->size),
1011 TIMEOUT_REL, GNUNET_YES,
1012 &transmit_ready_notify, c);
1015 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1016 size = ntohs (mq_entry->msg->size);
1017 memcpy (buf, mq_entry->msg, size);
1018 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1019 ntohs (mq_entry->msg->type), size);
1020 GNUNET_free (mq_entry->msg);
1021 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1022 GNUNET_free (mq_entry);
1023 mq_entry = c->mq_head;
1024 if (NULL != mq_entry)
1026 GNUNET_CLIENT_notify_transmit_ready (c->client,
1027 ntohs (mq_entry->msg->size),
1028 TIMEOUT_REL, GNUNET_YES,
1029 &transmit_ready_notify, c);
1030 if (GNUNET_NO == c->in_receive)
1032 c->in_receive = GNUNET_YES;
1033 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1034 GNUNET_TIME_UNIT_FOREVER_REL);
1041 * Queues a message in send queue for sending to the service
1043 * @param controller the handle to the controller
1044 * @param msg the message to queue
1047 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1048 struct GNUNET_MessageHeader *msg)
1050 struct MessageQueue *mq_entry;
1054 type = ntohs (msg->type);
1055 size = ntohs (msg->size);
1056 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1057 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1058 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1059 mq_entry->msg = msg;
1060 LOG (GNUNET_ERROR_TYPE_DEBUG,
1061 "Queueing message of type %u, size %u for sending\n", type,
1063 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1065 if (NULL == controller->th)
1067 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1068 TIMEOUT_REL, GNUNET_YES,
1069 &transmit_ready_notify,
1075 * Sends the given message as an operation. The given callback is called when a
1076 * reply for the operation is available. Call
1077 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1078 * operation context if the cc hasn't been called
1080 * @param controller the controller to which the message has to be sent
1081 * @param operation_id the operation id of the message
1082 * @param msg the message to send
1083 * @param cc the callback to call when reply is available
1084 * @param cc_cls the closure for the above callback
1085 * @return the operation context which can be used to cancel the forwarded
1088 struct OperationContext *
1089 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1090 *controller, uint64_t operation_id,
1091 const struct GNUNET_MessageHeader *msg,
1092 GNUNET_CLIENT_MessageHandler cc,
1095 struct OperationContext *opc;
1096 struct ForwardedOperationData *data;
1097 struct GNUNET_MessageHeader *dup_msg;
1100 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1102 data->cc_cls = cc_cls;
1103 opc = GNUNET_malloc (sizeof (struct OperationContext));
1104 opc->c = controller;
1105 opc->type = OP_FORWARDED;
1107 opc->id = operation_id;
1108 msize = ntohs (msg->size);
1109 dup_msg = GNUNET_malloc (msize);
1110 (void) memcpy (dup_msg, msg, msize);
1111 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1112 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1119 * Function to cancel an operation created by simply forwarding an operation
1122 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1125 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1127 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1128 GNUNET_free (opc->data);
1134 * Functions with this signature are called whenever a
1135 * complete message is received by the tokenizer.
1137 * Do not call GNUNET_SERVER_mst_destroy in callback
1139 * @param cls closure
1140 * @param client identification of the client
1141 * @param message the actual message
1143 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1146 helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1148 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1149 const struct GNUNET_TESTBED_HelperReply *msg;
1150 const char *hostname;
1153 uLongf xconfig_size;
1155 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1156 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1157 ntohs (msg->header.size));
1158 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1159 ntohs (msg->header.type));
1160 config_size = (uLongf) ntohs (msg->config_size);
1162 (uLongf) (ntohs (msg->header.size) -
1163 sizeof (struct GNUNET_TESTBED_HelperReply));
1164 config = GNUNET_malloc (config_size);
1165 GNUNET_assert (Z_OK ==
1166 uncompress ((Bytef *) config, &config_size,
1167 (const Bytef *) &msg[1], xconfig_size));
1168 GNUNET_assert (NULL == cp->cfg);
1169 cp->cfg = GNUNET_CONFIGURATION_create ();
1170 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1171 (cp->cfg, config, config_size, GNUNET_NO));
1172 GNUNET_free (config);
1173 if ((NULL == cp->host) ||
1174 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname (cp->host))))
1175 hostname = "localhost";
1176 /* Change the hostname so that we can connect to it */
1177 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1179 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1185 * Continuation function from GNUNET_HELPER_send()
1187 * @param cls closure
1188 * @param result GNUNET_OK on success,
1189 * GNUNET_NO if helper process died
1190 * GNUNET_SYSERR during GNUNET_HELPER_stop
1193 clear_msg (void *cls, int result)
1195 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1197 GNUNET_assert (NULL != cp->shandle);
1199 GNUNET_free (cp->msg);
1204 * Callback that will be called when the helper process dies. This is not called
1205 * when the helper process is stoped using GNUNET_HELPER_stop()
1207 * @param cls the closure from GNUNET_HELPER_start()
1210 helper_exp_cb (void *cls)
1212 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1213 GNUNET_TESTBED_ControllerStatusCallback cb;
1219 GNUNET_TESTBED_controller_stop (cp);
1221 cb (cb_cls, NULL, GNUNET_SYSERR);
1226 * Function to call to start a link-controllers type operation once all queues
1227 * the operation is part of declare that the operation can be activated.
1229 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1232 opstart_link_controllers (void *cls)
1234 struct OperationContext *opc = cls;
1235 struct ControllerLinkData *data;
1236 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1238 GNUNET_assert (NULL != opc->data);
1242 opc->state = OPC_STATE_STARTED;
1243 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1244 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1249 * Callback which will be called when link-controllers type operation is released
1251 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1254 oprelease_link_controllers (void *cls)
1256 struct OperationContext *opc = cls;
1257 struct ControllerLinkData *data;
1262 case OPC_STATE_INIT:
1263 GNUNET_free (data->msg);
1265 case OPC_STATE_STARTED:
1266 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1268 case OPC_STATE_FINISHED:
1271 GNUNET_free_non_null (data);
1277 * Function to be called when get slave config operation is ready
1279 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1282 opstart_get_slave_config (void *cls)
1284 struct OperationContext *opc = cls;
1285 struct GetSlaveConfigData *data;
1286 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1289 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1290 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1291 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1292 opc->state = OPC_STATE_STARTED;
1297 * Function to be called when get slave config operation is cancelled or finished
1299 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1302 oprelease_get_slave_config (void *cls)
1304 struct OperationContext *opc = cls;
1308 case OPC_STATE_INIT:
1309 GNUNET_free (opc->data);
1311 case OPC_STATE_STARTED:
1312 GNUNET_free (opc->data);
1313 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1315 case OPC_STATE_FINISHED:
1316 if (NULL != opc->data)
1317 GNUNET_CONFIGURATION_destroy (opc->data);
1325 * Function to copy NULL terminated list of arguments
1327 * @param argv the NULL terminated list of arguments. Cannot be NULL.
1328 * @return the copied NULL terminated arguments
1331 copy_argv (const char *const *argv)
1336 GNUNET_assert (NULL != argv);
1337 for (argp = 0; NULL != argv[argp]; argp++) ;
1338 argv_dup = GNUNET_malloc (sizeof (char *) * (argp + 1));
1339 for (argp = 0; NULL != argv[argp]; argp++)
1340 argv_dup[argp] = strdup (argv[argp]);
1346 * Function to join NULL terminated list of arguments
1348 * @param argv1 the NULL terminated list of arguments. Cannot be NULL.
1349 * @param argv2 the NULL terminated list of arguments. Cannot be NULL.
1350 * @return the joined NULL terminated arguments
1353 join_argv (const char *const *argv1, const char *const *argv2)
1362 for (cnt = 0; NULL != argv1[cnt]; cnt++)
1364 argv = GNUNET_strdup (argv1[cnt]);
1365 GNUNET_array_append (argvj, carg, argv);
1367 for (cnt = 0; NULL != argv2[cnt]; cnt++)
1369 argv = GNUNET_strdup (argv2[cnt]);
1370 GNUNET_array_append (argvj, carg, argv);
1372 GNUNET_array_append (argvj, carg, NULL);
1378 * Frees the given NULL terminated arguments
1380 * @param argv the NULL terminated list of arguments
1383 free_argv (char **argv)
1387 for (argp = 0; NULL != argv[argp]; argp++)
1388 GNUNET_free (argv[argp]);
1394 * Generates arguments for opening a remote shell. Builds up the arguments
1395 * from the environment variable GNUNET_TESTBED_RSH_CMD. The variable
1396 * should not mention `-p' (port) option and destination address as these will
1397 * be set locally in the function from its parameteres. If the environmental
1398 * variable is not found then it defaults to `ssh -o BatchMode=yes -o
1399 * NoHostAuthenticationForLocalhost=yes'
1401 * @param port the destination port number
1402 * @param dst the destination address
1403 * @return NULL terminated list of arguments
1406 gen_rsh_args (const char *port, const char *dst)
1408 static const char *default_ssh_args[] = {
1413 "NoHostAuthenticationForLocalhost=yes",
1423 if (NULL != (ssh_cmd = getenv ("GNUNET_TESTBED_RSH_CMD")))
1425 ssh_cmd = GNUNET_strdup (ssh_cmd);
1426 ssh_cmd_cp = ssh_cmd;
1427 for (cnt = 0; NULL != (arg = strtok (ssh_cmd, " ")); ssh_cmd = NULL)
1428 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (arg));
1429 GNUNET_free (ssh_cmd_cp);
1433 ssh_args = copy_argv (default_ssh_args);
1434 cnt = (sizeof (default_ssh_args)) / (sizeof (const char *));
1435 GNUNET_array_grow (ssh_args, cnt, cnt - 1);
1437 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup ("-p"));
1438 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (port));
1439 GNUNET_array_append (ssh_args, cnt, GNUNET_strdup (dst));
1440 GNUNET_array_append (ssh_args, cnt, NULL);
1446 * Generates the arguments needed for executing the given binary in a remote
1447 * shell. Builds the arguments from the environmental variable
1448 * GNUNET_TETSBED_RSH_CMD_SUFFIX. If the environmental variable is not found,
1449 * only the given binary name will be present in the returned arguments
1451 * @param helper_binary_path the path of the binary to execute
1452 * @return NULL-terminated args
1455 gen_rsh_suffix_args (const char *helper_binary_path)
1459 char *rshell_cmd_cp;
1465 if (NULL != (rshell_cmd = getenv ("GNUNET_TESTBED_RSH_CMD_SUFFIX")))
1467 rshell_cmd = GNUNET_strdup (rshell_cmd);
1468 rshell_cmd_cp = rshell_cmd;
1469 for (; NULL != (arg = strtok (rshell_cmd, " ")); rshell_cmd = NULL)
1470 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (arg));
1471 GNUNET_free (rshell_cmd_cp);
1473 GNUNET_array_append (rshell_args, cnt, GNUNET_strdup (helper_binary_path));
1474 GNUNET_array_append (rshell_args, cnt, NULL);
1480 * Starts a controller process at the given host
1482 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1483 * HOST(all connections form this ip are permitted by the testbed) when
1484 * starting testbed controller at host. This can either be a single ip
1485 * address or a network address in CIDR notation.
1486 * @param host the host where the controller has to be started; NULL for
1488 * @param cfg template configuration to use for the remote controller; the
1489 * remote controller will be started with a slightly modified
1490 * configuration (port numbers, unix domain sockets and service home
1491 * values are changed as per TESTING library on the remote host)
1492 * @param cb function called when the controller is successfully started or
1493 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1494 * called if cb is called with GNUNET_SYSERR as status. Will never be
1495 * called in the same task as 'GNUNET_TESTBED_controller_start'
1496 * (synchronous errors will be signalled by returning NULL). This
1497 * parameter cannot be NULL.
1498 * @param cls closure for above callbacks
1499 * @return the controller process handle, NULL on errors
1501 struct GNUNET_TESTBED_ControllerProc *
1502 GNUNET_TESTBED_controller_start (const char *trusted_ip,
1503 struct GNUNET_TESTBED_Host *host,
1504 const struct GNUNET_CONFIGURATION_Handle *cfg,
1505 GNUNET_TESTBED_ControllerStatusCallback cb,
1508 struct GNUNET_TESTBED_ControllerProc *cp;
1509 struct GNUNET_TESTBED_HelperInit *msg;
1510 const char *hostname;
1512 static char *const binary_argv[] = {
1513 HELPER_TESTBED_BINARY, NULL
1517 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1518 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1521 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1522 &helper_mst, &helper_exp_cb, cp);
1526 char *helper_binary_path;
1529 const char *username;
1533 username = GNUNET_TESTBED_host_get_username_ (host);
1534 hostname = GNUNET_TESTBED_host_get_hostname (host);
1535 GNUNET_asprintf (&port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1536 if (NULL == username)
1537 GNUNET_asprintf (&dst, "%s", hostname);
1539 GNUNET_asprintf (&dst, "%s@%s", username, hostname);
1540 LOG_DEBUG ("Starting SSH to destination %s\n", dst);
1543 GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1544 "HELPER_BINARY_PATH",
1545 &helper_binary_path))
1546 helper_binary_path =
1547 GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1548 ssh_args = gen_rsh_args (port, dst);
1549 rshell_args = gen_rsh_suffix_args (helper_binary_path);
1551 join_argv ((const char **) ssh_args, (const char **) rshell_args);
1552 free_argv (ssh_args);
1553 free_argv (rshell_args);
1557 GNUNET_HELPER_start (GNUNET_NO, "ssh", cp->helper_argv, &helper_mst,
1558 &helper_exp_cb, cp);
1559 GNUNET_free (helper_binary_path);
1561 if (NULL == cp->helper)
1563 if (NULL != cp->helper_argv)
1564 free_argv (cp->helper_argv);
1571 msg = GNUNET_TESTBED_create_helper_init_msg_ (trusted_ip, hostname, cfg);
1572 cp->msg = &msg->header;
1574 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1575 if (NULL == cp->shandle)
1578 GNUNET_TESTBED_controller_stop (cp);
1586 * Stop the controller process (also will terminate all peers and controllers
1587 * dependent on this controller). This function blocks until the testbed has
1588 * been fully terminated (!). The controller status cb from
1589 * GNUNET_TESTBED_controller_start() will not be called.
1591 * @param cproc the controller process handle
1594 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1596 if (NULL != cproc->shandle)
1597 GNUNET_HELPER_send_cancel (cproc->shandle);
1598 if (NULL != cproc->helper)
1599 GNUNET_HELPER_soft_stop (cproc->helper);
1600 if (NULL != cproc->cfg)
1601 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1602 if (NULL != cproc->helper_argv)
1603 free_argv (cproc->helper_argv);
1604 GNUNET_free (cproc);
1609 * Start a controller process using the given configuration at the
1612 * @param cfg configuration to use
1613 * @param host host to run the controller on; This should be the same host if
1614 * the controller was previously started with
1615 * GNUNET_TESTBED_controller_start; NULL for localhost
1616 * @param event_mask bit mask with set of events to call 'cc' for;
1617 * or-ed values of "1LL" shifted by the
1618 * respective 'enum GNUNET_TESTBED_EventType'
1619 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1620 * @param cc controller callback to invoke on events
1621 * @param cc_cls closure for cc
1622 * @return handle to the controller
1624 struct GNUNET_TESTBED_Controller *
1625 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1626 *cfg, struct GNUNET_TESTBED_Host *host,
1627 uint64_t event_mask,
1628 GNUNET_TESTBED_ControllerCallback cc,
1631 struct GNUNET_TESTBED_Controller *controller;
1632 struct GNUNET_TESTBED_InitMessage *msg;
1633 const char *controller_hostname;
1634 unsigned long long max_parallel_operations;
1635 unsigned long long max_parallel_service_connections;
1636 unsigned long long max_parallel_topology_config_operations;
1639 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1640 "MAX_PARALLEL_OPERATIONS",
1641 &max_parallel_operations))
1647 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1648 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1649 &max_parallel_service_connections))
1655 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1656 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1657 &max_parallel_topology_config_operations))
1662 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1663 controller->cc = cc;
1664 controller->cc_cls = cc_cls;
1665 controller->event_mask = event_mask;
1666 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1667 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1668 if (NULL == controller->client)
1670 GNUNET_TESTBED_controller_disconnect (controller);
1675 host = GNUNET_TESTBED_host_create_by_id_ (0);
1676 if (NULL == host) /* If the above host create fails */
1678 LOG (GNUNET_ERROR_TYPE_WARNING,
1679 "Treating NULL host as localhost. Multiple references to localhost "
1680 "may break when localhost freed before calling disconnect \n");
1681 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1685 controller->aux_host = GNUNET_YES;
1688 GNUNET_assert (NULL != host);
1689 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1690 controller->host = host;
1691 controller->opq_parallel_operations =
1692 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1693 max_parallel_operations);
1694 controller->opq_parallel_service_connections =
1695 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1696 max_parallel_service_connections);
1697 controller->opq_parallel_topology_config_operations =
1698 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1699 max_parallel_topology_config_operations);
1700 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1701 if (NULL == controller_hostname)
1702 controller_hostname = "127.0.0.1";
1704 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1705 strlen (controller_hostname) + 1);
1706 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1708 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1709 strlen (controller_hostname) + 1);
1710 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1711 msg->event_mask = GNUNET_htonll (controller->event_mask);
1712 strcpy ((char *) &msg[1], controller_hostname);
1713 GNUNET_TESTBED_queue_message_ (controller,
1714 (struct GNUNET_MessageHeader *) msg);
1720 * Configure shared services at a controller. Using this function,
1721 * you can specify that certain services (such as "resolver")
1722 * should not be run for each peer but instead be shared
1723 * across N peers on the specified host. This function
1724 * must be called before any peers are created at the host.
1726 * @param controller controller to configure
1727 * @param service_name name of the service to share
1728 * @param num_peers number of peers that should share one instance
1729 * of the specified service (1 for no sharing is the default),
1730 * use 0 to disable the service
1733 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1735 const char *service_name,
1738 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1739 uint16_t service_name_size;
1742 service_name_size = strlen (service_name) + 1;
1744 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1746 msg = GNUNET_malloc (msg_size);
1747 msg->header.size = htons (msg_size);
1748 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1749 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1750 msg->num_peers = htonl (num_peers);
1751 memcpy (&msg[1], service_name, service_name_size);
1752 GNUNET_TESTBED_queue_message_ (controller,
1753 (struct GNUNET_MessageHeader *) msg);
1754 GNUNET_break (0); /* This function is not yet implemented on the
1755 * testbed service */
1760 * disconnects from the controller.
1762 * @param controller handle to controller to stop
1765 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1768 struct MessageQueue *mq_entry;
1770 if (NULL != controller->th)
1771 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1772 /* Clear the message queue */
1773 while (NULL != (mq_entry = controller->mq_head))
1775 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1777 GNUNET_free (mq_entry->msg);
1778 GNUNET_free (mq_entry);
1780 if (NULL != controller->client)
1781 GNUNET_CLIENT_disconnect (controller->client);
1782 GNUNET_CONFIGURATION_destroy (controller->cfg);
1783 if (GNUNET_YES == controller->aux_host)
1784 GNUNET_TESTBED_host_destroy (controller->host);
1785 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1786 GNUNET_TESTBED_operation_queue_destroy_
1787 (controller->opq_parallel_service_connections);
1788 GNUNET_TESTBED_operation_queue_destroy_
1789 (controller->opq_parallel_topology_config_operations);
1790 GNUNET_free (controller);
1795 * Register a host with the controller
1797 * @param controller the controller handle
1798 * @param host the host to register
1799 * @param cc the completion callback to call to inform the status of
1800 * registration. After calling this callback the registration handle
1801 * will be invalid. Cannot be NULL.
1802 * @param cc_cls the closure for the cc
1803 * @return handle to the host registration which can be used to cancel the
1806 struct GNUNET_TESTBED_HostRegistrationHandle *
1807 GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller,
1808 struct GNUNET_TESTBED_Host *host,
1809 GNUNET_TESTBED_HostRegistrationCompletion cc,
1812 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
1813 struct GNUNET_TESTBED_AddHostMessage *msg;
1814 const char *username;
1815 const char *hostname;
1817 uint16_t user_name_length;
1819 if (NULL != controller->rh)
1821 hostname = GNUNET_TESTBED_host_get_hostname (host);
1822 if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller))
1824 LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n",
1825 (NULL == hostname) ? "localhost" : hostname);
1828 rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
1831 GNUNET_assert (NULL != cc);
1833 rh->cc_cls = cc_cls;
1834 controller->rh = rh;
1835 username = GNUNET_TESTBED_host_get_username_ (host);
1836 msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage));
1837 user_name_length = 0;
1838 if (NULL != username)
1840 user_name_length = strlen (username) + 1;
1841 msg_size += user_name_length;
1843 /* FIXME: what happens when hostname is NULL? localhost */
1844 GNUNET_assert (NULL != hostname);
1845 msg_size += strlen (hostname) + 1;
1846 msg = GNUNET_malloc (msg_size);
1847 msg->header.size = htons (msg_size);
1848 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST);
1849 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1850 msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host));
1851 if (NULL != username)
1853 msg->user_name_length = htons (user_name_length - 1);
1854 memcpy (&msg[1], username, user_name_length);
1857 msg->user_name_length = htons (user_name_length);
1858 strcpy (((void *) &msg[1]) + user_name_length, hostname);
1859 GNUNET_TESTBED_queue_message_ (controller,
1860 (struct GNUNET_MessageHeader *) msg);
1866 * Cancel the pending registration. Note that if the registration message is
1867 * already sent to the service the cancellation has only the effect that the
1868 * registration completion callback for the registration is never called.
1870 * @param handle the registration handle to cancel
1873 GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle
1876 if (handle != handle->c->rh)
1881 handle->c->rh = NULL;
1882 GNUNET_free (handle);
1887 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1890 * @param op_cls the operation closure for the event which is generated to
1891 * signal success or failure of this operation
1892 * @param master handle to the master controller who creates the association
1893 * @param delegated_host_id id of the host to which requests should be delegated
1894 * @param slave_host_id id of the host which is used to run the slave controller
1895 * @param sxcfg serialized and compressed configuration
1896 * @param sxcfg_size the size sxcfg
1897 * @param scfg_size the size of uncompressed serialized configuration
1898 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1899 * be started by the slave controller; GNUNET_NO if the slave
1900 * controller has to connect to the already started delegated
1901 * controller via TCP/IP
1902 * @return the operation handle
1904 struct GNUNET_TESTBED_Operation *
1905 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1906 struct GNUNET_TESTBED_Controller *master,
1907 uint32_t delegated_host_id,
1908 uint32_t slave_host_id, const char *sxcfg,
1909 size_t sxcfg_size, size_t scfg_size,
1912 struct OperationContext *opc;
1913 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1914 struct ControllerLinkData *data;
1917 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1918 msg = GNUNET_malloc (msg_size);
1919 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1920 msg->header.size = htons (msg_size);
1921 msg->delegated_host_id = htonl (delegated_host_id);
1922 msg->slave_host_id = htonl (slave_host_id);
1923 msg->config_size = htons ((uint16_t) scfg_size);
1924 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1925 memcpy (&msg[1], sxcfg, sxcfg_size);
1926 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1928 opc = GNUNET_malloc (sizeof (struct OperationContext));
1931 opc->type = OP_LINK_CONTROLLERS;
1932 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1933 opc->state = OPC_STATE_INIT;
1934 opc->op_cls = op_cls;
1935 msg->operation_id = GNUNET_htonll (opc->id);
1937 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1938 &oprelease_link_controllers);
1939 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1941 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1947 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1948 * serialized and compressed
1950 * @param op_cls the operation closure for the event which is generated to
1951 * signal success or failure of this operation
1952 * @param master handle to the master controller who creates the association
1953 * @param delegated_host requests to which host should be delegated; cannot be NULL
1954 * @param slave_host which host is used to run the slave controller; use NULL to
1955 * make the master controller connect to the delegated host
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 struct GNUNET_TESTBED_Host *delegated_host,
1969 struct GNUNET_TESTBED_Host *slave_host,
1970 const char *sxcfg, size_t sxcfg_size,
1971 size_t scfg_size, int is_subordinate)
1973 uint32_t delegated_host_id;
1974 uint32_t slave_host_id;
1976 GNUNET_assert (GNUNET_YES ==
1977 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1978 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1980 GNUNET_TESTBED_host_get_id_ ((NULL !=
1981 slave_host) ? slave_host : master->host);
1982 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1983 GNUNET_assert (GNUNET_YES ==
1984 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1986 return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1987 slave_host_id, sxcfg, sxcfg_size,
1988 scfg_size, is_subordinate);
1993 * Compresses given configuration using zlib compress
1995 * @param config the serialized configuration
1996 * @param size the size of config
1997 * @param xconfig will be set to the compressed configuration (memory is fresly
1999 * @return the size of the xconfig
2002 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
2007 xsize = compressBound ((uLong) size);
2008 *xconfig = GNUNET_malloc (xsize);
2009 GNUNET_assert (Z_OK ==
2010 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
2011 (const Bytef *) config, (uLongf) size,
2018 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
2021 * @param op_cls the operation closure for the event which is generated to
2022 * signal success or failure of this operation
2023 * @param master handle to the master controller who creates the association
2024 * @param delegated_host_id id of the host to which requests should be
2025 * delegated; cannot be NULL
2026 * @param slave_host_id id of the host which should connect to controller
2027 * running on delegated host ; use NULL to make the master controller
2028 * connect to the delegated host
2029 * @param slave_cfg configuration to use for the slave controller
2030 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2031 * be started by the slave controller; GNUNET_NO if the slave
2032 * controller has to connect to the already started delegated
2033 * controller via TCP/IP
2034 * @return the operation handle
2036 struct GNUNET_TESTBED_Operation *
2037 GNUNET_TESTBED_controller_link_ (void *op_cls,
2038 struct GNUNET_TESTBED_Controller *master,
2039 uint32_t delegated_host_id,
2040 uint32_t slave_host_id,
2041 const struct GNUNET_CONFIGURATION_Handle
2042 *slave_cfg, int is_subordinate)
2044 struct GNUNET_TESTBED_Operation *op;
2050 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
2051 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
2052 GNUNET_free (config);
2053 /* Configuration doesn't fit in 1 message */
2054 GNUNET_assert ((UINT16_MAX -
2055 sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
2057 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
2058 slave_host_id, (const char *) cconfig,
2059 cc_size, config_size, is_subordinate);
2060 GNUNET_free (cconfig);
2066 * Create a link from slave controller to delegated controller. Whenever the
2067 * master controller is asked to start a peer at the delegated controller the
2068 * request will be routed towards slave controller (if a route exists). The
2069 * slave controller will then route it to the delegated controller. The
2070 * configuration of the delegated controller is given and is used to either
2071 * create the delegated controller or to connect to an existing controller. Note
2072 * that while starting the delegated controller the configuration will be
2073 * modified to accommodate available free ports. the 'is_subordinate' specifies
2074 * if the given delegated controller should be started and managed by the slave
2075 * controller, or if the delegated controller already has a master and the slave
2076 * controller connects to it as a non master controller. The success or failure
2077 * of this operation will be signalled through the
2078 * GNUNET_TESTBED_ControllerCallback() with an event of type
2079 * GNUNET_TESTBED_ET_OPERATION_FINISHED
2081 * @param op_cls the operation closure for the event which is generated to
2082 * signal success or failure of this operation
2083 * @param master handle to the master controller who creates the association
2084 * @param delegated_host requests to which host should be delegated; cannot be NULL
2085 * @param slave_host which host is used to run the slave controller; use NULL to
2086 * make the master controller connect to the delegated host
2087 * @param slave_cfg configuration to use for the slave controller
2088 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
2089 * be started by the slave controller; GNUNET_NO if the slave
2090 * controller has to connect to the already started delegated
2091 * controller via TCP/IP
2092 * @return the operation handle
2094 struct GNUNET_TESTBED_Operation *
2095 GNUNET_TESTBED_controller_link (void *op_cls,
2096 struct GNUNET_TESTBED_Controller *master,
2097 struct GNUNET_TESTBED_Host *delegated_host,
2098 struct GNUNET_TESTBED_Host *slave_host,
2099 const struct GNUNET_CONFIGURATION_Handle
2100 *slave_cfg, int is_subordinate)
2102 uint32_t slave_host_id;
2103 uint32_t delegated_host_id;
2105 GNUNET_assert (GNUNET_YES ==
2106 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
2108 GNUNET_TESTBED_host_get_id_ ((NULL !=
2109 slave_host) ? slave_host : master->host);
2110 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
2111 if ((NULL != slave_host) && (0 != slave_host_id))
2112 GNUNET_assert (GNUNET_YES ==
2113 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
2114 return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
2115 slave_host_id, slave_cfg,
2122 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
2123 * check. Another difference is that this function takes the id of the slave
2126 * @param op_cls the closure for the operation
2127 * @param master the handle to master controller
2128 * @param slave_host_id id of the host where the slave controller is running to
2129 * the slave_host should remain valid until this operation is cancelled
2130 * or marked as finished
2131 * @return the operation handle;
2133 struct GNUNET_TESTBED_Operation *
2134 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
2135 struct GNUNET_TESTBED_Controller *master,
2136 uint32_t slave_host_id)
2138 struct OperationContext *opc;
2139 struct GetSlaveConfigData *data;
2141 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
2142 data->slave_id = slave_host_id;
2143 opc = GNUNET_malloc (sizeof (struct OperationContext));
2144 opc->state = OPC_STATE_INIT;
2146 opc->id = GNUNET_TESTBED_get_next_op_id (master);
2147 opc->type = OP_GET_SLAVE_CONFIG;
2149 opc->op_cls = op_cls;
2151 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
2152 &oprelease_get_slave_config);
2153 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2155 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2161 * Function to acquire the configuration of a running slave controller. The
2162 * completion of the operation is signalled through the controller_cb from
2163 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
2164 * handle to the configuration is available in the generic pointer of
2165 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
2167 * @param op_cls the closure for the operation
2168 * @param master the handle to master controller
2169 * @param slave_host the host where the slave controller is running; the handle
2170 * to the slave_host should remain valid until this operation is
2171 * cancelled or marked as finished
2172 * @return the operation handle; NULL if the slave_host is not registered at
2175 struct GNUNET_TESTBED_Operation *
2176 GNUNET_TESTBED_get_slave_config (void *op_cls,
2177 struct GNUNET_TESTBED_Controller *master,
2178 struct GNUNET_TESTBED_Host *slave_host)
2180 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
2182 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
2183 GNUNET_TESTBED_host_get_id_
2189 * Ask the testbed controller to write the current overlay topology to
2190 * a file. Naturally, the file will only contain a snapshot as the
2191 * topology may evolve all the time.
2193 * @param controller overlay controller to inspect
2194 * @param filename name of the file the topology should
2198 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
2200 const char *filename)
2207 * Creates a helper initialization message. This function is here because we
2208 * want to use this in testing
2210 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
2211 * HOST(all connections form this ip are permitted by the testbed) when
2212 * starting testbed controller at host. This can either be a single ip
2213 * address or a network address in CIDR notation.
2214 * @param hostname the hostname of the destination this message is intended for
2215 * @param cfg the configuration that has to used to start the testbed service
2217 * @return the initialization message
2219 struct GNUNET_TESTBED_HelperInit *
2220 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
2221 const char *hostname,
2222 const struct GNUNET_CONFIGURATION_Handle
2225 struct GNUNET_TESTBED_HelperInit *msg;
2229 size_t xconfig_size;
2230 uint16_t trusted_ip_len;
2231 uint16_t hostname_len;
2234 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
2235 GNUNET_assert (NULL != config);
2237 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
2238 GNUNET_free (config);
2239 trusted_ip_len = strlen (trusted_ip);
2240 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2242 xconfig_size + trusted_ip_len + 1 +
2243 sizeof (struct GNUNET_TESTBED_HelperInit);
2244 msg_size += hostname_len;
2245 msg = GNUNET_realloc (xconfig, msg_size);
2246 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
2248 msg->header.size = htons (msg_size);
2249 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2250 msg->trusted_ip_size = htons (trusted_ip_len);
2251 msg->hostname_size = htons (hostname_len);
2252 msg->config_size = htons (config_size);
2253 (void) strcpy ((char *) &msg[1], trusted_ip);
2254 if (0 != hostname_len)
2255 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
2262 * Cancel a pending operation. Releases all resources
2263 * of the operation and will ensure that no event
2264 * is generated for the operation. Does NOT guarantee
2265 * that the operation will be fully undone (or that
2266 * nothing ever happened).
2268 * @param operation operation to cancel
2271 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
2273 GNUNET_TESTBED_operation_done (operation);
2278 * Signal that the information from an operation has been fully
2279 * processed. This function MUST be called for each event
2280 * of type 'operation_finished' to fully remove the operation
2281 * from the operation queue. After calling this function, the
2282 * 'op_result' becomes invalid (!).
2284 * @param operation operation to signal completion for
2287 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2289 last_finished_operation = operation;
2290 GNUNET_TESTBED_operation_release_ (operation);
2295 * Generates configuration by uncompressing configuration in given message. The
2296 * given message should be of the following types:
2297 * GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG,
2298 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG
2300 * @param msg the message containing compressed configuration
2301 * @return handle to the parsed configuration
2303 struct GNUNET_CONFIGURATION_Handle *
2304 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2306 struct GNUNET_CONFIGURATION_Handle *cfg;
2313 switch (ntohs (msg->type))
2315 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
2317 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2320 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
2321 data_len = (uLong) ntohs (imsg->config_size);
2323 ntohs (imsg->header.size) -
2324 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2325 xdata = (const Bytef *) &imsg[1];
2328 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
2330 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2332 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2333 data_len = (uLong) ntohs (imsg->config_size);
2335 ntohs (imsg->header.size) -
2336 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2337 xdata = (const Bytef *) &imsg[1];
2343 data = GNUNET_malloc (data_len);
2344 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
2346 cfg = GNUNET_CONFIGURATION_create ();
2347 GNUNET_assert (GNUNET_OK ==
2348 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2357 * Checks the integrity of the OperationFailureEventMessage and if good returns
2358 * the error message it contains.
2360 * @param msg the OperationFailureEventMessage
2361 * @return the error message
2364 GNUNET_TESTBED_parse_error_string_ (const struct
2365 GNUNET_TESTBED_OperationFailureEventMessage
2371 msize = ntohs (msg->header.size);
2372 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2374 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2375 emsg = (const char *) &msg[1];
2376 if ('\0' != emsg[msize - 1])
2386 * Function to return the operation id for a controller. The operation id is
2387 * created from the controllers host id and its internal operation counter.
2389 * @param controller the handle to the controller whose operation id has to be incremented
2390 * @return the incremented operation id.
2393 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2397 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2398 op_id = op_id << 32;
2399 op_id |= (uint64_t) controller->operation_counter++;
2404 /* end of testbed_api.c */