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