aboutsummaryrefslogtreecommitdiff
path: root/src/testbed/testbed_api_testbed.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/testbed/testbed_api_testbed.c')
-rw-r--r--src/testbed/testbed_api_testbed.c1472
1 files changed, 0 insertions, 1472 deletions
diff --git a/src/testbed/testbed_api_testbed.c b/src/testbed/testbed_api_testbed.c
deleted file mode 100644
index e0b76ad78..000000000
--- a/src/testbed/testbed_api_testbed.c
+++ /dev/null
@@ -1,1472 +0,0 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2008--2013 GNUnet e.V.
4
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
9
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 Affero General Public License for more details.
14
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17
18 SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21/**
22 * @file testbed/testbed_api_testbed.c
23 * @brief high-level testbed management
24 * @author Christian Grothoff
25 * @author Sree Harsha Totakura
26 */
27
28#include "platform.h"
29#include "gnunet_util_lib.h"
30#include "gnunet_testbed_service.h"
31#include "testbed_api.h"
32#include "testbed_api_peers.h"
33#include "testbed_api_hosts.h"
34#include "testbed_api_topology.h"
35
36/**
37 * Generic loggins shorthand
38 */
39#define LOG(kind, ...) \
40 GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__)
41
42/**
43 * Debug logging shortcut
44 */
45#define DEBUG(...) \
46 LOG (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
47
48/**
49 * The default setup timeout in seconds
50 */
51#define DEFAULT_SETUP_TIMEOUT 300
52
53
54/**
55 * Configuration section for testbed
56 */
57#define TESTBED_CONFIG_SECTION "testbed"
58
59/**
60 * Option string for the maximum number of edges a peer is permitted to have
61 * while generating scale free topology
62 */
63#define SCALE_FREE_CAP "SCALE_FREE_TOPOLOGY_CAP"
64
65/**
66 * Option string for the number of edges to be established when adding a new
67 * node to the scale free network
68 */
69#define SCALE_FREE_M "SCALE_FREE_TOPOLOGY_M"
70
71/**
72 * Context information for the operation we start
73 */
74struct RunContextOperation
75{
76 /**
77 * The testbed operation handle
78 */
79 struct GNUNET_TESTBED_Operation *op;
80
81 /**
82 * Context information for GNUNET_TESTBED_run()
83 */
84 struct GNUNET_TESTBED_RunHandle *rc;
85
86 /**
87 * Closure
88 */
89 void *cls;
90};
91
92
93/**
94 * States of RunContext
95 */
96enum State
97{
98 /**
99 * Initial state
100 */
101 RC_INIT = 0,
102
103 /**
104 * Controllers on given hosts started and linked
105 */
106 RC_LINKED,
107
108 /**
109 * Peers are created
110 */
111 RC_PEERS_CREATED,
112
113 /**
114 * The testbed run is ready and the master callback can be called now. At this
115 * time the peers are all started and if a topology is provided in the
116 * configuration the topology would have been attempted
117 */
118 RC_READY,
119
120 /* /\** */
121 /* * Peers are stopped */
122 /* *\/ */
123 /* RC_PEERS_STOPPED, */
124
125 /* /\** */
126 /* * Peers are destroyed */
127 /* *\/ */
128 /* RC_PEERS_DESTROYED */
129
130 /**
131 * All peers shutdown (stopped and destroyed)
132 */
133 RC_PEERS_SHUTDOWN
134};
135
136
137/**
138 * Context for host compatibility checks
139 */
140struct CompatibilityCheckContext
141{
142 /**
143 * The run context
144 */
145 struct GNUNET_TESTBED_RunHandle *rc;
146
147 /**
148 * Handle for the compatibility check
149 */
150 struct GNUNET_TESTBED_HostHabitableCheckHandle *h;
151
152 /**
153 * Index of the host in the run context's hosts array
154 */
155 unsigned int index;
156};
157
158
159/**
160 * Testbed Run Handle
161 */
162struct GNUNET_TESTBED_RunHandle
163{
164 /**
165 * The controller handle
166 */
167 struct GNUNET_TESTBED_Controller *c;
168
169 /**
170 * The configuration of the controller. This is based on the cfg given to the
171 * function GNUNET_TESTBED_run(). We also use this config as a template while
172 * for peers
173 */
174 struct GNUNET_CONFIGURATION_Handle *cfg;
175
176 /**
177 * Handle to the host on which the controller runs
178 */
179 struct GNUNET_TESTBED_Host *h;
180
181 /**
182 * The handle to the controller process
183 */
184 struct GNUNET_TESTBED_ControllerProc *cproc;
185
186 /**
187 * The callback to use as controller callback
188 */
189 GNUNET_TESTBED_ControllerCallback cc;
190
191 /**
192 * The pointer to the controller callback
193 */
194 void *cc_cls;
195
196 /**
197 * The trusted IP string
198 */
199 char *trusted_ip;
200
201 /**
202 * TestMaster callback to call when testbed initialization is done
203 */
204 GNUNET_TESTBED_TestMaster test_master;
205
206 /**
207 * The closure for the TestMaster callback
208 */
209 void *test_master_cls;
210
211 /**
212 * A hashmap for operations started by us
213 */
214 struct GNUNET_CONTAINER_MultiHashMap32 *rcop_map;
215
216 /**
217 * An array of hosts loaded from the hostkeys file
218 */
219 struct GNUNET_TESTBED_Host **hosts;
220
221 /**
222 * Array of compatibility check contexts
223 */
224 struct CompatibilityCheckContext *hclist;
225
226 /**
227 * Array of peers which we create
228 */
229 struct GNUNET_TESTBED_Peer **peers;
230
231 /**
232 * The topology generation operation. Will be null if no topology is set in
233 * the configuration
234 */
235 struct GNUNET_TESTBED_Operation *topology_operation;
236
237 /**
238 * The file containing topology data. Only used if the topology is set to 'FROM_FILE'
239 */
240 char *topo_file;
241
242 /**
243 * Host registration handle
244 */
245 struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
246
247 /**
248 * Profiling start time
249 */
250 struct GNUNET_TIME_Absolute pstart_time;
251
252 /**
253 * Host registration task
254 */
255 struct GNUNET_SCHEDULER_Task *register_hosts_task;
256
257 /**
258 * Task to be run of a timeout
259 */
260 struct GNUNET_SCHEDULER_Task *timeout_task;
261
262 /**
263 * Task run upon shutdown interrupts
264 */
265 struct GNUNET_SCHEDULER_Task *interrupt_task;
266
267 /**
268 * The event mask for the controller
269 */
270 uint64_t event_mask;
271
272 /**
273 * State of this context
274 */
275 enum State state;
276
277 /**
278 * The topology which has to be achieved with the peers started in this context
279 */
280 enum GNUNET_TESTBED_TopologyOption topology;
281
282 /**
283 * Have we already shutdown
284 */
285 int shutdown;
286
287 /**
288 * Number of hosts in the given host file
289 */
290 unsigned int num_hosts;
291
292 /**
293 * Number of registered hosts. Also used as a counter while checking
294 * habitabillity of hosts
295 */
296 unsigned int reg_hosts;
297
298 /**
299 * Current peer count for an operation; Set this to 0 and increment for each
300 * successful operation on a peer
301 */
302 unsigned int peer_count;
303
304 /**
305 * number of peers to start
306 */
307 unsigned int num_peers;
308
309 /**
310 * Expected overlay connects. Should be zero if no topology is relevant
311 */
312 unsigned int num_oc;
313
314 /**
315 * Number of random links to established
316 */
317 unsigned int random_links;
318
319 /**
320 * the number of overlay link connection attempts that succeeded
321 */
322 unsigned int links_succeeded;
323
324 /**
325 * the number of overlay link connection attempts that failed
326 */
327 unsigned int links_failed;
328};
329
330
331/**
332 * Return a 32-bit key from a pointer
333 *
334 * @param rcop the pointer
335 * @return 32-bit key
336 */
337static uint32_t
338rcop_key (void *rcop)
339{
340 return *((uint32_t *) &rcop);
341}
342
343
344/**
345 * Context information used for finding a pointer in the rcop_map
346 */
347struct SearchContext
348{
349 /**
350 * The operation pointer to look for
351 */
352 struct GNUNET_TESTBED_Operation *query;
353
354 /**
355 * The Run context operation which has the operation being queried
356 */
357 struct RunContextOperation *result;
358};
359
360
361/**
362 * Iterator for searching over the elements matching a given query
363 *
364 * @param cls the SearchContext
365 * @param key the 32-bit key
366 * @param value the RunContextOperation element
367 * @return GNUNET_YES to continue iteration; GNUNET_NO to cancel it
368 */
369static int
370search_iterator (void *cls, uint32_t key, void *value)
371{
372 struct RunContextOperation *rcop = value;
373 struct SearchContext *sc = cls;
374
375 GNUNET_assert (NULL != rcop);
376 if (sc->query == rcop->op)
377 {
378 GNUNET_assert (NULL == sc->result);
379 sc->result = rcop;
380 return GNUNET_NO;
381 }
382 return GNUNET_YES;
383}
384
385
386/**
387 * Initiate a search for the given operation in the rcop_map
388 *
389 * @param rc the RunContext whose rcop_map will be searched for the given
390 * operation
391 * @param op the given operation to search for
392 * @return the matching RunContextOperation if found; NULL if not
393 */
394static struct RunContextOperation *
395search_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct
396 GNUNET_TESTBED_Operation *op)
397{
398 struct SearchContext sc;
399
400 sc.query = op;
401 sc.result = NULL;
402 if (GNUNET_SYSERR ==
403 GNUNET_CONTAINER_multihashmap32_get_multiple (rc->rcop_map,
404 rcop_key (op),
405 &search_iterator,
406 &sc))
407 {
408 GNUNET_assert (NULL != sc.result);
409 return sc.result;
410 }
411 return NULL;
412}
413
414
415/**
416 * Insert an RunContextOperation into the rcop_map of the given RunContext
417 *
418 * @param rc the RunContext into whose map is to be used for insertion
419 * @param rcop the RunContextOperation to insert
420 */
421static void
422insert_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct
423 RunContextOperation *rcop)
424{
425 GNUNET_assert (GNUNET_OK ==
426 GNUNET_CONTAINER_multihashmap32_put (rc->rcop_map,
427 rcop_key (rcop->op), rcop,
428 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE));
429}
430
431
432/**
433 * Remove a RunContextOperation from the rcop_map of the given RunContext
434 *
435 * @param rc the RunContext from whose map the given RunContextOperaton has to
436 * be removed
437 * @param rcop the RunContextOperation
438 */
439static void
440remove_rcop (struct GNUNET_TESTBED_RunHandle *rc, struct
441 RunContextOperation *rcop)
442{
443 GNUNET_assert (GNUNET_YES ==
444 GNUNET_CONTAINER_multihashmap32_remove (rc->rcop_map,
445 rcop_key (rcop->op),
446 rcop));
447}
448
449
450/**
451 * Assuming all peers have been destroyed cleanup run handle
452 *
453 * @param rc the run context
454 */
455static void
456cleanup (struct GNUNET_TESTBED_RunHandle *rc)
457{
458 unsigned int hid;
459
460 GNUNET_assert (NULL == rc->register_hosts_task);
461 GNUNET_assert (NULL == rc->reg_handle);
462 GNUNET_assert (NULL == rc->peers);
463 GNUNET_assert (NULL == rc->hclist);
464 GNUNET_assert (RC_PEERS_SHUTDOWN == rc->state);
465 GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (rc->rcop_map));
466 GNUNET_CONTAINER_multihashmap32_destroy (rc->rcop_map);
467 if (NULL != rc->c)
468 GNUNET_TESTBED_controller_disconnect (rc->c);
469 if (NULL != rc->cproc)
470 GNUNET_TESTBED_controller_stop (rc->cproc);
471 if (NULL != rc->h)
472 GNUNET_TESTBED_host_destroy (rc->h);
473 for (hid = 0; hid < rc->num_hosts; hid++)
474 GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
475 GNUNET_free (rc->hosts);
476 if (NULL != rc->cfg)
477 GNUNET_CONFIGURATION_destroy (rc->cfg);
478 GNUNET_free (rc->topo_file);
479 GNUNET_free (rc->trusted_ip);
480 GNUNET_free (rc);
481}
482
483
484/**
485 * Iterator for cleaning up elements from rcop_map
486 *
487 * @param cls the RunContext
488 * @param key the 32-bit key
489 * @param value the RunContextOperation element
490 * @return always GNUNET_YES
491 */
492static int
493rcop_cleanup_iterator (void *cls, uint32_t key, void *value)
494{
495 struct GNUNET_TESTBED_RunHandle *rc = cls;
496 struct RunContextOperation *rcop = value;
497
498 GNUNET_assert (rc == rcop->rc);
499 remove_rcop (rc, rcop);
500 GNUNET_TESTBED_operation_done (rcop->op);
501 GNUNET_free (rcop);
502 return GNUNET_YES;
503}
504
505
506/**
507 * Cancels operations and tasks which are assigned to the given run context
508 *
509 * @param rc the RunContext
510 */
511static void
512rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc)
513{
514 struct CompatibilityCheckContext *hc;
515 unsigned int nhost;
516
517 if (NULL != rc->hclist)
518 {
519 for (nhost = 0; nhost < rc->num_hosts; nhost++)
520 {
521 hc = &rc->hclist[nhost];
522 if (NULL != hc->h)
523 GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
524 }
525 GNUNET_free (rc->hclist);
526 rc->hclist = NULL;
527 }
528 /* Stop register hosts task if it is running */
529 if (NULL != rc->register_hosts_task)
530 {
531 GNUNET_SCHEDULER_cancel (rc->register_hosts_task);
532 rc->register_hosts_task = NULL;
533 }
534 if (NULL != rc->timeout_task)
535 {
536 GNUNET_SCHEDULER_cancel (rc->timeout_task);
537 rc->timeout_task = NULL;
538 }
539 if (NULL != rc->reg_handle)
540 {
541 GNUNET_TESTBED_cancel_registration (rc->reg_handle);
542 rc->reg_handle = NULL;
543 }
544 if (NULL != rc->topology_operation)
545 {
546 GNUNET_TESTBED_operation_done (rc->topology_operation);
547 rc->topology_operation = NULL;
548 }
549 /* cancel any exiting operations */
550 GNUNET_assert (GNUNET_SYSERR !=
551 GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map,
552 &rcop_cleanup_iterator,
553 rc));
554}
555
556
557/**
558 * Cancels the scheduled interrupt task
559 *
560 * @param rc the run context
561 */
562static void
563cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc)
564{
565 GNUNET_SCHEDULER_cancel (rc->interrupt_task);
566 rc->interrupt_task = NULL;
567}
568
569
570/**
571 * This callback will be called when all the operations are completed
572 * (done/cancelled)
573 *
574 * @param cls run context
575 */
576static void
577wait_op_completion (void *cls)
578{
579 struct GNUNET_TESTBED_RunHandle *rc = cls;
580 struct RunContextOperation *rcop;
581
582 if ((NULL == rc->cproc)
583 || (NULL == rc->c)
584 || (GNUNET_YES == rc->shutdown))
585 {
586 if (NULL != rc->peers)
587 {
588 GNUNET_free (rc->peers);
589 rc->peers = NULL;
590 }
591 goto cleanup_;
592 }
593 if (NULL == rc->peers)
594 goto cleanup_;
595 rc->shutdown = GNUNET_YES;
596 rcop = GNUNET_new (struct RunContextOperation);
597 rcop->rc = rc;
598 rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL);
599 GNUNET_assert (NULL != rcop->op);
600 DEBUG ("Shutting down peers\n");
601 rc->pstart_time = GNUNET_TIME_absolute_get ();
602 insert_rcop (rc, rcop);
603 return;
604
605cleanup_:
606 rc->state = RC_PEERS_SHUTDOWN;
607 cancel_interrupt_task (rc);
608 cleanup (rc);
609}
610
611
612/**
613 * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown.
614 *
615 * @param cls the RunContext which has to be acted upon
616 */
617static void
618interrupt (void *cls)
619{
620 struct GNUNET_TESTBED_RunHandle *rc = cls;
621 struct GNUNET_TESTBED_Controller *c = rc->c;
622 unsigned int size;
623
624 /* reschedule */
625 rc->interrupt_task = GNUNET_SCHEDULER_add_shutdown (&interrupt, rc);
626 rc_cleanup_operations (rc);
627 if ((GNUNET_NO == rc->shutdown) &&
628 (NULL != c) &&
629 (NULL != c->opc_map) &&
630 (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map))))
631 {
632 LOG (GNUNET_ERROR_TYPE_WARNING,
633 "Shutdown postponed as there are %u operations currently active\n",
634 size);
635 c->opcq_empty_cb = &wait_op_completion;
636 c->opcq_empty_cls = rc;
637 return;
638 }
639 wait_op_completion (rc);
640}
641
642
643/**
644 * Function to return the string representation of the duration between current
645 * time and `pstart_time' in `RunContext'
646 *
647 * @param rc the RunContext
648 * @return the representation string; this is NOT reentrant
649 */
650static const char *
651prof_time (struct GNUNET_TESTBED_RunHandle *rc)
652{
653 struct GNUNET_TIME_Relative ptime;
654
655 ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time);
656 return GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES);
657}
658
659
660/**
661 * Task for starting peers
662 *
663 * @param cls the RunHandle
664 */
665static void
666start_peers_task (void *cls)
667{
668 struct GNUNET_TESTBED_RunHandle *rc = cls;
669 struct RunContextOperation *rcop;
670 unsigned int peer;
671
672 DEBUG ("Starting Peers\n");
673 rc->pstart_time = GNUNET_TIME_absolute_get ();
674 for (peer = 0; peer < rc->num_peers; peer++)
675 {
676 rcop = GNUNET_new (struct RunContextOperation);
677 rcop->rc = rc;
678 rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL);
679 GNUNET_assert (NULL != rcop->op);
680 rcop->cls = rc->peers[peer];
681 insert_rcop (rc, rcop);
682 }
683 rc->peer_count = 0;
684}
685
686
687/**
688 * Functions of this signature are called when a peer has been successfully
689 * created
690 *
691 * @param cls the closure from GNUNET_TESTBED_peer_create()
692 * @param peer the handle for the created peer; NULL on any error during
693 * creation
694 * @param emsg NULL if peer is not NULL; else MAY contain the error description
695 */
696static void
697peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
698{
699 struct RunContextOperation *rcop = cls;
700 struct GNUNET_TESTBED_RunHandle *rc;
701
702 GNUNET_assert (NULL != rcop);
703 GNUNET_assert (NULL != (rc = rcop->rc));
704 remove_rcop (rc, rcop);
705 GNUNET_TESTBED_operation_done (rcop->op);
706 GNUNET_free (rcop);
707 if (NULL == peer)
708 {
709 if (NULL != emsg)
710 LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n",
711 emsg);
712 GNUNET_SCHEDULER_shutdown ();
713 return;
714 }
715 rc->peers[rc->peer_count] = peer;
716 rc->peer_count++;
717 if (rc->peer_count < rc->num_peers)
718 return;
719 DEBUG ("%u peers created in %s\n", rc->num_peers, prof_time (rc));
720 rc->state = RC_PEERS_CREATED;
721 GNUNET_SCHEDULER_add_now (&start_peers_task, rc);
722}
723
724
725/**
726 * call test master callback
727 *
728 * @param rc the RunContext
729 */
730static void
731call_master (struct GNUNET_TESTBED_RunHandle *rc)
732{
733 GNUNET_SCHEDULER_cancel (rc->timeout_task);
734 rc->timeout_task = NULL;
735 if (NULL != rc->test_master)
736 rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers,
737 rc->links_succeeded, rc->links_failed);
738}
739
740
741/**
742 * Callbacks of this type are called when topology configuration is completed
743 *
744 * @param cls the operation closure given to
745 * GNUNET_TESTBED_overlay_configure_topology_va() and
746 * GNUNET_TESTBED_overlay_configure() calls
747 * @param nsuccess the number of successful overlay connects
748 * @param nfailures the number of overlay connects which failed
749 */
750static void
751topology_completion_callback (void *cls, unsigned int nsuccess,
752 unsigned int nfailures)
753{
754 struct GNUNET_TESTBED_RunHandle *rc = cls;
755
756 DEBUG ("Overlay topology generated in %s\n", prof_time (rc));
757 GNUNET_TESTBED_operation_done (rc->topology_operation);
758 rc->topology_operation = NULL;
759 rc->links_succeeded = nsuccess;
760 rc->links_failed = nfailures;
761 rc->state = RC_READY;
762 call_master (rc);
763}
764
765
766/**
767 * Function to create peers
768 *
769 * @param rc the RunContext
770 */
771static void
772create_peers (struct GNUNET_TESTBED_RunHandle *rc)
773{
774 struct RunContextOperation *rcop;
775 unsigned int peer;
776
777 DEBUG ("Creating peers\n");
778 rc->pstart_time = GNUNET_TIME_absolute_get ();
779 rc->peers =
780 GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Peer *) * rc->num_peers);
781 GNUNET_assert (NULL != rc->c);
782 rc->peer_count = 0;
783 for (peer = 0; peer < rc->num_peers; peer++)
784 {
785 rcop = GNUNET_new (struct RunContextOperation);
786 rcop->rc = rc;
787 rcop->op =
788 GNUNET_TESTBED_peer_create (rc->c,
789 (0 ==
790 rc->num_hosts) ? rc->h : rc->hosts[peer
791 % rc->
792 num_hosts],
793 rc->cfg, &peer_create_cb, rcop);
794 GNUNET_assert (NULL != rcop->op);
795 insert_rcop (rc, rcop);
796 }
797}
798
799
800/**
801 * Signature of the event handler function called by the
802 * respective event controller.
803 *
804 * @param cls closure
805 * @param event information about the event
806 */
807static void
808event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
809{
810 struct GNUNET_TESTBED_RunHandle *rc = cls;
811 struct RunContextOperation *rcop;
812
813 if (RC_INIT == rc->state)
814 {
815 switch (event->type)
816 {
817 case GNUNET_TESTBED_ET_OPERATION_FINISHED:
818 rcop = event->op_cls;
819 if (NULL != event->details.operation_finished.emsg)
820 {
821 LOG (GNUNET_ERROR_TYPE_ERROR, _ (
822 "Linking controllers failed. Exiting"));
823 GNUNET_SCHEDULER_shutdown ();
824 }
825 else
826 rc->reg_hosts++;
827 GNUNET_assert (event->op == rcop->op);
828 remove_rcop (rc, rcop);
829 GNUNET_TESTBED_operation_done (rcop->op);
830 GNUNET_free (rcop);
831 if (rc->reg_hosts == rc->num_hosts)
832 {
833 rc->state = RC_LINKED;
834 create_peers (rc);
835 }
836 return;
837
838 default:
839 GNUNET_break (0);
840 GNUNET_SCHEDULER_shutdown ();
841 return;
842 }
843 }
844 if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type)
845 goto call_cc;
846 if (NULL == (rcop = search_rcop (rc, event->op)))
847 goto call_cc;
848 remove_rcop (rc, rcop);
849 GNUNET_TESTBED_operation_done (rcop->op);
850 GNUNET_free (rcop);
851 if ((GNUNET_NO == rc->shutdown)
852 && (NULL != event->details.operation_finished.emsg))
853 {
854 LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n",
855 event->details.operation_finished.emsg);
856 GNUNET_SCHEDULER_shutdown ();
857 return;
858 }
859 GNUNET_assert (GNUNET_YES == rc->shutdown);
860 switch (rc->state)
861 {
862 case RC_LINKED:
863 case RC_PEERS_CREATED:
864 case RC_READY:
865 rc->state = RC_PEERS_SHUTDOWN;
866 GNUNET_free (rc->peers);
867 rc->peers = NULL;
868 DEBUG ("Peers shut down in %s\n", prof_time (rc));
869 GNUNET_SCHEDULER_shutdown ();
870 break;
871
872 default:
873 GNUNET_assert (0);
874 }
875 return;
876
877call_cc:
878 if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc))
879 rc->cc (rc->cc_cls, event);
880 if (GNUNET_TESTBED_ET_PEER_START != event->type)
881 return;
882 if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */
883 return;
884 remove_rcop (rc, rcop);
885 GNUNET_TESTBED_operation_done (rcop->op);
886 GNUNET_free (rcop);
887 rc->peer_count++;
888 if (rc->peer_count < rc->num_peers)
889 return;
890 DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc));
891 if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology)
892 {
893 switch (rc->topology)
894 {
895 case GNUNET_TESTBED_TOPOLOGY_NONE:
896 GNUNET_assert (0);
897
898 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
899 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
900 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
901 rc->topology_operation =
902 GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
903 rc->peers, &rc->num_oc,
904 &topology_completion_callback,
905 rc,
906 rc->topology,
907 rc->random_links,
908 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
909 break;
910
911 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
912 GNUNET_assert (NULL != rc->topo_file);
913 rc->topology_operation =
914 GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
915 rc->peers, &rc->num_oc,
916 &topology_completion_callback,
917 rc,
918 rc->topology,
919 rc->topo_file,
920 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
921 break;
922
923 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
924 {
925 unsigned long long number;
926 unsigned int cap;
927 GNUNET_assert (GNUNET_OK ==
928 GNUNET_CONFIGURATION_get_value_number (rc->cfg,
929 TESTBED_CONFIG_SECTION,
930 SCALE_FREE_CAP,
931 &number));
932 cap = (unsigned int) number;
933 GNUNET_assert (GNUNET_OK ==
934 GNUNET_CONFIGURATION_get_value_number (rc->cfg,
935 TESTBED_CONFIG_SECTION,
936 SCALE_FREE_M,
937 &number));
938 rc->topology_operation =
939 GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
940 rc->peers, &rc->num_oc,
941 &
942 topology_completion_callback,
943 rc,
944 rc->topology,
945 cap, /* uint16_t */
946 (unsigned int) number, /* uint8_t */
947 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
948 }
949 break;
950
951 default:
952 rc->topology_operation =
953 GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
954 rc->peers, &rc->num_oc,
955 &topology_completion_callback,
956 rc,
957 rc->topology,
958 GNUNET_TESTBED_TOPOLOGY_OPTION_END);
959 }
960 if (NULL == rc->topology_operation)
961 LOG (GNUNET_ERROR_TYPE_WARNING,
962 "Not generating a topology. Check number of peers\n");
963 else
964 {
965 DEBUG ("Creating overlay topology\n");
966 rc->pstart_time = GNUNET_TIME_absolute_get ();
967 return;
968 }
969 }
970 rc->state = RC_READY;
971 call_master (rc);
972}
973
974
975/**
976 * Task to register all hosts available in the global host list
977 *
978 * @param cls the RunContext
979 */
980static void
981register_hosts (void *cls);
982
983
984/**
985 * Callback which will be called to after a host registration succeeded or failed
986 *
987 * @param cls the closure
988 * @param emsg the error message; NULL if host registration is successful
989 */
990static void
991host_registration_completion (void *cls, const char *emsg)
992{
993 struct GNUNET_TESTBED_RunHandle *rc = cls;
994
995 rc->reg_handle = NULL;
996 if (NULL != emsg)
997 {
998 LOG (GNUNET_ERROR_TYPE_WARNING,
999 _ ("Host registration failed for a host. Error: %s\n"), emsg);
1000 GNUNET_SCHEDULER_shutdown ();
1001 return;
1002 }
1003 rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts,
1004 rc);
1005}
1006
1007
1008/**
1009 * Task to register all hosts available in the global host list
1010 *
1011 * @param cls RunContext
1012 */
1013static void
1014register_hosts (void *cls)
1015{
1016 struct GNUNET_TESTBED_RunHandle *rc = cls;
1017 struct RunContextOperation *rcop;
1018 unsigned int slave;
1019
1020 rc->register_hosts_task = NULL;
1021 if (rc->reg_hosts == rc->num_hosts)
1022 {
1023 DEBUG ("All hosts successfully registered\n");
1024 /* Start slaves */
1025 for (slave = 0; slave < rc->num_hosts; slave++)
1026 {
1027 rcop = GNUNET_new (struct RunContextOperation);
1028 rcop->rc = rc;
1029 rcop->op =
1030 GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave],
1031 rc->h, GNUNET_YES);
1032 GNUNET_assert (NULL != rcop->op);
1033 insert_rcop (rc, rcop);
1034 }
1035 rc->reg_hosts = 0;
1036 return;
1037 }
1038 rc->reg_handle =
1039 GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts],
1040 host_registration_completion, rc);
1041 rc->reg_hosts++;
1042}
1043
1044
1045/**
1046 * Callback to signal successful startup of the controller process
1047 *
1048 * @param cls the closure from GNUNET_TESTBED_controller_start()
1049 * @param cfg the configuration with which the controller has been started;
1050 * NULL if status is not GNUNET_OK
1051 * @param status GNUNET_OK if the startup is successful; GNUNET_SYSERR if not,
1052 * GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1053 */
1054static void
1055controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1056 int status)
1057{
1058 struct GNUNET_TESTBED_RunHandle *rc = cls;
1059 uint64_t event_mask;
1060
1061 if (status != GNUNET_OK)
1062 {
1063 rc->cproc = NULL;
1064 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1065 _ ("Controller crash detected. Shutting down.\n"));
1066 GNUNET_SCHEDULER_shutdown ();
1067 return;
1068 }
1069 GNUNET_CONFIGURATION_destroy (rc->cfg);
1070 rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1071 event_mask = rc->event_mask;
1072 event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1073 event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
1074 if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE)
1075 event_mask |= GNUNET_TESTBED_ET_CONNECT;
1076 rc->c =
1077 GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc);
1078 if (0 < rc->num_hosts)
1079 {
1080 rc->reg_hosts = 0;
1081 rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
1082 return;
1083 }
1084 rc->state = RC_LINKED;
1085 create_peers (rc);
1086}
1087
1088
1089/**
1090 * Callback function invoked for each interface found.
1091 *
1092 * @param cls closure
1093 * @param name name of the interface (can be NULL for unknown)
1094 * @param isDefault is this presumably the default interface
1095 * @param addr address of this interface (can be NULL for unknown or unassigned)
1096 * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
1097 * @param netmask the network mask (can be NULL for unknown or unassigned))
1098 * @param addrlen length of the address
1099 * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
1100 */
1101static int
1102netint_proc (void *cls, const char *name, int isDefault,
1103 const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
1104 const struct sockaddr *netmask, socklen_t addrlen)
1105{
1106 struct GNUNET_TESTBED_RunHandle *rc = cls;
1107 char hostip[NI_MAXHOST];
1108 char *buf;
1109
1110 if (sizeof(struct sockaddr_in) != addrlen)
1111 return GNUNET_OK; /* Only consider IPv4 for now */
1112 if (0 !=
1113 getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))
1114 GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo");
1115 if (NULL == rc->trusted_ip)
1116 {
1117 rc->trusted_ip = GNUNET_strdup (hostip);
1118 return GNUNET_YES;
1119 }
1120 (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip);
1121 GNUNET_free (rc->trusted_ip);
1122 rc->trusted_ip = buf;
1123 return GNUNET_YES;
1124}
1125
1126
1127/**
1128 * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
1129 * inform whether the given host is habitable or not. The Handle returned by
1130 * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
1131 *
1132 * @param cls NULL
1133 * @param host the host whose status is being reported; will be NULL if the host
1134 * given to GNUNET_TESTBED_is_host_habitable() is NULL
1135 * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
1136 */
1137static void
1138host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host,
1139 int status)
1140{
1141 struct CompatibilityCheckContext *hc = cls;
1142 struct GNUNET_TESTBED_RunHandle *rc;
1143 struct GNUNET_TESTBED_Host **old_hosts;
1144 unsigned int nhost;
1145
1146 GNUNET_assert (NULL != (rc = hc->rc));
1147 nhost = hc->index;
1148 GNUNET_assert (nhost <= rc->num_hosts);
1149 GNUNET_assert (host == rc->hosts[nhost]);
1150 hc->h = NULL;
1151 if (GNUNET_NO == status)
1152 {
1153 if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host)))
1154 LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Host %s cannot start testbed\n"),
1155 GNUNET_TESTBED_host_get_hostname (host));
1156 else
1157 LOG (GNUNET_ERROR_TYPE_ERROR,
1158 _ ("Testbed cannot be started on localhost\n"));
1159 GNUNET_SCHEDULER_shutdown ();
1160 return;
1161 }
1162 rc->reg_hosts++;
1163 if (rc->reg_hosts < rc->num_hosts)
1164 return;
1165 GNUNET_free (rc->hclist);
1166 rc->hclist = NULL;
1167 rc->h = rc->hosts[0];
1168 rc->num_hosts--;
1169 if (0 < rc->num_hosts)
1170 {
1171 old_hosts = rc->hosts;
1172 rc->hosts =
1173 GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts);
1174 GNUNET_memcpy (rc->hosts, &old_hosts[1],
1175 (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts));
1176 GNUNET_free (old_hosts);
1177 }
1178 else
1179 {
1180 GNUNET_free (rc->hosts);
1181 rc->hosts = NULL;
1182 }
1183 GNUNET_TESTBED_host_resolve_ (rc->h);
1184 for (nhost = 0; nhost < rc->num_hosts; nhost++)
1185 GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]);
1186 GNUNET_OS_network_interfaces_list (netint_proc, rc);
1187 if (NULL == rc->trusted_ip)
1188 rc->trusted_ip = GNUNET_strdup ("127.0.0.1");
1189 rc->cproc =
1190 GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h,
1191 &controller_status_cb, rc);
1192 GNUNET_free (rc->trusted_ip);
1193 rc->trusted_ip = NULL;
1194 if (NULL == rc->cproc)
1195 {
1196 LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Cannot start the master controller"));
1197 GNUNET_SCHEDULER_shutdown ();
1198 }
1199}
1200
1201
1202/**
1203 * Task run upon timeout while setting up the testbed
1204 *
1205 * @param cls the RunContext
1206 */
1207static void
1208timeout_task (void *cls)
1209{
1210 struct GNUNET_TESTBED_RunHandle *rc = cls;
1211
1212 rc->timeout_task = NULL;
1213 LOG (GNUNET_ERROR_TYPE_ERROR,
1214 _ ("Shutting down testbed due to timeout while setup.\n"));
1215 GNUNET_SCHEDULER_shutdown ();
1216 if (NULL != rc->test_master)
1217 rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0);
1218 rc->test_master = NULL;
1219}
1220
1221
1222/**
1223 * Convenience method for running a testbed with
1224 * a single call. Underlay and overlay topology
1225 * are configured using the "UNDERLAY" and "OVERLAY"
1226 * options in the "[testbed]" section of the configuration\
1227 * (with possible options given in "UNDERLAY_XXX" and/or
1228 * "OVERLAY_XXX").
1229 *
1230 * The testbed is to be terminated using a call to
1231 * "GNUNET_SCHEDULER_shutdown".
1232 *
1233 * @param host_filename name of the file with the 'hosts', NULL
1234 * to run everything on 'localhost'
1235 * @param cfg configuration to use (for testbed, controller and peers)
1236 * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg?
1237 * @param event_mask bit mask with set of events to call 'cc' for;
1238 * or-ed values of "1LL" shifted by the
1239 * respective 'enum GNUNET_TESTBED_EventType'
1240 * (e.g. "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
1241 * @param cc controller callback to invoke on events; This callback is called
1242 * for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't
1243 * set in the event_mask as this is the only way get access to the
1244 * handle of each peer
1245 * @param cc_cls closure for cc
1246 * @param test_master this callback will be called once the test is ready
1247 * @param test_master_cls closure for 'test_master'.
1248 */
1249void
1250GNUNET_TESTBED_run (const char *host_filename,
1251 const struct GNUNET_CONFIGURATION_Handle *cfg,
1252 unsigned int num_peers, uint64_t event_mask,
1253 GNUNET_TESTBED_ControllerCallback cc, void *cc_cls,
1254 GNUNET_TESTBED_TestMaster test_master,
1255 void *test_master_cls)
1256{
1257 struct GNUNET_TESTBED_RunHandle *rc;
1258 char *topology;
1259 struct CompatibilityCheckContext *hc;
1260 struct GNUNET_TIME_Relative timeout;
1261 unsigned long long number;
1262 unsigned int hid;
1263 unsigned int nhost;
1264
1265 GNUNET_assert (num_peers > 0);
1266 rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle);
1267 rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1268 if (NULL != host_filename)
1269 {
1270 rc->num_hosts =
1271 GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg,
1272 &rc->hosts);
1273 if (0 == rc->num_hosts)
1274 {
1275 LOG (GNUNET_ERROR_TYPE_WARNING,
1276 _ ("No hosts loaded. Need at least one host\n"));
1277 goto error_cleanup;
1278 }
1279 }
1280 else
1281 rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0);
1282 rc->num_peers = num_peers;
1283 rc->event_mask = event_mask;
1284 rc->cc = cc;
1285 rc->cc_cls = cc_cls;
1286 rc->test_master = test_master;
1287 rc->test_master_cls = test_master_cls;
1288 rc->state = RC_INIT;
1289 rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE;
1290 if (GNUNET_OK ==
1291 GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION,
1292 "OVERLAY_TOPOLOGY", &topology))
1293 {
1294 if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology))
1295 {
1296 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1297 TESTBED_CONFIG_SECTION,
1298 "OVERLAY_TOPLOGY",
1299 _
1300 (
1301 "Specified topology must be supported by testbed"));
1302 }
1303 GNUNET_free (topology);
1304 }
1305 switch (rc->topology)
1306 {
1307 case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1308 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1309 case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1310 if (GNUNET_OK !=
1311 GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
1312 "OVERLAY_RANDOM_LINKS",
1313 &number))
1314 {
1315 /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS
1316 * option to be set to the number of random links to be established */
1317 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1318 TESTBED_CONFIG_SECTION,
1319 "OVERLAY_RANDOM_LINKS");
1320 goto error_cleanup;
1321 }
1322 if (number > UINT32_MAX)
1323 {
1324 GNUNET_break (0); /* Too big number */
1325 goto error_cleanup;
1326 }
1327 rc->random_links = (unsigned int) number;
1328 break;
1329
1330 case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1331 if (GNUNET_OK !=
1332 GNUNET_CONFIGURATION_get_value_filename (rc->cfg,
1333 TESTBED_CONFIG_SECTION,
1334 "OVERLAY_TOPOLOGY_FILE",
1335 &rc->topo_file))
1336 {
1337 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1338 TESTBED_CONFIG_SECTION,
1339 "OVERLAY_TOPOLOGY_FILE");
1340 goto error_cleanup;
1341 }
1342 goto warn_ignore;
1343
1344 case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1345 if (GNUNET_OK !=
1346 GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
1347 SCALE_FREE_CAP, &number))
1348 {
1349 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1350 TESTBED_CONFIG_SECTION,
1351 SCALE_FREE_CAP);
1352 goto error_cleanup;
1353 }
1354 if (UINT16_MAX < number)
1355 {
1356 LOG (GNUNET_ERROR_TYPE_ERROR,
1357 _ ("Maximum number of edges a peer can have in a scale free topology"
1358 " cannot be more than %u. Given `%s = %llu'"), UINT16_MAX,
1359 SCALE_FREE_CAP, number);
1360 goto error_cleanup;
1361 }
1362 if (GNUNET_OK !=
1363 GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
1364 SCALE_FREE_M, &number))
1365 {
1366 GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1367 TESTBED_CONFIG_SECTION,
1368 SCALE_FREE_M);
1369 goto error_cleanup;
1370 }
1371 if (UINT8_MAX < number)
1372 {
1373 LOG (GNUNET_ERROR_TYPE_ERROR,
1374 _ ("The number of edges that can established when adding a new node"
1375 " to scale free topology cannot be more than %u. Given `%s = %llu'"),
1376 UINT8_MAX, SCALE_FREE_M, number);
1377 goto error_cleanup;
1378 }
1379 goto warn_ignore;
1380
1381 case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
1382 /* not allowed! */
1383 GNUNET_assert (0);
1384
1385 default:
1386warn_ignore:
1387 /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */
1388 if (GNUNET_YES ==
1389 GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION,
1390 "OVERLAY_RANDOM_LINKS"))
1391 LOG (GNUNET_ERROR_TYPE_WARNING,
1392 "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n");
1393 break;
1394 }
1395 if (0 != rc->num_hosts)
1396 {
1397 rc->hclist = GNUNET_malloc (sizeof(struct CompatibilityCheckContext)
1398 * rc->num_hosts);
1399 for (nhost = 0; nhost < rc->num_hosts; nhost++)
1400 {
1401 hc = &rc->hclist[nhost];
1402 hc->index = nhost;
1403 hc->rc = rc;
1404 hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg,
1405 &host_habitable_cb, hc);
1406 if (NULL == hc->h)
1407 {
1408 GNUNET_break (0);
1409 for (nhost = 0; nhost < rc->num_hosts; nhost++)
1410 {
1411 hc = &rc->hclist[nhost];
1412 if (NULL != hc->h)
1413 GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
1414 }
1415 GNUNET_free (rc->hclist);
1416 rc->hclist = NULL;
1417 goto error_cleanup;
1418 }
1419 }
1420 }
1421 else
1422 rc->cproc =
1423 GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h,
1424 &controller_status_cb, rc);
1425 if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
1426 TESTBED_CONFIG_SECTION,
1427 "SETUP_TIMEOUT",
1428 &timeout))
1429 {
1430 timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1431 DEFAULT_SETUP_TIMEOUT);
1432 }
1433 rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256);
1434 rc->timeout_task =
1435 GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc);
1436 GNUNET_assert (NULL == rc->interrupt_task);
1437 rc->interrupt_task =
1438 GNUNET_SCHEDULER_add_shutdown (&interrupt,
1439 rc);
1440 return;
1441
1442error_cleanup:
1443 if (NULL != rc->h)
1444 GNUNET_TESTBED_host_destroy (rc->h);
1445 if (NULL != rc->hosts)
1446 {
1447 for (hid = 0; hid < rc->num_hosts; hid++)
1448 if (NULL != rc->hosts[hid])
1449 GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
1450 GNUNET_free (rc->hosts);
1451 }
1452 if (NULL != rc->cfg)
1453 GNUNET_CONFIGURATION_destroy (rc->cfg);
1454 GNUNET_free (rc);
1455}
1456
1457
1458/**
1459 * Obtain handle to the master controller from a testbed run. The handle
1460 * returned should not be disconnected.
1461 *
1462 * @param h the testbed run handle
1463 * @return handle to the master controller
1464 */
1465struct GNUNET_TESTBED_Controller *
1466GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h)
1467{
1468 return h->c;
1469}
1470
1471
1472/* end of testbed_api_testbed.c */