2 This file is part of GNUnet
3 (C) 2008--2012 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
46 * Generic logging shorthand
48 #define LOG(kind, ...) \
49 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
54 #define LOG_DEBUG(...) \
55 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__);
58 * Relative time seconds shorthand
60 #define TIME_REL_SECS(sec) \
61 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
65 * Default server message sending retry timeout
67 #define TIMEOUT_REL TIME_REL_SECS(1)
71 * Handle for controller process
73 struct GNUNET_TESTBED_ControllerProc
78 struct GNUNET_HELPER_Handle *helper;
81 * The host where the helper is run
83 struct GNUNET_TESTBED_Host *host;
86 * The controller error callback
88 GNUNET_TESTBED_ControllerStatusCallback cb;
91 * The closure for the above callback
96 * The send handle for the helper
98 struct GNUNET_HELPER_SendHandle *shandle;
101 * The message corresponding to send handle
103 struct GNUNET_MessageHeader *msg;
106 * The port number for ssh; used for helpers starting ssh
111 * The ssh destination string; used for helpers starting ssh
116 * The configuration of the running testbed service
118 struct GNUNET_CONFIGURATION_Handle *cfg;
124 * The message queue for sending messages to the controller service
129 * The message to be sent
131 struct GNUNET_MessageHeader *msg;
134 * next pointer for DLL
136 struct MessageQueue *next;
139 * prev pointer for DLL
141 struct MessageQueue *prev;
146 * Structure for a controller link
148 struct ControllerLink
151 * The next ptr for DLL
153 struct ControllerLink *next;
156 * The prev ptr for DLL
158 struct ControllerLink *prev;
161 * The host which will be referred in the peer start request. This is the
162 * host where the peer should be started
164 struct GNUNET_TESTBED_Host *delegated_host;
167 * The host which will contacted to delegate the peer start request
169 struct GNUNET_TESTBED_Host *slave_host;
172 * The configuration to be used to connect to slave host
174 const struct GNUNET_CONFIGURATION_Handle *slave_cfg;
177 * GNUNET_YES if the slave should be started (and stopped) by us; GNUNET_NO
178 * if we are just allowed to use the slave via TCP/IP
185 * handle for host registration
187 struct GNUNET_TESTBED_HostRegistrationHandle
190 * The host being registered
192 struct GNUNET_TESTBED_Host *host;
195 * The controller at which this host is being registered
197 struct GNUNET_TESTBED_Controller *c;
200 * The Registartion completion callback
202 GNUNET_TESTBED_HostRegistrationCompletion cc;
205 * The closure for above callback
212 * Context data for forwarded Operation
214 struct ForwardedOperationData
218 * The callback to call when reply is available
220 GNUNET_CLIENT_MessageHandler cc;
223 * The closure for the above callback
231 * Context data for get slave config operations
233 struct GetSlaveConfigData
236 * The id of the slave controller
244 * Context data for controller link operations
246 struct ControllerLinkData
249 * The controller link message
251 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
257 * Returns the operation context with the given id if found in the Operation
258 * context queues of the controller
260 * @param c the controller whose queues are searched
261 * @param id the id which has to be checked
262 * @return the matching operation context; NULL if no match found
264 static struct OperationContext *
265 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
267 struct OperationContext *opc;
269 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
279 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
280 * controller (testbed service)
282 * @param c the controller handler
283 * @param msg message received
284 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
288 handle_addhostconfirm (struct GNUNET_TESTBED_Controller *c,
289 const struct GNUNET_TESTBED_HostConfirmedMessage *msg)
291 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
300 if (GNUNET_TESTBED_host_get_id_ (rh->host) != ntohl (msg->host_id))
302 LOG_DEBUG ("Mismatch in host id's %u, %u of host confirm msg\n",
303 GNUNET_TESTBED_host_get_id_ (rh->host), ntohl (msg->host_id));
307 msg_size = ntohs (msg->header.size);
308 if (sizeof (struct GNUNET_TESTBED_HostConfirmedMessage) == msg_size)
310 LOG_DEBUG ("Host %u successfully registered\n", ntohl (msg->host_id));
311 GNUNET_TESTBED_mark_host_registered_at_ (rh->host, c);
312 rh->cc (rh->cc_cls, NULL);
316 /* We have an error message */
317 emsg = (char *) &msg[1];
319 emsg[msg_size - sizeof (struct GNUNET_TESTBED_HostConfirmedMessage)])
325 LOG (GNUNET_ERROR_TYPE_ERROR, _("Adding host %u failed with error: %s\n"),
326 ntohl (msg->host_id), emsg);
327 rh->cc (rh->cc_cls, emsg);
334 * Handler for forwarded operations
336 * @param c the controller handle
337 * @param opc the opearation context
338 * @param msg the message
341 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
342 struct OperationContext *opc,
343 const struct GNUNET_MessageHeader *msg)
345 struct ForwardedOperationData *fo_data;
348 if (NULL != fo_data->cc)
349 fo_data->cc (fo_data->cc_cls, msg);
350 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
351 GNUNET_free (fo_data);
357 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
358 * controller (testbed service)
360 * @param c the controller handler
361 * @param msg message received
362 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
366 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
368 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
370 struct OperationContext *opc;
371 struct GNUNET_TESTBED_EventInformation event;
374 op_id = GNUNET_ntohll (msg->operation_id);
375 LOG_DEBUG ("Operation %lu successful\n", op_id);
376 if (NULL == (opc = find_opc (c, op_id)))
378 LOG_DEBUG ("Operation not found\n");
381 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
382 event.details.operation_finished.operation = opc->op;
383 event.details.operation_finished.op_cls = opc->op_cls;
384 event.details.operation_finished.emsg = NULL;
385 event.details.operation_finished.generic = NULL;
390 handle_forwarded_operation_msg
391 (c, opc, (const struct GNUNET_MessageHeader *) msg);
395 case OP_PEER_DESTROY:
397 struct GNUNET_TESTBED_Peer *peer;
405 case OP_LINK_CONTROLLERS:
407 struct ControllerLinkData *data;
410 GNUNET_assert (NULL != data);
418 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
419 opc->state = OPC_STATE_FINISHED;
420 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
423 c->cc (c->cc_cls, &event);
426 LOG_DEBUG ("Not calling callback\n");
432 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
433 * controller (testbed service)
435 * @param c the controller handle
436 * @param msg message received
437 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
441 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
443 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
445 struct OperationContext *opc;
446 struct PeerCreateData *data;
447 struct GNUNET_TESTBED_Peer *peer;
448 GNUNET_TESTBED_PeerCreateCallback cb;
452 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
453 ntohs (msg->header.size));
454 op_id = GNUNET_ntohll (msg->operation_id);
455 if (NULL == (opc = find_opc (c, op_id)))
457 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
460 if (OP_FORWARDED == opc->type)
462 handle_forwarded_operation_msg (c, opc,
463 (const struct GNUNET_MessageHeader *) msg);
466 GNUNET_assert (OP_PEER_CREATE == opc->type);
467 GNUNET_assert (NULL != opc->data);
469 GNUNET_assert (NULL != data->peer);
471 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
472 peer->state = PS_CREATED;
475 GNUNET_free (opc->data);
476 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
477 opc->state = OPC_STATE_FINISHED;
479 cb (cls, peer, NULL);
485 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
486 * controller (testbed service)
488 * @param c the controller handler
489 * @param msg message received
490 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
494 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
495 const struct GNUNET_TESTBED_PeerEventMessage *msg)
497 struct OperationContext *opc;
498 struct GNUNET_TESTBED_Peer *peer;
499 struct PeerEventData *data;
500 GNUNET_TESTBED_PeerChurnCallback pcc;
502 struct GNUNET_TESTBED_EventInformation event;
505 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
506 ntohs (msg->header.size));
507 op_id = GNUNET_ntohll (msg->operation_id);
508 if (NULL == (opc = find_opc (c, op_id)))
510 LOG_DEBUG ("Operation not found\n");
513 if (OP_FORWARDED == opc->type)
515 handle_forwarded_operation_msg (c, opc,
516 (const struct GNUNET_MessageHeader *) msg);
519 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
521 GNUNET_assert (NULL != data);
523 GNUNET_assert (NULL != peer);
524 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
527 case GNUNET_TESTBED_ET_PEER_START:
528 peer->state = PS_STARTED;
529 event.details.peer_start.host = peer->host;
530 event.details.peer_start.peer = peer;
532 case GNUNET_TESTBED_ET_PEER_STOP:
533 peer->state = PS_STOPPED;
534 event.details.peer_stop.peer = peer;
537 GNUNET_assert (0); /* We should never reach this state */
540 pcc_cls = data->pcc_cls;
542 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
543 opc->state = OPC_STATE_FINISHED;
545 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
549 c->cc (c->cc_cls, &event);
558 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
559 * controller (testbed service)
561 * @param c the controller handler
562 * @param msg message received
563 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
567 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
568 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
570 struct OperationContext *opc;
571 struct OverlayConnectData *data;
572 GNUNET_TESTBED_OperationCompletionCallback cb;
574 struct GNUNET_TESTBED_EventInformation event;
577 op_id = GNUNET_ntohll (msg->operation_id);
578 if (NULL == (opc = find_opc (c, op_id)))
580 LOG_DEBUG ("Operation not found\n");
583 if (OP_FORWARDED == opc->type)
585 handle_forwarded_operation_msg (c, opc,
586 (const struct GNUNET_MessageHeader *) msg);
589 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
591 GNUNET_assert (NULL != data);
592 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
593 (ntohl (msg->peer2) == data->p2->unique_id));
594 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
597 case GNUNET_TESTBED_ET_CONNECT:
598 event.details.peer_connect.peer1 = data->p1;
599 event.details.peer_connect.peer2 = data->p2;
601 case GNUNET_TESTBED_ET_DISCONNECT:
602 GNUNET_assert (0); /* FIXME: implement */
605 GNUNET_assert (0); /* Should never reach here */
609 cb_cls = data->cb_cls;
610 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
611 opc->state = OPC_STATE_FINISHED;
614 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
618 c->cc (c->cc_cls, &event);
621 cb (cb_cls, opc->op, NULL);
627 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
628 * controller (testbed service)
630 * @param c the controller handler
631 * @param msg message received
632 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
636 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
638 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
640 struct OperationContext *opc;
641 struct GNUNET_TESTBED_Peer *peer;
642 struct PeerInfoData *data;
643 struct GNUNET_TESTBED_PeerInformation *pinfo;
644 GNUNET_TESTBED_PeerInfoCallback cb;
648 op_id = GNUNET_ntohll (msg->operation_id);
649 if (NULL == (opc = find_opc (c, op_id)))
651 LOG_DEBUG ("Operation not found\n");
654 if (OP_FORWARDED == opc->type)
656 handle_forwarded_operation_msg (c, opc,
657 (const struct GNUNET_MessageHeader *) msg);
661 GNUNET_assert (NULL != data);
663 GNUNET_assert (NULL != peer);
664 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
665 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
666 pinfo->pit = data->pit;
668 cb_cls = data->cb_cls;
673 case GNUNET_TESTBED_PIT_IDENTITY:
674 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
675 (void) memcpy (pinfo->result.id, &msg->peer_identity,
676 sizeof (struct GNUNET_PeerIdentity));
678 case GNUNET_TESTBED_PIT_CONFIGURATION:
679 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
680 GNUNET_TESTBED_extract_config_ (&msg->header);
682 case GNUNET_TESTBED_PIT_GENERIC:
683 GNUNET_assert (0); /* never reach here */
687 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
688 opc->state = OPC_STATE_FINISHED;
690 cb (cb_cls, opc->op, pinfo, NULL);
696 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
697 * controller (testbed service)
699 * @param c the controller handler
700 * @param msg message received
701 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
705 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
706 const struct GNUNET_TESTBED_OperationFailureEventMessage
709 struct OperationContext *opc;
712 struct GNUNET_TESTBED_EventInformation event;
714 op_id = GNUNET_ntohll (msg->operation_id);
715 if (NULL == (opc = find_opc (c, op_id)))
717 LOG_DEBUG ("Operation not found\n");
720 if (OP_FORWARDED == opc->type)
722 handle_forwarded_operation_msg (c, opc,
723 (const struct GNUNET_MessageHeader *) msg);
726 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
727 opc->state = OPC_STATE_FINISHED;
728 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
730 emsg = "Unknown error";
731 if (OP_PEER_INFO == opc->type)
733 struct PeerInfoData *data;
735 if (NULL != data->cb)
736 data->cb (data->cb_cls, opc->op, NULL, emsg);
738 return GNUNET_YES; /* We do not call controller callback for peer info */
740 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
743 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
744 event.details.operation_finished.operation = opc->op;
745 event.details.operation_finished.op_cls = opc->op_cls;
746 event.details.operation_finished.emsg = emsg;
747 event.details.operation_finished.generic = NULL;
748 c->cc (c->cc_cls, &event);
754 struct PeerCreateData *data;
756 GNUNET_free (data->peer);
757 if (NULL != data->cb)
758 data->cb (data->cls, NULL, emsg);
765 struct PeerEventData *data;
767 if (NULL != data->pcc)
768 data->pcc (data->pcc_cls, emsg);
772 case OP_PEER_DESTROY:
776 case OP_OVERLAY_CONNECT:
778 struct OverlayConnectData *data;
780 if (NULL != data->cb)
781 data->cb (data->cb_cls, opc->op, emsg);
787 case OP_LINK_CONTROLLERS: /* No secondary callback */
797 * Function to build GET_SLAVE_CONFIG message
799 * @param op_id the id this message should contain in its operation id field
800 * @param slave_id the id this message should contain in its slave id field
801 * @return newly allocated SlaveGetConfigurationMessage
803 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
804 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
806 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
809 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
810 msg = GNUNET_malloc (msize);
811 msg->header.size = htons (msize);
812 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_GETSLAVECONFIG);
813 msg->operation_id = GNUNET_htonll (op_id);
814 msg->slave_id = htonl (slave_id);
820 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
823 * @param c the controller handler
824 * @param msg message received
825 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
829 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
830 const struct GNUNET_TESTBED_SlaveConfiguration * msg)
832 struct OperationContext *opc;
834 struct GNUNET_TESTBED_EventInformation event;
836 op_id = GNUNET_ntohll (msg->operation_id);
837 if (NULL == (opc = find_opc (c, op_id)))
839 LOG_DEBUG ("Operation not found\n");
842 if (OP_GET_SLAVE_CONFIG != opc->type)
847 GNUNET_free (opc->data);
849 opc->state = OPC_STATE_FINISHED;
850 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
851 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
854 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
855 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
856 event.details.operation_finished.generic = opc->data;
857 event.details.operation_finished.operation = opc->op;
858 event.details.operation_finished.op_cls = opc->op_cls;
859 event.details.operation_finished.emsg = NULL;
860 c->cc (c->cc_cls, &event);
867 * Handler for messages from controller (testbed service)
869 * @param cls the controller handler
870 * @param msg message received, NULL on timeout or fatal error
873 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
875 struct GNUNET_TESTBED_Controller *c = cls;
879 c->in_receive = GNUNET_NO;
880 /* FIXME: Add checks for message integrity */
883 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
887 msize = ntohs (msg->size);
888 switch (ntohs (msg->type))
890 case GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM:
891 GNUNET_assert (msize >=
892 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
894 handle_addhostconfirm (c,
895 (const struct GNUNET_TESTBED_HostConfirmedMessage
898 case GNUNET_MESSAGE_TYPE_TESTBED_GENERICOPSUCCESS:
899 GNUNET_assert (msize ==
901 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
905 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
908 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS:
909 GNUNET_assert (msize ==
911 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
913 handle_peer_create_success (c,
915 GNUNET_TESTBED_PeerCreateSuccessEventMessage
918 case GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT:
919 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
921 handle_peer_event (c,
922 (const struct GNUNET_TESTBED_PeerEventMessage *)
926 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
927 GNUNET_assert (msize >=
929 GNUNET_TESTBED_PeerConfigurationInformationMessage));
931 handle_peer_config (c,
933 GNUNET_TESTBED_PeerConfigurationInformationMessage
936 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT:
937 GNUNET_assert (msize ==
938 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
940 handle_peer_conevent (c,
942 GNUNET_TESTBED_ConnectionEventMessage *) msg);
944 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT:
945 GNUNET_assert (msize >=
946 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
948 handle_op_fail_event (c,
950 GNUNET_TESTBED_OperationFailureEventMessage *)
953 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG:
954 GNUNET_assert (msize >
955 sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
957 handle_slave_config (c, (const struct
958 GNUNET_TESTBED_SlaveConfiguration *) msg);
963 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
965 c->in_receive = GNUNET_YES;
966 GNUNET_CLIENT_receive (c->client, &message_handler, c,
967 GNUNET_TIME_UNIT_FOREVER_REL);
973 * Function called to notify a client about the connection begin ready to queue
974 * more data. "buf" will be NULL and "size" zero if the connection was closed
975 * for writing in the meantime.
978 * @param size number of bytes available in buf
979 * @param buf where the callee should write the message
980 * @return number of bytes written to buf
983 transmit_ready_notify (void *cls, size_t size, void *buf)
985 struct GNUNET_TESTBED_Controller *c = cls;
986 struct MessageQueue *mq_entry;
989 mq_entry = c->mq_head;
990 GNUNET_assert (NULL != mq_entry);
991 if ((0 == size) && (NULL == buf)) /* Timeout */
993 LOG_DEBUG ("Message sending timed out -- retrying\n");
995 GNUNET_CLIENT_notify_transmit_ready (c->client,
996 ntohs (mq_entry->msg->size),
997 TIMEOUT_REL, GNUNET_YES,
998 &transmit_ready_notify, c);
1001 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1002 size = ntohs (mq_entry->msg->size);
1003 memcpy (buf, mq_entry->msg, size);
1004 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1005 ntohs (mq_entry->msg->type), size);
1006 GNUNET_free (mq_entry->msg);
1007 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1008 GNUNET_free (mq_entry);
1009 mq_entry = c->mq_head;
1010 if (NULL != mq_entry)
1012 GNUNET_CLIENT_notify_transmit_ready (c->client,
1013 ntohs (mq_entry->msg->size),
1014 TIMEOUT_REL, GNUNET_YES,
1015 &transmit_ready_notify, c);
1016 if (GNUNET_NO == c->in_receive)
1018 c->in_receive = GNUNET_YES;
1019 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1020 GNUNET_TIME_UNIT_FOREVER_REL);
1027 * Queues a message in send queue for sending to the service
1029 * @param controller the handle to the controller
1030 * @param msg the message to queue
1033 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1034 struct GNUNET_MessageHeader *msg)
1036 struct MessageQueue *mq_entry;
1040 type = ntohs (msg->type);
1041 size = ntohs (msg->size);
1042 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1043 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1044 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1045 mq_entry->msg = msg;
1046 LOG (GNUNET_ERROR_TYPE_DEBUG,
1047 "Queueing message of type %u, size %u for sending\n", type,
1049 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1051 if (NULL == controller->th)
1053 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1054 TIMEOUT_REL, GNUNET_YES,
1055 &transmit_ready_notify,
1061 * Sends the given message as an operation. The given callback is called when a
1062 * reply for the operation is available. Call
1063 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1064 * operation context if the cc hasn't been called
1066 * @param controller the controller to which the message has to be sent
1067 * @param operation_id the operation id of the message
1068 * @param msg the message to send
1069 * @param cc the callback to call when reply is available
1070 * @param cc_cls the closure for the above callback
1071 * @return the operation context which can be used to cancel the forwarded
1074 struct OperationContext *
1075 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1076 *controller, uint64_t operation_id,
1077 const struct GNUNET_MessageHeader *msg,
1078 GNUNET_CLIENT_MessageHandler cc,
1081 struct OperationContext *opc;
1082 struct ForwardedOperationData *data;
1083 struct GNUNET_MessageHeader *dup_msg;
1086 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1088 data->cc_cls = cc_cls;
1089 opc = GNUNET_malloc (sizeof (struct OperationContext));
1090 opc->c = controller;
1091 opc->type = OP_FORWARDED;
1093 opc->id = operation_id;
1094 msize = ntohs (msg->size);
1095 dup_msg = GNUNET_malloc (msize);
1096 (void) memcpy (dup_msg, msg, msize);
1097 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1098 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1105 * Function to cancel an operation created by simply forwarding an operation
1108 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1111 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1113 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1114 GNUNET_free (opc->data);
1120 * Functions with this signature are called whenever a
1121 * complete message is received by the tokenizer.
1123 * Do not call GNUNET_SERVER_mst_destroy in callback
1125 * @param cls closure
1126 * @param client identification of the client
1127 * @param message the actual message
1129 * @return GNUNET_OK on success, GNUNET_SYSERR to stop further processing
1132 helper_mst (void *cls, void *client, const struct GNUNET_MessageHeader *message)
1134 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1135 const struct GNUNET_TESTBED_HelperReply *msg;
1136 const char *hostname;
1139 uLongf xconfig_size;
1141 msg = (const struct GNUNET_TESTBED_HelperReply *) message;
1142 GNUNET_assert (sizeof (struct GNUNET_TESTBED_HelperReply) <
1143 ntohs (msg->header.size));
1144 GNUNET_assert (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_REPLY ==
1145 ntohs (msg->header.type));
1146 config_size = (uLongf) ntohs (msg->config_size);
1148 (uLongf) (ntohs (msg->header.size) -
1149 sizeof (struct GNUNET_TESTBED_HelperReply));
1150 config = GNUNET_malloc (config_size);
1151 GNUNET_assert (Z_OK ==
1152 uncompress ((Bytef *) config, &config_size,
1153 (const Bytef *) &msg[1], xconfig_size));
1154 GNUNET_assert (NULL == cp->cfg);
1155 cp->cfg = GNUNET_CONFIGURATION_create ();
1156 GNUNET_assert (GNUNET_CONFIGURATION_deserialize
1157 (cp->cfg, config, config_size, GNUNET_NO));
1158 GNUNET_free (config);
1159 if ((NULL == cp->host) ||
1160 (NULL == (hostname = GNUNET_TESTBED_host_get_hostname_ (cp->host))))
1161 hostname = "localhost";
1162 /* Change the hostname so that we can connect to it */
1163 GNUNET_CONFIGURATION_set_value_string (cp->cfg, "testbed", "hostname",
1165 cp->cb (cp->cls, cp->cfg, GNUNET_OK);
1171 * Continuation function from GNUNET_HELPER_send()
1173 * @param cls closure
1174 * @param result GNUNET_OK on success,
1175 * GNUNET_NO if helper process died
1176 * GNUNET_SYSERR during GNUNET_HELPER_stop
1179 clear_msg (void *cls, int result)
1181 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1183 GNUNET_assert (NULL != cp->shandle);
1185 GNUNET_free (cp->msg);
1190 * Callback that will be called when the helper process dies. This is not called
1191 * when the helper process is stoped using GNUNET_HELPER_stop()
1193 * @param cls the closure from GNUNET_HELPER_start()
1196 helper_exp_cb (void *cls)
1198 struct GNUNET_TESTBED_ControllerProc *cp = cls;
1199 GNUNET_TESTBED_ControllerStatusCallback cb;
1205 GNUNET_TESTBED_controller_stop (cp);
1207 cb (cb_cls, NULL, GNUNET_SYSERR);
1212 * Function to call to start a link-controllers type operation once all queues
1213 * the operation is part of declare that the operation can be activated.
1215 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1218 opstart_link_controllers (void *cls)
1220 struct OperationContext *opc = cls;
1221 struct ControllerLinkData *data;
1222 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1224 GNUNET_assert (NULL != opc->data);
1228 opc->state = OPC_STATE_STARTED;
1229 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1230 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1235 * Callback which will be called when link-controllers type operation is released
1237 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1240 oprelease_link_controllers (void *cls)
1242 struct OperationContext *opc = cls;
1243 struct ControllerLinkData *data;
1248 case OPC_STATE_INIT:
1249 GNUNET_free (data->msg);
1251 case OPC_STATE_STARTED:
1252 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1254 case OPC_STATE_FINISHED:
1257 GNUNET_free_non_null (data);
1263 * Function to be called when get slave config operation is ready
1265 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1268 opstart_get_slave_config (void *cls)
1270 struct OperationContext *opc = cls;
1271 struct GetSlaveConfigData *data;
1272 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1275 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1276 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1277 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1278 opc->state = OPC_STATE_STARTED;
1283 * Function to be called when get slave config operation is cancelled or finished
1285 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1288 oprelease_get_slave_config (void *cls)
1290 struct OperationContext *opc = cls;
1294 case OPC_STATE_INIT:
1295 GNUNET_free (opc->data);
1297 case OPC_STATE_STARTED:
1298 GNUNET_free (opc->data);
1299 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1301 case OPC_STATE_FINISHED:
1302 if (NULL != opc->data)
1303 GNUNET_CONFIGURATION_destroy (opc->data);
1311 * Starts a controller process at the host. FIXME: add controller start callback
1312 * with the configuration with which the controller is started
1314 * @param controller_ip the ip address of the controller. Will be set as TRUSTED
1315 * host when starting testbed controller at host
1316 * @param host the host where the controller has to be started; NULL for
1318 * @param cfg template configuration to use for the remote controller; the
1319 * remote controller will be started with a slightly modified
1320 * configuration (port numbers, unix domain sockets and service home
1321 * values are changed as per TESTING library on the remote host)
1322 * @param cb function called when the controller is successfully started or
1323 * dies unexpectedly; GNUNET_TESTBED_controller_stop shouldn't be
1324 * called if cb is called with GNUNET_SYSERR as status. Will never be
1325 * called in the same task as 'GNUNET_TESTBED_controller_start'
1326 * (synchronous errors will be signalled by returning NULL). This
1327 * parameter cannot be NULL.
1328 * @param cls closure for above callbacks
1329 * @return the controller process handle, NULL on errors
1331 struct GNUNET_TESTBED_ControllerProc *
1332 GNUNET_TESTBED_controller_start (const char *controller_ip,
1333 struct GNUNET_TESTBED_Host *host,
1334 const struct GNUNET_CONFIGURATION_Handle *cfg,
1335 GNUNET_TESTBED_ControllerStatusCallback cb,
1338 struct GNUNET_TESTBED_ControllerProc *cp;
1339 struct GNUNET_TESTBED_HelperInit *msg;
1340 const char *hostname;
1341 static char *const binary_argv[] = {
1342 HELPER_TESTBED_BINARY, NULL
1346 cp = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ControllerProc));
1347 if ((NULL == host) || (0 == GNUNET_TESTBED_host_get_id_ (host)))
1350 GNUNET_HELPER_start (GNUNET_YES, HELPER_TESTBED_BINARY, binary_argv,
1351 &helper_mst, &helper_exp_cb, cp);
1355 char *helper_binary_path;
1356 char *remote_args[10];
1358 const char *username;
1360 username = GNUNET_TESTBED_host_get_username_ (host);
1361 hostname = GNUNET_TESTBED_host_get_hostname_ (host);
1362 GNUNET_asprintf (&cp->port, "%u", GNUNET_TESTBED_host_get_ssh_port_ (host));
1363 if (NULL == username)
1364 GNUNET_asprintf (&cp->dst, "%s", hostname);
1366 GNUNET_asprintf (&cp->dst, "%s@%s", username, hostname);
1367 LOG_DEBUG ("Starting SSH to destination %s\n", cp->dst);
1369 remote_args[argp++] = "ssh";
1370 remote_args[argp++] = "-p";
1371 remote_args[argp++] = cp->port;
1372 remote_args[argp++] = "-o";
1373 remote_args[argp++] = "BatchMode=yes";
1374 remote_args[argp++] = "-o";
1375 remote_args[argp++] = "NoHostAuthenticationForLocalhost=yes";
1376 remote_args[argp++] = cp->dst;
1377 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "testbed",
1378 "HELPER_BINARY_PATH",
1379 &helper_binary_path))
1380 helper_binary_path = GNUNET_OS_get_libexec_binary_path (HELPER_TESTBED_BINARY);
1381 remote_args[argp++] = helper_binary_path;
1382 remote_args[argp++] = NULL;
1383 GNUNET_assert (argp == 10);
1385 GNUNET_HELPER_start (GNUNET_NO, "ssh", remote_args, &helper_mst,
1386 &helper_exp_cb, cp);
1387 GNUNET_free (helper_binary_path);
1389 if (NULL == cp->helper)
1391 GNUNET_free_non_null (cp->port);
1392 GNUNET_free_non_null (cp->dst);
1399 msg = GNUNET_TESTBED_create_helper_init_msg_ (controller_ip, hostname, cfg);
1400 cp->msg = &msg->header;
1402 GNUNET_HELPER_send (cp->helper, &msg->header, GNUNET_NO, &clear_msg, cp);
1403 if (NULL == cp->shandle)
1406 GNUNET_TESTBED_controller_stop (cp);
1414 * Stop the controller process (also will terminate all peers and controllers
1415 * dependent on this controller). This function blocks until the testbed has
1416 * been fully terminated (!). The controller status cb from
1417 * GNUNET_TESTBED_controller_start() will not be called.
1419 * @param cproc the controller process handle
1422 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_ControllerProc *cproc)
1424 if (NULL != cproc->shandle)
1425 GNUNET_HELPER_send_cancel (cproc->shandle);
1426 if (NULL != cproc->helper)
1427 GNUNET_HELPER_stop (cproc->helper);
1428 if (NULL != cproc->cfg)
1429 GNUNET_CONFIGURATION_destroy (cproc->cfg);
1430 GNUNET_free_non_null (cproc->port);
1431 GNUNET_free_non_null (cproc->dst);
1432 GNUNET_free (cproc);
1437 * Start a controller process using the given configuration at the
1440 * @param cfg configuration to use
1441 * @param host host to run the controller on; This should be the same host if
1442 * the controller was previously started with
1443 * GNUNET_TESTBED_controller_start; NULL for localhost
1444 * @param event_mask bit mask with set of events to call 'cc' for;
1445 * or-ed values of "1LL" shifted by the
1446 * respective 'enum GNUNET_TESTBED_EventType'
1447 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1448 * @param cc controller callback to invoke on events
1449 * @param cc_cls closure for cc
1450 * @return handle to the controller
1452 struct GNUNET_TESTBED_Controller *
1453 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1454 *cfg, struct GNUNET_TESTBED_Host *host,
1455 uint64_t event_mask,
1456 GNUNET_TESTBED_ControllerCallback cc,
1459 struct GNUNET_TESTBED_Controller *controller;
1460 struct GNUNET_TESTBED_InitMessage *msg;
1461 const char *controller_hostname;
1462 unsigned long long max_parallel_operations;
1463 unsigned long long max_parallel_service_connections;
1464 unsigned long long max_parallel_topology_config_operations;
1465 unsigned long long max_parallel_overlay_connect_operations;
1468 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1469 "MAX_PARALLEL_OPERATIONS",
1470 &max_parallel_operations))
1476 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1477 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1478 &max_parallel_service_connections))
1484 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1485 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1486 &max_parallel_topology_config_operations))
1492 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1493 "MAX_PARALLEL_OVERLAY_CONNECT_OPERATIONS",
1494 &max_parallel_overlay_connect_operations))
1499 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1500 controller->cc = cc;
1501 controller->cc_cls = cc_cls;
1502 controller->event_mask = event_mask;
1503 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1504 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1505 if (NULL == controller->client)
1507 GNUNET_TESTBED_controller_disconnect (controller);
1512 host = GNUNET_TESTBED_host_create_by_id_ (0);
1513 if (NULL == host) /* If the above host create fails */
1515 LOG (GNUNET_ERROR_TYPE_WARNING,
1516 "Treating NULL host as localhost. Multiple references to localhost "
1517 "may break when localhost freed before calling disconnect \n");
1518 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1522 controller->aux_host = GNUNET_YES;
1525 GNUNET_assert (NULL != host);
1526 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1527 controller->host = host;
1528 controller->opq_parallel_operations =
1529 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1530 max_parallel_operations);
1531 controller->opq_parallel_service_connections =
1532 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1533 max_parallel_service_connections);
1534 controller->opq_parallel_topology_config_operations=
1535 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1536 max_parallel_topology_config_operations);
1537 controller->opq_parallel_overlay_connect_operations=
1538 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1539 max_parallel_overlay_connect_operations);
1540 controller_hostname = GNUNET_TESTBED_host_get_hostname_ (host);
1541 if (NULL == controller_hostname)
1542 controller_hostname = "127.0.0.1";
1544 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1545 strlen (controller_hostname) + 1);
1546 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1548 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1549 strlen (controller_hostname) + 1);
1550 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1551 msg->event_mask = GNUNET_htonll (controller->event_mask);
1552 strcpy ((char *) &msg[1], controller_hostname);
1553 GNUNET_TESTBED_queue_message_ (controller,
1554 (struct GNUNET_MessageHeader *) msg);
1560 * Configure shared services at a controller. Using this function,
1561 * you can specify that certain services (such as "resolver")
1562 * should not be run for each peer but instead be shared
1563 * across N peers on the specified host. This function
1564 * must be called before any peers are created at the host.
1566 * @param controller controller to configure
1567 * @param service_name name of the service to share
1568 * @param num_peers number of peers that should share one instance
1569 * of the specified service (1 for no sharing is the default),
1570 * use 0 to disable the service
1573 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1575 const char *service_name,
1578 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1579 uint16_t service_name_size;
1582 service_name_size = strlen (service_name) + 1;
1584 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1586 msg = GNUNET_malloc (msg_size);
1587 msg->header.size = htons (msg_size);
1588 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE);
1589 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1590 msg->num_peers = htonl (num_peers);
1591 memcpy (&msg[1], service_name, service_name_size);
1592 GNUNET_TESTBED_queue_message_ (controller,
1593 (struct GNUNET_MessageHeader *) msg);
1594 GNUNET_break (0); /* This function is not yet implemented on the
1600 * disconnects from the controller.
1602 * @param controller handle to controller to stop
1605 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1608 struct MessageQueue *mq_entry;
1610 if (NULL != controller->th)
1611 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1612 /* Clear the message queue */
1613 while (NULL != (mq_entry = controller->mq_head))
1615 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1617 GNUNET_free (mq_entry->msg);
1618 GNUNET_free (mq_entry);
1620 if (NULL != controller->client)
1621 GNUNET_CLIENT_disconnect (controller->client);
1622 GNUNET_CONFIGURATION_destroy (controller->cfg);
1623 if (GNUNET_YES == controller->aux_host)
1624 GNUNET_TESTBED_host_destroy (controller->host);
1625 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1626 GNUNET_TESTBED_operation_queue_destroy_
1627 (controller->opq_parallel_service_connections);
1628 GNUNET_TESTBED_operation_queue_destroy_
1629 (controller->opq_parallel_topology_config_operations);
1630 GNUNET_TESTBED_operation_queue_destroy_
1631 (controller->opq_parallel_overlay_connect_operations);
1632 GNUNET_free (controller);
1637 * Register a host with the controller
1639 * @param controller the controller handle
1640 * @param host the host to register
1641 * @param cc the completion callback to call to inform the status of
1642 * registration. After calling this callback the registration handle
1643 * will be invalid. Cannot be NULL.
1644 * @param cc_cls the closure for the cc
1645 * @return handle to the host registration which can be used to cancel the
1648 struct GNUNET_TESTBED_HostRegistrationHandle *
1649 GNUNET_TESTBED_register_host (struct GNUNET_TESTBED_Controller *controller,
1650 struct GNUNET_TESTBED_Host *host,
1651 GNUNET_TESTBED_HostRegistrationCompletion cc,
1654 struct GNUNET_TESTBED_HostRegistrationHandle *rh;
1655 struct GNUNET_TESTBED_AddHostMessage *msg;
1656 const char *username;
1657 const char *hostname;
1659 uint16_t user_name_length;
1661 if (NULL != controller->rh)
1663 hostname = GNUNET_TESTBED_host_get_hostname_ (host);
1664 if (GNUNET_YES == GNUNET_TESTBED_is_host_registered_ (host, controller))
1666 LOG (GNUNET_ERROR_TYPE_WARNING, "Host hostname: %s already registered\n",
1667 (NULL == hostname) ? "localhost" : hostname);
1670 rh = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_HostRegistrationHandle));
1673 GNUNET_assert (NULL != cc);
1675 rh->cc_cls = cc_cls;
1676 controller->rh = rh;
1677 username = GNUNET_TESTBED_host_get_username_ (host);
1678 msg_size = (sizeof (struct GNUNET_TESTBED_AddHostMessage));
1679 user_name_length = 0;
1680 if (NULL != username)
1682 user_name_length = strlen (username) + 1;
1683 msg_size += user_name_length;
1685 /* FIXME: what happens when hostname is NULL? localhost */
1686 GNUNET_assert (NULL != hostname);
1687 msg_size += strlen (hostname) + 1;
1688 msg = GNUNET_malloc (msg_size);
1689 msg->header.size = htons (msg_size);
1690 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_ADDHOST);
1691 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1692 msg->ssh_port = htons (GNUNET_TESTBED_host_get_ssh_port_ (host));
1693 if (NULL != username)
1695 msg->user_name_length = htons (user_name_length - 1);
1696 memcpy (&msg[1], username, user_name_length);
1699 msg->user_name_length = htons (user_name_length);
1700 strcpy (((void *) &msg[1]) + user_name_length, hostname);
1701 GNUNET_TESTBED_queue_message_ (controller,
1702 (struct GNUNET_MessageHeader *) msg);
1708 * Cancel the pending registration. Note that if the registration message is
1709 * already sent to the service the cancellation has only the effect that the
1710 * registration completion callback for the registration is never called.
1712 * @param handle the registration handle to cancel
1715 GNUNET_TESTBED_cancel_registration (struct GNUNET_TESTBED_HostRegistrationHandle
1718 if (handle != handle->c->rh)
1723 handle->c->rh = NULL;
1724 GNUNET_free (handle);
1729 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1732 * @param op_cls the operation closure for the event which is generated to
1733 * signal success or failure of this operation
1734 * @param master handle to the master controller who creates the association
1735 * @param delegated_host_id id of the host to which requests should be delegated
1736 * @param slave_host_id id of the host which is used to run the slave controller
1737 * @param sxcfg serialized and compressed configuration
1738 * @param sxcfg_size the size sxcfg
1739 * @param scfg_size the size of uncompressed serialized configuration
1740 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1741 * be started by the slave controller; GNUNET_NO if the slave
1742 * controller has to connect to the already started delegated
1743 * controller via TCP/IP
1744 * @return the operation handle
1746 struct GNUNET_TESTBED_Operation *
1747 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1748 struct GNUNET_TESTBED_Controller *master,
1749 uint32_t delegated_host_id,
1750 uint32_t slave_host_id,
1751 const char *sxcfg, size_t sxcfg_size,
1752 size_t scfg_size, int is_subordinate)
1754 struct OperationContext *opc;
1755 struct GNUNET_TESTBED_ControllerLinkMessage *msg;
1756 struct ControllerLinkData *data;
1759 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkMessage);
1760 msg = GNUNET_malloc (msg_size);
1761 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LCONTROLLERS);
1762 msg->header.size = htons (msg_size);
1763 msg->delegated_host_id = htonl (delegated_host_id);
1764 msg->slave_host_id = htonl (slave_host_id);
1765 msg->config_size = htons ((uint16_t) scfg_size);
1766 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1767 memcpy (&msg[1], sxcfg, sxcfg_size);
1768 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1770 opc = GNUNET_malloc (sizeof (struct OperationContext));
1773 opc->type = OP_LINK_CONTROLLERS;
1774 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1775 opc->state = OPC_STATE_INIT;
1776 opc->op_cls = op_cls;
1777 msg->operation_id = GNUNET_htonll (opc->id);
1779 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1780 &oprelease_link_controllers);
1781 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1783 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1789 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1790 * serialized and compressed
1792 * @param op_cls the operation closure for the event which is generated to
1793 * signal success or failure of this operation
1794 * @param master handle to the master controller who creates the association
1795 * @param delegated_host requests to which host should be delegated; cannot be NULL
1796 * @param slave_host which host is used to run the slave controller; use NULL to
1797 * make the master controller connect to the delegated host
1798 * @param sxcfg serialized and compressed configuration
1799 * @param sxcfg_size the size sxcfg
1800 * @param scfg_size the size of uncompressed serialized configuration
1801 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1802 * be started by the slave controller; GNUNET_NO if the slave
1803 * controller has to connect to the already started delegated
1804 * controller via TCP/IP
1805 * @return the operation handle
1807 struct GNUNET_TESTBED_Operation *
1808 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1809 struct GNUNET_TESTBED_Controller *master,
1810 struct GNUNET_TESTBED_Host *delegated_host,
1811 struct GNUNET_TESTBED_Host *slave_host,
1812 const char *sxcfg, size_t sxcfg_size,
1813 size_t scfg_size, int is_subordinate)
1815 uint32_t delegated_host_id;
1816 uint32_t slave_host_id;
1818 GNUNET_assert (GNUNET_YES ==
1819 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1820 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1822 GNUNET_TESTBED_host_get_id_ ((NULL != slave_host)
1823 ? slave_host : master->host);
1824 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1825 GNUNET_assert (GNUNET_YES ==
1826 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1828 return GNUNET_TESTBED_controller_link_2_ (op_cls,
1833 scfg_size, is_subordinate);
1838 * Compresses given configuration using zlib compress
1840 * @param config the serialized configuration
1841 * @param size the size of config
1842 * @param xconfig will be set to the compressed configuration (memory is fresly
1844 * @return the size of the xconfig
1847 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1852 xsize = compressBound ((uLong) size);
1853 *xconfig = GNUNET_malloc (xsize);
1854 GNUNET_assert (Z_OK ==
1855 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1856 (const Bytef *) config, (uLongf) size,
1863 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1866 * @param op_cls the operation closure for the event which is generated to
1867 * signal success or failure of this operation
1868 * @param master handle to the master controller who creates the association
1869 * @param delegated_host_id id of the host to which requests should be
1870 * delegated; cannot be NULL
1871 * @param slave_host_id id of the host which should connect to controller
1872 * running on delegated host ; use NULL to make the master controller
1873 * connect to the delegated host
1874 * @param slave_cfg configuration to use for the slave controller
1875 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1876 * be started by the slave controller; GNUNET_NO if the slave
1877 * controller has to connect to the already started delegated
1878 * controller via TCP/IP
1879 * @return the operation handle
1881 struct GNUNET_TESTBED_Operation *
1882 GNUNET_TESTBED_controller_link_ (void *op_cls,
1883 struct GNUNET_TESTBED_Controller *master,
1884 uint32_t delegated_host_id,
1885 uint32_t slave_host_id,
1886 const struct GNUNET_CONFIGURATION_Handle
1890 struct GNUNET_TESTBED_Operation *op;
1896 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1897 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1898 GNUNET_free (config);
1899 /* Configuration doesn't fit in 1 message */
1900 GNUNET_assert ((UINT16_MAX -
1901 sizeof (struct GNUNET_TESTBED_ControllerLinkMessage)) >=
1903 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1904 slave_host_id, (const char *) cconfig,
1905 cc_size, config_size, is_subordinate);
1906 GNUNET_free (cconfig);
1912 * Create a link from slave controller to delegated controller. Whenever the
1913 * master controller is asked to start a peer at the delegated controller the
1914 * request will be routed towards slave controller (if a route exists). The
1915 * slave controller will then route it to the delegated controller. The
1916 * configuration of the delegated controller is given and is used to either
1917 * create the delegated controller or to connect to an existing controller. Note
1918 * that while starting the delegated controller the configuration will be
1919 * modified to accommodate available free ports. the 'is_subordinate' specifies
1920 * if the given delegated controller should be started and managed by the slave
1921 * controller, or if the delegated controller already has a master and the slave
1922 * controller connects to it as a non master controller. The success or failure
1923 * of this operation will be signalled through the
1924 * GNUNET_TESTBED_ControllerCallback() with an event of type
1925 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1927 * @param op_cls the operation closure for the event which is generated to
1928 * signal success or failure of this operation
1929 * @param master handle to the master controller who creates the association
1930 * @param delegated_host requests to which host should be delegated; cannot be NULL
1931 * @param slave_host which host is used to run the slave controller; use NULL to
1932 * make the master controller connect to the delegated host
1933 * @param slave_cfg configuration to use for the slave controller
1934 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1935 * be started by the slave controller; GNUNET_NO if the slave
1936 * controller has to connect to the already started delegated
1937 * controller via TCP/IP
1938 * @return the operation handle
1940 struct GNUNET_TESTBED_Operation *
1941 GNUNET_TESTBED_controller_link (void *op_cls,
1942 struct GNUNET_TESTBED_Controller *master,
1943 struct GNUNET_TESTBED_Host *delegated_host,
1944 struct GNUNET_TESTBED_Host *slave_host,
1945 const struct GNUNET_CONFIGURATION_Handle
1946 *slave_cfg, int is_subordinate)
1948 uint32_t slave_host_id;
1949 uint32_t delegated_host_id;
1951 GNUNET_assert (GNUNET_YES ==
1952 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1954 GNUNET_TESTBED_host_get_id_ ((NULL != slave_host)
1955 ? slave_host : master->host);
1956 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1957 if ((NULL != slave_host) && (0 != slave_host_id))
1958 GNUNET_assert (GNUNET_YES ==
1959 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1960 return GNUNET_TESTBED_controller_link_ (op_cls, master,
1970 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1971 * check. Another difference is that this function takes the id of the slave
1974 * @param op_cls the closure for the operation
1975 * @param master the handle to master controller
1976 * @param slave_host_id id of the host where the slave controller is running to
1977 * the slave_host should remain valid until this operation is cancelled
1978 * or marked as finished
1979 * @return the operation handle;
1981 struct GNUNET_TESTBED_Operation *
1982 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1983 struct GNUNET_TESTBED_Controller *master,
1984 uint32_t slave_host_id)
1986 struct OperationContext *opc;
1987 struct GetSlaveConfigData *data;
1989 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1990 data->slave_id = slave_host_id;
1991 opc = GNUNET_malloc (sizeof (struct OperationContext));
1992 opc->state = OPC_STATE_INIT;
1994 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1995 opc->type = OP_GET_SLAVE_CONFIG;
1997 opc->op_cls = op_cls;
1999 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
2000 &oprelease_get_slave_config);
2001 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
2003 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2009 * Function to acquire the configuration of a running slave controller. The
2010 * completion of the operation is signalled through the controller_cb from
2011 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
2012 * handle to the configuration is available in the generic pointer of
2013 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
2015 * @param op_cls the closure for the operation
2016 * @param master the handle to master controller
2017 * @param slave_host the host where the slave controller is running; the handle
2018 * to the slave_host should remain valid until this operation is
2019 * cancelled or marked as finished
2020 * @return the operation handle; NULL if the slave_host is not registered at
2023 struct GNUNET_TESTBED_Operation *
2024 GNUNET_TESTBED_get_slave_config (void *op_cls,
2025 struct GNUNET_TESTBED_Controller *master,
2026 struct GNUNET_TESTBED_Host *slave_host)
2028 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
2030 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
2031 GNUNET_TESTBED_host_get_id_ (slave_host));
2036 * Ask the testbed controller to write the current overlay topology to
2037 * a file. Naturally, the file will only contain a snapshot as the
2038 * topology may evolve all the time.
2040 * @param controller overlay controller to inspect
2041 * @param filename name of the file the topology should
2045 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
2047 const char *filename)
2054 * Creates a helper initialization message. This function is here because we
2055 * want to use this in testing
2057 * @param cname the ip address of the controlling host
2058 * @param hostname the hostname of the destination this message is intended for
2059 * @param cfg the configuration that has to used to start the testbed service
2061 * @return the initialization message
2063 struct GNUNET_TESTBED_HelperInit *
2064 GNUNET_TESTBED_create_helper_init_msg_ (const char *cname,
2065 const char *hostname,
2066 const struct GNUNET_CONFIGURATION_Handle
2069 struct GNUNET_TESTBED_HelperInit *msg;
2073 size_t xconfig_size;
2075 uint16_t hostname_len;
2078 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
2079 GNUNET_assert (NULL != config);
2081 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
2082 GNUNET_free (config);
2083 cname_len = strlen (cname);
2084 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
2086 xconfig_size + cname_len + 1 + sizeof (struct GNUNET_TESTBED_HelperInit);
2087 msg_size += hostname_len;
2088 msg = GNUNET_realloc (xconfig, msg_size);
2089 (void) memmove (((void *) &msg[1]) + cname_len + 1 + hostname_len,
2092 msg->header.size = htons (msg_size);
2093 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
2094 msg->cname_size = htons (cname_len);
2095 msg->hostname_size = htons (hostname_len);
2096 msg->config_size = htons (config_size);
2097 (void) strcpy ((char *) &msg[1], cname);
2098 if (0 != hostname_len)
2099 (void) strncpy (((char *) &msg[1]) + cname_len + 1, hostname, hostname_len);
2105 * Cancel a pending operation. Releases all resources
2106 * of the operation and will ensure that no event
2107 * is generated for the operation. Does NOT guarantee
2108 * that the operation will be fully undone (or that
2109 * nothing ever happened).
2111 * @param operation operation to cancel
2114 GNUNET_TESTBED_operation_cancel (struct GNUNET_TESTBED_Operation *operation)
2116 GNUNET_TESTBED_operation_done (operation);
2121 * Signal that the information from an operation has been fully
2122 * processed. This function MUST be called for each event
2123 * of type 'operation_finished' to fully remove the operation
2124 * from the operation queue. After calling this function, the
2125 * 'op_result' becomes invalid (!).
2127 * @param operation operation to signal completion for
2130 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
2132 GNUNET_TESTBED_operation_release_ (operation);
2137 * Generates configuration by uncompressing configuration in given message. The
2138 * given message should be of the following types:
2139 * GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG,
2140 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG
2142 * @param msg the message containing compressed configuration
2143 * @return handle to the parsed configuration
2145 struct GNUNET_CONFIGURATION_Handle *
2146 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
2148 struct GNUNET_CONFIGURATION_Handle *cfg;
2155 switch (ntohs (msg->type))
2157 case GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG:
2159 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
2161 imsg = (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *)
2163 data_len = (uLong) ntohs (imsg->config_size);
2164 xdata_len = ntohs (imsg->header.size)
2165 - sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
2166 xdata = (const Bytef *) &imsg[1];
2169 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG:
2171 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
2173 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
2174 data_len = (uLong) ntohs (imsg->config_size);
2175 xdata_len = ntohs (imsg->header.size)
2176 - sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
2177 xdata = (const Bytef *) &imsg[1];
2183 data = GNUNET_malloc (data_len);
2186 uncompress (data, &data_len, xdata, xdata_len)))
2188 cfg = GNUNET_CONFIGURATION_create ();
2189 GNUNET_assert (GNUNET_OK ==
2190 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
2199 * Checks the integrity of the OperationFailureEventMessage and if good returns
2200 * the error message it contains.
2202 * @param msg the OperationFailureEventMessage
2203 * @return the error message
2206 GNUNET_TESTBED_parse_error_string_ (const struct
2207 GNUNET_TESTBED_OperationFailureEventMessage
2213 msize = ntohs (msg->header.size);
2214 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2216 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2217 emsg = (const char *) &msg[1];
2218 if ('\0' != emsg[msize - 1])
2228 * Function to return the operation id for a controller. The operation id is
2229 * created from the controllers host id and its internal operation counter.
2231 * @param controller the handle to the controller whose operation id has to be incremented
2232 * @return the incremented operation id.
2235 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller *controller)
2239 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2240 op_id = op_id << 32;
2241 op_id |= (uint64_t) controller->operation_counter++;
2245 /* end of testbed_api.c */