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