yapf format.
[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   /**
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  */
96 enum 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 compability checks
139  */
140 struct CompatibilityCheckContext
141 {
142   /**
143    * The run context
144    */
145   struct GNUNET_TESTBED_RunHandle *rc;
146
147   /**
148    * Handle for the compability 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  */
162 struct 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 relavant
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  */
337 static uint32_t
338 rcop_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  */
347 struct 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  */
369 static int
370 search_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  */
394 static struct RunContextOperation *
395 search_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  */
421 static void
422 insert_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  */
439 static void
440 remove_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  * Assuming all peers have been destroyed cleanup run handle
451  *
452  * @param rc the run context
453  */
454 static void
455 cleanup (struct GNUNET_TESTBED_RunHandle *rc)
456 {
457   unsigned int hid;
458
459   GNUNET_assert (NULL == rc->register_hosts_task);
460   GNUNET_assert (NULL == rc->reg_handle);
461   GNUNET_assert (NULL == rc->peers);
462   GNUNET_assert (NULL == rc->hclist);
463   GNUNET_assert (RC_PEERS_SHUTDOWN == rc->state);
464   GNUNET_assert (0 == GNUNET_CONTAINER_multihashmap32_size (rc->rcop_map));
465   GNUNET_CONTAINER_multihashmap32_destroy (rc->rcop_map);
466   if (NULL != rc->c)
467     GNUNET_TESTBED_controller_disconnect (rc->c);
468   if (NULL != rc->cproc)
469     GNUNET_TESTBED_controller_stop (rc->cproc);
470   if (NULL != rc->h)
471     GNUNET_TESTBED_host_destroy (rc->h);
472   for (hid = 0; hid < rc->num_hosts; hid++)
473     GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
474   GNUNET_free_non_null (rc->hosts);
475   if (NULL != rc->cfg)
476     GNUNET_CONFIGURATION_destroy (rc->cfg);
477   GNUNET_free_non_null (rc->topo_file);
478   GNUNET_free_non_null (rc->trusted_ip);
479   GNUNET_free (rc);
480 }
481
482
483 /**
484  * Iterator for cleaning up elements from rcop_map
485  *
486  * @param cls the RunContext
487  * @param key the 32-bit key
488  * @param value the RunContextOperation element
489  * @return always GNUNET_YES
490  */
491 static int
492 rcop_cleanup_iterator (void *cls, uint32_t key, void *value)
493 {
494   struct GNUNET_TESTBED_RunHandle *rc = cls;
495   struct RunContextOperation *rcop = value;
496
497   GNUNET_assert (rc == rcop->rc);
498   remove_rcop (rc, rcop);
499   GNUNET_TESTBED_operation_done (rcop->op);
500   GNUNET_free (rcop);
501   return GNUNET_YES;
502 }
503
504
505 /**
506  * Cancels operations and tasks which are assigned to the given run context
507  *
508  * @param rc the RunContext
509  */
510 static void
511 rc_cleanup_operations (struct GNUNET_TESTBED_RunHandle *rc)
512 {
513   struct CompatibilityCheckContext *hc;
514   unsigned int nhost;
515
516   if (NULL != rc->hclist)
517   {
518     for (nhost = 0; nhost < rc->num_hosts; nhost++)
519     {
520       hc = &rc->hclist[nhost];
521       if (NULL != hc->h)
522         GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
523     }
524     GNUNET_free (rc->hclist);
525     rc->hclist = NULL;
526   }
527   /* Stop register hosts task if it is running */
528   if (NULL != rc->register_hosts_task)
529   {
530     GNUNET_SCHEDULER_cancel (rc->register_hosts_task);
531     rc->register_hosts_task = NULL;
532   }
533   if (NULL != rc->timeout_task)
534   {
535     GNUNET_SCHEDULER_cancel (rc->timeout_task);
536     rc->timeout_task = NULL;
537   }
538   if (NULL != rc->reg_handle)
539   {
540     GNUNET_TESTBED_cancel_registration (rc->reg_handle);
541     rc->reg_handle = NULL;
542   }
543   if (NULL != rc->topology_operation)
544   {
545     GNUNET_TESTBED_operation_done (rc->topology_operation);
546     rc->topology_operation = NULL;
547   }
548   /* cancel any exiting operations */
549   GNUNET_assert (GNUNET_SYSERR !=
550                  GNUNET_CONTAINER_multihashmap32_iterate (rc->rcop_map,
551                                                           &rcop_cleanup_iterator,
552                                                           rc));
553 }
554
555
556 /**
557  * Cancels the scheduled interrupt task
558  *
559  * @param rc the run context
560  */
561 static void
562 cancel_interrupt_task (struct GNUNET_TESTBED_RunHandle *rc)
563 {
564   GNUNET_SCHEDULER_cancel (rc->interrupt_task);
565   rc->interrupt_task = NULL;
566 }
567
568
569 /**
570  * This callback will be called when all the operations are completed
571  * (done/cancelled)
572  *
573  * @param cls run context
574  */
575 static void
576 wait_op_completion (void *cls)
577 {
578   struct GNUNET_TESTBED_RunHandle *rc = cls;
579   struct RunContextOperation *rcop;
580
581   if ((NULL == rc->cproc)
582       || (NULL == rc->c)
583       || (GNUNET_YES == rc->shutdown))
584   {
585     if (NULL != rc->peers)
586     {
587       GNUNET_free (rc->peers);
588       rc->peers = NULL;
589     }
590     goto cleanup_;
591   }
592   if (NULL == rc->peers)
593     goto cleanup_;
594   rc->shutdown = GNUNET_YES;
595   rcop = GNUNET_new (struct RunContextOperation);
596   rcop->rc = rc;
597   rcop->op = GNUNET_TESTBED_shutdown_peers (rc->c, rcop, NULL, NULL);
598   GNUNET_assert (NULL != rcop->op);
599   DEBUG ("Shutting down peers\n");
600   rc->pstart_time = GNUNET_TIME_absolute_get ();
601   insert_rcop (rc, rcop);
602   return;
603
604 cleanup_:
605   rc->state = RC_PEERS_SHUTDOWN;
606   cancel_interrupt_task (rc);
607   cleanup (rc);
608 }
609
610
611 /**
612  * Task run upon interrupts (SIGINT, SIGTERM) and upon scheduler shutdown.
613  *
614  * @param cls the RunContext which has to be acted upon
615  */
616 static void
617 interrupt (void *cls)
618 {
619   struct GNUNET_TESTBED_RunHandle *rc = cls;
620   struct GNUNET_TESTBED_Controller *c = rc->c;
621   unsigned int size;
622
623   /* reschedule */
624   rc->interrupt_task = GNUNET_SCHEDULER_add_shutdown (&interrupt, rc);
625   rc_cleanup_operations (rc);
626   if ((GNUNET_NO == rc->shutdown) &&
627       (NULL != c) &&
628       (NULL != c->opc_map) &&
629       (0 != (size = GNUNET_CONTAINER_multihashmap32_size (c->opc_map))))
630   {
631     LOG (GNUNET_ERROR_TYPE_WARNING,
632          "Shutdown postponed as there are %u operations currently active\n",
633          size);
634     c->opcq_empty_cb = &wait_op_completion;
635     c->opcq_empty_cls = rc;
636     return;
637   }
638   wait_op_completion (rc);
639 }
640
641
642 /**
643  * Function to return the string representation of the duration between current
644  * time and `pstart_time' in `RunContext'
645  *
646  * @param rc the RunContext
647  * @return the representation string; this is NOT reentrant
648  */
649 static const char *
650 prof_time (struct GNUNET_TESTBED_RunHandle *rc)
651 {
652   struct GNUNET_TIME_Relative ptime;
653
654   ptime = GNUNET_TIME_absolute_get_duration (rc->pstart_time);
655   return GNUNET_STRINGS_relative_time_to_string (ptime, GNUNET_YES);
656 }
657
658
659 /**
660  * Task for starting peers
661  *
662  * @param cls the RunHandle
663  */
664 static void
665 start_peers_task (void *cls)
666 {
667   struct GNUNET_TESTBED_RunHandle *rc = cls;
668   struct RunContextOperation *rcop;
669   unsigned int peer;
670
671   DEBUG ("Starting Peers\n");
672   rc->pstart_time = GNUNET_TIME_absolute_get ();
673   for (peer = 0; peer < rc->num_peers; peer++)
674   {
675     rcop = GNUNET_new (struct RunContextOperation);
676     rcop->rc = rc;
677     rcop->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL);
678     GNUNET_assert (NULL != rcop->op);
679     rcop->cls = rc->peers[peer];
680     insert_rcop (rc, rcop);
681   }
682   rc->peer_count = 0;
683 }
684
685
686 /**
687  * Functions of this signature are called when a peer has been successfully
688  * created
689  *
690  * @param cls the closure from GNUNET_TESTBED_peer_create()
691  * @param peer the handle for the created peer; NULL on any error during
692  *          creation
693  * @param emsg NULL if peer is not NULL; else MAY contain the error description
694  */
695 static void
696 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
697 {
698   struct RunContextOperation *rcop = cls;
699   struct GNUNET_TESTBED_RunHandle *rc;
700
701   GNUNET_assert (NULL != rcop);
702   GNUNET_assert (NULL != (rc = rcop->rc));
703   remove_rcop (rc, rcop);
704   GNUNET_TESTBED_operation_done (rcop->op);
705   GNUNET_free (rcop);
706   if (NULL == peer)
707   {
708     if (NULL != emsg)
709       LOG (GNUNET_ERROR_TYPE_ERROR, "Error while creating a peer: %s\n",
710            emsg);
711     GNUNET_SCHEDULER_shutdown ();
712     return;
713   }
714   rc->peers[rc->peer_count] = peer;
715   rc->peer_count++;
716   if (rc->peer_count < rc->num_peers)
717     return;
718   DEBUG ("%u peers created in %s\n", rc->num_peers, prof_time (rc));
719   rc->state = RC_PEERS_CREATED;
720   GNUNET_SCHEDULER_add_now (&start_peers_task, rc);
721 }
722
723
724 /**
725  * call test master callback
726  *
727  * @param rc the RunContext
728  */
729 static void
730 call_master (struct GNUNET_TESTBED_RunHandle *rc)
731 {
732   GNUNET_SCHEDULER_cancel (rc->timeout_task);
733   rc->timeout_task = NULL;
734   if (NULL != rc->test_master)
735     rc->test_master (rc->test_master_cls, rc, rc->num_peers, rc->peers,
736                      rc->links_succeeded, rc->links_failed);
737 }
738
739
740 /**
741  * Callbacks of this type are called when topology configuration is completed
742  *
743  * @param cls the operation closure given to
744  *          GNUNET_TESTBED_overlay_configure_topology_va() and
745  *          GNUNET_TESTBED_overlay_configure() calls
746  * @param nsuccess the number of successful overlay connects
747  * @param nfailures the number of overlay connects which failed
748  */
749 static void
750 topology_completion_callback (void *cls, unsigned int nsuccess,
751                               unsigned int nfailures)
752 {
753   struct GNUNET_TESTBED_RunHandle *rc = cls;
754
755   DEBUG ("Overlay topology generated in %s\n", prof_time (rc));
756   GNUNET_TESTBED_operation_done (rc->topology_operation);
757   rc->topology_operation = NULL;
758   rc->links_succeeded = nsuccess;
759   rc->links_failed = nfailures;
760   rc->state = RC_READY;
761   call_master (rc);
762 }
763
764
765 /**
766  * Function to create peers
767  *
768  * @param rc the RunContext
769  */
770 static void
771 create_peers (struct GNUNET_TESTBED_RunHandle *rc)
772 {
773   struct RunContextOperation *rcop;
774   unsigned int peer;
775
776   DEBUG ("Creating peers\n");
777   rc->pstart_time = GNUNET_TIME_absolute_get ();
778   rc->peers =
779     GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Peer *) * rc->num_peers);
780   GNUNET_assert (NULL != rc->c);
781   rc->peer_count = 0;
782   for (peer = 0; peer < rc->num_peers; peer++)
783   {
784     rcop = GNUNET_new (struct RunContextOperation);
785     rcop->rc = rc;
786     rcop->op =
787       GNUNET_TESTBED_peer_create (rc->c,
788                                   (0 ==
789                                    rc->num_hosts) ? rc->h : rc->hosts[peer
790                                                                       % rc->
791                                                                       num_hosts],
792                                   rc->cfg, &peer_create_cb, rcop);
793     GNUNET_assert (NULL != rcop->op);
794     insert_rcop (rc, rcop);
795   }
796 }
797
798
799 /**
800  * Signature of the event handler function called by the
801  * respective event controller.
802  *
803  * @param cls closure
804  * @param event information about the event
805  */
806 static void
807 event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
808 {
809   struct GNUNET_TESTBED_RunHandle *rc = cls;
810   struct RunContextOperation *rcop;
811
812   if (RC_INIT == rc->state)
813   {
814     switch (event->type)
815     {
816     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
817       rcop = event->op_cls;
818       if (NULL != event->details.operation_finished.emsg)
819       {
820         LOG (GNUNET_ERROR_TYPE_ERROR, _ (
821                "Linking controllers failed. Exiting"));
822         GNUNET_SCHEDULER_shutdown ();
823       }
824       else
825         rc->reg_hosts++;
826       GNUNET_assert (event->op == rcop->op);
827       remove_rcop (rc, rcop);
828       GNUNET_TESTBED_operation_done (rcop->op);
829       GNUNET_free (rcop);
830       if (rc->reg_hosts == rc->num_hosts)
831       {
832         rc->state = RC_LINKED;
833         create_peers (rc);
834       }
835       return;
836
837     default:
838       GNUNET_break (0);
839       GNUNET_SCHEDULER_shutdown ();
840       return;
841     }
842   }
843   if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type)
844     goto call_cc;
845   if (NULL == (rcop = search_rcop (rc, event->op)))
846     goto call_cc;
847   remove_rcop (rc, rcop);
848   GNUNET_TESTBED_operation_done (rcop->op);
849   GNUNET_free (rcop);
850   if ((GNUNET_NO == rc->shutdown)
851       && (NULL != event->details.operation_finished.emsg))
852   {
853     LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n",
854          event->details.operation_finished.emsg);
855     GNUNET_SCHEDULER_shutdown ();
856     return;
857   }
858   GNUNET_assert (GNUNET_YES == rc->shutdown);
859   switch (rc->state)
860   {
861   case RC_LINKED:
862   case RC_PEERS_CREATED:
863   case RC_READY:
864     rc->state = RC_PEERS_SHUTDOWN;
865     GNUNET_free_non_null (rc->peers);
866     rc->peers = NULL;
867     DEBUG ("Peers shut down in %s\n", prof_time (rc));
868     GNUNET_SCHEDULER_shutdown ();
869     break;
870
871   default:
872     GNUNET_assert (0);
873   }
874   return;
875
876 call_cc:
877   if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc))
878     rc->cc (rc->cc_cls, event);
879   if (GNUNET_TESTBED_ET_PEER_START != event->type)
880     return;
881   if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */
882     return;
883   remove_rcop (rc, rcop);
884   GNUNET_TESTBED_operation_done (rcop->op);
885   GNUNET_free (rcop);
886   rc->peer_count++;
887   if (rc->peer_count < rc->num_peers)
888     return;
889   DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc));
890   if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology)
891   {
892     switch (rc->topology)
893     {
894     case GNUNET_TESTBED_TOPOLOGY_NONE:
895       GNUNET_assert (0);
896
897     case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
898     case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
899     case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
900       rc->topology_operation =
901         GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
902                                                    rc->peers, &rc->num_oc,
903                                                    &topology_completion_callback,
904                                                    rc,
905                                                    rc->topology,
906                                                    rc->random_links,
907                                                    GNUNET_TESTBED_TOPOLOGY_OPTION_END);
908       break;
909
910     case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
911       GNUNET_assert (NULL != rc->topo_file);
912       rc->topology_operation =
913         GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
914                                                    rc->peers, &rc->num_oc,
915                                                    &topology_completion_callback,
916                                                    rc,
917                                                    rc->topology,
918                                                    rc->topo_file,
919                                                    GNUNET_TESTBED_TOPOLOGY_OPTION_END);
920       break;
921
922     case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
923       {
924         unsigned long long number;
925         unsigned int cap;
926         GNUNET_assert (GNUNET_OK ==
927                        GNUNET_CONFIGURATION_get_value_number (rc->cfg,
928                                                               TESTBED_CONFIG_SECTION,
929                                                               SCALE_FREE_CAP,
930                                                               &number));
931         cap = (unsigned int) number;
932         GNUNET_assert (GNUNET_OK ==
933                        GNUNET_CONFIGURATION_get_value_number (rc->cfg,
934                                                               TESTBED_CONFIG_SECTION,
935                                                               SCALE_FREE_M,
936                                                               &number));
937         rc->topology_operation =
938           GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
939                                                      rc->peers, &rc->num_oc,
940                                                      &
941                                                      topology_completion_callback,
942                                                      rc,
943                                                      rc->topology,
944                                                      cap,      /* uint16_t */
945                                                      (unsigned int) number,   /* uint8_t */
946                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
947       }
948       break;
949
950     default:
951       rc->topology_operation =
952         GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
953                                                    rc->peers, &rc->num_oc,
954                                                    &topology_completion_callback,
955                                                    rc,
956                                                    rc->topology,
957                                                    GNUNET_TESTBED_TOPOLOGY_OPTION_END);
958     }
959     if (NULL == rc->topology_operation)
960       LOG (GNUNET_ERROR_TYPE_WARNING,
961            "Not generating a topology. Check number of peers\n");
962     else
963     {
964       DEBUG ("Creating overlay topology\n");
965       rc->pstart_time = GNUNET_TIME_absolute_get ();
966       return;
967     }
968   }
969   rc->state = RC_READY;
970   call_master (rc);
971 }
972
973
974 /**
975  * Task to register all hosts available in the global host list
976  *
977  * @param cls the RunContext
978  */
979 static void
980 register_hosts (void *cls);
981
982
983 /**
984  * Callback which will be called to after a host registration succeeded or failed
985  *
986  * @param cls the closure
987  * @param emsg the error message; NULL if host registration is successful
988  */
989 static void
990 host_registration_completion (void *cls, const char *emsg)
991 {
992   struct GNUNET_TESTBED_RunHandle *rc = cls;
993
994   rc->reg_handle = NULL;
995   if (NULL != emsg)
996   {
997     LOG (GNUNET_ERROR_TYPE_WARNING,
998          _ ("Host registration failed for a host. Error: %s\n"), emsg);
999     GNUNET_SCHEDULER_shutdown ();
1000     return;
1001   }
1002   rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts,
1003                                                       rc);
1004 }
1005
1006
1007 /**
1008  * Task to register all hosts available in the global host list
1009  *
1010  * @param cls RunContext
1011  */
1012 static void
1013 register_hosts (void *cls)
1014 {
1015   struct GNUNET_TESTBED_RunHandle *rc = cls;
1016   struct RunContextOperation *rcop;
1017   unsigned int slave;
1018
1019   rc->register_hosts_task = NULL;
1020   if (rc->reg_hosts == rc->num_hosts)
1021   {
1022     DEBUG ("All hosts successfully registered\n");
1023     /* Start slaves */
1024     for (slave = 0; slave < rc->num_hosts; slave++)
1025     {
1026       rcop = GNUNET_new (struct RunContextOperation);
1027       rcop->rc = rc;
1028       rcop->op =
1029         GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[slave],
1030                                         rc->h, GNUNET_YES);
1031       GNUNET_assert (NULL != rcop->op);
1032       insert_rcop (rc, rcop);
1033     }
1034     rc->reg_hosts = 0;
1035     return;
1036   }
1037   rc->reg_handle =
1038     GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts],
1039                                   host_registration_completion, rc);
1040   rc->reg_hosts++;
1041 }
1042
1043
1044 /**
1045  * Callback to signal successfull startup of the controller process
1046  *
1047  * @param cls the closure from GNUNET_TESTBED_controller_start()
1048  * @param cfg the configuration with which the controller has been started;
1049  *          NULL if status is not GNUNET_OK
1050  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
1051  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1052  */
1053 static void
1054 controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1055                       int status)
1056 {
1057   struct GNUNET_TESTBED_RunHandle *rc = cls;
1058   uint64_t event_mask;
1059
1060   if (status != GNUNET_OK)
1061   {
1062     rc->cproc = NULL;
1063     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1064                 _ ("Controller crash detected. Shutting down.\n"));
1065     GNUNET_SCHEDULER_shutdown ();
1066     return;
1067   }
1068   GNUNET_CONFIGURATION_destroy (rc->cfg);
1069   rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1070   event_mask = rc->event_mask;
1071   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1072   event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
1073   if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE)
1074     event_mask |= GNUNET_TESTBED_ET_CONNECT;
1075   rc->c =
1076     GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc);
1077   if (0 < rc->num_hosts)
1078   {
1079     rc->reg_hosts = 0;
1080     rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
1081     return;
1082   }
1083   rc->state = RC_LINKED;
1084   create_peers (rc);
1085 }
1086
1087
1088 /**
1089  * Callback function invoked for each interface found.
1090  *
1091  * @param cls closure
1092  * @param name name of the interface (can be NULL for unknown)
1093  * @param isDefault is this presumably the default interface
1094  * @param addr address of this interface (can be NULL for unknown or unassigned)
1095  * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
1096  * @param netmask the network mask (can be NULL for unknown or unassigned))
1097  * @param addrlen length of the address
1098  * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
1099  */
1100 static int
1101 netint_proc (void *cls, const char *name, int isDefault,
1102              const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
1103              const struct sockaddr *netmask, socklen_t addrlen)
1104 {
1105   struct GNUNET_TESTBED_RunHandle *rc = cls;
1106   char hostip[NI_MAXHOST];
1107   char *buf;
1108
1109   if (sizeof(struct sockaddr_in) != addrlen)
1110     return GNUNET_OK;           /* Only consider IPv4 for now */
1111   if (0 !=
1112       getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))
1113     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo");
1114   if (NULL == rc->trusted_ip)
1115   {
1116     rc->trusted_ip = GNUNET_strdup (hostip);
1117     return GNUNET_YES;
1118   }
1119   (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip);
1120   GNUNET_free (rc->trusted_ip);
1121   rc->trusted_ip = buf;
1122   return GNUNET_YES;
1123 }
1124
1125
1126 /**
1127  * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
1128  * inform whether the given host is habitable or not. The Handle returned by
1129  * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
1130  *
1131  * @param cls NULL
1132  * @param host the host whose status is being reported; will be NULL if the host
1133  *          given to GNUNET_TESTBED_is_host_habitable() is NULL
1134  * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
1135  */
1136 static void
1137 host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host,
1138                    int status)
1139 {
1140   struct CompatibilityCheckContext *hc = cls;
1141   struct GNUNET_TESTBED_RunHandle *rc;
1142   struct GNUNET_TESTBED_Host **old_hosts;
1143   unsigned int nhost;
1144
1145   GNUNET_assert (NULL != (rc = hc->rc));
1146   nhost = hc->index;
1147   GNUNET_assert (nhost <= rc->num_hosts);
1148   GNUNET_assert (host == rc->hosts[nhost]);
1149   hc->h = NULL;
1150   if (GNUNET_NO == status)
1151   {
1152     if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host)))
1153       LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Host %s cannot start testbed\n"),
1154            GNUNET_TESTBED_host_get_hostname (host));
1155     else
1156       LOG (GNUNET_ERROR_TYPE_ERROR,
1157            _ ("Testbed cannot be started on localhost\n"));
1158     GNUNET_SCHEDULER_shutdown ();
1159     return;
1160   }
1161   rc->reg_hosts++;
1162   if (rc->reg_hosts < rc->num_hosts)
1163     return;
1164   GNUNET_free (rc->hclist);
1165   rc->hclist = NULL;
1166   rc->h = rc->hosts[0];
1167   rc->num_hosts--;
1168   if (0 < rc->num_hosts)
1169   {
1170     old_hosts = rc->hosts;
1171     rc->hosts =
1172       GNUNET_malloc (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts);
1173     GNUNET_memcpy (rc->hosts, &old_hosts[1],
1174                    (sizeof(struct GNUNET_TESTBED_Host *) * rc->num_hosts));
1175     GNUNET_free (old_hosts);
1176   }
1177   else
1178   {
1179     GNUNET_free (rc->hosts);
1180     rc->hosts = NULL;
1181   }
1182   GNUNET_TESTBED_host_resolve_ (rc->h);
1183   for (nhost = 0; nhost < rc->num_hosts; nhost++)
1184     GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]);
1185   GNUNET_OS_network_interfaces_list (netint_proc, rc);
1186   if (NULL == rc->trusted_ip)
1187     rc->trusted_ip = GNUNET_strdup ("127.0.0.1");
1188   rc->cproc =
1189     GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h,
1190                                      &controller_status_cb, rc);
1191   GNUNET_free (rc->trusted_ip);
1192   rc->trusted_ip = NULL;
1193   if (NULL == rc->cproc)
1194   {
1195     LOG (GNUNET_ERROR_TYPE_ERROR, _ ("Cannot start the master controller"));
1196     GNUNET_SCHEDULER_shutdown ();
1197   }
1198 }
1199
1200
1201 /**
1202  * Task run upon timeout while setting up the testbed
1203  *
1204  * @param cls the RunContext
1205  */
1206 static void
1207 timeout_task (void *cls)
1208 {
1209   struct GNUNET_TESTBED_RunHandle *rc = cls;
1210
1211   rc->timeout_task = NULL;
1212   LOG (GNUNET_ERROR_TYPE_ERROR,
1213        _ ("Shutting down testbed due to timeout while setup.\n"));
1214   GNUNET_SCHEDULER_shutdown ();
1215   if (NULL != rc->test_master)
1216     rc->test_master (rc->test_master_cls, rc, 0, NULL, 0, 0);
1217   rc->test_master = NULL;
1218 }
1219
1220
1221 /**
1222  * Convenience method for running a testbed with
1223  * a single call.  Underlay and overlay topology
1224  * are configured using the "UNDERLAY" and "OVERLAY"
1225  * options in the "[testbed]" section of the configuration\
1226  * (with possible options given in "UNDERLAY_XXX" and/or
1227  * "OVERLAY_XXX").
1228  *
1229  * The testbed is to be terminated using a call to
1230  * "GNUNET_SCHEDULER_shutdown".
1231  *
1232  * @param host_filename name of the file with the 'hosts', NULL
1233  *        to run everything on 'localhost'
1234  * @param cfg configuration to use (for testbed, controller and peers)
1235  * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg?
1236  * @param event_mask bit mask with set of events to call 'cc' for;
1237  *                   or-ed values of "1LL" shifted by the
1238  *                   respective 'enum GNUNET_TESTBED_EventType'
1239  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
1240  * @param cc controller callback to invoke on events; This callback is called
1241  *          for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't
1242  *          set in the event_mask as this is the only way get access to the
1243  *          handle of each peer
1244  * @param cc_cls closure for cc
1245  * @param test_master this callback will be called once the test is ready
1246  * @param test_master_cls closure for 'test_master'.
1247  */
1248 void
1249 GNUNET_TESTBED_run (const char *host_filename,
1250                     const struct GNUNET_CONFIGURATION_Handle *cfg,
1251                     unsigned int num_peers, uint64_t event_mask,
1252                     GNUNET_TESTBED_ControllerCallback cc, void *cc_cls,
1253                     GNUNET_TESTBED_TestMaster test_master,
1254                     void *test_master_cls)
1255 {
1256   struct GNUNET_TESTBED_RunHandle *rc;
1257   char *topology;
1258   struct CompatibilityCheckContext *hc;
1259   struct GNUNET_TIME_Relative timeout;
1260   unsigned long long number;
1261   unsigned int hid;
1262   unsigned int nhost;
1263
1264   GNUNET_assert (num_peers > 0);
1265   rc = GNUNET_new (struct GNUNET_TESTBED_RunHandle);
1266   rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1267 #if ENABLE_SUPERMUC
1268   rc->num_hosts = GNUNET_TESTBED_hosts_load_from_loadleveler (rc->cfg,
1269                                                               &rc->hosts);
1270   if (0 == rc->num_hosts)
1271   {
1272     LOG (GNUNET_ERROR_TYPE_WARNING,
1273          _ ("No hosts loaded from LoadLeveler. Need at least one host\n"));
1274     goto error_cleanup;
1275   }
1276 #else
1277   if (NULL != host_filename)
1278   {
1279     rc->num_hosts =
1280       GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg,
1281                                            &rc->hosts);
1282     if (0 == rc->num_hosts)
1283     {
1284       LOG (GNUNET_ERROR_TYPE_WARNING,
1285            _ ("No hosts loaded. Need at least one host\n"));
1286       goto error_cleanup;
1287     }
1288   }
1289   else
1290     rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0);
1291 #endif
1292   rc->num_peers = num_peers;
1293   rc->event_mask = event_mask;
1294   rc->cc = cc;
1295   rc->cc_cls = cc_cls;
1296   rc->test_master = test_master;
1297   rc->test_master_cls = test_master_cls;
1298   rc->state = RC_INIT;
1299   rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE;
1300   if (GNUNET_OK ==
1301       GNUNET_CONFIGURATION_get_value_string (rc->cfg, TESTBED_CONFIG_SECTION,
1302                                              "OVERLAY_TOPOLOGY", &topology))
1303   {
1304     if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology))
1305     {
1306       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1307                                  TESTBED_CONFIG_SECTION,
1308                                  "OVERLAY_TOPLOGY",
1309                                  _
1310                                  (
1311                                    "Specified topology must be supported by testbed"));
1312     }
1313     GNUNET_free (topology);
1314   }
1315   switch (rc->topology)
1316   {
1317   case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1318   case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1319   case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1320     if (GNUNET_OK !=
1321         GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
1322                                                "OVERLAY_RANDOM_LINKS",
1323                                                &number))
1324     {
1325       /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS
1326        * option to be set to the number of random links to be established  */
1327       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1328                                  TESTBED_CONFIG_SECTION,
1329                                  "OVERLAY_RANDOM_LINKS");
1330       goto error_cleanup;
1331     }
1332     if (number > UINT32_MAX)
1333     {
1334       GNUNET_break (0);         /* Too big number */
1335       goto error_cleanup;
1336     }
1337     rc->random_links = (unsigned int) number;
1338     break;
1339
1340   case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1341     if (GNUNET_OK !=
1342         GNUNET_CONFIGURATION_get_value_filename (rc->cfg,
1343                                                  TESTBED_CONFIG_SECTION,
1344                                                  "OVERLAY_TOPOLOGY_FILE",
1345                                                  &rc->topo_file))
1346     {
1347       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1348                                  TESTBED_CONFIG_SECTION,
1349                                  "OVERLAY_TOPOLOGY_FILE");
1350       goto error_cleanup;
1351     }
1352     goto warn_ignore;
1353
1354   case GNUNET_TESTBED_TOPOLOGY_SCALE_FREE:
1355     if (GNUNET_OK !=
1356         GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
1357                                                SCALE_FREE_CAP, &number))
1358     {
1359       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1360                                  TESTBED_CONFIG_SECTION,
1361                                  SCALE_FREE_CAP);
1362       goto error_cleanup;
1363     }
1364     if (UINT16_MAX < number)
1365     {
1366       LOG (GNUNET_ERROR_TYPE_ERROR,
1367            _ ("Maximum number of edges a peer can have in a scale free topology"
1368               " cannot be more than %u.  Given `%s = %llu'"), UINT16_MAX,
1369            SCALE_FREE_CAP, number);
1370       goto error_cleanup;
1371     }
1372     if (GNUNET_OK !=
1373         GNUNET_CONFIGURATION_get_value_number (rc->cfg, TESTBED_CONFIG_SECTION,
1374                                                SCALE_FREE_M, &number))
1375     {
1376       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1377                                  TESTBED_CONFIG_SECTION,
1378                                  SCALE_FREE_M);
1379       goto error_cleanup;
1380     }
1381     if (UINT8_MAX < number)
1382     {
1383       LOG (GNUNET_ERROR_TYPE_ERROR,
1384            _ ("The number of edges that can established when adding a new node"
1385               " to scale free topology cannot be more than %u.  Given `%s = %llu'"),
1386            UINT8_MAX, SCALE_FREE_M, number);
1387       goto error_cleanup;
1388     }
1389     goto warn_ignore;
1390
1391   case GNUNET_TESTBED_TOPOLOGY_OPTION_END:
1392     /* not allowed! */
1393     GNUNET_assert (0);
1394
1395   default:
1396 warn_ignore:
1397     /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */
1398     if (GNUNET_YES ==
1399         GNUNET_CONFIGURATION_have_value (rc->cfg, TESTBED_CONFIG_SECTION,
1400                                          "OVERLAY_RANDOM_LINKS"))
1401       LOG (GNUNET_ERROR_TYPE_WARNING,
1402            "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n");
1403     break;
1404   }
1405   if (0 != rc->num_hosts)
1406   {
1407     rc->hclist = GNUNET_malloc (sizeof(struct CompatibilityCheckContext)
1408                                 * rc->num_hosts);
1409     for (nhost = 0; nhost < rc->num_hosts; nhost++)
1410     {
1411       hc = &rc->hclist[nhost];
1412       hc->index = nhost;
1413       hc->rc = rc;
1414       hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg,
1415                                                 &host_habitable_cb, hc);
1416       if (NULL == hc->h)
1417       {
1418         GNUNET_break (0);
1419         for (nhost = 0; nhost < rc->num_hosts; nhost++)
1420         {
1421           hc = &rc->hclist[nhost];
1422           if (NULL != hc->h)
1423             GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
1424         }
1425         GNUNET_free (rc->hclist);
1426         rc->hclist = NULL;
1427         goto error_cleanup;
1428       }
1429     }
1430   }
1431   else
1432     rc->cproc =
1433       GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h,
1434                                        &controller_status_cb, rc);
1435   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg,
1436                                                         TESTBED_CONFIG_SECTION,
1437                                                         "SETUP_TIMEOUT",
1438                                                         &timeout))
1439   {
1440     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1441                                              DEFAULT_SETUP_TIMEOUT);
1442   }
1443   rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256);
1444   rc->timeout_task =
1445     GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc);
1446   GNUNET_assert (NULL == rc->interrupt_task);
1447   rc->interrupt_task =
1448     GNUNET_SCHEDULER_add_shutdown (&interrupt,
1449                                    rc);
1450   return;
1451
1452 error_cleanup:
1453   if (NULL != rc->h)
1454     GNUNET_TESTBED_host_destroy (rc->h);
1455   if (NULL != rc->hosts)
1456   {
1457     for (hid = 0; hid < rc->num_hosts; hid++)
1458       if (NULL != rc->hosts[hid])
1459         GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
1460     GNUNET_free (rc->hosts);
1461   }
1462   if (NULL != rc->cfg)
1463     GNUNET_CONFIGURATION_destroy (rc->cfg);
1464   GNUNET_free (rc);
1465 }
1466
1467
1468 /**
1469  * Obtain handle to the master controller from a testbed run.  The handle
1470  * returned should not be disconnected.
1471  *
1472  * @param h the testbed run handle
1473  * @return handle to the master controller
1474  */
1475 struct GNUNET_TESTBED_Controller *
1476 GNUNET_TESTBED_run_get_controller_handle (struct GNUNET_TESTBED_RunHandle *h)
1477 {
1478   return h->c;
1479 }
1480
1481
1482 /* end of testbed_api_testbed.c */