2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
47 * Generic logging shorthand
49 #define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
55 #define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
59 * Relative time seconds shorthand
61 #define TIME_REL_SECS(sec) \
62 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
66 * Default server message sending retry timeout
68 #define TIMEOUT_REL TIME_REL_SECS(1)
72 * The message queue for sending messages to the controller service
77 * The message to be sent
79 struct GNUNET_MessageHeader *msg;
82 * next pointer for DLL
84 struct MessageQueue *next;
87 * prev pointer for DLL
89 struct MessageQueue *prev;
94 * Context data for forwarded Operation
96 struct ForwardedOperationData
100 * The callback to call when reply is available
102 GNUNET_CLIENT_MessageHandler cc;
105 * The closure for the above callback
113 * Context data for get slave config operations
115 struct GetSlaveConfigData
118 * The id of the slave controller
126 * Context data for controller link operations
128 struct ControllerLinkData
131 * The controller link message
133 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
136 * The id of the host which is hosting the controller to be linked
144 * This variable is set to the operation that has been last marked as done. It
145 * is used to verify whether the state associated with an operation is valid
146 * after the first notify callback is called. Such checks are necessary for
147 * certain operations where we have 2 notify callbacks. Examples are
148 * OP_PEER_CREATE, OP_PEER_START/STOP, OP_OVERLAY_CONNECT.
150 * This variable should ONLY be used to compare; it is a dangling pointer!!
152 static const struct GNUNET_TESTBED_Operation *last_finished_operation;
156 * Returns the operation context with the given id if found in the Operation
157 * context queues of the controller
159 * @param c the controller whose queues are searched
160 * @param id the id which has to be checked
161 * @return the matching operation context; NULL if no match found
163 static struct OperationContext *
164 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
166 struct OperationContext *opc;
168 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
178 * Handler for forwarded operations
180 * @param c the controller handle
181 * @param opc the opearation context
182 * @param msg the message
185 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
186 struct OperationContext *opc,
187 const struct GNUNET_MessageHeader *msg)
189 struct ForwardedOperationData *fo_data;
192 if (NULL != fo_data->cc)
193 fo_data->cc (fo_data->cc_cls, msg);
194 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
195 GNUNET_free (fo_data);
201 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
202 * controller (testbed service)
204 * @param c the controller handler
205 * @param msg message received
206 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
210 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
212 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
214 struct OperationContext *opc;
215 struct GNUNET_TESTBED_EventInformation event;
218 op_id = GNUNET_ntohll (msg->operation_id);
219 LOG_DEBUG ("Operation %lu successful\n", op_id);
220 if (NULL == (opc = find_opc (c, op_id)))
222 LOG_DEBUG ("Operation not found\n");
225 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
226 event.details.operation_finished.operation = opc->op;
227 event.details.operation_finished.op_cls = opc->op_cls;
228 event.details.operation_finished.emsg = NULL;
229 event.details.operation_finished.generic = NULL;
234 handle_forwarded_operation_msg (c, opc,
235 (const struct GNUNET_MessageHeader *) msg);
239 case OP_PEER_DESTROY:
241 struct GNUNET_TESTBED_Peer *peer;
252 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
253 opc->state = OPC_STATE_FINISHED;
254 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
257 c->cc (c->cc_cls, &event);
260 LOG_DEBUG ("Not calling callback\n");
266 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
267 * controller (testbed service)
269 * @param c the controller handle
270 * @param msg message received
271 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
275 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
277 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
279 struct OperationContext *opc;
280 struct PeerCreateData *data;
281 struct GNUNET_TESTBED_Peer *peer;
282 GNUNET_TESTBED_PeerCreateCallback cb;
286 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
287 ntohs (msg->header.size));
288 op_id = GNUNET_ntohll (msg->operation_id);
289 if (NULL == (opc = find_opc (c, op_id)))
291 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
294 if (OP_FORWARDED == opc->type)
296 handle_forwarded_operation_msg (c, opc,
297 (const struct GNUNET_MessageHeader *) msg);
300 GNUNET_assert (OP_PEER_CREATE == opc->type);
301 GNUNET_assert (NULL != opc->data);
303 GNUNET_assert (NULL != data->peer);
305 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
306 peer->state = PS_CREATED;
309 GNUNET_free (opc->data);
310 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
311 opc->state = OPC_STATE_FINISHED;
313 cb (cls, peer, NULL);
319 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
320 * controller (testbed service)
322 * @param c the controller handler
323 * @param msg message received
324 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
328 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
329 const struct GNUNET_TESTBED_PeerEventMessage *msg)
331 struct OperationContext *opc;
332 struct GNUNET_TESTBED_Peer *peer;
333 struct PeerEventData *data;
334 GNUNET_TESTBED_PeerChurnCallback pcc;
336 struct GNUNET_TESTBED_EventInformation event;
339 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
340 ntohs (msg->header.size));
341 op_id = GNUNET_ntohll (msg->operation_id);
342 if (NULL == (opc = find_opc (c, op_id)))
344 LOG_DEBUG ("Operation not found\n");
347 if (OP_FORWARDED == opc->type)
349 handle_forwarded_operation_msg (c, opc,
350 (const struct GNUNET_MessageHeader *) msg);
353 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
355 GNUNET_assert (NULL != data);
357 GNUNET_assert (NULL != peer);
358 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
361 case GNUNET_TESTBED_ET_PEER_START:
362 peer->state = PS_STARTED;
363 event.details.peer_start.host = peer->host;
364 event.details.peer_start.peer = peer;
366 case GNUNET_TESTBED_ET_PEER_STOP:
367 peer->state = PS_STOPPED;
368 event.details.peer_stop.peer = peer;
371 GNUNET_assert (0); /* We should never reach this state */
374 pcc_cls = data->pcc_cls;
376 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
377 opc->state = OPC_STATE_FINISHED;
379 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
383 c->cc (c->cc_cls, &event);
392 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
393 * controller (testbed service)
395 * @param c the controller handler
396 * @param msg message received
397 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
401 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
402 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
404 struct OperationContext *opc;
405 struct OverlayConnectData *data;
406 GNUNET_TESTBED_OperationCompletionCallback cb;
408 struct GNUNET_TESTBED_EventInformation event;
411 op_id = GNUNET_ntohll (msg->operation_id);
412 if (NULL == (opc = find_opc (c, op_id)))
414 LOG_DEBUG ("Operation not found\n");
417 if (OP_FORWARDED == opc->type)
419 handle_forwarded_operation_msg (c, opc,
420 (const struct GNUNET_MessageHeader *) msg);
423 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
425 GNUNET_assert (NULL != data);
426 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
427 (ntohl (msg->peer2) == data->p2->unique_id));
428 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
431 case GNUNET_TESTBED_ET_CONNECT:
432 event.details.peer_connect.peer1 = data->p1;
433 event.details.peer_connect.peer2 = data->p2;
435 case GNUNET_TESTBED_ET_DISCONNECT:
436 GNUNET_assert (0); /* FIXME: implement */
439 GNUNET_assert (0); /* Should never reach here */
443 cb_cls = data->cb_cls;
444 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
445 opc->state = OPC_STATE_FINISHED;
447 cb (cb_cls, opc->op, NULL);
449 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
453 c->cc (c->cc_cls, &event);
460 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
461 * controller (testbed service)
463 * @param c the controller handler
464 * @param msg message received
465 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
469 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
471 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
473 struct OperationContext *opc;
474 struct GNUNET_TESTBED_Peer *peer;
475 struct PeerInfoData *data;
476 struct GNUNET_TESTBED_PeerInformation *pinfo;
477 GNUNET_TESTBED_PeerInfoCallback cb;
481 op_id = GNUNET_ntohll (msg->operation_id);
482 if (NULL == (opc = find_opc (c, op_id)))
484 LOG_DEBUG ("Operation not found\n");
487 if (OP_FORWARDED == opc->type)
489 handle_forwarded_operation_msg (c, opc,
490 (const struct GNUNET_MessageHeader *) msg);
494 GNUNET_assert (NULL != data);
496 GNUNET_assert (NULL != peer);
497 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
498 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
499 pinfo->pit = data->pit;
501 cb_cls = data->cb_cls;
506 case GNUNET_TESTBED_PIT_IDENTITY:
507 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
508 (void) memcpy (pinfo->result.id, &msg->peer_identity,
509 sizeof (struct GNUNET_PeerIdentity));
511 case GNUNET_TESTBED_PIT_CONFIGURATION:
512 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
513 GNUNET_TESTBED_extract_config_ (&msg->header);
515 case GNUNET_TESTBED_PIT_GENERIC:
516 GNUNET_assert (0); /* never reach here */
520 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
521 opc->state = OPC_STATE_FINISHED;
523 cb (cb_cls, opc->op, pinfo, NULL);
529 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
530 * controller (testbed service)
532 * @param c the controller handler
533 * @param msg message received
534 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
538 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
539 const struct GNUNET_TESTBED_OperationFailureEventMessage
542 struct OperationContext *opc;
545 struct GNUNET_TESTBED_EventInformation event;
547 op_id = GNUNET_ntohll (msg->operation_id);
548 if (NULL == (opc = find_opc (c, op_id)))
550 LOG_DEBUG ("Operation not found\n");
553 if (OP_FORWARDED == opc->type)
555 handle_forwarded_operation_msg (c, opc,
556 (const struct GNUNET_MessageHeader *) msg);
559 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
560 opc->state = OPC_STATE_FINISHED;
561 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
563 emsg = "Unknown error";
564 if (OP_PEER_INFO == opc->type)
566 struct PeerInfoData *data;
569 if (NULL != data->cb)
570 data->cb (data->cb_cls, opc->op, NULL, emsg);
572 return GNUNET_YES; /* We do not call controller callback for peer info */
574 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
577 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
578 event.details.operation_finished.operation = opc->op;
579 event.details.operation_finished.op_cls = opc->op_cls;
580 event.details.operation_finished.emsg = emsg;
581 event.details.operation_finished.generic = NULL;
582 c->cc (c->cc_cls, &event);
583 if (event.details.operation_finished.operation == last_finished_operation)
590 struct PeerCreateData *data;
593 GNUNET_free (data->peer);
594 if (NULL != data->cb)
595 data->cb (data->cls, NULL, emsg);
602 struct PeerEventData *data;
605 if (NULL != data->pcc)
606 data->pcc (data->pcc_cls, emsg);
610 case OP_PEER_DESTROY:
614 case OP_OVERLAY_CONNECT:
616 struct OverlayConnectData *data;
619 data->failed = GNUNET_YES;
620 if (NULL != data->cb)
621 data->cb (data->cb_cls, opc->op, emsg);
626 case OP_LINK_CONTROLLERS: /* No secondary callback */
636 * Function to build GET_SLAVE_CONFIG message
638 * @param op_id the id this message should contain in its operation id field
639 * @param slave_id the id this message should contain in its slave id field
640 * @return newly allocated SlaveGetConfigurationMessage
642 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
643 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
645 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
648 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
649 msg = GNUNET_malloc (msize);
650 msg->header.size = htons (msize);
652 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
653 msg->operation_id = GNUNET_htonll (op_id);
654 msg->slave_id = htonl (slave_id);
660 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
663 * @param c the controller handler
664 * @param msg message received
665 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
669 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
670 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
672 struct OperationContext *opc;
674 struct GNUNET_TESTBED_EventInformation event;
676 op_id = GNUNET_ntohll (msg->operation_id);
677 if (NULL == (opc = find_opc (c, op_id)))
679 LOG_DEBUG ("Operation not found\n");
682 if (OP_GET_SLAVE_CONFIG != opc->type)
687 GNUNET_free (opc->data);
689 opc->state = OPC_STATE_FINISHED;
690 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
691 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
694 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
695 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
696 event.details.operation_finished.generic = opc->data;
697 event.details.operation_finished.operation = opc->op;
698 event.details.operation_finished.op_cls = opc->op_cls;
699 event.details.operation_finished.emsg = NULL;
700 c->cc (c->cc_cls, &event);
707 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
710 * @param c the controller handler
711 * @param msg message received
712 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
716 handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
718 GNUNET_TESTBED_ControllerLinkResponse *msg)
720 struct OperationContext *opc;
721 struct ControllerLinkData *data;
722 struct GNUNET_CONFIGURATION_Handle *cfg;
723 struct GNUNET_TESTBED_Host *host;
726 struct GNUNET_TESTBED_EventInformation event;
728 op_id = GNUNET_ntohll (msg->operation_id);
729 if (NULL == (opc = find_opc (c, op_id)))
731 LOG_DEBUG ("Operation not found\n");
734 if (OP_FORWARDED == opc->type)
736 handle_forwarded_operation_msg (c, opc,
737 (const struct GNUNET_MessageHeader *) msg);
740 if (OP_LINK_CONTROLLERS != opc->type)
746 GNUNET_assert (NULL != data);
747 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
748 GNUNET_assert (NULL != host);
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 = NULL;
755 event.details.operation_finished.generic = NULL;
758 if (GNUNET_NO == ntohs (msg->success))
760 emsg = GNUNET_malloc (ntohs (msg->header.size)
762 GNUNET_TESTBED_ControllerLinkResponse) + 1);
763 memcpy (emsg, &msg[1], ntohs (msg->header.size)
765 GNUNET_TESTBED_ControllerLinkResponse));
766 event.details.operation_finished.emsg = emsg;
770 if (0 != ntohs (msg->config_size))
772 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
773 GNUNET_assert (NULL != cfg);
774 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
777 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
778 opc->state = OPC_STATE_FINISHED;
779 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
782 c->cc (c->cc_cls, &event);
785 LOG_DEBUG ("Not calling callback\n");
787 GNUNET_CONFIGURATION_destroy (cfg);
788 GNUNET_free_non_null (emsg);
794 * Handler for messages from controller (testbed service)
796 * @param cls the controller handler
797 * @param msg message received, NULL on timeout or fatal error
800 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
802 struct GNUNET_TESTBED_Controller *c = cls;
806 c->in_receive = GNUNET_NO;
807 /* FIXME: Add checks for message integrity */
810 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
814 msize = ntohs (msg->size);
815 switch (ntohs (msg->type))
817 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
818 GNUNET_assert (msize >=
819 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
821 GNUNET_TESTBED_host_handle_addhostconfirm_
822 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
824 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
825 GNUNET_assert (msize ==
827 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
831 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
834 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
835 GNUNET_assert (msize ==
837 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
839 handle_peer_create_success (c,
841 GNUNET_TESTBED_PeerCreateSuccessEventMessage
844 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
845 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
847 handle_peer_event (c,
848 (const struct GNUNET_TESTBED_PeerEventMessage *)
852 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
853 GNUNET_assert (msize >=
855 GNUNET_TESTBED_PeerConfigurationInformationMessage));
857 handle_peer_config (c,
859 GNUNET_TESTBED_PeerConfigurationInformationMessage
862 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
863 GNUNET_assert (msize ==
864 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
866 handle_peer_conevent (c,
868 GNUNET_TESTBED_ConnectionEventMessage *) msg);
870 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
871 GNUNET_assert (msize >=
872 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
874 handle_op_fail_event (c,
876 GNUNET_TESTBED_OperationFailureEventMessage *)
879 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
880 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
882 handle_slave_config (c,
883 (const struct GNUNET_TESTBED_SlaveConfiguration *)
886 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
888 handle_link_controllers_result (c,
890 GNUNET_TESTBED_ControllerLinkResponse
896 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
898 c->in_receive = GNUNET_YES;
899 GNUNET_CLIENT_receive (c->client, &message_handler, c,
900 GNUNET_TIME_UNIT_FOREVER_REL);
906 * Function called to notify a client about the connection begin ready to queue
907 * more data. "buf" will be NULL and "size" zero if the connection was closed
908 * for writing in the meantime.
911 * @param size number of bytes available in buf
912 * @param buf where the callee should write the message
913 * @return number of bytes written to buf
916 transmit_ready_notify (void *cls, size_t size, void *buf)
918 struct GNUNET_TESTBED_Controller *c = cls;
919 struct MessageQueue *mq_entry;
922 mq_entry = c->mq_head;
923 GNUNET_assert (NULL != mq_entry);
924 if ((0 == size) && (NULL == buf)) /* Timeout */
926 LOG_DEBUG ("Message sending timed out -- retrying\n");
928 GNUNET_CLIENT_notify_transmit_ready (c->client,
929 ntohs (mq_entry->msg->size),
930 TIMEOUT_REL, GNUNET_YES,
931 &transmit_ready_notify, c);
934 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
935 size = ntohs (mq_entry->msg->size);
936 memcpy (buf, mq_entry->msg, size);
937 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
938 ntohs (mq_entry->msg->type), size);
939 GNUNET_free (mq_entry->msg);
940 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
941 GNUNET_free (mq_entry);
942 mq_entry = c->mq_head;
943 if (NULL != mq_entry)
945 GNUNET_CLIENT_notify_transmit_ready (c->client,
946 ntohs (mq_entry->msg->size),
947 TIMEOUT_REL, GNUNET_YES,
948 &transmit_ready_notify, c);
949 if (GNUNET_NO == c->in_receive)
951 c->in_receive = GNUNET_YES;
952 GNUNET_CLIENT_receive (c->client, &message_handler, c,
953 GNUNET_TIME_UNIT_FOREVER_REL);
960 * Queues a message in send queue for sending to the service
962 * @param controller the handle to the controller
963 * @param msg the message to queue
966 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
967 struct GNUNET_MessageHeader *msg)
969 struct MessageQueue *mq_entry;
973 type = ntohs (msg->type);
974 size = ntohs (msg->size);
975 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
976 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
977 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
979 LOG (GNUNET_ERROR_TYPE_DEBUG,
980 "Queueing message of type %u, size %u for sending\n", type,
982 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
984 if (NULL == controller->th)
986 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
987 TIMEOUT_REL, GNUNET_YES,
988 &transmit_ready_notify,
994 * Sends the given message as an operation. The given callback is called when a
995 * reply for the operation is available. Call
996 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
997 * operation context if the cc hasn't been called
999 * @param controller the controller to which the message has to be sent
1000 * @param operation_id the operation id of the message
1001 * @param msg the message to send
1002 * @param cc the callback to call when reply is available
1003 * @param cc_cls the closure for the above callback
1004 * @return the operation context which can be used to cancel the forwarded
1007 struct OperationContext *
1008 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1009 *controller, uint64_t operation_id,
1010 const struct GNUNET_MessageHeader *msg,
1011 GNUNET_CLIENT_MessageHandler cc,
1014 struct OperationContext *opc;
1015 struct ForwardedOperationData *data;
1016 struct GNUNET_MessageHeader *dup_msg;
1019 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1021 data->cc_cls = cc_cls;
1022 opc = GNUNET_malloc (sizeof (struct OperationContext));
1023 opc->c = controller;
1024 opc->type = OP_FORWARDED;
1026 opc->id = operation_id;
1027 msize = ntohs (msg->size);
1028 dup_msg = GNUNET_malloc (msize);
1029 (void) memcpy (dup_msg, msg, msize);
1030 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1031 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1038 * Function to cancel an operation created by simply forwarding an operation
1041 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1044 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1046 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1047 GNUNET_free (opc->data);
1053 * Function to call to start a link-controllers type operation once all queues
1054 * the operation is part of declare that the operation can be activated.
1056 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1059 opstart_link_controllers (void *cls)
1061 struct OperationContext *opc = cls;
1062 struct ControllerLinkData *data;
1063 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1065 GNUNET_assert (NULL != opc->data);
1069 opc->state = OPC_STATE_STARTED;
1070 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1071 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1076 * Callback which will be called when link-controllers type operation is released
1078 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1081 oprelease_link_controllers (void *cls)
1083 struct OperationContext *opc = cls;
1084 struct ControllerLinkData *data;
1089 case OPC_STATE_INIT:
1090 GNUNET_free (data->msg);
1092 case OPC_STATE_STARTED:
1093 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1095 case OPC_STATE_FINISHED:
1098 GNUNET_free_non_null (data);
1104 * Function to be called when get slave config operation is ready
1106 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1109 opstart_get_slave_config (void *cls)
1111 struct OperationContext *opc = cls;
1112 struct GetSlaveConfigData *data;
1113 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1116 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1117 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1118 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1119 opc->state = OPC_STATE_STARTED;
1124 * Function to be called when get slave config operation is cancelled or finished
1126 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1129 oprelease_get_slave_config (void *cls)
1131 struct OperationContext *opc = cls;
1135 case OPC_STATE_INIT:
1136 GNUNET_free (opc->data);
1138 case OPC_STATE_STARTED:
1139 GNUNET_free (opc->data);
1140 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1142 case OPC_STATE_FINISHED:
1143 if (NULL != opc->data)
1144 GNUNET_CONFIGURATION_destroy (opc->data);
1152 * Start a controller process using the given configuration at the
1155 * @param cfg configuration to use
1156 * @param host host to run the controller on; This should be the same host if
1157 * the controller was previously started with
1158 * GNUNET_TESTBED_controller_start; NULL for localhost
1159 * @param event_mask bit mask with set of events to call 'cc' for;
1160 * or-ed values of "1LL" shifted by the
1161 * respective 'enum GNUNET_TESTBED_EventType'
1162 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1163 * @param cc controller callback to invoke on events
1164 * @param cc_cls closure for cc
1165 * @return handle to the controller
1167 struct GNUNET_TESTBED_Controller *
1168 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1169 *cfg, struct GNUNET_TESTBED_Host *host,
1170 uint64_t event_mask,
1171 GNUNET_TESTBED_ControllerCallback cc,
1174 struct GNUNET_TESTBED_Controller *controller;
1175 struct GNUNET_TESTBED_InitMessage *msg;
1176 const char *controller_hostname;
1177 unsigned long long max_parallel_operations;
1178 unsigned long long max_parallel_service_connections;
1179 unsigned long long max_parallel_topology_config_operations;
1182 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1183 "MAX_PARALLEL_OPERATIONS",
1184 &max_parallel_operations))
1190 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1191 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1192 &max_parallel_service_connections))
1198 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1199 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1200 &max_parallel_topology_config_operations))
1205 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1206 controller->cc = cc;
1207 controller->cc_cls = cc_cls;
1208 controller->event_mask = event_mask;
1209 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1210 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1211 if (NULL == controller->client)
1213 GNUNET_TESTBED_controller_disconnect (controller);
1218 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1219 if (NULL == host) /* If the above host create fails */
1221 LOG (GNUNET_ERROR_TYPE_WARNING,
1222 "Treating NULL host as localhost. Multiple references to localhost "
1223 "may break when localhost freed before calling disconnect \n");
1224 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1228 controller->aux_host = GNUNET_YES;
1231 GNUNET_assert (NULL != host);
1232 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1233 controller->host = host;
1234 controller->opq_parallel_operations =
1235 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1236 max_parallel_operations);
1237 controller->opq_parallel_service_connections =
1238 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1239 max_parallel_service_connections);
1240 controller->opq_parallel_topology_config_operations =
1241 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1242 max_parallel_topology_config_operations);
1243 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1244 if (NULL == controller_hostname)
1245 controller_hostname = "127.0.0.1";
1247 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1248 strlen (controller_hostname) + 1);
1249 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1251 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1252 strlen (controller_hostname) + 1);
1253 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1254 msg->event_mask = GNUNET_htonll (controller->event_mask);
1255 strcpy ((char *) &msg[1], controller_hostname);
1256 GNUNET_TESTBED_queue_message_ (controller,
1257 (struct GNUNET_MessageHeader *) msg);
1263 * Configure shared services at a controller. Using this function,
1264 * you can specify that certain services (such as "resolver")
1265 * should not be run for each peer but instead be shared
1266 * across N peers on the specified host. This function
1267 * must be called before any peers are created at the host.
1269 * @param controller controller to configure
1270 * @param service_name name of the service to share
1271 * @param num_peers number of peers that should share one instance
1272 * of the specified service (1 for no sharing is the default),
1273 * use 0 to disable the service
1276 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1278 const char *service_name,
1281 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1282 uint16_t service_name_size;
1285 service_name_size = strlen (service_name) + 1;
1287 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1289 msg = GNUNET_malloc (msg_size);
1290 msg->header.size = htons (msg_size);
1291 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1292 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1293 msg->num_peers = htonl (num_peers);
1294 memcpy (&msg[1], service_name, service_name_size);
1295 GNUNET_TESTBED_queue_message_ (controller,
1296 (struct GNUNET_MessageHeader *) msg);
1297 GNUNET_break (0); /* This function is not yet implemented on the
1298 * testbed service */
1303 * disconnects from the controller.
1305 * @param controller handle to controller to stop
1308 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1311 struct MessageQueue *mq_entry;
1313 if (NULL != controller->th)
1314 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1315 /* Clear the message queue */
1316 while (NULL != (mq_entry = controller->mq_head))
1318 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1320 GNUNET_free (mq_entry->msg);
1321 GNUNET_free (mq_entry);
1323 if (NULL != controller->client)
1324 GNUNET_CLIENT_disconnect (controller->client);
1325 GNUNET_CONFIGURATION_destroy (controller->cfg);
1326 if (GNUNET_YES == controller->aux_host)
1327 GNUNET_TESTBED_host_destroy (controller->host);
1328 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1329 GNUNET_TESTBED_operation_queue_destroy_
1330 (controller->opq_parallel_service_connections);
1331 GNUNET_TESTBED_operation_queue_destroy_
1332 (controller->opq_parallel_topology_config_operations);
1333 GNUNET_free (controller);
1338 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1341 * @param op_cls the operation closure for the event which is generated to
1342 * signal success or failure of this operation
1343 * @param master handle to the master controller who creates the association
1344 * @param delegated_host_id id of the host to which requests should be delegated
1345 * @param slave_host_id id of the host which is used to run the slave controller
1346 * @param sxcfg serialized and compressed configuration
1347 * @param sxcfg_size the size sxcfg
1348 * @param scfg_size the size of uncompressed serialized configuration
1349 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1350 * be started by the slave controller; GNUNET_NO if the slave
1351 * controller has to connect to the already started delegated
1352 * controller via TCP/IP
1353 * @return the operation handle
1355 struct GNUNET_TESTBED_Operation *
1356 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1357 struct GNUNET_TESTBED_Controller *master,
1358 uint32_t delegated_host_id,
1359 uint32_t slave_host_id, const char *sxcfg,
1360 size_t sxcfg_size, size_t scfg_size,
1363 struct OperationContext *opc;
1364 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1365 struct ControllerLinkData *data;
1368 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1369 msg = GNUNET_malloc (msg_size);
1370 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1371 msg->header.size = htons (msg_size);
1372 msg->delegated_host_id = htonl (delegated_host_id);
1373 msg->slave_host_id = htonl (slave_host_id);
1374 msg->config_size = htons ((uint16_t) scfg_size);
1375 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1376 memcpy (&msg[1], sxcfg, sxcfg_size);
1377 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1379 data->host_id = delegated_host_id;
1380 opc = GNUNET_malloc (sizeof (struct OperationContext));
1383 opc->type = OP_LINK_CONTROLLERS;
1384 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1385 opc->state = OPC_STATE_INIT;
1386 opc->op_cls = op_cls;
1387 msg->operation_id = GNUNET_htonll (opc->id);
1389 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1390 &oprelease_link_controllers);
1391 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1393 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1399 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1400 * serialized and compressed
1402 * @param op_cls the operation closure for the event which is generated to
1403 * signal success or failure of this operation
1404 * @param master handle to the master controller who creates the association
1405 * @param delegated_host requests to which host should be delegated; cannot be NULL
1406 * @param slave_host which host is used to run the slave controller; use NULL to
1407 * make the master controller connect to the delegated host
1408 * @param sxcfg serialized and compressed configuration
1409 * @param sxcfg_size the size sxcfg
1410 * @param scfg_size the size of uncompressed serialized configuration
1411 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1412 * be started by the slave controller; GNUNET_NO if the slave
1413 * controller has to connect to the already started delegated
1414 * controller via TCP/IP
1415 * @return the operation handle
1417 struct GNUNET_TESTBED_Operation *
1418 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1419 struct GNUNET_TESTBED_Controller *master,
1420 struct GNUNET_TESTBED_Host *delegated_host,
1421 struct GNUNET_TESTBED_Host *slave_host,
1422 const char *sxcfg, size_t sxcfg_size,
1423 size_t scfg_size, int is_subordinate)
1425 uint32_t delegated_host_id;
1426 uint32_t slave_host_id;
1428 GNUNET_assert (GNUNET_YES ==
1429 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1430 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1432 GNUNET_TESTBED_host_get_id_ ((NULL !=
1433 slave_host) ? slave_host : master->host);
1434 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1435 GNUNET_assert (GNUNET_YES ==
1436 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1438 return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1439 slave_host_id, sxcfg, sxcfg_size,
1440 scfg_size, is_subordinate);
1445 * Compresses given configuration using zlib compress
1447 * @param config the serialized configuration
1448 * @param size the size of config
1449 * @param xconfig will be set to the compressed configuration (memory is fresly
1451 * @return the size of the xconfig
1454 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1459 xsize = compressBound ((uLong) size);
1460 *xconfig = GNUNET_malloc (xsize);
1461 GNUNET_assert (Z_OK ==
1462 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1463 (const Bytef *) config, (uLongf) size,
1470 * Function to serialize and compress using zlib a configuration through a
1471 * configuration handle
1473 * @param cfg the configuration
1474 * @param size the size of configuration when serialize. Will be set on success.
1475 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1476 * @return the serialized and compressed configuration
1479 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1480 size_t *size, size_t *xsize)
1487 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1488 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1489 GNUNET_free (config);
1497 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1500 * @param op_cls the operation closure for the event which is generated to
1501 * signal success or failure of this operation
1502 * @param master handle to the master controller who creates the association
1503 * @param delegated_host_id id of the host to which requests should be
1504 * delegated; cannot be NULL
1505 * @param slave_host_id id of the host which should connect to controller
1506 * running on delegated host ; use NULL to make the master controller
1507 * connect to the delegated host
1508 * @param slave_cfg configuration to use for the slave controller
1509 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1510 * be started by the slave controller; GNUNET_NO if the slave
1511 * controller has to connect to the already started delegated
1512 * controller via TCP/IP
1513 * @return the operation handle
1515 struct GNUNET_TESTBED_Operation *
1516 GNUNET_TESTBED_controller_link_ (void *op_cls,
1517 struct GNUNET_TESTBED_Controller *master,
1518 uint32_t delegated_host_id,
1519 uint32_t slave_host_id,
1520 const struct GNUNET_CONFIGURATION_Handle
1521 *slave_cfg, int is_subordinate)
1523 struct GNUNET_TESTBED_Operation *op;
1529 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1530 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1531 GNUNET_free (config);
1532 /* Configuration doesn't fit in 1 message */
1533 GNUNET_assert ((UINT16_MAX -
1534 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)) >=
1536 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1537 slave_host_id, (const char *) cconfig,
1538 cc_size, config_size, is_subordinate);
1539 GNUNET_free (cconfig);
1545 * Create a link from slave controller to delegated controller. Whenever the
1546 * master controller is asked to start a peer at the delegated controller the
1547 * request will be routed towards slave controller (if a route exists). The
1548 * slave controller will then route it to the delegated controller. The
1549 * configuration of the delegated controller is given and is used to either
1550 * create the delegated controller or to connect to an existing controller. Note
1551 * that while starting the delegated controller the configuration will be
1552 * modified to accommodate available free ports. the 'is_subordinate' specifies
1553 * if the given delegated controller should be started and managed by the slave
1554 * controller, or if the delegated controller already has a master and the slave
1555 * controller connects to it as a non master controller. The success or failure
1556 * of this operation will be signalled through the
1557 * GNUNET_TESTBED_ControllerCallback() with an event of type
1558 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1560 * @param op_cls the operation closure for the event which is generated to
1561 * signal success or failure of this operation
1562 * @param master handle to the master controller who creates the association
1563 * @param delegated_host requests to which host should be delegated; cannot be NULL
1564 * @param slave_host which host is used to run the slave controller; use NULL to
1565 * make the master controller connect to the delegated host
1566 * @param slave_cfg configuration to use for the slave controller
1567 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1568 * be started by the slave controller; GNUNET_NO if the slave
1569 * controller has to connect to the already started delegated
1570 * controller via TCP/IP
1571 * @return the operation handle
1573 struct GNUNET_TESTBED_Operation *
1574 GNUNET_TESTBED_controller_link (void *op_cls,
1575 struct GNUNET_TESTBED_Controller *master,
1576 struct GNUNET_TESTBED_Host *delegated_host,
1577 struct GNUNET_TESTBED_Host *slave_host,
1578 const struct GNUNET_CONFIGURATION_Handle
1579 *slave_cfg, int is_subordinate)
1581 uint32_t slave_host_id;
1582 uint32_t delegated_host_id;
1585 GNUNET_assert (GNUNET_YES ==
1586 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1588 GNUNET_TESTBED_host_get_id_ ((NULL !=
1589 slave_host) ? slave_host : master->host);
1590 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1591 if ((NULL != slave_host) && (0 != slave_host_id))
1592 GNUNET_assert (GNUNET_YES ==
1593 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1594 return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
1596 GNUNET_TESTBED_host_get_cfg_ (delegated_host),
1603 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1604 * check. Another difference is that this function takes the id of the slave
1607 * @param op_cls the closure for the operation
1608 * @param master the handle to master controller
1609 * @param slave_host_id id of the host where the slave controller is running to
1610 * the slave_host should remain valid until this operation is cancelled
1611 * or marked as finished
1612 * @return the operation handle;
1614 struct GNUNET_TESTBED_Operation *
1615 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1616 struct GNUNET_TESTBED_Controller *master,
1617 uint32_t slave_host_id)
1619 struct OperationContext *opc;
1620 struct GetSlaveConfigData *data;
1622 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1623 data->slave_id = slave_host_id;
1624 opc = GNUNET_malloc (sizeof (struct OperationContext));
1625 opc->state = OPC_STATE_INIT;
1627 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1628 opc->type = OP_GET_SLAVE_CONFIG;
1630 opc->op_cls = op_cls;
1632 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1633 &oprelease_get_slave_config);
1634 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1636 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1642 * Function to acquire the configuration of a running slave controller. The
1643 * completion of the operation is signalled through the controller_cb from
1644 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1645 * handle to the configuration is available in the generic pointer of
1646 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1648 * @param op_cls the closure for the operation
1649 * @param master the handle to master controller
1650 * @param slave_host the host where the slave controller is running; the handle
1651 * to the slave_host should remain valid until this operation is
1652 * cancelled or marked as finished
1653 * @return the operation handle; NULL if the slave_host is not registered at
1656 struct GNUNET_TESTBED_Operation *
1657 GNUNET_TESTBED_get_slave_config (void *op_cls,
1658 struct GNUNET_TESTBED_Controller *master,
1659 struct GNUNET_TESTBED_Host *slave_host)
1661 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1663 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1664 GNUNET_TESTBED_host_get_id_
1670 * Ask the testbed controller to write the current overlay topology to
1671 * a file. Naturally, the file will only contain a snapshot as the
1672 * topology may evolve all the time.
1674 * @param controller overlay controller to inspect
1675 * @param filename name of the file the topology should
1679 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1681 const char *filename)
1688 * Creates a helper initialization message. This function is here because we
1689 * want to use this in testing
1691 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1692 * HOST(all connections form this ip are permitted by the testbed) when
1693 * starting testbed controller at host. This can either be a single ip
1694 * address or a network address in CIDR notation.
1695 * @param hostname the hostname of the destination this message is intended for
1696 * @param cfg the configuration that has to used to start the testbed service
1698 * @return the initialization message
1700 struct GNUNET_TESTBED_HelperInit *
1701 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1702 const char *hostname,
1703 const struct GNUNET_CONFIGURATION_Handle
1706 struct GNUNET_TESTBED_HelperInit *msg;
1710 size_t xconfig_size;
1711 uint16_t trusted_ip_len;
1712 uint16_t hostname_len;
1715 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1716 GNUNET_assert (NULL != config);
1718 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1719 GNUNET_free (config);
1720 trusted_ip_len = strlen (trusted_ip);
1721 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1723 xconfig_size + trusted_ip_len + 1 +
1724 sizeof (struct GNUNET_TESTBED_HelperInit);
1725 msg_size += hostname_len;
1726 msg = GNUNET_realloc (xconfig, msg_size);
1727 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1729 msg->header.size = htons (msg_size);
1730 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1731 msg->trusted_ip_size = htons (trusted_ip_len);
1732 msg->hostname_size = htons (hostname_len);
1733 msg->config_size = htons (config_size);
1734 (void) strcpy ((char *) &msg[1], trusted_ip);
1735 if (0 != hostname_len)
1736 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1743 * Cancel a pending operation. Releases all resources
1744 * of the operation and will ensure that no event
1745 * is generated for the operation. Does NOT guarantee
1746 * that the operation will be fully undone (or that
1747 * nothing ever happened).
1749 * @param operation operation to cancel
1752 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
1754 GNUNET_TESTBED_operation_done (operation);
1759 * Signal that the information from an operation has been fully
1760 * processed. This function MUST be called for each event
1761 * of type 'operation_finished' to fully remove the operation
1762 * from the operation queue. After calling this function, the
1763 * 'op_result' becomes invalid (!).
1765 * @param operation operation to signal completion for
1768 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1770 last_finished_operation = operation;
1771 GNUNET_TESTBED_operation_release_ (operation);
1776 * Generates configuration by uncompressing configuration in given message. The
1777 * given message should be of the following types:
1778 * GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION,
1779 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1780 * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
1781 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
1782 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1784 * @param msg the message containing compressed configuration
1785 * @return handle to the parsed configuration; NULL upon error while parsing the message
1787 struct GNUNET_CONFIGURATION_Handle *
1788 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1790 struct GNUNET_CONFIGURATION_Handle *cfg;
1797 switch (ntohs (msg->type))
1799 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1801 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1804 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1805 data_len = (uLong) ntohs (imsg->config_size);
1807 ntohs (imsg->header.size) -
1808 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1809 xdata = (const Bytef *) &imsg[1];
1812 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1814 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1816 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1817 data_len = (uLong) ntohs (imsg->config_size);
1819 ntohs (imsg->header.size) -
1820 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1821 xdata = (const Bytef *) &imsg[1];
1824 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1826 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1829 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1830 data_len = (uLong) ntohs (imsg->config_size);
1831 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1832 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1833 xdata_len = ntohs (imsg->header.size) - osize;
1834 xdata = (const Bytef *) ((const void *) imsg + osize);
1837 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1839 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
1841 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
1842 data_len = ntohs (imsg->config_size);
1843 xdata_len = ntohs (imsg->header.size) -
1844 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
1845 xdata = (const Bytef *) &imsg[1];
1848 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS:
1850 const struct GNUNET_TESTBED_ControllerLinkRequest *imsg;
1851 imsg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) msg;
1852 data_len = ntohs (imsg->config_size);
1853 xdata_len = ntohs (imsg->header.size) - sizeof (const struct
1854 GNUNET_TESTBED_ControllerLinkRequest);
1855 xdata = (const Bytef *) &imsg[1];
1861 data = GNUNET_malloc (data_len);
1862 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1865 GNUNET_break_op (0);
1868 cfg = GNUNET_CONFIGURATION_create ();
1870 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
1875 GNUNET_break_op (0);
1884 * Checks the integrity of the OperationFailureEventMessage and if good returns
1885 * the error message it contains.
1887 * @param msg the OperationFailureEventMessage
1888 * @return the error message
1891 GNUNET_TESTBED_parse_error_string_ (const struct
1892 GNUNET_TESTBED_OperationFailureEventMessage
1898 msize = ntohs (msg->header.size);
1899 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
1901 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
1902 emsg = (const char *) &msg[1];
1903 if ('\0' != emsg[msize - 1])
1913 * Function to return the operation id for a controller. The operation id is
1914 * created from the controllers host id and its internal operation counter.
1916 * @param controller the handle to the controller whose operation id has to be incremented
1917 * @return the incremented operation id.
1920 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
1924 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
1925 op_id = op_id << 32;
1926 op_id |= (uint64_t) controller->operation_counter++;
1931 /* end of testbed_api.c */