2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
47 * Generic logging shorthand
49 #define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
55 #define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
59 * Relative time seconds shorthand
61 #define TIME_REL_SECS(sec) \
62 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
66 * Default server message sending retry timeout
68 #define TIMEOUT_REL TIME_REL_SECS(1)
72 * The message queue for sending messages to the controller service
77 * The message to be sent
79 struct GNUNET_MessageHeader *msg;
82 * next pointer for DLL
84 struct MessageQueue *next;
87 * prev pointer for DLL
89 struct MessageQueue *prev;
94 * Structure for a controller link
99 * The next ptr for DLL
101 struct ControllerLink *next;
104 * The prev ptr for DLL
106 struct ControllerLink *prev;
109 * The host which will be referred in the peer start request. This is the
110 * host where the peer should be started
112 struct GNUNET_TESTBED_Host *delegated_host;
115 * The host which will contacted to delegate the peer start request
117 struct GNUNET_TESTBED_Host *slave_host;
120 * The configuration to be used to connect to slave host
122 const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
125 * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
126 * if we are just allowed to use the slave via TCP/IP
133 * Context data for forwarded Operation
135 struct ForwardedOperationData
139 * The callback to call when reply is available
141 GNUNET_CLIENT_MessageHandler cc;
144 * The closure for the above callback
152 * Context data for get slave config operations
154 struct GetSlaveConfigData
157 * The id of the slave controller
165 * Context data for controller link operations
167 struct ControllerLinkData
170 * The controller link message
172 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
178 * This variable is set to the operation that has been last marked as done. It
179 * is used to verify whether the state associated with an operation is valid
180 * after the first notify callback is called. Such checks are necessary for
181 * certain operations where we have 2 notify callbacks. Examples are
182 * OP_PEER_CREATE, OP_PEER_START/STOP, OP_OVERLAY_CONNECT.
184 * This variable should ONLY be used to compare; it is a dangling pointer!!
186 static const struct GNUNET_TESTBED_Operation *last_finished_operation;
190 * Returns the operation context with the given id if found in the Operation
191 * context queues of the controller
193 * @param c the controller whose queues are searched
194 * @param id the id which has to be checked
195 * @return the matching operation context; NULL if no match found
197 static struct OperationContext *
198 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
200 struct OperationContext *opc;
202 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
212 * Handler for forwarded operations
214 * @param c the controller handle
215 * @param opc the opearation context
216 * @param msg the message
219 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
220 struct OperationContext *opc,
221 const struct GNUNET_MessageHeader *msg)
223 struct ForwardedOperationData *fo_data;
226 if (NULL != fo_data->cc)
227 fo_data->cc (fo_data->cc_cls, msg);
228 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
229 GNUNET_free (fo_data);
235 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
236 * controller (testbed service)
238 * @param c the controller handler
239 * @param msg message received
240 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
244 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
246 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
248 struct OperationContext *opc;
249 struct GNUNET_TESTBED_EventInformation event;
252 op_id = GNUNET_ntohll (msg->operation_id);
253 LOG_DEBUG ("Operation %lu successful\n", op_id);
254 if (NULL == (opc = find_opc (c, op_id)))
256 LOG_DEBUG ("Operation not found\n");
259 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
260 event.details.operation_finished.operation = opc->op;
261 event.details.operation_finished.op_cls = opc->op_cls;
262 event.details.operation_finished.emsg = NULL;
263 event.details.operation_finished.generic = NULL;
268 handle_forwarded_operation_msg (c, opc,
269 (const struct GNUNET_MessageHeader *) msg);
273 case OP_PEER_DESTROY:
275 struct GNUNET_TESTBED_Peer *peer;
283 case OP_LINK_CONTROLLERS:
285 struct ControllerLinkData *data;
288 GNUNET_assert (NULL != data);
296 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
297 opc->state = OPC_STATE_FINISHED;
298 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
301 c->cc (c->cc_cls, &event);
304 LOG_DEBUG ("Not calling callback\n");
310 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
311 * controller (testbed service)
313 * @param c the controller handle
314 * @param msg message received
315 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
319 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
321 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
323 struct OperationContext *opc;
324 struct PeerCreateData *data;
325 struct GNUNET_TESTBED_Peer *peer;
326 GNUNET_TESTBED_PeerCreateCallback cb;
330 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
331 ntohs (msg->header.size));
332 op_id = GNUNET_ntohll (msg->operation_id);
333 if (NULL == (opc = find_opc (c, op_id)))
335 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
338 if (OP_FORWARDED == opc->type)
340 handle_forwarded_operation_msg (c, opc,
341 (const struct GNUNET_MessageHeader *) msg);
344 GNUNET_assert (OP_PEER_CREATE == opc->type);
345 GNUNET_assert (NULL != opc->data);
347 GNUNET_assert (NULL != data->peer);
349 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
350 peer->state = PS_CREATED;
353 GNUNET_free (opc->data);
354 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
355 opc->state = OPC_STATE_FINISHED;
357 cb (cls, peer, NULL);
363 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
364 * controller (testbed service)
366 * @param c the controller handler
367 * @param msg message received
368 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
372 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
373 const struct GNUNET_TESTBED_PeerEventMessage *msg)
375 struct OperationContext *opc;
376 struct GNUNET_TESTBED_Peer *peer;
377 struct PeerEventData *data;
378 GNUNET_TESTBED_PeerChurnCallback pcc;
380 struct GNUNET_TESTBED_EventInformation event;
383 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
384 ntohs (msg->header.size));
385 op_id = GNUNET_ntohll (msg->operation_id);
386 if (NULL == (opc = find_opc (c, op_id)))
388 LOG_DEBUG ("Operation not found\n");
391 if (OP_FORWARDED == opc->type)
393 handle_forwarded_operation_msg (c, opc,
394 (const struct GNUNET_MessageHeader *) msg);
397 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
399 GNUNET_assert (NULL != data);
401 GNUNET_assert (NULL != peer);
402 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
405 case GNUNET_TESTBED_ET_PEER_START:
406 peer->state = PS_STARTED;
407 event.details.peer_start.host = peer->host;
408 event.details.peer_start.peer = peer;
410 case GNUNET_TESTBED_ET_PEER_STOP:
411 peer->state = PS_STOPPED;
412 event.details.peer_stop.peer = peer;
415 GNUNET_assert (0); /* We should never reach this state */
418 pcc_cls = data->pcc_cls;
420 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
421 opc->state = OPC_STATE_FINISHED;
423 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
427 c->cc (c->cc_cls, &event);
436 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
437 * controller (testbed service)
439 * @param c the controller handler
440 * @param msg message received
441 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
445 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
446 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
448 struct OperationContext *opc;
449 struct OverlayConnectData *data;
450 GNUNET_TESTBED_OperationCompletionCallback cb;
452 struct GNUNET_TESTBED_EventInformation event;
455 op_id = GNUNET_ntohll (msg->operation_id);
456 if (NULL == (opc = find_opc (c, op_id)))
458 LOG_DEBUG ("Operation not found\n");
461 if (OP_FORWARDED == opc->type)
463 handle_forwarded_operation_msg (c, opc,
464 (const struct GNUNET_MessageHeader *) msg);
467 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
469 GNUNET_assert (NULL != data);
470 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
471 (ntohl (msg->peer2) == data->p2->unique_id));
472 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
475 case GNUNET_TESTBED_ET_CONNECT:
476 event.details.peer_connect.peer1 = data->p1;
477 event.details.peer_connect.peer2 = data->p2;
479 case GNUNET_TESTBED_ET_DISCONNECT:
480 GNUNET_assert (0); /* FIXME: implement */
483 GNUNET_assert (0); /* Should never reach here */
487 cb_cls = data->cb_cls;
488 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
489 opc->state = OPC_STATE_FINISHED;
491 cb (cb_cls, opc->op, NULL);
493 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
497 c->cc (c->cc_cls, &event);
504 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
505 * controller (testbed service)
507 * @param c the controller handler
508 * @param msg message received
509 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
513 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
515 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
517 struct OperationContext *opc;
518 struct GNUNET_TESTBED_Peer *peer;
519 struct PeerInfoData *data;
520 struct GNUNET_TESTBED_PeerInformation *pinfo;
521 GNUNET_TESTBED_PeerInfoCallback cb;
525 op_id = GNUNET_ntohll (msg->operation_id);
526 if (NULL == (opc = find_opc (c, op_id)))
528 LOG_DEBUG ("Operation not found\n");
531 if (OP_FORWARDED == opc->type)
533 handle_forwarded_operation_msg (c, opc,
534 (const struct GNUNET_MessageHeader *) msg);
538 GNUNET_assert (NULL != data);
540 GNUNET_assert (NULL != peer);
541 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
542 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
543 pinfo->pit = data->pit;
545 cb_cls = data->cb_cls;
550 case GNUNET_TESTBED_PIT_IDENTITY:
551 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
552 (void) memcpy (pinfo->result.id, &msg->peer_identity,
553 sizeof (struct GNUNET_PeerIdentity));
555 case GNUNET_TESTBED_PIT_CONFIGURATION:
556 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
557 GNUNET_TESTBED_extract_config_ (&msg->header);
559 case GNUNET_TESTBED_PIT_GENERIC:
560 GNUNET_assert (0); /* never reach here */
564 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
565 opc->state = OPC_STATE_FINISHED;
567 cb (cb_cls, opc->op, pinfo, NULL);
573 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
574 * controller (testbed service)
576 * @param c the controller handler
577 * @param msg message received
578 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
582 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
583 const struct GNUNET_TESTBED_OperationFailureEventMessage
586 struct OperationContext *opc;
589 struct GNUNET_TESTBED_EventInformation event;
591 op_id = GNUNET_ntohll (msg->operation_id);
592 if (NULL == (opc = find_opc (c, op_id)))
594 LOG_DEBUG ("Operation not found\n");
597 if (OP_FORWARDED == opc->type)
599 handle_forwarded_operation_msg (c, opc,
600 (const struct GNUNET_MessageHeader *) msg);
603 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
604 opc->state = OPC_STATE_FINISHED;
605 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
607 emsg = "Unknown error";
608 if (OP_PEER_INFO == opc->type)
610 struct PeerInfoData *data;
613 if (NULL != data->cb)
614 data->cb (data->cb_cls, opc->op, NULL, emsg);
616 return GNUNET_YES; /* We do not call controller callback for peer info */
618 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
621 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
622 event.details.operation_finished.operation = opc->op;
623 event.details.operation_finished.op_cls = opc->op_cls;
624 event.details.operation_finished.emsg = emsg;
625 event.details.operation_finished.generic = NULL;
626 c->cc (c->cc_cls, &event);
627 if (event.details.operation_finished.operation == last_finished_operation)
634 struct PeerCreateData *data;
637 GNUNET_free (data->peer);
638 if (NULL != data->cb)
639 data->cb (data->cls, NULL, emsg);
646 struct PeerEventData *data;
649 if (NULL != data->pcc)
650 data->pcc (data->pcc_cls, emsg);
654 case OP_PEER_DESTROY:
658 case OP_OVERLAY_CONNECT:
660 struct OverlayConnectData *data;
663 data->failed = GNUNET_YES;
664 if (NULL != data->cb)
665 data->cb (data->cb_cls, opc->op, emsg);
670 case OP_LINK_CONTROLLERS: /* No secondary callback */
680 * Function to build GET_SLAVE_CONFIG message
682 * @param op_id the id this message should contain in its operation id field
683 * @param slave_id the id this message should contain in its slave id field
684 * @return newly allocated SlaveGetConfigurationMessage
686 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
687 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
689 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
692 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
693 msg = GNUNET_malloc (msize);
694 msg->header.size = htons (msize);
696 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
697 msg->operation_id = GNUNET_htonll (op_id);
698 msg->slave_id = htonl (slave_id);
704 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
707 * @param c the controller handler
708 * @param msg message received
709 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
713 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
714 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
716 struct OperationContext *opc;
718 struct GNUNET_TESTBED_EventInformation event;
720 op_id = GNUNET_ntohll (msg->operation_id);
721 if (NULL == (opc = find_opc (c, op_id)))
723 LOG_DEBUG ("Operation not found\n");
726 if (OP_GET_SLAVE_CONFIG != opc->type)
731 GNUNET_free (opc->data);
733 opc->state = OPC_STATE_FINISHED;
734 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
735 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
738 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
739 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
740 event.details.operation_finished.generic = opc->data;
741 event.details.operation_finished.operation = opc->op;
742 event.details.operation_finished.op_cls = opc->op_cls;
743 event.details.operation_finished.emsg = NULL;
744 c->cc (c->cc_cls, &event);
751 * Handler for messages from controller (testbed service)
753 * @param cls the controller handler
754 * @param msg message received, NULL on timeout or fatal error
757 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
759 struct GNUNET_TESTBED_Controller *c = cls;
763 c->in_receive = GNUNET_NO;
764 /* FIXME: Add checks for message integrity */
767 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
771 msize = ntohs (msg->size);
772 switch (ntohs (msg->type))
774 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
775 GNUNET_assert (msize >=
776 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
778 GNUNET_TESTBED_host_handle_addhostconfirm_
779 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
781 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
782 GNUNET_assert (msize ==
784 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
788 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
791 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
792 GNUNET_assert (msize ==
794 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
796 handle_peer_create_success (c,
798 GNUNET_TESTBED_PeerCreateSuccessEventMessage
801 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
802 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
804 handle_peer_event (c,
805 (const struct GNUNET_TESTBED_PeerEventMessage *)
809 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
810 GNUNET_assert (msize >=
812 GNUNET_TESTBED_PeerConfigurationInformationMessage));
814 handle_peer_config (c,
816 GNUNET_TESTBED_PeerConfigurationInformationMessage
819 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
820 GNUNET_assert (msize ==
821 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
823 handle_peer_conevent (c,
825 GNUNET_TESTBED_ConnectionEventMessage *) msg);
827 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
828 GNUNET_assert (msize >=
829 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
831 handle_op_fail_event (c,
833 GNUNET_TESTBED_OperationFailureEventMessage *)
836 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
837 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
839 handle_slave_config (c,
840 (const struct GNUNET_TESTBED_SlaveConfiguration *)
846 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
848 c->in_receive = GNUNET_YES;
849 GNUNET_CLIENT_receive (c->client, &message_handler, c,
850 GNUNET_TIME_UNIT_FOREVER_REL);
856 * Function called to notify a client about the connection begin ready to queue
857 * more data. "buf" will be NULL and "size" zero if the connection was closed
858 * for writing in the meantime.
861 * @param size number of bytes available in buf
862 * @param buf where the callee should write the message
863 * @return number of bytes written to buf
866 transmit_ready_notify (void *cls, size_t size, void *buf)
868 struct GNUNET_TESTBED_Controller *c = cls;
869 struct MessageQueue *mq_entry;
872 mq_entry = c->mq_head;
873 GNUNET_assert (NULL != mq_entry);
874 if ((0 == size) && (NULL == buf)) /* Timeout */
876 LOG_DEBUG ("Message sending timed out -- retrying\n");
878 GNUNET_CLIENT_notify_transmit_ready (c->client,
879 ntohs (mq_entry->msg->size),
880 TIMEOUT_REL, GNUNET_YES,
881 &transmit_ready_notify, c);
884 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
885 size = ntohs (mq_entry->msg->size);
886 memcpy (buf, mq_entry->msg, size);
887 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
888 ntohs (mq_entry->msg->type), size);
889 GNUNET_free (mq_entry->msg);
890 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
891 GNUNET_free (mq_entry);
892 mq_entry = c->mq_head;
893 if (NULL != mq_entry)
895 GNUNET_CLIENT_notify_transmit_ready (c->client,
896 ntohs (mq_entry->msg->size),
897 TIMEOUT_REL, GNUNET_YES,
898 &transmit_ready_notify, c);
899 if (GNUNET_NO == c->in_receive)
901 c->in_receive = GNUNET_YES;
902 GNUNET_CLIENT_receive (c->client, &message_handler, c,
903 GNUNET_TIME_UNIT_FOREVER_REL);
910 * Queues a message in send queue for sending to the service
912 * @param controller the handle to the controller
913 * @param msg the message to queue
916 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
917 struct GNUNET_MessageHeader *msg)
919 struct MessageQueue *mq_entry;
923 type = ntohs (msg->type);
924 size = ntohs (msg->size);
925 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
926 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
927 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
929 LOG (GNUNET_ERROR_TYPE_DEBUG,
930 "Queueing message of type %u, size %u for sending\n", type,
932 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
934 if (NULL == controller->th)
936 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
937 TIMEOUT_REL, GNUNET_YES,
938 &transmit_ready_notify,
944 * Sends the given message as an operation. The given callback is called when a
945 * reply for the operation is available. Call
946 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
947 * operation context if the cc hasn't been called
949 * @param controller the controller to which the message has to be sent
950 * @param operation_id the operation id of the message
951 * @param msg the message to send
952 * @param cc the callback to call when reply is available
953 * @param cc_cls the closure for the above callback
954 * @return the operation context which can be used to cancel the forwarded
957 struct OperationContext *
958 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
959 *controller, uint64_t operation_id,
960 const struct GNUNET_MessageHeader *msg,
961 GNUNET_CLIENT_MessageHandler cc,
964 struct OperationContext *opc;
965 struct ForwardedOperationData *data;
966 struct GNUNET_MessageHeader *dup_msg;
969 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
971 data->cc_cls = cc_cls;
972 opc = GNUNET_malloc (sizeof (struct OperationContext));
974 opc->type = OP_FORWARDED;
976 opc->id = operation_id;
977 msize = ntohs (msg->size);
978 dup_msg = GNUNET_malloc (msize);
979 (void) memcpy (dup_msg, msg, msize);
980 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
981 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
988 * Function to cancel an operation created by simply forwarding an operation
991 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
994 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
996 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
997 GNUNET_free (opc->data);
1003 * Function to call to start a link-controllers type operation once all queues
1004 * the operation is part of declare that the operation can be activated.
1006 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1009 opstart_link_controllers (void *cls)
1011 struct OperationContext *opc = cls;
1012 struct ControllerLinkData *data;
1013 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1015 GNUNET_assert (NULL != opc->data);
1019 opc->state = OPC_STATE_STARTED;
1020 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1021 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1026 * Callback which will be called when link-controllers type operation is released
1028 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1031 oprelease_link_controllers (void *cls)
1033 struct OperationContext *opc = cls;
1034 struct ControllerLinkData *data;
1039 case OPC_STATE_INIT:
1040 GNUNET_free (data->msg);
1042 case OPC_STATE_STARTED:
1043 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1045 case OPC_STATE_FINISHED:
1048 GNUNET_free_non_null (data);
1054 * Function to be called when get slave config operation is ready
1056 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1059 opstart_get_slave_config (void *cls)
1061 struct OperationContext *opc = cls;
1062 struct GetSlaveConfigData *data;
1063 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1066 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1067 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1068 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1069 opc->state = OPC_STATE_STARTED;
1074 * Function to be called when get slave config operation is cancelled or finished
1076 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1079 oprelease_get_slave_config (void *cls)
1081 struct OperationContext *opc = cls;
1085 case OPC_STATE_INIT:
1086 GNUNET_free (opc->data);
1088 case OPC_STATE_STARTED:
1089 GNUNET_free (opc->data);
1090 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1092 case OPC_STATE_FINISHED:
1093 if (NULL != opc->data)
1094 GNUNET_CONFIGURATION_destroy (opc->data);
1102 * Start a controller process using the given configuration at the
1105 * @param cfg configuration to use
1106 * @param host host to run the controller on; This should be the same host if
1107 * the controller was previously started with
1108 * GNUNET_TESTBED_controller_start; NULL for localhost
1109 * @param event_mask bit mask with set of events to call 'cc' for;
1110 * or-ed values of "1LL" shifted by the
1111 * respective 'enum GNUNET_TESTBED_EventType'
1112 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1113 * @param cc controller callback to invoke on events
1114 * @param cc_cls closure for cc
1115 * @return handle to the controller
1117 struct GNUNET_TESTBED_Controller *
1118 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1119 *cfg, struct GNUNET_TESTBED_Host *host,
1120 uint64_t event_mask,
1121 GNUNET_TESTBED_ControllerCallback cc,
1124 struct GNUNET_TESTBED_Controller *controller;
1125 struct GNUNET_TESTBED_InitMessage *msg;
1126 const char *controller_hostname;
1127 unsigned long long max_parallel_operations;
1128 unsigned long long max_parallel_service_connections;
1129 unsigned long long max_parallel_topology_config_operations;
1132 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1133 "MAX_PARALLEL_OPERATIONS",
1134 &max_parallel_operations))
1140 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1141 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1142 &max_parallel_service_connections))
1148 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1149 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1150 &max_parallel_topology_config_operations))
1155 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1156 controller->cc = cc;
1157 controller->cc_cls = cc_cls;
1158 controller->event_mask = event_mask;
1159 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1160 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1161 if (NULL == controller->client)
1163 GNUNET_TESTBED_controller_disconnect (controller);
1168 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1169 if (NULL == host) /* If the above host create fails */
1171 LOG (GNUNET_ERROR_TYPE_WARNING,
1172 "Treating NULL host as localhost. Multiple references to localhost "
1173 "may break when localhost freed before calling disconnect \n");
1174 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1178 controller->aux_host = GNUNET_YES;
1181 GNUNET_assert (NULL != host);
1182 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1183 controller->host = host;
1184 controller->opq_parallel_operations =
1185 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1186 max_parallel_operations);
1187 controller->opq_parallel_service_connections =
1188 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1189 max_parallel_service_connections);
1190 controller->opq_parallel_topology_config_operations =
1191 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1192 max_parallel_topology_config_operations);
1193 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1194 if (NULL == controller_hostname)
1195 controller_hostname = "127.0.0.1";
1197 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1198 strlen (controller_hostname) + 1);
1199 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1201 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1202 strlen (controller_hostname) + 1);
1203 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1204 msg->event_mask = GNUNET_htonll (controller->event_mask);
1205 strcpy ((char *) &msg[1], controller_hostname);
1206 GNUNET_TESTBED_queue_message_ (controller,
1207 (struct GNUNET_MessageHeader *) msg);
1213 * Configure shared services at a controller. Using this function,
1214 * you can specify that certain services (such as "resolver")
1215 * should not be run for each peer but instead be shared
1216 * across N peers on the specified host. This function
1217 * must be called before any peers are created at the host.
1219 * @param controller controller to configure
1220 * @param service_name name of the service to share
1221 * @param num_peers number of peers that should share one instance
1222 * of the specified service (1 for no sharing is the default),
1223 * use 0 to disable the service
1226 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1228 const char *service_name,
1231 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1232 uint16_t service_name_size;
1235 service_name_size = strlen (service_name) + 1;
1237 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1239 msg = GNUNET_malloc (msg_size);
1240 msg->header.size = htons (msg_size);
1241 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1242 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1243 msg->num_peers = htonl (num_peers);
1244 memcpy (&msg[1], service_name, service_name_size);
1245 GNUNET_TESTBED_queue_message_ (controller,
1246 (struct GNUNET_MessageHeader *) msg);
1247 GNUNET_break (0); /* This function is not yet implemented on the
1248 * testbed service */
1253 * disconnects from the controller.
1255 * @param controller handle to controller to stop
1258 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1261 struct MessageQueue *mq_entry;
1263 if (NULL != controller->th)
1264 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1265 /* Clear the message queue */
1266 while (NULL != (mq_entry = controller->mq_head))
1268 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1270 GNUNET_free (mq_entry->msg);
1271 GNUNET_free (mq_entry);
1273 if (NULL != controller->client)
1274 GNUNET_CLIENT_disconnect (controller->client);
1275 GNUNET_CONFIGURATION_destroy (controller->cfg);
1276 if (GNUNET_YES == controller->aux_host)
1277 GNUNET_TESTBED_host_destroy (controller->host);
1278 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1279 GNUNET_TESTBED_operation_queue_destroy_
1280 (controller->opq_parallel_service_connections);
1281 GNUNET_TESTBED_operation_queue_destroy_
1282 (controller->opq_parallel_topology_config_operations);
1283 GNUNET_free (controller);
1288 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1291 * @param op_cls the operation closure for the event which is generated to
1292 * signal success or failure of this operation
1293 * @param master handle to the master controller who creates the association
1294 * @param delegated_host_id id of the host to which requests should be delegated
1295 * @param slave_host_id id of the host which is used to run the slave controller
1296 * @param sxcfg serialized and compressed configuration
1297 * @param sxcfg_size the size sxcfg
1298 * @param scfg_size the size of uncompressed serialized configuration
1299 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1300 * be started by the slave controller; GNUNET_NO if the slave
1301 * controller has to connect to the already started delegated
1302 * controller via TCP/IP
1303 * @return the operation handle
1305 struct GNUNET_TESTBED_Operation *
1306 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1307 struct GNUNET_TESTBED_Controller *master,
1308 uint32_t delegated_host_id,
1309 uint32_t slave_host_id, const char *sxcfg,
1310 size_t sxcfg_size, size_t scfg_size,
1313 struct OperationContext *opc;
1314 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1315 struct ControllerLinkData *data;
1318 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1319 msg = GNUNET_malloc (msg_size);
1320 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1321 msg->header.size = htons (msg_size);
1322 msg->delegated_host_id = htonl (delegated_host_id);
1323 msg->slave_host_id = htonl (slave_host_id);
1324 msg->config_size = htons ((uint16_t) scfg_size);
1325 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1326 memcpy (&msg[1], sxcfg, sxcfg_size);
1327 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1329 opc = GNUNET_malloc (sizeof (struct OperationContext));
1332 opc->type = OP_LINK_CONTROLLERS;
1333 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1334 opc->state = OPC_STATE_INIT;
1335 opc->op_cls = op_cls;
1336 msg->operation_id = GNUNET_htonll (opc->id);
1338 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1339 &oprelease_link_controllers);
1340 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1342 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1348 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1349 * serialized and compressed
1351 * @param op_cls the operation closure for the event which is generated to
1352 * signal success or failure of this operation
1353 * @param master handle to the master controller who creates the association
1354 * @param delegated_host requests to which host should be delegated; cannot be NULL
1355 * @param slave_host which host is used to run the slave controller; use NULL to
1356 * make the master controller connect to the delegated host
1357 * @param sxcfg serialized and compressed configuration
1358 * @param sxcfg_size the size sxcfg
1359 * @param scfg_size the size of uncompressed serialized configuration
1360 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1361 * be started by the slave controller; GNUNET_NO if the slave
1362 * controller has to connect to the already started delegated
1363 * controller via TCP/IP
1364 * @return the operation handle
1366 struct GNUNET_TESTBED_Operation *
1367 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1368 struct GNUNET_TESTBED_Controller *master,
1369 struct GNUNET_TESTBED_Host *delegated_host,
1370 struct GNUNET_TESTBED_Host *slave_host,
1371 const char *sxcfg, size_t sxcfg_size,
1372 size_t scfg_size, int is_subordinate)
1374 uint32_t delegated_host_id;
1375 uint32_t slave_host_id;
1377 GNUNET_assert (GNUNET_YES ==
1378 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1379 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1381 GNUNET_TESTBED_host_get_id_ ((NULL !=
1382 slave_host) ? slave_host : master->host);
1383 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1384 GNUNET_assert (GNUNET_YES ==
1385 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1387 return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1388 slave_host_id, sxcfg, sxcfg_size,
1389 scfg_size, is_subordinate);
1394 * Compresses given configuration using zlib compress
1396 * @param config the serialized configuration
1397 * @param size the size of config
1398 * @param xconfig will be set to the compressed configuration (memory is fresly
1400 * @return the size of the xconfig
1403 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1408 xsize = compressBound ((uLong) size);
1409 *xconfig = GNUNET_malloc (xsize);
1410 GNUNET_assert (Z_OK ==
1411 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1412 (const Bytef *) config, (uLongf) size,
1419 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1422 * @param op_cls the operation closure for the event which is generated to
1423 * signal success or failure of this operation
1424 * @param master handle to the master controller who creates the association
1425 * @param delegated_host_id id of the host to which requests should be
1426 * delegated; cannot be NULL
1427 * @param slave_host_id id of the host which should connect to controller
1428 * running on delegated host ; use NULL to make the master controller
1429 * connect to the delegated host
1430 * @param slave_cfg configuration to use for the slave controller
1431 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1432 * be started by the slave controller; GNUNET_NO if the slave
1433 * controller has to connect to the already started delegated
1434 * controller via TCP/IP
1435 * @return the operation handle
1437 struct GNUNET_TESTBED_Operation *
1438 GNUNET_TESTBED_controller_link_ (void *op_cls,
1439 struct GNUNET_TESTBED_Controller *master,
1440 uint32_t delegated_host_id,
1441 uint32_t slave_host_id,
1442 const struct GNUNET_CONFIGURATION_Handle
1443 *slave_cfg, int is_subordinate)
1445 struct GNUNET_TESTBED_Operation *op;
1451 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1452 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1453 GNUNET_free (config);
1454 /* Configuration doesn't fit in 1 message */
1455 GNUNET_assert ((UINT16_MAX -
1456 sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
1458 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1459 slave_host_id, (const char *) cconfig,
1460 cc_size, config_size, is_subordinate);
1461 GNUNET_free (cconfig);
1467 * Create a link from slave controller to delegated controller. Whenever the
1468 * master controller is asked to start a peer at the delegated controller the
1469 * request will be routed towards slave controller (if a route exists). The
1470 * slave controller will then route it to the delegated controller. The
1471 * configuration of the delegated controller is given and is used to either
1472 * create the delegated controller or to connect to an existing controller. Note
1473 * that while starting the delegated controller the configuration will be
1474 * modified to accommodate available free ports. the 'is_subordinate' specifies
1475 * if the given delegated controller should be started and managed by the slave
1476 * controller, or if the delegated controller already has a master and the slave
1477 * controller connects to it as a non master controller. The success or failure
1478 * of this operation will be signalled through the
1479 * GNUNET_TESTBED_ControllerCallback() with an event of type
1480 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1482 * @param op_cls the operation closure for the event which is generated to
1483 * signal success or failure of this operation
1484 * @param master handle to the master controller who creates the association
1485 * @param delegated_host requests to which host should be delegated; cannot be NULL
1486 * @param slave_host which host is used to run the slave controller; use NULL to
1487 * make the master controller connect to the delegated host
1488 * @param slave_cfg configuration to use for the slave controller
1489 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1490 * be started by the slave controller; GNUNET_NO if the slave
1491 * controller has to connect to the already started delegated
1492 * controller via TCP/IP
1493 * @return the operation handle
1495 struct GNUNET_TESTBED_Operation *
1496 GNUNET_TESTBED_controller_link (void *op_cls,
1497 struct GNUNET_TESTBED_Controller *master,
1498 struct GNUNET_TESTBED_Host *delegated_host,
1499 struct GNUNET_TESTBED_Host *slave_host,
1500 const struct GNUNET_CONFIGURATION_Handle
1501 *slave_cfg, int is_subordinate)
1503 uint32_t slave_host_id;
1504 uint32_t delegated_host_id;
1506 GNUNET_assert (GNUNET_YES ==
1507 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1509 GNUNET_TESTBED_host_get_id_ ((NULL !=
1510 slave_host) ? slave_host : master->host);
1511 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1512 if ((NULL != slave_host) && (0 != slave_host_id))
1513 GNUNET_assert (GNUNET_YES ==
1514 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1515 return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
1516 slave_host_id, slave_cfg,
1523 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1524 * check. Another difference is that this function takes the id of the slave
1527 * @param op_cls the closure for the operation
1528 * @param master the handle to master controller
1529 * @param slave_host_id id of the host where the slave controller is running to
1530 * the slave_host should remain valid until this operation is cancelled
1531 * or marked as finished
1532 * @return the operation handle;
1534 struct GNUNET_TESTBED_Operation *
1535 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1536 struct GNUNET_TESTBED_Controller *master,
1537 uint32_t slave_host_id)
1539 struct OperationContext *opc;
1540 struct GetSlaveConfigData *data;
1542 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1543 data->slave_id = slave_host_id;
1544 opc = GNUNET_malloc (sizeof (struct OperationContext));
1545 opc->state = OPC_STATE_INIT;
1547 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1548 opc->type = OP_GET_SLAVE_CONFIG;
1550 opc->op_cls = op_cls;
1552 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1553 &oprelease_get_slave_config);
1554 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1556 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1562 * Function to acquire the configuration of a running slave controller. The
1563 * completion of the operation is signalled through the controller_cb from
1564 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1565 * handle to the configuration is available in the generic pointer of
1566 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1568 * @param op_cls the closure for the operation
1569 * @param master the handle to master controller
1570 * @param slave_host the host where the slave controller is running; the handle
1571 * to the slave_host should remain valid until this operation is
1572 * cancelled or marked as finished
1573 * @return the operation handle; NULL if the slave_host is not registered at
1576 struct GNUNET_TESTBED_Operation *
1577 GNUNET_TESTBED_get_slave_config (void *op_cls,
1578 struct GNUNET_TESTBED_Controller *master,
1579 struct GNUNET_TESTBED_Host *slave_host)
1581 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1583 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1584 GNUNET_TESTBED_host_get_id_
1590 * Ask the testbed controller to write the current overlay topology to
1591 * a file. Naturally, the file will only contain a snapshot as the
1592 * topology may evolve all the time.
1594 * @param controller overlay controller to inspect
1595 * @param filename name of the file the topology should
1599 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1601 const char *filename)
1608 * Creates a helper initialization message. This function is here because we
1609 * want to use this in testing
1611 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1612 * HOST(all connections form this ip are permitted by the testbed) when
1613 * starting testbed controller at host. This can either be a single ip
1614 * address or a network address in CIDR notation.
1615 * @param hostname the hostname of the destination this message is intended for
1616 * @param cfg the configuration that has to used to start the testbed service
1618 * @return the initialization message
1620 struct GNUNET_TESTBED_HelperInit *
1621 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1622 const char *hostname,
1623 const struct GNUNET_CONFIGURATION_Handle
1626 struct GNUNET_TESTBED_HelperInit *msg;
1630 size_t xconfig_size;
1631 uint16_t trusted_ip_len;
1632 uint16_t hostname_len;
1635 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1636 GNUNET_assert (NULL != config);
1638 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1639 GNUNET_free (config);
1640 trusted_ip_len = strlen (trusted_ip);
1641 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1643 xconfig_size + trusted_ip_len + 1 +
1644 sizeof (struct GNUNET_TESTBED_HelperInit);
1645 msg_size += hostname_len;
1646 msg = GNUNET_realloc (xconfig, msg_size);
1647 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1649 msg->header.size = htons (msg_size);
1650 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1651 msg->trusted_ip_size = htons (trusted_ip_len);
1652 msg->hostname_size = htons (hostname_len);
1653 msg->config_size = htons (config_size);
1654 (void) strcpy ((char *) &msg[1], trusted_ip);
1655 if (0 != hostname_len)
1656 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1663 * Cancel a pending operation. Releases all resources
1664 * of the operation and will ensure that no event
1665 * is generated for the operation. Does NOT guarantee
1666 * that the operation will be fully undone (or that
1667 * nothing ever happened).
1669 * @param operation operation to cancel
1672 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
1674 GNUNET_TESTBED_operation_done (operation);
1679 * Signal that the information from an operation has been fully
1680 * processed. This function MUST be called for each event
1681 * of type 'operation_finished' to fully remove the operation
1682 * from the operation queue. After calling this function, the
1683 * 'op_result' becomes invalid (!).
1685 * @param operation operation to signal completion for
1688 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1690 last_finished_operation = operation;
1691 GNUNET_TESTBED_operation_release_ (operation);
1696 * Generates configuration by uncompressing configuration in given message. The
1697 * given message should be of the following types:
1698 * GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION,
1699 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1700 * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST
1702 * @param msg the message containing compressed configuration
1703 * @return handle to the parsed configuration; NULL upon error while parsing the message
1705 struct GNUNET_CONFIGURATION_Handle *
1706 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1708 struct GNUNET_CONFIGURATION_Handle *cfg;
1715 switch (ntohs (msg->type))
1717 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1719 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1722 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1723 data_len = (uLong) ntohs (imsg->config_size);
1725 ntohs (imsg->header.size) -
1726 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1727 xdata = (const Bytef *) &imsg[1];
1730 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1732 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1734 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1735 data_len = (uLong) ntohs (imsg->config_size);
1737 ntohs (imsg->header.size) -
1738 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1739 xdata = (const Bytef *) &imsg[1];
1742 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1744 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1747 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1748 data_len = (uLong) ntohs (imsg->config_size);
1749 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1750 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1751 xdata_len = ntohs (imsg->header.size) - osize;
1752 xdata = (const Bytef *) ((const void *) imsg + osize);
1758 data = GNUNET_malloc (data_len);
1759 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1764 cfg = GNUNET_CONFIGURATION_create ();
1765 GNUNET_assert (GNUNET_OK ==
1766 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
1775 * Checks the integrity of the OperationFailureEventMessage and if good returns
1776 * the error message it contains.
1778 * @param msg the OperationFailureEventMessage
1779 * @return the error message
1782 GNUNET_TESTBED_parse_error_string_ (const struct
1783 GNUNET_TESTBED_OperationFailureEventMessage
1789 msize = ntohs (msg->header.size);
1790 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
1792 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
1793 emsg = (const char *) &msg[1];
1794 if ('\0' != emsg[msize - 1])
1804 * Function to return the operation id for a controller. The operation id is
1805 * created from the controllers host id and its internal operation counter.
1807 * @param controller the handle to the controller whose operation id has to be incremented
1808 * @return the incremented operation id.
1811 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
1815 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
1816 op_id = op_id << 32;
1817 op_id |= (uint64_t) controller->operation_counter++;
1822 /* end of testbed_api.c */