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
29 #include "gnunet_testbed_service.h"
30 #include "gnunet_core_service.h"
31 #include "gnunet_constants.h"
32 #include "gnunet_transport_service.h"
33 #include "gnunet_hello_lib.h"
36 #include "testbed_api_hosts.h"
39 #define LOG(kind, ...) \
40 GNUNET_log_from (kind, "testbed-api", __VA_ARGS__);
44 * The message queue for sending messages to the controller service
49 * The message to be sent
51 struct GNUNET_MessageHeader *msg;
54 * next pointer for DLL
56 struct MessageQueue *next;
59 * prev pointer for DLL
61 struct MessageQueue *prev;
66 * Handle to interact with a GNUnet testbed controller. Each
67 * controller has at least one master handle which is created when the
68 * controller is created; this master handle interacts with the
69 * controller process, destroying it destroys the controller (by
70 * closing stdin of the controller process). Additionally,
71 * controllers can interact with each other (in a P2P fashion); those
72 * links are established via TCP/IP on the controller's service port.
74 struct GNUNET_TESTBED_Controller
78 * The host where the controller is running
80 const struct GNUNET_TESTBED_Host *host;
85 struct GNUNET_TESTBED_HelperHandle *helper;
88 * The controller callback
90 GNUNET_TESTBED_ControllerCallback cc;
93 * The closure for controller callback
98 * The configuration to use while connecting to controller
100 struct GNUNET_CONFIGURATION_Handle *cfg;
103 * The client connection handle to the controller service
105 struct GNUNET_CLIENT_Connection *client;
108 * The head of the message queue
110 struct MessageQueue *mq_head;
113 * The tail of the message queue
115 struct MessageQueue *mq_tail;
118 * The client transmit handle
120 struct GNUNET_CLIENT_TransmitHandle *th;
123 * The controller event mask
128 * Did we start the receive loop yet?
136 * Handler for messages from controller (testbed service)
138 * @param cls the controller handler
139 * @param msg message received, NULL on timeout or fatal error
142 message_handler (void *cls, const struct GNUNET_MessageHeader *msg)
144 struct GNUNET_TESTBED_Controller *c = cls;
146 /* FIXME: Add checks for message integrity */
147 switch (ntohs (msg->type))
152 GNUNET_CLIENT_receive (c->client, &message_handler, c,
153 GNUNET_TIME_UNIT_FOREVER_REL);
158 * Function called to notify a client about the connection begin ready to queue
159 * more data. "buf" will be NULL and "size" zero if the connection was closed
160 * for writing in the meantime.
163 * @param size number of bytes available in buf
164 * @param buf where the callee should write the message
165 * @return number of bytes written to buf
168 transmit_ready_notify (void *cls, size_t size, void *buf)
170 struct GNUNET_TESTBED_Controller *c = cls;
171 struct MessageQueue *mq_entry;
174 mq_entry = c->mq_head;
175 GNUNET_assert (NULL != mq_entry);
176 GNUNET_assert (ntohs (mq_entry->msg->size) <= size);
177 size = ntohs (mq_entry->msg->size);
178 memcpy (buf, mq_entry->msg, size);
179 GNUNET_free (mq_entry->msg);
180 GNUNET_CONTAINER_DLL_remove (c->mq_head, c->mq_tail, mq_entry);
181 GNUNET_free (mq_entry);
182 mq_entry = c->mq_head;
183 if (NULL != mq_entry)
185 GNUNET_CLIENT_notify_transmit_ready (c->client,
186 ntohs (mq_entry->msg->size),
187 GNUNET_TIME_UNIT_FOREVER_REL,
188 GNUNET_NO, &transmit_ready_notify,
190 if ( (GNUNET_NO == c->in_receive) &&
193 c->in_receive = GNUNET_YES;
194 GNUNET_CLIENT_receive (c->client, &message_handler, c,
195 GNUNET_TIME_UNIT_FOREVER_REL);
202 * Queues a message in send queue for sending to the service
204 * @param controller the handle to the controller
205 * @param msg the message to queue
208 queue_message (struct GNUNET_TESTBED_Controller *controller,
209 struct GNUNET_MessageHeader *msg)
211 struct MessageQueue *mq_entry;
215 type = ntohs (msg->type);
216 size = ntohs (msg->size);
217 GNUNET_assert ((GNUNET_MESSAGE_TYPE_TESTBED_INIT <= type) &&
218 (GNUNET_MESSAGE_TYPE_TESTBED_MAX > type));
219 mq_entry = GNUNET_malloc (sizeof (struct MessageQueue));
221 LOG (GNUNET_ERROR_TYPE_DEBUG,
222 "Queueing message of type %u, size %u for sending\n", type,
224 GNUNET_CONTAINER_DLL_insert_tail (controller->mq_head, controller->mq_tail,
226 if (NULL == controller->th)
228 GNUNET_CLIENT_notify_transmit_ready (controller->client, size,
229 GNUNET_TIME_UNIT_FOREVER_REL,
230 GNUNET_NO, &transmit_ready_notify,
236 * Start a controller process using the given configuration at the
239 * @param cfg configuration to use
240 * @param host host to run the controller on, NULL for 'localhost'
241 * @param event_mask bit mask with set of events to call 'cc' for;
242 * or-ed values of "1LL" shifted by the
243 * respective 'enum GNUNET_TESTBED_EventType'
244 * (i.e. "(1LL << GNUNET_TESTBED_ET_CONNECT) | ...")
245 * @param cc controller callback to invoke on events
246 * @param cc_cls closure for cc
247 * @return handle to the controller
249 struct GNUNET_TESTBED_Controller *
250 GNUNET_TESTBED_controller_start (const struct GNUNET_CONFIGURATION_Handle *cfg,
251 struct GNUNET_TESTBED_Host *host,
253 GNUNET_TESTBED_ControllerCallback cc,
256 struct GNUNET_TESTBED_Controller *controller;
257 char * const binary_argv[] = {
258 "gnunet-service-testbed",
259 "gnunet-service-testbed",
262 struct GNUNET_TESTBED_InitMessage *msg;
264 controller = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Controller));
265 controller->helper = GNUNET_TESTBED_host_run_ (host, binary_argv);
266 if (NULL == controller->helper)
268 GNUNET_free (controller);
271 controller->host = host;
273 controller->cc_cls = cc_cls;
274 controller->event_mask = event_mask;
275 controller->cfg = GNUNET_CONFIGURATION_dup (cfg);
276 controller->client = GNUNET_CLIENT_connect ("testbed", controller->cfg);
277 if (NULL == controller->client)
279 GNUNET_TESTBED_controller_stop (controller);
282 msg = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_InitMessage));
283 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_INIT);
284 msg->header.size = htons (sizeof (struct GNUNET_TESTBED_InitMessage));
285 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
286 msg->event_mask = GNUNET_htonll (controller->event_mask);
287 queue_message (controller, (struct GNUNET_MessageHeader *) msg);
293 * Configure shared services at a controller. Using this function,
294 * you can specify that certain services (such as "resolver")
295 * should not be run for each peer but instead be shared
296 * across N peers on the specified host. This function
297 * must be called before any peers are created at the host.
299 * @param controller controller to configure
300 * @param service_name name of the service to share
301 * @param num_peers number of peers that should share one instance
302 * of the specified service (1 for no sharing is the default),
303 * use 0 to disable the service
306 GNUNET_TESTBED_controller_configure_sharing (struct GNUNET_TESTBED_Controller *controller,
307 const char *service_name,
310 struct GNUNET_TESTBED_ConfigureSharedServiceMessage *msg;
311 uint16_t service_name_size;
314 service_name_size = strlen (service_name) + 1;
315 msg_size = sizeof (struct GNUNET_TESTBED_ConfigureSharedServiceMessage)
317 msg = GNUNET_malloc (msg_size);
318 msg->header.size = htons (msg_size);
319 msg->header.type = htons (GNUNET_MESSAGE_TYPE_TESTBED_SERVICESHARE);
320 msg->host_id = htonl (GNUNET_TESTBED_host_get_id_ (controller->host));
321 msg->num_peers = htonl (num_peers);
322 memcpy (&msg[1], service_name, service_name_size);
323 queue_message (controller, (struct GNUNET_MessageHeader *) msg);
328 * Stop the given controller (also will terminate all peers and
329 * controllers dependent on this controller). This function
330 * blocks until the testbed has been fully terminated (!).
332 * @param controller handle to controller to stop
335 GNUNET_TESTBED_controller_stop (struct GNUNET_TESTBED_Controller *controller)
337 struct MessageQueue *mq_entry;
339 if (NULL != controller->th)
340 GNUNET_CLIENT_notify_transmit_ready_cancel (controller->th);
341 /* Clear the message queue */
342 while (NULL != (mq_entry = controller->mq_head))
344 GNUNET_CONTAINER_DLL_remove (controller->mq_head,
347 GNUNET_free (mq_entry->msg);
348 GNUNET_free (mq_entry);
350 if (NULL != controller->client)
351 GNUNET_CLIENT_disconnect (controller->client);
352 GNUNET_TESTBED_host_stop_ (controller->helper);
353 GNUNET_CONFIGURATION_destroy (controller->cfg);
354 GNUNET_free (controller);
359 * Create a link from a 'master' controller to a slave controller.
360 * Whenever the master controller is asked to start a peer at the
361 * given 'delegated_host', it will delegate the request to the
362 * specified slave controller. Note that the slave controller runs at
363 * the 'slave_host', which may or may not be the same host as the
364 * 'delegated_host' (for hierarchical delegations). The configuration
365 * of the slave controller is given and to be used to either create
366 * the slave controller or to connect to an existing slave controller
367 * process. 'is_subordinate' specifies if the given slave controller
368 * should be started and managed by the master controller, or if the
369 * slave already has a master and this is just a secondary master that
370 * is also allowed to use the existing slave.
372 * @param master handle to the master controller who creates the association
373 * @param delegated_host requests to which host should be delegated
374 * @param slave_host which host is used to run the slave controller
375 * @param slave_cfg configuration to use for the slave controller
376 * @param is_subordinate GNUNET_YES if the slave should be started (and stopped)
377 * by the master controller; GNUNET_NO if we are just
378 * allowed to use the slave via TCP/IP
381 GNUNET_TESTBED_controller_link (struct GNUNET_TESTBED_Controller *master,
382 struct GNUNET_TESTBED_Host *delegated_host,
383 struct GNUNET_TESTBED_Host *slave_host,
384 const struct GNUNET_CONFIGURATION_Handle *slave_cfg,
392 * Ask the testbed controller to write the current overlay topology to
393 * a file. Naturally, the file will only contain a snapshot as the
394 * topology may evolve all the time.
396 * @param controller overlay controller to inspect
397 * @param filename name of the file the topology should
401 GNUNET_TESTBED_overlay_write_topology_to_file (struct GNUNET_TESTBED_Controller *controller,
402 const char *filename)
409 /* end of testbed_api.c */