2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
46 * Generic logging shorthand
48 #define LOG(kind, ...) \
49 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
54 #define LOG_DEBUG(...) \
55 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
58 * Relative time seconds shorthand
60 #define TIME_REL_SECS(sec) \
61 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
65 * Default server message sending retry timeout
67 #define TIMEOUT_REL TIME_REL_SECS(1)
71 * Testbed Helper binary name
73 #define HELPER_TESTBED_BINARY "gnunet-helper-testbed"
77 * The message queue for sending messages to the controller service
82 * The message to be sent
84 struct GNUNET_MessageHeader *msg;
87 * next pointer for DLL
89 struct MessageQueue *next;
92 * prev pointer for DLL
94 struct MessageQueue *prev;
99 * Structure for a controller link
101 struct ControllerLink
104 * The next ptr for DLL
106 struct ControllerLink *next;
109 * The prev ptr for DLL
111 struct ControllerLink *prev;
114 * The host which will be referred in the peer start request. This is the
115 * host where the peer should be started
117 struct GNUNET_TESTBED_Host *delegated_host;
120 * The host which will contacted to delegate the peer start request
122 struct GNUNET_TESTBED_Host *slave_host;
125 * The configuration to be used to connect to slave host
127 const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
130 * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
131 * if we are just allowed to use the slave via TCP/IP
138 * handle for host registration
140 struct GNUNET_TESTBED_HostRegistrationHandle
143 * The host being registered
145 struct GNUNET_TESTBED_Host *host;
148 * The controller at which this host is being registered
150 struct GNUNET_TESTBED_Controller *c;
153 * The Registartion completion callback
155 GNUNET_TESTBED_HostRegistrationCompletion cc;
158 * The closure for above callback
165 * Context data for forwarded Operation
167 struct ForwardedOperationData
171 * The callback to call when reply is available
173 GNUNET_CLIENT_MessageHandler cc;
176 * The closure for the above callback
184 * Returns the operation context with the given id if found in the Operation
185 * context queues of the controller
187 * @param c the controller whose queues are searched
188 * @param id the id which has to be checked
189 * @return the matching operation context; NULL if no match found
191 static struct OperationContext *
192 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
194 struct OperationContext *opc;
196 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
206 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
207 * controller (testbed service)
209 * @param c the controller handler
210 * @param msg message received
211 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
215 handle_addhostconfirm (struct GNUNET_TESTBED_Controller *c,
216 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
218 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
227 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
229 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
230 GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
234 msg_size = ntohs (msg->header.size);
235 if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
237 LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
238 GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
239 rh->cc (rh->cc_cls, NULL);
243 /* We have an error message */
244 emsg = (char *) &msg[1];
246 emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
252 LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
253 ntohl (msg->host_id), emsg);
254 rh->cc (rh->cc_cls, emsg);
261 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
262 * controller (testbed service)
264 * @param c the controller handler
265 * @param msg message received
266 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
270 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
272 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
274 struct OperationContext *opc;
275 struct GNUNET_TESTBED_EventInformation *event;
278 op_id = GNUNET_ntohll (msg->operation_id);
279 LOG_DEBUG ("Operation %ul successful\n", op_id);
280 if (NULL == (opc = find_opc (c, op_id)))
282 LOG_DEBUG ("Operation not found\n");
286 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
287 event = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_EventInformation));
289 event->type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
294 struct ForwardedOperationData *fo_data;
297 if (NULL != fo_data->cc)
298 fo_data->cc (fo_data->cc_cls, (const struct GNUNET_MessageHeader *) msg);
299 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
300 GNUNET_free (fo_data);
305 case OP_PEER_DESTROY:
307 struct GNUNET_TESTBED_Peer *peer;
315 case OP_LINK_CONTROLLERS:
322 event->details.operation_finished.operation = opc->op;
323 event->details.operation_finished.op_cls = NULL;
324 event->details.operation_finished.emsg = NULL;
325 event->details.operation_finished.generic = NULL;
327 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
328 opc->state = OPC_STATE_FINISHED;
332 c->cc (c->cc_cls, event);
340 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
341 * controller (testbed service)
343 * @param c the controller handler
344 * @param msg message received
345 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
349 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
351 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
353 struct OperationContext *opc;
354 struct PeerCreateData *data;
355 struct GNUNET_TESTBED_Peer *peer;
356 GNUNET_TESTBED_PeerCreateCallback cb;
360 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
361 ntohs (msg->header.size));
362 op_id = GNUNET_ntohll (msg->operation_id);
363 if (NULL == (opc = find_opc (c, op_id)))
365 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
368 if (OP_FORWARDED == opc->type)
370 struct ForwardedOperationData *fo_data;
373 if (NULL != fo_data->cc)
374 fo_data->cc (fo_data->cc_cls, (const struct GNUNET_MessageHeader *) msg);
375 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
376 GNUNET_free (fo_data);
380 GNUNET_assert (OP_PEER_CREATE == opc->type);
381 GNUNET_assert (NULL != opc->data);
383 GNUNET_assert (NULL != data->peer);
385 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
386 peer->state = PS_CREATED;
389 GNUNET_free (opc->data);
390 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
391 opc->state = OPC_STATE_FINISHED;
393 cb (cls, peer, NULL);
399 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
400 * controller (testbed service)
402 * @param c the controller handler
403 * @param msg message received
404 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
408 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
409 const struct GNUNET_TESTBED_PeerEventMessage *msg)
411 struct OperationContext *opc;
412 struct GNUNET_TESTBED_Peer *peer;
413 struct PeerEventData *data;
414 GNUNET_TESTBED_PeerChurnCallback pcc;
416 struct GNUNET_TESTBED_EventInformation event;
419 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
420 ntohs (msg->header.size));
421 op_id = GNUNET_ntohll (msg->operation_id);
422 if (NULL == (opc = find_opc (c, op_id)))
424 LOG_DEBUG ("Operation not found\n");
427 if (OP_FORWARDED == opc->type)
429 struct ForwardedOperationData *fo_data;
432 if (NULL != fo_data->cc)
433 fo_data->cc (fo_data->cc_cls, (const struct GNUNET_MessageHeader *) msg);
434 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
435 GNUNET_free (fo_data);
439 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
441 GNUNET_assert (NULL != data);
443 GNUNET_assert (NULL != peer);
444 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
447 case GNUNET_TESTBED_ET_PEER_START:
448 peer->state = PS_STARTED;
449 event.details.peer_start.host = peer->host;
450 event.details.peer_start.peer = peer;
452 case GNUNET_TESTBED_ET_PEER_STOP:
453 peer->state = PS_STOPPED;
454 event.details.peer_stop.peer = peer;
457 GNUNET_assert (0); /* We should never reach this state */
460 pcc_cls = data->pcc_cls;
462 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
463 opc->state = OPC_STATE_FINISHED;
465 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
469 c->cc (c->cc_cls, &event);
478 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
479 * controller (testbed service)
481 * @param c the controller handler
482 * @param msg message received
483 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
487 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
488 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
490 struct OperationContext *opc;
491 struct OverlayConnectData *data;
492 GNUNET_TESTBED_OperationCompletionCallback cb;
494 struct GNUNET_TESTBED_EventInformation event;
497 op_id = GNUNET_ntohll (msg->operation_id);
498 if (NULL == (opc = find_opc (c, op_id)))
500 LOG_DEBUG ("Operation not found\n");
504 GNUNET_assert (NULL != data);
505 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
506 (ntohl (msg->peer2) == data->p2->unique_id));
507 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
510 case GNUNET_TESTBED_ET_CONNECT:
511 event.details.peer_connect.peer1 = data->p1;
512 event.details.peer_connect.peer2 = data->p2;
514 case GNUNET_TESTBED_ET_DISCONNECT:
515 GNUNET_assert (0); /* FIXME: implement */
518 GNUNET_assert (0); /* Should never reach here */
522 cb_cls = data->cb_cls;
523 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
524 opc->state = OPC_STATE_FINISHED;
527 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
531 c->cc (c->cc_cls, &event);
534 cb (cb_cls, opc->op, NULL);
540 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
541 * controller (testbed service)
543 * @param c the controller handler
544 * @param msg message received
545 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
549 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
551 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
553 struct OperationContext *opc;
554 struct GNUNET_TESTBED_Peer *peer;
555 struct PeerInfoData *data;
556 struct GNUNET_TESTBED_PeerInformation *pinfo;
557 GNUNET_TESTBED_PeerInfoCallback cb;
561 op_id = GNUNET_ntohll (msg->operation_id);
562 if (NULL == (opc = find_opc (c, op_id)))
564 LOG_DEBUG ("Operation not found\n");
567 if (OP_FORWARDED == opc->type)
569 struct ForwardedOperationData *fo_data;
572 if (NULL != fo_data->cc)
573 fo_data->cc (fo_data->cc_cls, (const struct GNUNET_MessageHeader *) msg);
574 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
575 GNUNET_free (fo_data);
580 GNUNET_assert (NULL != data);
582 GNUNET_assert (NULL != peer);
583 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
584 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
585 pinfo->pit = data->pit;
587 cb_cls = data->cb_cls;
592 case GNUNET_TESTBED_PIT_IDENTITY:
593 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
594 (void) memcpy (pinfo->result.id, &msg->peer_identity,
595 sizeof (struct GNUNET_PeerIdentity));
597 case GNUNET_TESTBED_PIT_CONFIGURATION:
598 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
599 GNUNET_TESTBED_get_config_from_peerinfo_msg_ (msg);
601 case GNUNET_TESTBED_PIT_GENERIC:
602 GNUNET_assert (0); /* never reach here */
606 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
607 opc->state = OPC_STATE_FINISHED;
609 cb (cb_cls, opc->op, pinfo, NULL);
615 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
616 * controller (testbed service)
618 * @param c the controller handler
619 * @param msg message received
620 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
624 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
625 const struct GNUNET_TESTBED_OperationFailureEventMessage
628 struct OperationContext *opc;
631 struct GNUNET_TESTBED_EventInformation event;
634 op_id = GNUNET_ntohll (msg->operation_id);
635 if (NULL == (opc = find_opc (c, op_id)))
637 LOG_DEBUG ("Operation not found\n");
640 if (OP_FORWARDED == opc->type)
642 struct ForwardedOperationData *fo_data;
645 if (NULL != fo_data->cc)
646 fo_data->cc (fo_data->cc_cls, (const struct GNUNET_MessageHeader *) msg);
647 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
648 GNUNET_free (fo_data);
652 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
653 opc->state = OPC_STATE_FINISHED;
656 /* FIXME: Cleanup the data pointer depending on the type of opc */
660 msize = ntohs (msg->header.size);
662 if (msize > sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage))
664 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
665 emsg = (char *) &msg[1];
666 GNUNET_assert ('\0' == emsg[msize - 1]);
668 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
671 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
672 event.details.operation_finished.operation = opc->op;
673 event.details.operation_finished.op_cls = NULL;
674 event.details.operation_finished.emsg = emsg;
675 event.details.operation_finished.generic = NULL;
676 c->cc (c->cc_cls, &event);
683 * Handler for messages from controller (testbed service)
685 * @param cls the controller handler
686 * @param msg message received, NULL on timeout or fatal error
689 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
691 struct GNUNET_TESTBED_Controller *c = cls;
695 c->in_receive = GNUNET_NO;
696 /* FIXME: Add checks for message integrity */
699 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
703 msize = ntohs (msg->size);
704 switch (ntohs (msg->type))
706 case GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM:
707 GNUNET_assert (msize >=
708 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
710 handle_addhostconfirm (c,
711 (const struct GNUNET_TESTBED_HostConfirmedMessage
714 case GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS:
715 GNUNET_assert (msize ==
717 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
721 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
724 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS:
725 GNUNET_assert (msize ==
727 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
729 handle_peer_create_success (c,
731 GNUNET_TESTBED_PeerCreateSuccessEventMessage
734 case GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT:
735 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
737 handle_peer_event (c,
738 (const struct GNUNET_TESTBED_PeerEventMessage *)
742 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
743 GNUNET_assert (msize >=
745 GNUNET_TESTBED_PeerConfigurationInformationMessage));
747 handle_peer_config (c,
749 GNUNET_TESTBED_PeerConfigurationInformationMessage
752 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT:
753 GNUNET_assert (msize ==
754 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
756 handle_peer_conevent (c,
758 GNUNET_TESTBED_ConnectionEventMessage *) msg);
760 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT:
761 GNUNET_assert (msize >=
762 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
764 handle_op_fail_event (c,
766 GNUNET_TESTBED_OperationFailureEventMessage *)
772 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
774 c->in_receive = GNUNET_YES;
775 GNUNET_CLIENT_receive (c->client, &message_handler, c,
776 GNUNET_TIME_UNIT_FOREVER_REL);
782 * Function called to notify a client about the connection begin ready to queue
783 * more data. "buf" will be NULL and "size" zero if the connection was closed
784 * for writing in the meantime.
787 * @param size number of bytes available in buf
788 * @param buf where the callee should write the message
789 * @return number of bytes written to buf
792 transmit_ready_notify (void *cls, size_t size, void *buf)
794 struct GNUNET_TESTBED_Controller *c = cls;
795 struct MessageQueue *mq_entry;
798 mq_entry = c->mq_head;
799 GNUNET_assert (NULL != mq_entry);
800 if ((0 == size) && (NULL == buf)) /* Timeout */
802 LOG_DEBUG ("Message sending timed out -- retrying\n");
804 GNUNET_CLIENT_notify_transmit_ready (c->client,
805 ntohs (mq_entry->msg->size),
806 TIMEOUT_REL, GNUNET_YES,
807 &transmit_ready_notify, c);
810 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
811 size = ntohs (mq_entry->msg->size);
812 memcpy (buf, mq_entry->msg, size);
813 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
814 ntohs (mq_entry->msg->type), size);
815 GNUNET_free (mq_entry->msg);
816 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
817 GNUNET_free (mq_entry);
818 mq_entry = c->mq_head;
819 if (NULL != mq_entry)
821 GNUNET_CLIENT_notify_transmit_ready (c->client,
822 ntohs (mq_entry->msg->size),
823 TIMEOUT_REL, GNUNET_YES,
824 &transmit_ready_notify, c);
825 if (GNUNET_NO == c->in_receive)
827 c->in_receive = GNUNET_YES;
828 GNUNET_CLIENT_receive (c->client, &message_handler, c,
829 GNUNET_TIME_UNIT_FOREVER_REL);
836 * Queues a message in send queue for sending to the service
838 * @param controller the handle to the controller
839 * @param msg the message to queue
842 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
843 struct GNUNET_MessageHeader *msg)
845 struct MessageQueue *mq_entry;
849 type = ntohs (msg->type);
850 size = ntohs (msg->size);
851 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
852 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
853 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
855 LOG (GNUNET_ERROR_TYPE_DEBUG,
856 "Queueing message of type %u, size %u for sending\n", type,
858 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
860 if (NULL == controller->th)
862 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
863 TIMEOUT_REL, GNUNET_YES,
864 &transmit_ready_notify,
870 * Sends the given message as an operation. The given callback is called when a
871 * reply for the operation is available. Call
872 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
873 * operation context if the cc hasn't been called
875 * @param controller the controller to which the message has to be sent
876 * @param operation_id the operation id of the message
877 * @param msg the message to send
878 * @param cc the callback to call when reply is available
879 * @param cc_cls the closure for the above callback
880 * @return the operation context which can be used to cancel the forwarded
883 struct OperationContext *
884 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
885 *controller, uint64_t operation_id,
886 const struct GNUNET_MessageHeader *msg,
887 GNUNET_CLIENT_MessageHandler cc,
890 struct OperationContext *opc;
891 struct ForwardedOperationData *data;
892 struct GNUNET_MessageHeader *dup_msg;
895 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
897 data->cc_cls = cc_cls;
898 opc = GNUNET_malloc (sizeof (struct OperationContext));
900 opc->type = OP_FORWARDED;
902 opc->id = operation_id;
903 msize = ntohs (msg->size);
904 dup_msg = GNUNET_malloc (msize);
905 (void) memcpy (dup_msg, msg, msize);
906 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
907 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
914 * Function to cancel an operation created by simply forwarding an operation
917 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
920 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
922 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
923 GNUNET_free (opc->data);
929 * Handle for controller process
931 struct GNUNET_TESTBED_ControllerProc
936 struct GNUNET_HELPER_Handle *helper;
939 * The host where the helper is run
941 struct GNUNET_TESTBED_Host *host;
944 * The controller error callback
946 GNUNET_TESTBED_ControllerStatusCallback cb;
949 * The closure for the above callback
954 * The send handle for the helper
956 struct GNUNET_HELPER_SendHandle *shandle;
959 * The message corresponding to send handle
961 struct GNUNET_MessageHeader *msg;
964 * The port number for ssh; used for helpers starting ssh
969 * The ssh destination string; used for helpers starting ssh
974 * The configuration of the running testbed service
976 struct GNUNET_CONFIGURATION_Handle *cfg;
982 * Functions with this signature are called whenever a
983 * complete message is received by the tokenizer.
985 * Do not call GNUNET_SERVER_mst_destroy in callback
988 * @param client identification of the client
989 * @param message the actual message
991 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
994 helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
996 struct GNUNET_TESTBED_ControllerProc *cp = cls;
997 const struct GNUNET_TESTBED_HelperReply *msg;
998 const char *hostname;
1001 uLongf xconfig_size;
1003 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1004 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1005 ntohs (msg->header.size));
1006 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1007 ntohs (msg->header.type));
1008 config_size = (uLongf) ntohs (msg->config_size);
1010 (uLongf) (ntohs (msg->header.size) -
1011 sizeof (struct GNUNET_TESTBED_HelperReply));
1012 config = GNUNET_malloc (config_size);
1013 GNUNET_assert (Z_OK ==
1014 uncompress ((Bytef *) config, &config_size,
1015 (const Bytef *) &msg[1], xconfig_size));
1016 GNUNET_assert (NULL == cp->cfg);
1017 cp->cfg = GNUNET_CONFIGURATION_create ();
1018 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1019 (cp->cfg, config, config_size, GNUNET_NO));
1020 GNUNET_free (config);
1021 if ((NULL == cp->host) ||
1022 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname_ (cp->host))))
1023 hostname = "localhost";
1024 /* Change the hostname so that we can connect to it */
1025 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1027 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1033 * Continuation function from GNUNET_HELPER_send()
1035 * @param cls closure
1036 * @param result GNUNET_OK on success,
1037 * GNUNET_NO if helper process died
1038 * GNUNET_SYSERR during GNUNET_HELPER_stop
1041 clear_msg (void *cls, int result)
1043 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1045 GNUNET_assert (NULL != cp->shandle);
1047 GNUNET_free (cp->msg);
1052 * Callback that will be called when the helper process dies. This is not called
1053 * when the helper process is stoped using GNUNET_HELPER_stop()
1055 * @param cls the closure from GNUNET_HELPER_start()
1058 helper_exp_cb (void *cls)
1060 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1061 GNUNET_TESTBED_ControllerStatusCallback cb;
1067 GNUNET_TESTBED_controller_stop (cp);
1069 cb (cb_cls, NULL, GNUNET_SYSERR);
1074 * Function to call to start a link-controllers type operation once all queues
1075 * the operation is part of declare that the operation can be activated.
1077 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1080 opstart_link_controllers (void *cls)
1082 struct OperationContext *opc = cls;
1083 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1085 GNUNET_assert (NULL != opc->data);
1088 opc->state = OPC_STATE_STARTED;
1089 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1090 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1095 * Callback which will be called when link-controllers type operation is released
1097 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1100 oprelease_link_controllers (void *cls)
1102 struct OperationContext *opc = cls;
1104 if (OPC_STATE_INIT == opc->state)
1105 GNUNET_free (opc->data);
1106 if (OPC_STATE_STARTED == opc->state)
1107 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1113 * Starts a controller process at the host. FIXME: add controller start callback
1114 * with the configuration with which the controller is started
1116 * @param controller_ip the ip address of the controller. Will be set as TRUSTED
1117 * host when starting testbed controller at host
1118 * @param host the host where the controller has to be started; NULL for
1120 * @param cfg template configuration to use for the remote controller; the
1121 * remote controller will be started with a slightly modified
1122 * configuration (port numbers, unix domain sockets and service home
1123 * values are changed as per TESTING library on the remote host)
1124 * @param cb function called when the controller is successfully started or
1125 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1126 * called if cb is called with GNUNET_SYSERR as status. Will never be
1127 * called in the same task as 'GNUNET_TESTBED_controller_start'
1128 * (synchronous errors will be signalled by returning NULL). This
1129 * parameter cannot be NULL.
1130 * @param cls closure for above callbacks
1131 * @return the controller process handle, NULL on errors
1133 struct GNUNET_TESTBED_ControllerProc *
1134 GNUNET_TESTBED_controller_start (const char *controller_ip,
1135 struct GNUNET_TESTBED_Host *host,
1136 const struct GNUNET_CONFIGURATION_Handle *cfg,
1137 GNUNET_TESTBED_ControllerStatusCallback cb,
1140 struct GNUNET_TESTBED_ControllerProc *cp;
1141 struct GNUNET_TESTBED_HelperInit *msg;
1143 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1144 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1146 char *const binary_argv[] = {
1147 HELPER_TESTBED_BINARY, NULL
1151 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1152 &helper_mst, &helper_exp_cb, cp);
1156 char *remote_args[8];
1158 const char *username;
1159 const char *hostname;
1161 username = GNUNET_TESTBED_host_get_username_ (host);
1162 hostname = GNUNET_TESTBED_host_get_hostname_ (host);
1163 GNUNET_asprintf (&cp->port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1164 if (NULL == username)
1165 GNUNET_asprintf (&cp->dst, "%s", hostname);
1167 GNUNET_asprintf (&cp->dst, "%s@%s", username, hostname);
1168 LOG_DEBUG ("Starting SSH to destination %s\n", cp->dst);
1170 remote_args[argp++] = "ssh";
1171 remote_args[argp++] = "-p";
1172 remote_args[argp++] = cp->port;
1173 remote_args[argp++] = "-o";
1174 remote_args[argp++] = "BatchMode=yes";
1175 remote_args[argp++] = cp->dst;
1176 remote_args[argp++] = HELPER_TESTBED_BINARY;
1177 remote_args[argp++] = NULL;
1178 GNUNET_assert (argp == 8);
1180 GNUNET_HELPER_start (GNUNET_NO, "ssh", remote_args, &helper_mst,
1181 &helper_exp_cb, cp);
1183 if (NULL == cp->helper)
1185 GNUNET_free_non_null (cp->port);
1186 GNUNET_free_non_null (cp->dst);
1193 msg = GNUNET_TESTBED_create_helper_init_msg_ (controller_ip, cfg);
1194 cp->msg = &msg->header;
1196 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1197 if (NULL == cp->shandle)
1200 GNUNET_TESTBED_controller_stop (cp);
1208 * Stop the controller process (also will terminate all peers and controllers
1209 * dependent on this controller). This function blocks until the testbed has
1210 * been fully terminated (!).
1212 * @param cproc the controller process handle
1215 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1217 if (NULL != cproc->shandle)
1218 GNUNET_HELPER_send_cancel (cproc->shandle);
1219 if (NULL != cproc->helper)
1220 GNUNET_HELPER_stop (cproc->helper);
1221 if (NULL != cproc->cfg)
1222 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1223 GNUNET_free_non_null (cproc->port);
1224 GNUNET_free_non_null (cproc->dst);
1225 GNUNET_free (cproc);
1230 * Start a controller process using the given configuration at the
1233 * @param cfg configuration to use
1234 * @param host host to run the controller on; This should be the same host if
1235 * the controller was previously started with
1236 * GNUNET_TESTBED_controller_start; NULL for localhost
1237 * @param event_mask bit mask with set of events to call 'cc' for;
1238 * or-ed values of "1LL" shifted by the
1239 * respective 'enum GNUNET_TESTBED_EventType'
1240 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1241 * @param cc controller callback to invoke on events
1242 * @param cc_cls closure for cc
1243 * @return handle to the controller
1245 struct GNUNET_TESTBED_Controller *
1246 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1247 *cfg, struct GNUNET_TESTBED_Host *host,
1248 uint64_t event_mask,
1249 GNUNET_TESTBED_ControllerCallback cc,
1252 struct GNUNET_TESTBED_Controller *controller;
1253 struct GNUNET_TESTBED_InitMessage *msg;
1254 const char *controller_hostname;
1255 unsigned long long max_parallel_operations;
1256 unsigned long long max_parallel_service_connections;
1259 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1260 "MAX_PARALLEL_OPERATIONS",
1261 &max_parallel_operations))
1267 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1268 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1269 &max_parallel_service_connections))
1274 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1275 controller->cc = cc;
1276 controller->cc_cls = cc_cls;
1277 controller->event_mask = event_mask;
1278 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1279 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1280 if (NULL == controller->client)
1282 GNUNET_TESTBED_controller_disconnect (controller);
1287 host = GNUNET_TESTBED_host_create_by_id_ (0);
1288 if (NULL == host) /* If the above host create fails */
1290 LOG (GNUNET_ERROR_TYPE_WARNING,
1291 "Treating NULL host as localhost. Multiple references to localhost "
1292 "may break when localhost freed before calling disconnect \n");
1293 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1297 controller->aux_host = GNUNET_YES;
1300 GNUNET_assert (NULL != host);
1301 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1302 controller->host = host;
1303 controller->opq_parallel_operations =
1304 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1305 max_parallel_operations);
1306 controller->opq_parallel_service_connections =
1307 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1308 max_parallel_service_connections);
1309 controller_hostname = GNUNET_TESTBED_host_get_hostname_ (host);
1310 if (NULL == controller_hostname)
1311 controller_hostname = "127.0.0.1";
1313 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1314 strlen (controller_hostname) + 1);
1315 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1317 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1318 strlen (controller_hostname) + 1);
1319 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1320 msg->event_mask = GNUNET_htonll (controller->event_mask);
1321 strcpy ((char *) &msg[1], controller_hostname);
1322 GNUNET_TESTBED_queue_message_ (controller,
1323 (struct GNUNET_MessageHeader *) msg);
1329 * Configure shared services at a controller. Using this function,
1330 * you can specify that certain services (such as "resolver")
1331 * should not be run for each peer but instead be shared
1332 * across N peers on the specified host. This function
1333 * must be called before any peers are created at the host.
1335 * @param controller controller to configure
1336 * @param service_name name of the service to share
1337 * @param num_peers number of peers that should share one instance
1338 * of the specified service (1 for no sharing is the default),
1339 * use 0 to disable the service
1342 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1344 const char *service_name,
1347 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1348 uint16_t service_name_size;
1351 service_name_size = strlen (service_name) + 1;
1353 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1355 msg = GNUNET_malloc (msg_size);
1356 msg->header.size = htons (msg_size);
1357 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE);
1358 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1359 msg->num_peers = htonl (num_peers);
1360 memcpy (&msg[1], service_name, service_name_size);
1361 GNUNET_TESTBED_queue_message_ (controller,
1362 (struct GNUNET_MessageHeader *) msg);
1367 * disconnects from the controller.
1369 * @param controller handle to controller to stop
1372 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1375 struct MessageQueue *mq_entry;
1377 if (NULL != controller->th)
1378 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1379 /* Clear the message queue */
1380 while (NULL != (mq_entry = controller->mq_head))
1382 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1384 GNUNET_free (mq_entry->msg);
1385 GNUNET_free (mq_entry);
1387 if (NULL != controller->client)
1388 GNUNET_CLIENT_disconnect (controller->client);
1389 GNUNET_CONFIGURATION_destroy (controller->cfg);
1390 if (GNUNET_YES == controller->aux_host)
1391 GNUNET_TESTBED_host_destroy (controller->host);
1392 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1393 GNUNET_TESTBED_operation_queue_destroy_
1394 (controller->opq_parallel_service_connections);
1395 GNUNET_free (controller);
1400 * Register a host with the controller
1402 * @param controller the controller handle
1403 * @param host the host to register
1404 * @param cc the completion callback to call to inform the status of
1405 * registration. After calling this callback the registration handle
1406 * will be invalid. Cannot be NULL.
1407 * @param cc_cls the closure for the cc
1408 * @return handle to the host registration which can be used to cancel the
1411 struct GNUNET_TESTBED_HostRegistrationHandle *
1412 GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller,
1413 struct GNUNET_TESTBED_Host *host,
1414 GNUNET_TESTBED_HostRegistrationCompletion cc,
1417 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
1418 struct GNUNET_TESTBED_AddHostMessage *msg;
1419 const char *username;
1420 const char *hostname;
1422 uint16_t user_name_length;
1424 if (NULL != controller->rh)
1426 hostname = GNUNET_TESTBED_host_get_hostname_ (host);
1427 if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller))
1429 LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n",
1430 (NULL == hostname) ? "localhost" : hostname);
1433 rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
1436 GNUNET_assert (NULL != cc);
1438 rh->cc_cls = cc_cls;
1439 controller->rh = rh;
1440 username = GNUNET_TESTBED_host_get_username_ (host);
1441 msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage));
1442 user_name_length = 0;
1443 if (NULL != username)
1445 user_name_length = strlen (username) + 1;
1446 msg_size += user_name_length;
1448 /* FIXME: what happens when hostname is NULL? localhost */
1449 GNUNET_assert (NULL != hostname);
1450 msg_size += strlen (hostname) + 1;
1451 msg = GNUNET_malloc (msg_size);
1452 msg->header.size = htons (msg_size);
1453 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST);
1454 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1455 msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host));
1456 msg->user_name_length = htons (user_name_length);
1457 if (NULL != username)
1458 memcpy (&msg[1], username, user_name_length);
1459 strcpy (((void *) &msg[1]) + user_name_length, hostname);
1460 GNUNET_TESTBED_queue_message_ (controller,
1461 (struct GNUNET_MessageHeader *) msg);
1467 * Cancel the pending registration. Note that if the registration message is
1468 * already sent to the service the cancellation has only the effect that the
1469 * registration completion callback for the registration is never called.
1471 * @param handle the registration handle to cancel
1474 GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle
1477 if (handle != handle->c->rh)
1482 handle->c->rh = NULL;
1483 GNUNET_free (handle);
1488 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1489 * serialized and compressed
1491 * @param master handle to the master controller who creates the association
1492 * @param delegated_host requests to which host should be delegated; cannot be NULL
1493 * @param slave_host which host is used to run the slave controller; use NULL to
1494 * make the master controller connect to the delegated host
1495 * @param sxcfg serialized and compressed configuration
1496 * @param sxcfg_size the size scfg
1497 * @param scfg_size the size of uncompressed serialized configuration
1498 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1499 * be started by the master controller; GNUNET_NO if we are just
1500 * allowed to use the slave via TCP/IP
1502 struct GNUNET_TESTBED_Operation *
1503 GNUNET_TESTBED_controller_link_2 (struct GNUNET_TESTBED_Controller *master,
1504 struct GNUNET_TESTBED_Host *delegated_host,
1505 struct GNUNET_TESTBED_Host *slave_host,
1506 const char *sxcfg, size_t sxcfg_size,
1507 size_t scfg_size, int is_subordinate)
1509 struct OperationContext *opc;
1510 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1513 GNUNET_assert (GNUNET_YES ==
1514 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1515 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1516 GNUNET_assert (GNUNET_YES ==
1517 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1518 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1519 msg = GNUNET_malloc (msg_size);
1520 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS);
1521 msg->header.size = htons (msg_size);
1522 msg->delegated_host_id = htonl (GNUNET_TESTBED_host_get_id_ (delegated_host));
1523 msg->slave_host_id =
1524 htonl (GNUNET_TESTBED_host_get_id_
1525 ((NULL != slave_host) ? slave_host : master->host));
1526 msg->config_size = htons ((uint16_t) scfg_size);
1527 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1528 memcpy (&msg[1], sxcfg, sxcfg_size);
1529 opc = GNUNET_malloc (sizeof (struct OperationContext));
1532 opc->type = OP_LINK_CONTROLLERS;
1533 opc->id = master->operation_counter++;
1534 opc->state = OPC_STATE_INIT;
1535 msg->operation_id = GNUNET_htonll (opc->id);
1537 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1538 &oprelease_link_controllers);
1539 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1546 * Compresses given configuration using zlib compress
1548 * @param config the serialized configuration
1549 * @param size the size of config
1550 * @param xconfig will be set to the compressed configuration (memory is fresly
1552 * @return the size of the xconfig
1555 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1560 xsize = compressBound ((uLong) size);
1561 *xconfig = GNUNET_malloc (xsize);
1562 GNUNET_assert (Z_OK ==
1563 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1564 (const Bytef *) config, (uLongf) size,
1571 * Create a link from slave controller to delegated controller. Whenever the
1572 * master controller is asked to start a peer at the delegated controller the
1573 * request will be routed towards slave controller (if a route exists). The
1574 * slave controller will then route it to the delegated controller. The
1575 * configuration of the slave controller is given and to be used to either
1576 * create the slave controller or to connect to an existing slave controller
1577 * process. 'is_subordinate' specifies if the given slave controller should be
1578 * started and managed by the master controller, or if the slave already has a
1579 * master and this is just a secondary master that is also allowed to use the
1582 * @param master handle to the master controller who creates the association
1583 * @param delegated_host requests to which host should be delegated
1584 * @param slave_host which host is used to run the slave controller
1585 * @param slave_cfg configuration to use for the slave controller
1586 * @param is_subordinate GNUNET_YES if the slave should be started (and stopped)
1587 * by the master controller; GNUNET_NO if we are just
1588 * allowed to use the slave via TCP/IP
1589 * @return the operation handle
1591 struct GNUNET_TESTBED_Operation *
1592 GNUNET_TESTBED_controller_link (struct GNUNET_TESTBED_Controller *master,
1593 struct GNUNET_TESTBED_Host *delegated_host,
1594 struct GNUNET_TESTBED_Host *slave_host,
1595 const struct GNUNET_CONFIGURATION_Handle
1596 *slave_cfg, int is_subordinate)
1598 struct GNUNET_TESTBED_Operation *op;
1604 GNUNET_assert (GNUNET_YES ==
1605 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1606 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1607 GNUNET_assert (GNUNET_YES ==
1608 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1609 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1610 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1611 GNUNET_free (config);
1612 GNUNET_assert ((UINT16_MAX - sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >= cc_size); /* Configuration doesn't fit in 1 message */
1613 op = GNUNET_TESTBED_controller_link_2 (master, delegated_host, slave_host,
1614 (const char *) cconfig, cc_size,
1615 config_size, is_subordinate);
1616 GNUNET_free (cconfig);
1622 * Ask the testbed controller to write the current overlay topology to
1623 * a file. Naturally, the file will only contain a snapshot as the
1624 * topology may evolve all the time.
1626 * @param controller overlay controller to inspect
1627 * @param filename name of the file the topology should
1631 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1633 const char *filename)
1640 * Creates a helper initialization message. This function is here because we
1641 * want to use this in testing
1643 * @param cname the ip address of the controlling host
1644 * @param cfg the configuration that has to used to start the testbed service
1646 * @return the initialization message
1648 struct GNUNET_TESTBED_HelperInit *
1649 GNUNET_TESTBED_create_helper_init_msg_ (const char *cname,
1650 const struct GNUNET_CONFIGURATION_Handle
1653 struct GNUNET_TESTBED_HelperInit *msg;
1657 size_t xconfig_size;
1661 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1662 GNUNET_assert (NULL != config);
1664 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1665 GNUNET_free (config);
1666 cname_len = strlen (cname);
1668 xconfig_size + cname_len + 1 + sizeof (struct GNUNET_TESTBED_HelperInit);
1669 msg = GNUNET_realloc (xconfig, msg_size);
1670 (void) memmove (((void *) &msg[1]) + cname_len + 1, msg, xconfig_size);
1671 msg->header.size = htons (msg_size);
1672 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1673 msg->cname_size = htons (cname_len);
1674 msg->config_size = htons (config_size);
1675 (void) strcpy ((char *) &msg[1], cname);
1681 * Cancel a pending operation. Releases all resources
1682 * of the operation and will ensure that no event
1683 * is generated for the operation. Does NOT guarantee
1684 * that the operation will be fully undone (or that
1685 * nothing ever happened).
1687 * @param operation operation to cancel
1690 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
1692 GNUNET_TESTBED_operation_done (operation);
1697 * Signal that the information from an operation has been fully
1698 * processed. This function MUST be called for each event
1699 * of type 'operation_finished' to fully remove the operation
1700 * from the operation queue. After calling this function, the
1701 * 'op_result' becomes invalid (!).
1703 * @param operation operation to signal completion for
1706 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1708 switch (operation->type)
1710 case OP_PEER_CREATE:
1711 case OP_PEER_DESTROY:
1715 case OP_OVERLAY_CONNECT:
1716 case OP_LINK_CONTROLLERS:
1717 GNUNET_TESTBED_operation_release_ (operation);
1727 * Generates configuration by parsing Peer configuration information reply message
1729 * @param msg the peer configuration information message
1730 * @return handle to the parsed configuration
1732 struct GNUNET_CONFIGURATION_Handle *
1733 GNUNET_TESTBED_get_config_from_peerinfo_msg_ (const struct
1734 GNUNET_TESTBED_PeerConfigurationInformationMessage
1737 struct GNUNET_CONFIGURATION_Handle *cfg;
1743 config_size = (uLong) ntohs (msg->config_size);
1744 config = GNUNET_malloc (config_size);
1745 msize = ntohs (msg->header.size);
1746 msize -= sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1749 uncompress ((Bytef *) config, &config_size, (const Bytef *) &msg[1],
1752 cfg = GNUNET_CONFIGURATION_create ();
1753 GNUNET_assert (GNUNET_OK ==
1754 GNUNET_CONFIGURATION_deserialize (cfg, config,
1755 (size_t) config_size,
1757 GNUNET_free (config);
1761 /* end of testbed_api.c */