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