2 This file is part of GNUnet
3 (C) 2008--2013 Christian Grothoff (and other contributing authors)
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
22 * @file testbed/testbed_api.c
23 * @brief API for accessing the GNUnet testing service.
24 * This library is supposed to make it easier to write
25 * testcases and script large-scale benchmarks.
26 * @author Christian Grothoff
27 * @author Sree Harsha Totakura
32 #include "gnunet_testbed_service.h"
33 #include "gnunet_core_service.h"
34 #include "gnunet_constants.h"
35 #include "gnunet_transport_service.h"
36 #include "gnunet_hello_lib.h"
40 #include "testbed_api.h"
41 #include "testbed_api_hosts.h"
42 #include "testbed_api_peers.h"
43 #include "testbed_api_operations.h"
44 #include "testbed_api_sd.h"
47 * Generic logging shorthand
49 #define LOG(kind, ...) \
50 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__)
55 #define LOG_DEBUG(...) \
56 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
59 * Relative time seconds shorthand
61 #define TIME_REL_SECS(sec) \
62 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, sec)
66 * Default server message sending retry timeout
68 #define TIMEOUT_REL TIME_REL_SECS(1)
72 * The message queue for sending messages to the controller service
77 * The message to be sent
79 struct GNUNET_MessageHeader *msg;
82 * next pointer for DLL
84 struct MessageQueue *next;
87 * prev pointer for DLL
89 struct MessageQueue *prev;
94 * Context data for forwarded Operation
96 struct ForwardedOperationData
100 * The callback to call when reply is available
102 GNUNET_CLIENT_MessageHandler cc;
105 * The closure for the above callback
113 * Context data for get slave config operations
115 struct GetSlaveConfigData
118 * The id of the slave controller
126 * Context data for controller link operations
128 struct ControllerLinkData
131 * The controller link message
133 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
136 * The id of the host which is hosting the controller to be linked
144 * Date context for OP_SHUTDOWN_PEERS operations
146 struct ShutdownPeersData
149 * The operation completion callback to call
151 GNUNET_TESTBED_OperationCompletionCallback cb;
154 * The closure for the above callback
161 * An entry in the stack for keeping operations which are about to expire
163 struct ExpireOperationEntry
166 * DLL head; new entries are to be inserted here
168 struct ExpireOperationEntry *next;
171 * DLL tail; entries are deleted from here
173 struct ExpireOperationEntry *prev;
176 * The operation. This will be a dangling pointer when the operation is freed
178 const struct GNUNET_TESTBED_Operation *op;
181 static struct ExpireOperationEntry *exop_head;
183 static struct ExpireOperationEntry *exop_tail;
187 exop_insert (struct GNUNET_TESTBED_Operation *op)
189 struct ExpireOperationEntry *entry;
191 entry = GNUNET_malloc (sizeof (struct ExpireOperationEntry));
193 GNUNET_CONTAINER_DLL_insert_tail (exop_head, exop_tail, entry);
198 exop_check (const struct GNUNET_TESTBED_Operation *const op)
200 struct ExpireOperationEntry *entry;
201 struct ExpireOperationEntry *entry2;
206 while (NULL != entry)
215 if (GNUNET_NO == found)
217 /* Truncate the tail */
218 while (NULL != entry)
220 entry2 = entry->next;
221 GNUNET_CONTAINER_DLL_remove (exop_head, exop_tail, entry);
230 * Returns the operation context with the given id if found in the Operation
231 * context queues of the controller
233 * @param c the controller whose queues are searched
234 * @param id the id which has to be checked
235 * @return the matching operation context; NULL if no match found
237 static struct OperationContext *
238 find_opc (const struct GNUNET_TESTBED_Controller *c, const uint64_t id)
240 struct OperationContext *opc;
242 for (opc = c->ocq_head; NULL != opc; opc = opc->next)
252 * Handler for forwarded operations
254 * @param c the controller handle
255 * @param opc the opearation context
256 * @param msg the message
259 handle_forwarded_operation_msg (struct GNUNET_TESTBED_Controller *c,
260 struct OperationContext *opc,
261 const struct GNUNET_MessageHeader *msg)
263 struct ForwardedOperationData *fo_data;
266 if (NULL != fo_data->cc)
267 fo_data->cc (fo_data->cc_cls, msg);
268 GNUNET_CONTAINER_DLL_remove (c->ocq_head, c->ocq_tail, opc);
269 GNUNET_free (fo_data);
275 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_ADDHOSTCONFIRM message from
276 * controller (testbed service)
278 * @param c the controller handler
279 * @param msg message received
280 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
284 handle_opsuccess (struct GNUNET_TESTBED_Controller *c,
286 GNUNET_TESTBED_GenericOperationSuccessEventMessage *msg)
288 struct OperationContext *opc;
289 GNUNET_TESTBED_OperationCompletionCallback op_comp_cb;
290 void *op_comp_cb_cls;
291 struct GNUNET_TESTBED_EventInformation event;
294 op_id = GNUNET_ntohll (msg->operation_id);
295 LOG_DEBUG ("Operation %lu successful\n", op_id);
296 if (NULL == (opc = find_opc (c, op_id)))
298 LOG_DEBUG ("Operation not found\n");
301 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
303 event.op_cls = opc->op_cls;
304 event.details.operation_finished.emsg = NULL;
305 event.details.operation_finished.generic = NULL;
307 op_comp_cb_cls = NULL;
312 handle_forwarded_operation_msg (c, opc,
313 (const struct GNUNET_MessageHeader *) msg);
317 case OP_PEER_DESTROY:
319 struct GNUNET_TESTBED_Peer *peer;
322 GNUNET_TESTBED_peer_deregister_ (peer);
328 case OP_SHUTDOWN_PEERS:
330 struct ShutdownPeersData *data;
333 op_comp_cb = data->cb;
334 op_comp_cb_cls = data->cb_cls;
337 GNUNET_TESTBED_cleanup_peers_ ();
343 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
344 opc->state = OPC_STATE_FINISHED;
345 exop_insert (event.op);
346 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
349 c->cc (c->cc_cls, &event);
350 if (GNUNET_NO == exop_check (event.op))
354 LOG_DEBUG ("Not calling callback\n");
355 if (NULL != op_comp_cb)
356 op_comp_cb (op_comp_cb_cls, event.op, NULL);
357 /* You could have marked the operation as done by now */
358 GNUNET_break (GNUNET_NO == exop_check (event.op));
364 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCREATESUCCESS message from
365 * controller (testbed service)
367 * @param c the controller handle
368 * @param msg message received
369 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
373 handle_peer_create_success (struct GNUNET_TESTBED_Controller *c,
375 GNUNET_TESTBED_PeerCreateSuccessEventMessage *msg)
377 struct OperationContext *opc;
378 struct PeerCreateData *data;
379 struct GNUNET_TESTBED_Peer *peer;
380 struct GNUNET_TESTBED_Operation *op;
381 GNUNET_TESTBED_PeerCreateCallback cb;
385 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerCreateSuccessEventMessage) ==
386 ntohs (msg->header.size));
387 op_id = GNUNET_ntohll (msg->operation_id);
388 if (NULL == (opc = find_opc (c, op_id)))
390 LOG_DEBUG ("Operation context for PeerCreateSuccessEvent not found\n");
393 if (OP_FORWARDED == opc->type)
395 handle_forwarded_operation_msg (c, opc,
396 (const struct GNUNET_MessageHeader *) msg);
399 GNUNET_assert (OP_PEER_CREATE == opc->type);
400 GNUNET_assert (NULL != opc->data);
402 GNUNET_assert (NULL != data->peer);
404 GNUNET_assert (peer->unique_id == ntohl (msg->peer_id));
405 peer->state = PS_CREATED;
406 GNUNET_TESTBED_peer_register_ (peer);
410 GNUNET_free (opc->data);
411 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
412 opc->state = OPC_STATE_FINISHED;
415 cb (cls, peer, NULL);
416 /* You could have marked the operation as done by now */
417 GNUNET_break (GNUNET_NO == exop_check (op));
423 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEEREVENT message from
424 * controller (testbed service)
426 * @param c the controller handler
427 * @param msg message received
428 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
432 handle_peer_event (struct GNUNET_TESTBED_Controller *c,
433 const struct GNUNET_TESTBED_PeerEventMessage *msg)
435 struct OperationContext *opc;
436 struct GNUNET_TESTBED_Peer *peer;
437 struct PeerEventData *data;
438 GNUNET_TESTBED_PeerChurnCallback pcc;
440 struct GNUNET_TESTBED_EventInformation event;
443 GNUNET_assert (sizeof (struct GNUNET_TESTBED_PeerEventMessage) ==
444 ntohs (msg->header.size));
445 op_id = GNUNET_ntohll (msg->operation_id);
446 if (NULL == (opc = find_opc (c, op_id)))
448 LOG_DEBUG ("Operation not found\n");
451 if (OP_FORWARDED == opc->type)
453 handle_forwarded_operation_msg (c, opc,
454 (const struct GNUNET_MessageHeader *) msg);
457 GNUNET_assert ((OP_PEER_START == opc->type) || (OP_PEER_STOP == opc->type));
459 GNUNET_assert (NULL != data);
461 GNUNET_assert (NULL != peer);
462 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
464 event.op_cls = opc->op_cls;
467 case GNUNET_TESTBED_ET_PEER_START:
468 peer->state = PS_STARTED;
469 event.details.peer_start.host = peer->host;
470 event.details.peer_start.peer = peer;
472 case GNUNET_TESTBED_ET_PEER_STOP:
473 peer->state = PS_STOPPED;
474 event.details.peer_stop.peer = peer;
477 GNUNET_assert (0); /* We should never reach this state */
480 pcc_cls = data->pcc_cls;
482 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
483 opc->state = OPC_STATE_FINISHED;
484 exop_insert (event.op);
486 ((GNUNET_TESTBED_ET_PEER_START | GNUNET_TESTBED_ET_PEER_STOP) &
490 c->cc (c->cc_cls, &event);
491 if (GNUNET_NO == exop_check (event.op))
496 /* You could have marked the operation as done by now */
497 GNUNET_break (GNUNET_NO == exop_check (event.op));
503 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONEVENT message from
504 * controller (testbed service)
506 * @param c the controller handler
507 * @param msg message received
508 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
512 handle_peer_conevent (struct GNUNET_TESTBED_Controller *c,
513 const struct GNUNET_TESTBED_ConnectionEventMessage *msg)
515 struct OperationContext *opc;
516 struct OverlayConnectData *data;
517 GNUNET_TESTBED_OperationCompletionCallback cb;
519 struct GNUNET_TESTBED_EventInformation event;
522 op_id = GNUNET_ntohll (msg->operation_id);
523 if (NULL == (opc = find_opc (c, op_id)))
525 LOG_DEBUG ("Operation not found\n");
528 if (OP_FORWARDED == opc->type)
530 handle_forwarded_operation_msg (c, opc,
531 (const struct GNUNET_MessageHeader *) msg);
534 GNUNET_assert (OP_OVERLAY_CONNECT == opc->type);
535 GNUNET_assert (NULL != (data = opc->data));
536 GNUNET_assert ((ntohl (msg->peer1) == data->p1->unique_id) &&
537 (ntohl (msg->peer2) == data->p2->unique_id));
538 event.type = (enum GNUNET_TESTBED_EventType) ntohl (msg->event_type);
540 event.op_cls = opc->op_cls;
543 case GNUNET_TESTBED_ET_CONNECT:
544 event.details.peer_connect.peer1 = data->p1;
545 event.details.peer_connect.peer2 = data->p2;
547 case GNUNET_TESTBED_ET_DISCONNECT:
548 GNUNET_assert (0); /* FIXME: implement */
551 GNUNET_assert (0); /* Should never reach here */
555 cb_cls = data->cb_cls;
556 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
557 opc->state = OPC_STATE_FINISHED;
558 exop_insert (event.op);
560 ((GNUNET_TESTBED_ET_CONNECT | GNUNET_TESTBED_ET_DISCONNECT) &
564 c->cc (c->cc_cls, &event);
565 if (GNUNET_NO == exop_check (event.op))
569 cb (cb_cls, opc->op, NULL);
570 /* You could have marked the operation as done by now */
571 GNUNET_break (GNUNET_NO == exop_check (event.op));
577 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_PEERCONFIG message from
578 * controller (testbed service)
580 * @param c the controller handler
581 * @param msg message received
582 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
586 handle_peer_config (struct GNUNET_TESTBED_Controller *c,
588 GNUNET_TESTBED_PeerConfigurationInformationMessage *msg)
590 struct OperationContext *opc;
591 struct GNUNET_TESTBED_Peer *peer;
592 struct PeerInfoData *data;
593 struct GNUNET_TESTBED_PeerInformation *pinfo;
594 GNUNET_TESTBED_PeerInfoCallback cb;
598 op_id = GNUNET_ntohll (msg->operation_id);
599 if (NULL == (opc = find_opc (c, op_id)))
601 LOG_DEBUG ("Operation not found\n");
604 if (OP_FORWARDED == opc->type)
606 handle_forwarded_operation_msg (c, opc,
607 (const struct GNUNET_MessageHeader *) msg);
611 GNUNET_assert (NULL != data);
613 GNUNET_assert (NULL != peer);
614 GNUNET_assert (ntohl (msg->peer_id) == peer->unique_id);
615 pinfo = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_PeerInformation));
616 pinfo->pit = data->pit;
618 cb_cls = data->cb_cls;
619 GNUNET_assert (NULL != cb);
624 case GNUNET_TESTBED_PIT_IDENTITY:
625 pinfo->result.id = GNUNET_malloc (sizeof (struct GNUNET_PeerIdentity));
626 (void) memcpy (pinfo->result.id, &msg->peer_identity,
627 sizeof (struct GNUNET_PeerIdentity));
629 case GNUNET_TESTBED_PIT_CONFIGURATION:
630 pinfo->result.cfg = /* Freed in oprelease_peer_getinfo */
631 GNUNET_TESTBED_extract_config_ (&msg->header);
633 case GNUNET_TESTBED_PIT_GENERIC:
634 GNUNET_assert (0); /* never reach here */
638 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
639 opc->state = OPC_STATE_FINISHED;
640 cb (cb_cls, opc->op, pinfo, NULL);
641 /* We dont check whether the operation is marked as done here as the
642 operation contains data (cfg/identify) which will be freed at a later point
649 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_OPERATIONFAILEVENT message from
650 * controller (testbed service)
652 * @param c the controller handler
653 * @param msg message received
654 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
658 handle_op_fail_event (struct GNUNET_TESTBED_Controller *c,
659 const struct GNUNET_TESTBED_OperationFailureEventMessage
662 struct OperationContext *opc;
665 struct GNUNET_TESTBED_EventInformation event;
667 op_id = GNUNET_ntohll (msg->operation_id);
668 if (NULL == (opc = find_opc (c, op_id)))
670 LOG_DEBUG ("Operation not found\n");
673 if (OP_FORWARDED == opc->type)
675 handle_forwarded_operation_msg (c, opc,
676 (const struct GNUNET_MessageHeader *) msg);
679 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
680 opc->state = OPC_STATE_FINISHED;
681 emsg = GNUNET_TESTBED_parse_error_string_ (msg);
683 emsg = "Unknown error";
684 if (OP_PEER_INFO == opc->type)
686 struct PeerInfoData *data;
689 if (NULL != data->cb)
690 data->cb (data->cb_cls, opc->op, NULL, emsg);
692 return GNUNET_YES; /* We do not call controller callback for peer info */
694 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
697 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
699 event.op_cls = opc->op_cls;
700 event.details.operation_finished.emsg = emsg;
701 event.details.operation_finished.generic = NULL;
702 exop_insert (event.op);
703 c->cc (c->cc_cls, &event);
704 if (GNUNET_NO == exop_check (event.op))
711 struct PeerCreateData *data;
714 GNUNET_free (data->peer);
715 if (NULL != data->cb)
716 data->cb (data->cls, NULL, emsg);
723 struct PeerEventData *data;
726 if (NULL != data->pcc)
727 data->pcc (data->pcc_cls, emsg);
731 case OP_PEER_DESTROY:
735 case OP_OVERLAY_CONNECT:
737 struct OverlayConnectData *data;
740 data->failed = GNUNET_YES;
741 if (NULL != data->cb)
742 data->cb (data->cb_cls, opc->op, emsg);
747 case OP_LINK_CONTROLLERS: /* No secondary callback */
749 case OP_SHUTDOWN_PEERS:
751 struct ShutdownPeersData *data;
754 GNUNET_free (data); /* FIXME: Decide whether we call data->op_cb */
766 * Function to build GET_SLAVE_CONFIG message
768 * @param op_id the id this message should contain in its operation id field
769 * @param slave_id the id this message should contain in its slave id field
770 * @return newly allocated SlaveGetConfigurationMessage
772 static struct GNUNET_TESTBED_SlaveGetConfigurationMessage *
773 GNUNET_TESTBED_generate_slavegetconfig_msg_ (uint64_t op_id, uint32_t slave_id)
775 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
778 msize = sizeof (struct GNUNET_TESTBED_SlaveGetConfigurationMessage);
779 msg = GNUNET_malloc (msize);
780 msg->header.size = htons (msize);
782 htons (GNUNET_MESSAGE_TYPE_TESTBED_GET_SLAVE_CONFIGURATION);
783 msg->operation_id = GNUNET_htonll (op_id);
784 msg->slave_id = htonl (slave_id);
790 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
793 * @param c the controller handler
794 * @param msg message received
795 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
799 handle_slave_config (struct GNUNET_TESTBED_Controller *c,
800 const struct GNUNET_TESTBED_SlaveConfiguration *msg)
802 struct OperationContext *opc;
804 struct GNUNET_TESTBED_EventInformation event;
806 op_id = GNUNET_ntohll (msg->operation_id);
807 if (NULL == (opc = find_opc (c, op_id)))
809 LOG_DEBUG ("Operation not found\n");
812 if (OP_GET_SLAVE_CONFIG != opc->type)
817 opc->state = OPC_STATE_FINISHED;
818 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
819 if ((0 != (GNUNET_TESTBED_ET_OPERATION_FINISHED & c->event_mask)) &&
822 opc->data = GNUNET_TESTBED_extract_config_ (&msg->header);
823 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
825 event.op_cls = opc->op_cls;
826 event.details.operation_finished.generic = opc->data;
827 event.details.operation_finished.emsg = NULL;
828 c->cc (c->cc_cls, &event);
835 * Handler for GNUNET_MESSAGE_TYPE_TESTBED_SLAVECONFIG message from controller
838 * @param c the controller handler
839 * @param msg message received
840 * @return GNUNET_YES if we can continue receiving from service; GNUNET_NO if
844 handle_link_controllers_result (struct GNUNET_TESTBED_Controller *c,
846 GNUNET_TESTBED_ControllerLinkResponse *msg)
848 struct OperationContext *opc;
849 struct ControllerLinkData *data;
850 struct GNUNET_CONFIGURATION_Handle *cfg;
851 struct GNUNET_TESTBED_Host *host;
854 struct GNUNET_TESTBED_EventInformation event;
856 op_id = GNUNET_ntohll (msg->operation_id);
857 if (NULL == (opc = find_opc (c, op_id)))
859 LOG_DEBUG ("Operation not found\n");
862 if (OP_FORWARDED == opc->type)
864 handle_forwarded_operation_msg (c, opc,
865 (const struct GNUNET_MessageHeader *) msg);
868 if (OP_LINK_CONTROLLERS != opc->type)
873 GNUNET_assert (NULL != (data = opc->data));
874 host = GNUNET_TESTBED_host_lookup_by_id_ (data->host_id);
875 GNUNET_assert (NULL != host);
878 opc->state = OPC_STATE_FINISHED;
879 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
880 event.type = GNUNET_TESTBED_ET_OPERATION_FINISHED;
882 event.op_cls = opc->op_cls;
883 event.details.operation_finished.emsg = NULL;
884 event.details.operation_finished.generic = NULL;
887 if (GNUNET_NO == ntohs (msg->success))
889 emsg = GNUNET_malloc (ntohs (msg->header.size)
891 GNUNET_TESTBED_ControllerLinkResponse) + 1);
892 memcpy (emsg, &msg[1], ntohs (msg->header.size)
894 GNUNET_TESTBED_ControllerLinkResponse));
895 event.details.operation_finished.emsg = emsg;
899 if (0 != ntohs (msg->config_size))
901 cfg = GNUNET_TESTBED_extract_config_ ((const struct GNUNET_MessageHeader *) msg);
902 GNUNET_assert (NULL != cfg);
903 GNUNET_TESTBED_host_replace_cfg_ (host, cfg);
906 if (0 != (c->event_mask & (1L << GNUNET_TESTBED_ET_OPERATION_FINISHED)))
909 c->cc (c->cc_cls, &event);
912 LOG_DEBUG ("Not calling callback\n");
914 GNUNET_CONFIGURATION_destroy (cfg);
915 GNUNET_free_non_null (emsg);
921 * Handler for messages from controller (testbed service)
923 * @param cls the controller handler
924 * @param msg message received, NULL on timeout or fatal error
927 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
929 struct GNUNET_TESTBED_Controller *c = cls;
933 c->in_receive = GNUNET_NO;
934 /* FIXME: Add checks for message integrity */
937 LOG_DEBUG ("Receive timed out or connection to service dropped\n");
941 msize = ntohs (msg->size);
942 switch (ntohs (msg->type))
944 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST_SUCCESS:
945 GNUNET_assert (msize >=
946 sizeof (struct GNUNET_TESTBED_HostConfirmedMessage));
948 GNUNET_TESTBED_host_handle_addhostconfirm_
949 (c, (const struct GNUNET_TESTBED_HostConfirmedMessage*) msg);
951 case GNUNET_MESSAGE_TYPE_TESTBED_GENERIC_OPERATION_SUCCESS:
952 GNUNET_assert (msize ==
954 GNUNET_TESTBED_GenericOperationSuccessEventMessage));
958 GNUNET_TESTBED_GenericOperationSuccessEventMessage *)
961 case GNUNET_MESSAGE_TYPE_TESTBED_OPERATION_FAIL_EVENT:
962 GNUNET_assert (msize >=
963 sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage));
965 handle_op_fail_event (c,
967 GNUNET_TESTBED_OperationFailureEventMessage *)
970 case GNUNET_MESSAGE_TYPE_TESTBED_CREATE_PEER_SUCCESS:
971 GNUNET_assert (msize ==
973 GNUNET_TESTBED_PeerCreateSuccessEventMessage));
975 handle_peer_create_success (c,
977 GNUNET_TESTBED_PeerCreateSuccessEventMessage
980 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_EVENT:
981 GNUNET_assert (msize == sizeof (struct GNUNET_TESTBED_PeerEventMessage));
983 handle_peer_event (c,
984 (const struct GNUNET_TESTBED_PeerEventMessage *)
988 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
989 GNUNET_assert (msize >=
991 GNUNET_TESTBED_PeerConfigurationInformationMessage));
993 handle_peer_config (c,
995 GNUNET_TESTBED_PeerConfigurationInformationMessage
998 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONNECT_EVENT:
999 GNUNET_assert (msize ==
1000 sizeof (struct GNUNET_TESTBED_ConnectionEventMessage));
1002 handle_peer_conevent (c,
1004 GNUNET_TESTBED_ConnectionEventMessage *) msg);
1006 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1007 GNUNET_assert (msize > sizeof (struct GNUNET_TESTBED_SlaveConfiguration));
1009 handle_slave_config (c,
1010 (const struct GNUNET_TESTBED_SlaveConfiguration *)
1013 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1015 handle_link_controllers_result (c,
1017 GNUNET_TESTBED_ControllerLinkResponse
1023 if ((GNUNET_OK == status) && (GNUNET_NO == c->in_receive))
1025 c->in_receive = GNUNET_YES;
1026 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1027 GNUNET_TIME_UNIT_FOREVER_REL);
1033 * Function called to notify a client about the connection begin ready to queue
1034 * more data. "buf" will be NULL and "size" zero if the connection was closed
1035 * for writing in the meantime.
1037 * @param cls closure
1038 * @param size number of bytes available in buf
1039 * @param buf where the callee should write the message
1040 * @return number of bytes written to buf
1043 transmit_ready_notify (void *cls, size_t size, void *buf)
1045 struct GNUNET_TESTBED_Controller *c = cls;
1046 struct MessageQueue *mq_entry;
1049 mq_entry = c->mq_head;
1050 GNUNET_assert (NULL != mq_entry);
1051 if ((0 == size) && (NULL == buf)) /* Timeout */
1053 LOG_DEBUG ("Message sending timed out -- retrying\n");
1055 GNUNET_CLIENT_notify_transmit_ready (c->client,
1056 ntohs (mq_entry->msg->size),
1057 TIMEOUT_REL, GNUNET_YES,
1058 &transmit_ready_notify, c);
1061 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
1062 size = ntohs (mq_entry->msg->size);
1063 memcpy (buf, mq_entry->msg, size);
1064 LOG_DEBUG ("Message of type: %u and size: %u sent\n",
1065 ntohs (mq_entry->msg->type), size);
1066 GNUNET_free (mq_entry->msg);
1067 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
1068 GNUNET_free (mq_entry);
1069 mq_entry = c->mq_head;
1070 if (NULL != mq_entry)
1072 GNUNET_CLIENT_notify_transmit_ready (c->client,
1073 ntohs (mq_entry->msg->size),
1074 TIMEOUT_REL, GNUNET_YES,
1075 &transmit_ready_notify, c);
1076 if (GNUNET_NO == c->in_receive)
1078 c->in_receive = GNUNET_YES;
1079 GNUNET_CLIENT_receive (c->client, &message_handler, c,
1080 GNUNET_TIME_UNIT_FOREVER_REL);
1087 * Queues a message in send queue for sending to the service
1089 * @param controller the handle to the controller
1090 * @param msg the message to queue
1093 GNUNET_TESTBED_queue_message_ (struct GNUNET_TESTBED_Controller *controller,
1094 struct GNUNET_MessageHeader *msg)
1096 struct MessageQueue *mq_entry;
1100 type = ntohs (msg->type);
1101 size = ntohs (msg->size);
1102 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
1103 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
1104 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
1105 mq_entry->msg = msg;
1106 LOG (GNUNET_ERROR_TYPE_DEBUG,
1107 "Queueing message of type %u, size %u for sending\n", type,
1109 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
1111 if (NULL == controller->th)
1113 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
1114 TIMEOUT_REL, GNUNET_YES,
1115 &transmit_ready_notify,
1121 * Sends the given message as an operation. The given callback is called when a
1122 * reply for the operation is available. Call
1123 * GNUNET_TESTBED_forward_operation_msg_cancel_() to cleanup the returned
1124 * operation context if the cc hasn't been called
1126 * @param controller the controller to which the message has to be sent
1127 * @param operation_id the operation id of the message
1128 * @param msg the message to send
1129 * @param cc the callback to call when reply is available
1130 * @param cc_cls the closure for the above callback
1131 * @return the operation context which can be used to cancel the forwarded
1134 struct OperationContext *
1135 GNUNET_TESTBED_forward_operation_msg_ (struct GNUNET_TESTBED_Controller
1136 *controller, uint64_t operation_id,
1137 const struct GNUNET_MessageHeader *msg,
1138 GNUNET_CLIENT_MessageHandler cc,
1141 struct OperationContext *opc;
1142 struct ForwardedOperationData *data;
1143 struct GNUNET_MessageHeader *dup_msg;
1146 data = GNUNET_malloc (sizeof (struct ForwardedOperationData));
1148 data->cc_cls = cc_cls;
1149 opc = GNUNET_malloc (sizeof (struct OperationContext));
1150 opc->c = controller;
1151 opc->type = OP_FORWARDED;
1153 opc->id = operation_id;
1154 msize = ntohs (msg->size);
1155 dup_msg = GNUNET_malloc (msize);
1156 (void) memcpy (dup_msg, msg, msize);
1157 GNUNET_TESTBED_queue_message_ (opc->c, dup_msg);
1158 GNUNET_CONTAINER_DLL_insert_tail (controller->ocq_head, controller->ocq_tail,
1165 * Function to cancel an operation created by simply forwarding an operation
1168 * @param opc the operation context from GNUNET_TESTBED_forward_operation_msg_()
1171 GNUNET_TESTBED_forward_operation_msg_cancel_ (struct OperationContext *opc)
1173 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1174 GNUNET_free (opc->data);
1180 * Function to call to start a link-controllers type operation once all queues
1181 * the operation is part of declare that the operation can be activated.
1183 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1186 opstart_link_controllers (void *cls)
1188 struct OperationContext *opc = cls;
1189 struct ControllerLinkData *data;
1190 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1192 GNUNET_assert (NULL != opc->data);
1196 opc->state = OPC_STATE_STARTED;
1197 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1198 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1203 * Callback which will be called when link-controllers type operation is released
1205 * @param cls the closure from GNUNET_TESTBED_operation_create_()
1208 oprelease_link_controllers (void *cls)
1210 struct OperationContext *opc = cls;
1211 struct ControllerLinkData *data;
1216 case OPC_STATE_INIT:
1217 GNUNET_free (data->msg);
1219 case OPC_STATE_STARTED:
1220 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1222 case OPC_STATE_FINISHED:
1225 GNUNET_free_non_null (data);
1231 * Function to be called when get slave config operation is ready
1233 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1236 opstart_get_slave_config (void *cls)
1238 struct OperationContext *opc = cls;
1239 struct GetSlaveConfigData *data = opc->data;
1240 struct GNUNET_TESTBED_SlaveGetConfigurationMessage *msg;
1242 GNUNET_assert (NULL != data);
1243 msg = GNUNET_TESTBED_generate_slavegetconfig_msg_ (opc->id, data->slave_id);
1244 GNUNET_free (opc->data);
1247 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
1248 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
1249 opc->state = OPC_STATE_STARTED;
1254 * Function to be called when get slave config operation is cancelled or finished
1256 * @param cls the OperationContext of type OP_GET_SLAVE_CONFIG
1259 oprelease_get_slave_config (void *cls)
1261 struct OperationContext *opc = cls;
1265 case OPC_STATE_INIT:
1266 GNUNET_free (opc->data);
1268 case OPC_STATE_STARTED:
1269 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
1271 case OPC_STATE_FINISHED:
1272 if (NULL != opc->data)
1273 GNUNET_CONFIGURATION_destroy (opc->data);
1281 * Start a controller process using the given configuration at the
1284 * @param cfg configuration to use
1285 * @param host host to run the controller on; This should be the same host if
1286 * the controller was previously started with
1287 * GNUNET_TESTBED_controller_start; NULL for localhost
1288 * @param event_mask bit mask with set of events to call 'cc' for;
1289 * or-ed values of "1LL" shifted by the
1290 * respective 'enum GNUNET_TESTBED_EventType'
1291 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
1292 * @param cc controller callback to invoke on events
1293 * @param cc_cls closure for cc
1294 * @return handle to the controller
1296 struct GNUNET_TESTBED_Controller *
1297 GNUNET_TESTBED_controller_connect (const struct GNUNET_CONFIGURATION_Handle
1298 *cfg, struct GNUNET_TESTBED_Host *host,
1299 uint64_t event_mask,
1300 GNUNET_TESTBED_ControllerCallback cc,
1303 struct GNUNET_TESTBED_Controller *controller;
1304 struct GNUNET_TESTBED_InitMessage *msg;
1305 const char *controller_hostname;
1306 unsigned long long max_parallel_operations;
1307 unsigned long long max_parallel_service_connections;
1308 unsigned long long max_parallel_topology_config_operations;
1311 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1312 "MAX_PARALLEL_OPERATIONS",
1313 &max_parallel_operations))
1319 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1320 "MAX_PARALLEL_SERVICE_CONNECTIONS",
1321 &max_parallel_service_connections))
1327 GNUNET_CONFIGURATION_get_value_number (cfg, "testbed",
1328 "MAX_PARALLEL_TOPOLOGY_CONFIG_OPERATIONS",
1329 &max_parallel_topology_config_operations))
1334 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
1335 controller->cc = cc;
1336 controller->cc_cls = cc_cls;
1337 controller->event_mask = event_mask;
1338 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
1339 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
1340 if (NULL == controller->client)
1342 GNUNET_TESTBED_controller_disconnect (controller);
1347 host = GNUNET_TESTBED_host_create_by_id_ (0, controller->cfg);
1348 if (NULL == host) /* If the above host create fails */
1350 LOG (GNUNET_ERROR_TYPE_WARNING,
1351 "Treating NULL host as localhost. Multiple references to localhost "
1352 "may break when localhost freed before calling disconnect \n");
1353 host = GNUNET_TESTBED_host_lookup_by_id_ (0);
1357 controller->aux_host = GNUNET_YES;
1360 GNUNET_assert (NULL != host);
1361 GNUNET_TESTBED_mark_host_registered_at_ (host, controller);
1362 controller->host = host;
1363 controller->opq_parallel_operations =
1364 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1365 max_parallel_operations);
1366 controller->opq_parallel_service_connections =
1367 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1368 max_parallel_service_connections);
1369 controller->opq_parallel_topology_config_operations =
1370 GNUNET_TESTBED_operation_queue_create_ ((unsigned int)
1371 max_parallel_topology_config_operations);
1372 controller_hostname = GNUNET_TESTBED_host_get_hostname (host);
1373 if (NULL == controller_hostname)
1374 controller_hostname = "127.0.0.1";
1376 GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage) +
1377 strlen (controller_hostname) + 1);
1378 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
1380 htons (sizeof (struct GNUNET_TESTBED_InitMessage) +
1381 strlen (controller_hostname) + 1);
1382 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (host));
1383 msg->event_mask = GNUNET_htonll (controller->event_mask);
1384 strcpy ((char *) &msg[1], controller_hostname);
1385 GNUNET_TESTBED_queue_message_ (controller,
1386 (struct GNUNET_MessageHeader *) msg);
1392 * Configure shared services at a controller. Using this function,
1393 * you can specify that certain services (such as "resolver")
1394 * should not be run for each peer but instead be shared
1395 * across N peers on the specified host. This function
1396 * must be called before any peers are created at the host.
1398 * @param controller controller to configure
1399 * @param service_name name of the service to share
1400 * @param num_peers number of peers that should share one instance
1401 * of the specified service (1 for no sharing is the default),
1402 * use 0 to disable the service
1405 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller
1407 const char *service_name,
1410 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
1411 uint16_t service_name_size;
1414 service_name_size = strlen (service_name) + 1;
1416 sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage) +
1418 msg = GNUNET_malloc (msg_size);
1419 msg->header.size = htons (msg_size);
1420 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHARE_SERVICE);
1421 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
1422 msg->num_peers = htonl (num_peers);
1423 memcpy (&msg[1], service_name, service_name_size);
1424 GNUNET_TESTBED_queue_message_ (controller,
1425 (struct GNUNET_MessageHeader *) msg);
1426 GNUNET_break (0); /* This function is not yet implemented on the
1427 * testbed service */
1432 * disconnects from the controller.
1434 * @param controller handle to controller to stop
1437 GNUNET_TESTBED_controller_disconnect (struct GNUNET_TESTBED_Controller
1440 struct MessageQueue *mq_entry;
1442 if (NULL != controller->th)
1443 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
1444 /* Clear the message queue */
1445 while (NULL != (mq_entry = controller->mq_head))
1447 GNUNET_CONTAINER_DLL_remove (controller->mq_head, controller->mq_tail,
1449 GNUNET_free (mq_entry->msg);
1450 GNUNET_free (mq_entry);
1452 if (NULL != controller->client)
1453 GNUNET_CLIENT_disconnect (controller->client);
1454 GNUNET_CONFIGURATION_destroy (controller->cfg);
1455 if (GNUNET_YES == controller->aux_host)
1456 GNUNET_TESTBED_host_destroy (controller->host);
1457 GNUNET_TESTBED_operation_queue_destroy_ (controller->opq_parallel_operations);
1458 GNUNET_TESTBED_operation_queue_destroy_
1459 (controller->opq_parallel_service_connections);
1460 GNUNET_TESTBED_operation_queue_destroy_
1461 (controller->opq_parallel_topology_config_operations);
1462 GNUNET_free (controller);
1467 * Same as the GNUNET_TESTBED_controller_link_2, but with ids for delegated host
1470 * @param op_cls the operation closure for the event which is generated to
1471 * signal success or failure of this operation
1472 * @param master handle to the master controller who creates the association
1473 * @param delegated_host_id id of the host to which requests should be delegated
1474 * @param slave_host_id id of the host which is used to run the slave controller
1475 * @param sxcfg serialized and compressed configuration
1476 * @param sxcfg_size the size sxcfg
1477 * @param scfg_size the size of uncompressed serialized configuration
1478 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1479 * be started by the slave controller; GNUNET_NO if the slave
1480 * controller has to connect to the already started delegated
1481 * controller via TCP/IP
1482 * @return the operation handle
1484 struct GNUNET_TESTBED_Operation *
1485 GNUNET_TESTBED_controller_link_2_ (void *op_cls,
1486 struct GNUNET_TESTBED_Controller *master,
1487 uint32_t delegated_host_id,
1488 uint32_t slave_host_id, const char *sxcfg,
1489 size_t sxcfg_size, size_t scfg_size,
1492 struct OperationContext *opc;
1493 struct GNUNET_TESTBED_ControllerLinkRequest *msg;
1494 struct ControllerLinkData *data;
1497 msg_size = sxcfg_size + sizeof (struct GNUNET_TESTBED_ControllerLinkRequest);
1498 msg = GNUNET_malloc (msg_size);
1499 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS);
1500 msg->header.size = htons (msg_size);
1501 msg->delegated_host_id = htonl (delegated_host_id);
1502 msg->slave_host_id = htonl (slave_host_id);
1503 msg->config_size = htons ((uint16_t) scfg_size);
1504 msg->is_subordinate = (GNUNET_YES == is_subordinate) ? 1 : 0;
1505 memcpy (&msg[1], sxcfg, sxcfg_size);
1506 data = GNUNET_malloc (sizeof (struct ControllerLinkData));
1508 data->host_id = delegated_host_id;
1509 opc = GNUNET_malloc (sizeof (struct OperationContext));
1512 opc->type = OP_LINK_CONTROLLERS;
1513 opc->id = GNUNET_TESTBED_get_next_op_id (opc->c);
1514 opc->state = OPC_STATE_INIT;
1515 opc->op_cls = op_cls;
1516 msg->operation_id = GNUNET_htonll (opc->id);
1518 GNUNET_TESTBED_operation_create_ (opc, &opstart_link_controllers,
1519 &oprelease_link_controllers);
1520 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1522 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1528 * Same as the GNUNET_TESTBED_controller_link, however expects configuration in
1529 * serialized and compressed
1531 * @param op_cls the operation closure for the event which is generated to
1532 * signal success or failure of this operation
1533 * @param master handle to the master controller who creates the association
1534 * @param delegated_host requests to which host should be delegated; cannot be NULL
1535 * @param slave_host which host is used to run the slave controller; use NULL to
1536 * make the master controller connect to the delegated host
1537 * @param sxcfg serialized and compressed configuration
1538 * @param sxcfg_size the size sxcfg
1539 * @param scfg_size the size of uncompressed serialized configuration
1540 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1541 * be started by the slave controller; GNUNET_NO if the slave
1542 * controller has to connect to the already started delegated
1543 * controller via TCP/IP
1544 * @return the operation handle
1546 struct GNUNET_TESTBED_Operation *
1547 GNUNET_TESTBED_controller_link_2 (void *op_cls,
1548 struct GNUNET_TESTBED_Controller *master,
1549 struct GNUNET_TESTBED_Host *delegated_host,
1550 struct GNUNET_TESTBED_Host *slave_host,
1551 const char *sxcfg, size_t sxcfg_size,
1552 size_t scfg_size, int is_subordinate)
1554 uint32_t delegated_host_id;
1555 uint32_t slave_host_id;
1557 GNUNET_assert (GNUNET_YES ==
1558 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1559 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1561 GNUNET_TESTBED_host_get_id_ ((NULL !=
1562 slave_host) ? slave_host : master->host);
1563 if ((NULL != slave_host) && (0 != GNUNET_TESTBED_host_get_id_ (slave_host)))
1564 GNUNET_assert (GNUNET_YES ==
1565 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1567 return GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1568 slave_host_id, sxcfg, sxcfg_size,
1569 scfg_size, is_subordinate);
1574 * Compresses given configuration using zlib compress
1576 * @param config the serialized configuration
1577 * @param size the size of config
1578 * @param xconfig will be set to the compressed configuration (memory is fresly
1580 * @return the size of the xconfig
1583 GNUNET_TESTBED_compress_config_ (const char *config, size_t size,
1588 xsize = compressBound ((uLong) size);
1589 *xconfig = GNUNET_malloc (xsize);
1590 GNUNET_assert (Z_OK ==
1591 compress2 ((Bytef *) * xconfig, (uLongf *) & xsize,
1592 (const Bytef *) config, (uLongf) size,
1599 * Function to serialize and compress using zlib a configuration through a
1600 * configuration handle
1602 * @param cfg the configuration
1603 * @param size the size of configuration when serialize. Will be set on success.
1604 * @param xsize the sizeo of the compressed configuration. Will be set on success.
1605 * @return the serialized and compressed configuration
1608 GNUNET_TESTBED_compress_cfg_ (const struct GNUNET_CONFIGURATION_Handle *cfg,
1609 size_t *size, size_t *xsize)
1616 config = GNUNET_CONFIGURATION_serialize (cfg, &size_);
1617 xsize_ = GNUNET_TESTBED_compress_config_ (config, size_, &xconfig);
1618 GNUNET_free (config);
1626 * Same as the GNUNET_TESTBED_controller_link, but with ids for delegated host
1629 * @param op_cls the operation closure for the event which is generated to
1630 * signal success or failure of this operation
1631 * @param master handle to the master controller who creates the association
1632 * @param delegated_host_id id of the host to which requests should be
1633 * delegated; cannot be NULL
1634 * @param slave_host_id id of the host which should connect to controller
1635 * running on delegated host ; use NULL to make the master controller
1636 * connect to the delegated host
1637 * @param slave_cfg configuration to use for the slave controller
1638 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1639 * be started by the slave controller; GNUNET_NO if the slave
1640 * controller has to connect to the already started delegated
1641 * controller via TCP/IP
1642 * @return the operation handle
1644 struct GNUNET_TESTBED_Operation *
1645 GNUNET_TESTBED_controller_link_ (void *op_cls,
1646 struct GNUNET_TESTBED_Controller *master,
1647 uint32_t delegated_host_id,
1648 uint32_t slave_host_id,
1649 const struct GNUNET_CONFIGURATION_Handle
1650 *slave_cfg, int is_subordinate)
1652 struct GNUNET_TESTBED_Operation *op;
1658 config = GNUNET_CONFIGURATION_serialize (slave_cfg, &config_size);
1659 cc_size = GNUNET_TESTBED_compress_config_ (config, config_size, &cconfig);
1660 GNUNET_free (config);
1661 /* Configuration doesn't fit in 1 message */
1662 GNUNET_assert ((UINT16_MAX -
1663 sizeof (struct GNUNET_TESTBED_ControllerLinkRequest)) >=
1665 op = GNUNET_TESTBED_controller_link_2_ (op_cls, master, delegated_host_id,
1666 slave_host_id, (const char *) cconfig,
1667 cc_size, config_size, is_subordinate);
1668 GNUNET_free (cconfig);
1674 * Create a link from slave controller to delegated controller. Whenever the
1675 * master controller is asked to start a peer at the delegated controller the
1676 * request will be routed towards slave controller (if a route exists). The
1677 * slave controller will then route it to the delegated controller. The
1678 * configuration of the delegated controller is given and is used to either
1679 * create the delegated controller or to connect to an existing controller. Note
1680 * that while starting the delegated controller the configuration will be
1681 * modified to accommodate available free ports. the 'is_subordinate' specifies
1682 * if the given delegated controller should be started and managed by the slave
1683 * controller, or if the delegated controller already has a master and the slave
1684 * controller connects to it as a non master controller. The success or failure
1685 * of this operation will be signalled through the
1686 * GNUNET_TESTBED_ControllerCallback() with an event of type
1687 * GNUNET_TESTBED_ET_OPERATION_FINISHED
1689 * @param op_cls the operation closure for the event which is generated to
1690 * signal success or failure of this operation
1691 * @param master handle to the master controller who creates the association
1692 * @param delegated_host requests to which host should be delegated; cannot be NULL
1693 * @param slave_host which host is used to run the slave controller; use NULL to
1694 * make the master controller connect to the delegated host
1695 * @param slave_cfg configuration to use for the slave controller
1696 * @param is_subordinate GNUNET_YES if the controller at delegated_host should
1697 * be started by the slave controller; GNUNET_NO if the slave
1698 * controller has to connect to the already started delegated
1699 * controller via TCP/IP
1700 * @return the operation handle
1702 struct GNUNET_TESTBED_Operation *
1703 GNUNET_TESTBED_controller_link (void *op_cls,
1704 struct GNUNET_TESTBED_Controller *master,
1705 struct GNUNET_TESTBED_Host *delegated_host,
1706 struct GNUNET_TESTBED_Host *slave_host,
1707 const struct GNUNET_CONFIGURATION_Handle
1708 *slave_cfg, int is_subordinate)
1710 uint32_t slave_host_id;
1711 uint32_t delegated_host_id;
1714 GNUNET_assert (GNUNET_YES ==
1715 GNUNET_TESTBED_is_host_registered_ (delegated_host, master));
1717 GNUNET_TESTBED_host_get_id_ ((NULL !=
1718 slave_host) ? slave_host : master->host);
1719 delegated_host_id = GNUNET_TESTBED_host_get_id_ (delegated_host);
1720 if ((NULL != slave_host) && (0 != slave_host_id))
1721 GNUNET_assert (GNUNET_YES ==
1722 GNUNET_TESTBED_is_host_registered_ (slave_host, master));
1723 return GNUNET_TESTBED_controller_link_ (op_cls, master, delegated_host_id,
1725 GNUNET_TESTBED_host_get_cfg_ (delegated_host),
1732 * Like GNUNET_TESTBED_get_slave_config(), however without the host registration
1733 * check. Another difference is that this function takes the id of the slave
1736 * @param op_cls the closure for the operation
1737 * @param master the handle to master controller
1738 * @param slave_host_id id of the host where the slave controller is running to
1739 * the slave_host should remain valid until this operation is cancelled
1740 * or marked as finished
1741 * @return the operation handle;
1743 struct GNUNET_TESTBED_Operation *
1744 GNUNET_TESTBED_get_slave_config_ (void *op_cls,
1745 struct GNUNET_TESTBED_Controller *master,
1746 uint32_t slave_host_id)
1748 struct OperationContext *opc;
1749 struct GetSlaveConfigData *data;
1751 data = GNUNET_malloc (sizeof (struct GetSlaveConfigData));
1752 data->slave_id = slave_host_id;
1753 opc = GNUNET_malloc (sizeof (struct OperationContext));
1754 opc->state = OPC_STATE_INIT;
1756 opc->id = GNUNET_TESTBED_get_next_op_id (master);
1757 opc->type = OP_GET_SLAVE_CONFIG;
1759 opc->op_cls = op_cls;
1761 GNUNET_TESTBED_operation_create_ (opc, &opstart_get_slave_config,
1762 &oprelease_get_slave_config);
1763 GNUNET_TESTBED_operation_queue_insert_ (master->opq_parallel_operations,
1765 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
1771 * Function to acquire the configuration of a running slave controller. The
1772 * completion of the operation is signalled through the controller_cb from
1773 * GNUNET_TESTBED_controller_connect(). If the operation is successful the
1774 * handle to the configuration is available in the generic pointer of
1775 * operation_finished field of struct GNUNET_TESTBED_EventInformation.
1777 * @param op_cls the closure for the operation
1778 * @param master the handle to master controller
1779 * @param slave_host the host where the slave controller is running; the handle
1780 * to the slave_host should remain valid until this operation is
1781 * cancelled or marked as finished
1782 * @return the operation handle; NULL if the slave_host is not registered at
1785 struct GNUNET_TESTBED_Operation *
1786 GNUNET_TESTBED_get_slave_config (void *op_cls,
1787 struct GNUNET_TESTBED_Controller *master,
1788 struct GNUNET_TESTBED_Host *slave_host)
1790 if (GNUNET_NO == GNUNET_TESTBED_is_host_registered_ (slave_host, master))
1792 return GNUNET_TESTBED_get_slave_config_ (op_cls, master,
1793 GNUNET_TESTBED_host_get_id_
1799 * Ask the testbed controller to write the current overlay topology to
1800 * a file. Naturally, the file will only contain a snapshot as the
1801 * topology may evolve all the time.
1803 * @param controller overlay controller to inspect
1804 * @param filename name of the file the topology should
1808 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller
1810 const char *filename)
1817 * Creates a helper initialization message. This function is here because we
1818 * want to use this in testing
1820 * @param trusted_ip the ip address of the controller which will be set as TRUSTED
1821 * HOST(all connections form this ip are permitted by the testbed) when
1822 * starting testbed controller at host. This can either be a single ip
1823 * address or a network address in CIDR notation.
1824 * @param hostname the hostname of the destination this message is intended for
1825 * @param cfg the configuration that has to used to start the testbed service
1827 * @return the initialization message
1829 struct GNUNET_TESTBED_HelperInit *
1830 GNUNET_TESTBED_create_helper_init_msg_ (const char *trusted_ip,
1831 const char *hostname,
1832 const struct GNUNET_CONFIGURATION_Handle
1835 struct GNUNET_TESTBED_HelperInit *msg;
1839 size_t xconfig_size;
1840 uint16_t trusted_ip_len;
1841 uint16_t hostname_len;
1844 config = GNUNET_CONFIGURATION_serialize (cfg, &config_size);
1845 GNUNET_assert (NULL != config);
1847 GNUNET_TESTBED_compress_config_ (config, config_size, &xconfig);
1848 GNUNET_free (config);
1849 trusted_ip_len = strlen (trusted_ip);
1850 hostname_len = (NULL == hostname) ? 0 : strlen (hostname);
1852 xconfig_size + trusted_ip_len + 1 +
1853 sizeof (struct GNUNET_TESTBED_HelperInit);
1854 msg_size += hostname_len;
1855 msg = GNUNET_realloc (xconfig, msg_size);
1856 (void) memmove (((void *) &msg[1]) + trusted_ip_len + 1 + hostname_len, msg,
1858 msg->header.size = htons (msg_size);
1859 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_HELPER_INIT);
1860 msg->trusted_ip_size = htons (trusted_ip_len);
1861 msg->hostname_size = htons (hostname_len);
1862 msg->config_size = htons (config_size);
1863 (void) strcpy ((char *) &msg[1], trusted_ip);
1864 if (0 != hostname_len)
1865 (void) strncpy (((char *) &msg[1]) + trusted_ip_len + 1, hostname,
1872 * Signal that the information from an operation has been fully
1873 * processed. This function MUST be called for each event
1874 * of type 'operation_finished' to fully remove the operation
1875 * from the operation queue. After calling this function, the
1876 * 'op_result' becomes invalid (!).
1878 * @param operation operation to signal completion for
1881 GNUNET_TESTBED_operation_done (struct GNUNET_TESTBED_Operation *operation)
1883 (void) exop_check (operation);
1884 GNUNET_TESTBED_operation_release_ (operation);
1889 * Generates configuration by uncompressing configuration in given message. The
1890 * given message should be of the following types:
1891 * GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION,
1892 * GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION,
1893 * GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST,
1894 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS,
1895 * GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT,
1897 * @param msg the message containing compressed configuration
1898 * @return handle to the parsed configuration; NULL upon error while parsing the message
1900 struct GNUNET_CONFIGURATION_Handle *
1901 GNUNET_TESTBED_extract_config_ (const struct GNUNET_MessageHeader *msg)
1903 struct GNUNET_CONFIGURATION_Handle *cfg;
1910 switch (ntohs (msg->type))
1912 case GNUNET_MESSAGE_TYPE_TESTBED_PEER_CONFIGURATION:
1914 const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *imsg;
1917 (const struct GNUNET_TESTBED_PeerConfigurationInformationMessage *) msg;
1918 data_len = (uLong) ntohs (imsg->config_size);
1920 ntohs (imsg->header.size) -
1921 sizeof (struct GNUNET_TESTBED_PeerConfigurationInformationMessage);
1922 xdata = (const Bytef *) &imsg[1];
1925 case GNUNET_MESSAGE_TYPE_TESTBED_SLAVE_CONFIGURATION:
1927 const struct GNUNET_TESTBED_SlaveConfiguration *imsg;
1929 imsg = (const struct GNUNET_TESTBED_SlaveConfiguration *) msg;
1930 data_len = (uLong) ntohs (imsg->config_size);
1932 ntohs (imsg->header.size) -
1933 sizeof (struct GNUNET_TESTBED_SlaveConfiguration);
1934 xdata = (const Bytef *) &imsg[1];
1937 case GNUNET_MESSAGE_TYPE_TESTBED_ADD_HOST:
1939 const struct GNUNET_TESTBED_AddHostMessage *imsg;
1942 imsg = (const struct GNUNET_TESTBED_AddHostMessage *) msg;
1943 data_len = (uLong) ntohs (imsg->config_size);
1944 osize = sizeof (struct GNUNET_TESTBED_AddHostMessage) +
1945 ntohs (imsg->username_length) + ntohs (imsg->hostname_length);
1946 xdata_len = ntohs (imsg->header.size) - osize;
1947 xdata = (const Bytef *) ((const void *) imsg + osize);
1950 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS_RESULT:
1952 const struct GNUNET_TESTBED_ControllerLinkResponse *imsg;
1954 imsg = (const struct GNUNET_TESTBED_ControllerLinkResponse *) msg;
1955 data_len = ntohs (imsg->config_size);
1956 xdata_len = ntohs (imsg->header.size) -
1957 sizeof (const struct GNUNET_TESTBED_ControllerLinkResponse);
1958 xdata = (const Bytef *) &imsg[1];
1961 case GNUNET_MESSAGE_TYPE_TESTBED_LINK_CONTROLLERS:
1963 const struct GNUNET_TESTBED_ControllerLinkRequest *imsg;
1964 imsg = (const struct GNUNET_TESTBED_ControllerLinkRequest *) msg;
1965 data_len = ntohs (imsg->config_size);
1966 xdata_len = ntohs (imsg->header.size) - sizeof (const struct
1967 GNUNET_TESTBED_ControllerLinkRequest);
1968 xdata = (const Bytef *) &imsg[1];
1974 data = GNUNET_malloc (data_len);
1975 if (Z_OK != (ret = uncompress (data, &data_len, xdata, xdata_len)))
1978 GNUNET_break_op (0);
1981 cfg = GNUNET_CONFIGURATION_create ();
1983 GNUNET_CONFIGURATION_deserialize (cfg, (const char *) data,
1988 GNUNET_break_op (0);
1997 * Checks the integrity of the OperationFailureEventMessage and if good returns
1998 * the error message it contains.
2000 * @param msg the OperationFailureEventMessage
2001 * @return the error message
2004 GNUNET_TESTBED_parse_error_string_ (const struct
2005 GNUNET_TESTBED_OperationFailureEventMessage
2011 msize = ntohs (msg->header.size);
2012 if (sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage) >= msize)
2014 msize -= sizeof (struct GNUNET_TESTBED_OperationFailureEventMessage);
2015 emsg = (const char *) &msg[1];
2016 if ('\0' != emsg[msize - 1])
2026 * Function to return the operation id for a controller. The operation id is
2027 * created from the controllers host id and its internal operation counter.
2029 * @param controller the handle to the controller whose operation id has to be incremented
2030 * @return the incremented operation id.
2033 GNUNET_TESTBED_get_next_op_id (struct GNUNET_TESTBED_Controller * controller)
2037 op_id = (uint64_t) GNUNET_TESTBED_host_get_id_ (controller->host);
2038 op_id = op_id << 32;
2039 op_id |= (uint64_t) controller->operation_counter++;
2045 * Function called when a shutdown peers operation is ready
2047 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2050 opstart_shutdown_peers (void *cls)
2052 struct OperationContext *opc = cls;
2053 struct GNUNET_TESTBED_ShutdownPeersMessage *msg;
2055 opc->state = OPC_STATE_STARTED;
2056 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2058 htons (sizeof (struct GNUNET_TESTBED_ShutdownPeersMessage));
2059 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SHUTDOWN_PEERS);
2060 msg->operation_id = GNUNET_htonll (opc->id);
2061 GNUNET_CONTAINER_DLL_insert_tail (opc->c->ocq_head, opc->c->ocq_tail, opc);
2062 GNUNET_TESTBED_queue_message_ (opc->c, &msg->header);
2067 * Callback which will be called when shutdown peers operation is released
2069 * @param cls the closure from GNUNET_TESTBED_operation_create_()
2072 oprelease_shutdown_peers (void *cls)
2074 struct OperationContext *opc = cls;
2076 if (OPC_STATE_FINISHED != opc->state)
2078 GNUNET_free (opc->data);
2079 GNUNET_CONTAINER_DLL_remove (opc->c->ocq_head, opc->c->ocq_tail, opc);
2086 * Stops and destroys all peers. Is equivalent of calling
2087 * GNUNET_TESTBED_peer_stop() and GNUNET_TESTBED_peer_destroy() on all peers,
2088 * except that the peer stop event and operation finished event corresponding to
2089 * the respective functions are not generated. This function should be called
2090 * when there are no other pending operations. If there are pending operations,
2091 * it will return NULL
2093 * @param controller the controller to send this message to
2094 * @param op_cls closure for the operation
2095 * @param cb the callback to call when all peers are stopped and destroyed
2096 * @param cb_cls the closure for the callback
2097 * @return operation handle on success; NULL if any pending operations are
2100 struct GNUNET_TESTBED_Operation *
2101 GNUNET_TESTBED_shutdown_peers (struct GNUNET_TESTBED_Controller *controller,
2103 GNUNET_TESTBED_OperationCompletionCallback cb,
2106 struct OperationContext *opc;
2107 struct ShutdownPeersData *data;
2109 if (NULL != controller->ocq_head)
2111 data = GNUNET_malloc (sizeof (struct ShutdownPeersData));
2113 data->cb_cls = cb_cls;
2114 opc = GNUNET_malloc (sizeof (struct OperationContext));
2115 opc->c = controller;
2116 opc->op_cls = op_cls;
2118 opc->id = GNUNET_TESTBED_get_next_op_id (controller);
2119 opc->type = OP_SHUTDOWN_PEERS;
2120 opc->state = OPC_STATE_INIT;
2121 opc->op = GNUNET_TESTBED_operation_create_ (opc, &opstart_shutdown_peers,
2122 &oprelease_shutdown_peers);
2123 GNUNET_TESTBED_operation_queue_insert_ (opc->c->opq_parallel_operations,
2125 GNUNET_TESTBED_operation_begin_wait_ (opc->op);
2130 /* end of testbed_api.c */