- do not create peers on the island controller
[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   struct GNUNET_TESTBED_Host *host;
819   unsigned int peer;
820 #if ENABLE_LL
821   struct Island *island;
822   unsigned int icnt;
823   unsigned int hcnt;
824
825   island = NULL;
826   icnt = 0;
827   hcnt = 0;
828 #endif
829   DEBUG ("Creating peers\n");
830   rc->pstart_time = GNUNET_TIME_absolute_get ();
831   rc->peers =
832       GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers);
833   GNUNET_assert (NULL != rc->c);
834   rc->peer_count = 0;
835   for (peer = 0; peer < rc->num_peers; peer++)
836   {
837     rcop = GNUNET_malloc (sizeof (struct RunContextOperation));
838     rcop->rc = rc;
839 #if ENABLE_LL
840     if (0 != rc->nislands)
841     {
842       island = rc->islands[icnt];      
843       if (hcnt == island->nhosts)
844       {
845         icnt++;
846         if (icnt == rc->nislands)
847           icnt = 0;
848         island = rc->islands[icnt];
849         hcnt = 0;
850       }
851       if ( (0 == hcnt) && (1 < island->nhosts) )
852         hcnt = 1;
853       GNUNET_assert (icnt < rc->nislands);
854       GNUNET_assert (hcnt < island->nhosts);
855       GNUNET_assert (NULL != island->hosts[hcnt]);
856       host = island->hosts[hcnt];
857       hcnt++;
858     }
859     else
860       host = rc->h;
861 #else
862     host = (0 == rc->num_hosts) ? rc->h : rc->hosts[peer % rc->num_hosts];
863 #endif
864     rcop->op = GNUNET_TESTBED_peer_create (rc->c, host, rc->cfg,
865                                            &peer_create_cb, rcop);
866     GNUNET_assert (NULL != rcop->op);
867     insert_rcop (rc, rcop);
868   }
869 }
870
871
872 /**
873  * Signature of the event handler function called by the
874  * respective event controller.
875  *
876  * @param cls closure
877  * @param event information about the event
878  */
879 static void
880 event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
881 {
882   struct RunContext *rc = cls;
883   struct RunContextOperation *rcop;
884
885   if (RC_INIT == rc->state)
886   {
887     switch (event->type)
888     {
889     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
890       rcop = event->op_cls;
891       if (NULL != event->details.operation_finished.emsg)
892       {
893         LOG (GNUNET_ERROR_TYPE_ERROR, _("Linking controllers failed. Exiting"));
894         shutdown_now (rc);
895       }
896       else
897         rc->reg_hosts++;
898       GNUNET_assert (event->op == rcop->op);
899       remove_rcop (rc, rcop);
900       GNUNET_TESTBED_operation_done (rcop->op);
901       GNUNET_free (rcop);
902 #if !ENABLE_LL
903       if (rc->reg_hosts != rc->num_hosts)
904         return;
905       rc->state = RC_LINKED;
906       create_peers (rc);
907 #else
908       if (rc->reg_hosts != rc->nislands)
909         return;
910       struct Island *island;
911       struct GNUNET_TESTBED_Host *host;
912       unsigned int cnt;
913       unsigned int cnt2;
914       rc->state = RC_ISLANDS_LINKED;
915       rc->reg_hosts = 0;
916       for (cnt = 0; cnt < rc->nislands; cnt++)
917       {
918         island = rc->islands[cnt];
919         for (cnt2 = 1; cnt2 < island->nhosts; cnt2++)
920         {
921           host = island->hosts[cnt2];
922           rcop = GNUNET_malloc (sizeof (struct RunContextOperation));
923           rcop->rc = rc;
924           rcop->op =
925                 GNUNET_TESTBED_controller_link (rcop, rc->c, host,
926                                                 island->hosts[0], GNUNET_YES);
927           GNUNET_assert (NULL != rcop->op);
928           insert_rcop (rc, rcop);
929           rc->reg_hosts++;
930         }
931       }
932       if (0 != rc->reg_hosts)
933         return;      
934       rc->state = RC_LINKED;
935       create_peers (rc);
936 #endif
937       return;
938     default:
939       GNUNET_break (0);
940       shutdown_now (rc);
941       return;
942     }
943   }
944 #if ENABLE_LL
945   if (RC_ISLANDS_LINKED == rc->state)
946   {
947     switch (event->type)
948     {
949     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
950       rcop = event->op_cls;
951       if (NULL != event->details.operation_finished.emsg)
952       {
953         LOG (GNUNET_ERROR_TYPE_ERROR,
954              "Linking 2nd level controllers failed. Exiting");
955         shutdown_now (rc);
956       }
957       else
958         rc->reg_hosts--;
959       GNUNET_assert (event->op == rcop->op);
960       remove_rcop (rc, rcop);
961       GNUNET_TESTBED_operation_done (rcop->op);
962       GNUNET_free (rcop);
963       if (0 != rc->reg_hosts)
964         return;
965       rc->state = RC_LINKED;
966       create_peers (rc);
967       return;
968     default:
969       GNUNET_break (0);
970       shutdown_now (rc);
971       return;
972     }
973   }
974 #endif
975   if (GNUNET_TESTBED_ET_OPERATION_FINISHED != event->type)
976     goto call_cc;
977   if (NULL == (rcop = search_rcop (rc, event->op)))
978     goto call_cc;
979   remove_rcop (rc, rcop);
980   GNUNET_TESTBED_operation_done (rcop->op);
981   GNUNET_free (rcop);
982   if ( (GNUNET_NO == rc->shutdown)
983        && (NULL != event->details.operation_finished.emsg) )
984   {
985     LOG (GNUNET_ERROR_TYPE_ERROR, "A operation has failed with error: %s\n",
986          event->details.operation_finished.emsg);
987     shutdown_now (rc);
988     return;
989   }
990   GNUNET_assert (GNUNET_YES == rc->shutdown);
991   switch (rc->state)
992   {
993   case RC_LINKED:
994   case RC_PEERS_CREATED:
995   case RC_READY:
996     rc->state = RC_PEERS_SHUTDOWN;
997     GNUNET_free_non_null (rc->peers);
998     rc->peers = NULL;
999     DEBUG ("Peers shut down in %s\n", prof_time (rc));
1000     GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
1001     break;
1002   default:
1003     GNUNET_assert (0);
1004   }
1005   return;
1006
1007 call_cc:
1008   if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc))
1009     rc->cc (rc->cc_cls, event);
1010   if (GNUNET_TESTBED_ET_PEER_START != event->type)
1011     return;
1012   if (NULL == (rcop = search_rcop (rc, event->op))) /* Not our operation */
1013     return;
1014   remove_rcop (rc, rcop);
1015   GNUNET_TESTBED_operation_done (rcop->op);
1016   GNUNET_free (rcop);
1017   rc->peer_count++;
1018   if (rc->peer_count < rc->num_peers)
1019     return;
1020   DEBUG ("%u peers started in %s\n", rc->num_peers, prof_time (rc));
1021   if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology)
1022   {
1023     if ((GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI == rc->topology) ||
1024         (GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING == rc->topology) ||
1025         (GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD == rc->topology))
1026     {
1027       rc->topology_operation =
1028           GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
1029                                                      rc->peers, &rc->num_oc,
1030                                                      &topology_completion_callback,
1031                                                      rc,
1032                                                      rc->topology,
1033                                                      rc->random_links,
1034                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1035     }
1036     else if (GNUNET_TESTBED_TOPOLOGY_FROM_FILE == rc->topology)
1037     {
1038       GNUNET_assert (NULL != rc->topo_file);
1039       rc->topology_operation =
1040           GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
1041                                                      rc->peers, &rc->num_oc,
1042                                                      &topology_completion_callback,
1043                                                      rc,
1044                                                      rc->topology,
1045                                                      rc->topo_file,
1046                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1047     }
1048     else
1049       rc->topology_operation =
1050           GNUNET_TESTBED_overlay_configure_topology (NULL, rc->num_peers,
1051                                                      rc->peers, &rc->num_oc,
1052                                                      &topology_completion_callback,
1053                                                      rc,
1054                                                      rc->topology,
1055                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
1056     if (NULL == rc->topology_operation)
1057       LOG (GNUNET_ERROR_TYPE_WARNING,
1058            "Not generating topology. Check number of peers\n");
1059     else
1060     {
1061       DEBUG ("Creating overlay topology\n");
1062       rc->pstart_time = GNUNET_TIME_absolute_get ();
1063       return;
1064     }
1065   }
1066   rc->state = RC_READY;
1067   call_master (rc);
1068 }
1069
1070
1071 /**
1072  * Task to register all hosts available in the global host list
1073  *
1074  * @param cls the RunContext
1075  * @param tc the scheduler task context
1076  */
1077 static void
1078 register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
1079
1080
1081 /**
1082  * Callback which will be called to after a host registration succeeded or failed
1083  *
1084  * @param cls the closure
1085  * @param emsg the error message; NULL if host registration is successful
1086  */
1087 static void
1088 host_registration_completion (void *cls, const char *emsg)
1089 {
1090   struct RunContext *rc = cls;
1091
1092   rc->reg_handle = NULL;
1093   if (NULL != emsg)
1094   {
1095     LOG (GNUNET_ERROR_TYPE_WARNING,
1096          _("Host registration failed for a host. Error: %s\n"), emsg);
1097     shutdown_now (rc);
1098     return;
1099   }
1100   rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
1101 }
1102
1103
1104 /**
1105  * Task to register all hosts available in the global host list
1106  *
1107  * @param cls RunContext
1108  * @param tc the scheduler task context
1109  */
1110 static void
1111 register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1112 {
1113   struct RunContext *rc = cls;
1114   struct RunContextOperation *rcop;
1115   unsigned int cnt;
1116
1117   rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
1118   if (rc->reg_hosts == rc->num_hosts)
1119   {
1120     DEBUG ("All hosts successfully registered\n");
1121     /* Start cnts */
1122 #if !ENABLE_LL
1123     for (cnt = 0; cnt < rc->num_hosts; cnt++)
1124     {
1125       rcop = GNUNET_malloc (sizeof (struct RunContextOperation));
1126       rcop->rc = rc;
1127       rcop->op =
1128           GNUNET_TESTBED_controller_link (rcop, rc->c, rc->hosts[cnt],
1129                                           rc->h, GNUNET_YES);
1130       GNUNET_assert (NULL != rcop->op);
1131       insert_rcop (rc, rcop);
1132     }
1133 #else
1134     struct Island *island;
1135     for (cnt = 0; cnt < rc->nislands; cnt++)
1136     {
1137       island = rc->islands[cnt];
1138       GNUNET_assert (0 < island->nhosts);
1139       rcop = GNUNET_malloc (sizeof (struct RunContextOperation));
1140       rcop->rc = rc;
1141       rcop->op =
1142           GNUNET_TESTBED_controller_link (rcop, rc->c, island->hosts[0],
1143                                           rc->h, GNUNET_YES);
1144       GNUNET_assert (NULL != rcop->op);
1145       insert_rcop (rc, rcop);
1146     }
1147 #endif
1148     rc->reg_hosts = 0;
1149     return;
1150   }
1151   rc->reg_handle =
1152       GNUNET_TESTBED_register_host (rc->c, rc->hosts[rc->reg_hosts],
1153                                     host_registration_completion, rc);
1154   rc->reg_hosts++;
1155 }
1156
1157
1158 /**
1159  * Callback to signal successfull startup of the controller process
1160  *
1161  * @param cls the closure from GNUNET_TESTBED_controller_start()
1162  * @param cfg the configuration with which the controller has been started;
1163  *          NULL if status is not GNUNET_OK
1164  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
1165  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
1166  */
1167 static void
1168 controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
1169                       int status)
1170 {
1171   struct RunContext *rc = cls;
1172   uint64_t event_mask;
1173
1174   if (status != GNUNET_OK)
1175   {
1176     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1177                 _("Controller crash detected. Shutting down.\n"));
1178     rc->cproc = NULL;
1179     cleanup (rc);
1180     if (NULL != rc->peers)
1181     {
1182       GNUNET_free (rc->peers);
1183       rc->peers = NULL;
1184     }
1185     if (GNUNET_YES == rc->shutdown)
1186     {
1187       rc->state = RC_PEERS_SHUTDOWN;
1188       GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
1189     }
1190     else
1191       shutdown_now (rc);
1192     return;
1193   }
1194   GNUNET_CONFIGURATION_destroy (rc->cfg);
1195   rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1196   event_mask = rc->event_mask;
1197   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
1198   event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
1199   if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE)
1200     event_mask |= GNUNET_TESTBED_ET_CONNECT;
1201   rc->c =
1202       GNUNET_TESTBED_controller_connect (rc->h, event_mask, &event_cb, rc);
1203   if (0 < rc->num_hosts)
1204   {
1205     rc->reg_hosts = 0;
1206     rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
1207     return;
1208   }
1209   rc->state = RC_LINKED;
1210   create_peers (rc);
1211 }
1212
1213
1214 #if ENABLE_LL
1215 #define ISLANDNAME_SIZE 4
1216 static void
1217 parse_islands (struct RunContext *rc)
1218 {
1219   char island_id[ISLANDNAME_SIZE];
1220   struct GNUNET_TESTBED_Host *host;
1221   struct Island *island;
1222   const char *hostname;
1223   unsigned int nhost;
1224
1225   DEBUG ("Parsing for islands\n");
1226   memset (island_id, 0, ISLANDNAME_SIZE);
1227   island = NULL;
1228   for (nhost = 0; nhost < rc->num_hosts; nhost++)
1229   {
1230     host = rc->hosts[nhost];
1231     hostname = GNUNET_TESTBED_host_get_hostname (host);
1232     GNUNET_assert (NULL != hostname);
1233     if (NULL == island)
1234     {
1235       strncpy (island_id, hostname, ISLANDNAME_SIZE - 1);
1236       island = GNUNET_malloc (sizeof (struct Island));
1237     }
1238     if (0 == strncmp (island_id, hostname, ISLANDNAME_SIZE - 1))
1239     {      
1240       GNUNET_array_append (island->hosts, island->nhosts, host);
1241       continue;
1242     }
1243     DEBUG ("Adding island `%s' with %u hosts\n", island_id, island->nhosts);
1244     GNUNET_array_append (rc->islands, rc->nislands, island);
1245     island = NULL;
1246   }
1247   if (NULL != island)
1248   {
1249     DEBUG ("Adding island `%s' with %u hosts\n", island_id, island->nhosts);
1250     GNUNET_array_append (rc->islands, rc->nislands, island);
1251   }
1252   DEBUG ("Total islands parsed: %u\n", rc->nislands);
1253 }
1254 #endif
1255
1256
1257 /**
1258  * Callback function invoked for each interface found.
1259  *
1260  * @param cls closure
1261  * @param name name of the interface (can be NULL for unknown)
1262  * @param isDefault is this presumably the default interface
1263  * @param addr address of this interface (can be NULL for unknown or unassigned)
1264  * @param broadcast_addr the broadcast address (can be NULL for unknown or unassigned)
1265  * @param netmask the network mask (can be NULL for unknown or unassigned))
1266  * @param addrlen length of the address
1267  * @return GNUNET_OK to continue iteration, GNUNET_SYSERR to abort
1268  */
1269 static int
1270 netint_proc (void *cls, const char *name, int isDefault,
1271              const struct sockaddr *addr, const struct sockaddr *broadcast_addr,
1272              const struct sockaddr *netmask, socklen_t addrlen)
1273 {
1274   struct RunContext *rc = cls;
1275   char hostip[NI_MAXHOST];
1276   char *buf;
1277
1278   if (sizeof (struct sockaddr_in) != addrlen)
1279     return GNUNET_OK;           /* Only consider IPv4 for now */
1280   if (0 !=
1281       getnameinfo (addr, addrlen, hostip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST))
1282     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "getnameinfo");
1283   if (NULL == rc->trusted_ip)
1284   {
1285     rc->trusted_ip = GNUNET_strdup (hostip);
1286     return GNUNET_YES;
1287   }
1288   (void) GNUNET_asprintf (&buf, "%s; %s", rc->trusted_ip, hostip);
1289   GNUNET_free (rc->trusted_ip);
1290   rc->trusted_ip = buf;
1291   return GNUNET_YES;
1292 }
1293
1294
1295 /**
1296  * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
1297  * inform whether the given host is habitable or not. The Handle returned by
1298  * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
1299  *
1300  * @param cls NULL
1301  * @param host the host whose status is being reported; will be NULL if the host
1302  *          given to GNUNET_TESTBED_is_host_habitable() is NULL
1303  * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
1304  */
1305 static void
1306 host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host,
1307                    int status)
1308 {
1309   struct CompatibilityCheckContext *hc = cls;
1310   struct RunContext *rc;
1311   struct GNUNET_TESTBED_Host **old_hosts;
1312   unsigned int nhost;
1313
1314   GNUNET_assert (NULL != (rc = hc->rc));
1315   nhost = hc->index;
1316   GNUNET_assert (nhost <= rc->num_hosts);
1317   GNUNET_assert (host == rc->hosts[nhost]);
1318   hc->h = NULL;
1319   if (GNUNET_NO == status)
1320   {
1321     if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host)))
1322       LOG (GNUNET_ERROR_TYPE_ERROR, _("Host %s cannot start testbed\n"),
1323            GNUNET_TESTBED_host_get_hostname (host));
1324     else
1325       LOG (GNUNET_ERROR_TYPE_ERROR,
1326            _("Testbed cannot be started on localhost\n"));
1327     shutdown_now (rc);
1328     return;
1329   }
1330   rc->reg_hosts++;
1331   if (rc->reg_hosts < rc->num_hosts)
1332     return;
1333   GNUNET_free (rc->hclist);
1334   rc->hclist = NULL;
1335   rc->h = rc->hosts[0];
1336   rc->num_hosts--;
1337   if (0 < rc->num_hosts)
1338   {
1339     old_hosts = rc->hosts;
1340     rc->hosts =
1341         GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * rc->num_hosts);
1342     memcpy (rc->hosts, &old_hosts[1],
1343             (sizeof (struct GNUNET_TESTBED_Host *) * rc->num_hosts));
1344     GNUNET_free (old_hosts);
1345   }
1346   else
1347   {
1348     GNUNET_free (rc->hosts);
1349     rc->hosts = NULL;
1350   }
1351 #if ENABLE_LL
1352   parse_islands (rc);
1353 #endif
1354   GNUNET_TESTBED_host_resolve_ (rc->h);
1355   for (nhost = 0; nhost < rc->num_hosts; nhost++)
1356     GNUNET_TESTBED_host_resolve_ (rc->hosts[nhost]);
1357   GNUNET_OS_network_interfaces_list (netint_proc, rc);
1358   if (NULL == rc->trusted_ip)
1359     rc->trusted_ip = GNUNET_strdup ("127.0.0.1");
1360   rc->cproc =
1361       GNUNET_TESTBED_controller_start (rc->trusted_ip, rc->h,
1362                                        &controller_status_cb, rc);
1363   GNUNET_free (rc->trusted_ip);
1364   rc->trusted_ip = NULL;
1365   if (NULL == rc->cproc)
1366   {
1367     LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller"));
1368     shutdown_now (rc);
1369   }
1370 }
1371
1372
1373 /**
1374  * Task run upon timeout while setting up the testbed
1375  *
1376  * @param cls the RunContext
1377  * @param tc the task context
1378  */
1379 static void
1380 timeout_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1381 {
1382   struct RunContext *rc = cls;
1383   
1384   rc->timeout_task = GNUNET_SCHEDULER_NO_TASK;
1385   LOG (GNUNET_ERROR_TYPE_ERROR, _("Shutting down testbed due to timeout while setup.\n"));
1386   shutdown_now (rc);
1387    if (NULL != rc->test_master)
1388      rc->test_master (rc->test_master_cls, 0, NULL, 0, 0);
1389    rc->test_master = NULL;
1390 }
1391
1392
1393 /**
1394  * Convenience method for running a testbed with
1395  * a single call.  Underlay and overlay topology
1396  * are configured using the "UNDERLAY" and "OVERLAY"
1397  * options in the "[testbed]" section of the configuration\
1398  * (with possible options given in "UNDERLAY_XXX" and/or
1399  * "OVERLAY_XXX").
1400  *
1401  * The testbed is to be terminated using a call to
1402  * "GNUNET_SCHEDULER_shutdown".
1403  *
1404  * @param host_filename name of the file with the 'hosts', NULL
1405  *        to run everything on 'localhost'
1406  * @param cfg configuration to use (for testbed, controller and peers)
1407  * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg?
1408  * @param event_mask bit mask with set of events to call 'cc' for;
1409  *                   or-ed values of "1LL" shifted by the
1410  *                   respective 'enum GNUNET_TESTBED_EventType'
1411  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
1412  * @param cc controller callback to invoke on events; This callback is called
1413  *          for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't
1414  *          set in the event_mask as this is the only way get access to the
1415  *          handle of each peer
1416  * @param cc_cls closure for cc
1417  * @param test_master this callback will be called once the test is ready
1418  * @param test_master_cls closure for 'test_master'.
1419  */
1420 void
1421 GNUNET_TESTBED_run (const char *host_filename,
1422                     const struct GNUNET_CONFIGURATION_Handle *cfg,
1423                     unsigned int num_peers, uint64_t event_mask,
1424                     GNUNET_TESTBED_ControllerCallback cc, void *cc_cls,
1425                     GNUNET_TESTBED_TestMaster test_master,
1426                     void *test_master_cls)
1427 {
1428   struct RunContext *rc;
1429   char *topology;
1430   struct CompatibilityCheckContext *hc;      
1431   struct GNUNET_TIME_Relative timeout;
1432   unsigned long long random_links;
1433   unsigned int hid;
1434   unsigned int nhost;
1435
1436   GNUNET_assert (num_peers > 0);
1437   rc = GNUNET_malloc (sizeof (struct RunContext));
1438   rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
1439 #if ENABLE_LL
1440   rc->num_hosts = GNUNET_TESTBED_hosts_load_from_loadleveler (rc->cfg,
1441                                                               &rc->hosts);
1442   if (0 == rc->num_hosts)
1443   {
1444     LOG (GNUNET_ERROR_TYPE_WARNING,
1445            _("No hosts loaded from LoadLeveler. Need at least one host\n"));
1446     goto error_cleanup;
1447   }
1448 #else
1449   if (NULL != host_filename)
1450   {
1451     rc->num_hosts =
1452         GNUNET_TESTBED_hosts_load_from_file (host_filename, rc->cfg,
1453                                              &rc->hosts);
1454     if (0 == rc->num_hosts)
1455     {
1456       LOG (GNUNET_ERROR_TYPE_WARNING,
1457            _("No hosts loaded. Need at least one host\n"));
1458       goto error_cleanup;
1459     }
1460   }
1461   else
1462     rc->h = GNUNET_TESTBED_host_create (NULL, NULL, rc->cfg, 0);
1463 #endif
1464   rc->num_peers = num_peers;
1465   rc->event_mask = event_mask;
1466   rc->cc = cc;
1467   rc->cc_cls = cc_cls;
1468   rc->test_master = test_master;
1469   rc->test_master_cls = test_master_cls;
1470   rc->state = RC_INIT;
1471   rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE;
1472   if (GNUNET_OK ==
1473       GNUNET_CONFIGURATION_get_value_string (rc->cfg, "testbed",
1474                                              "OVERLAY_TOPOLOGY", &topology))
1475   {
1476     if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology, topology))
1477     {
1478       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, "testbed",
1479                                  "OVERLAY_TOPLOGY",
1480                                  _
1481                                  ("Specified topology must be supported by testbed"));
1482     }
1483     GNUNET_free (topology);
1484   }
1485   switch (rc->topology)
1486   {
1487   case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
1488   case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
1489   case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
1490     if (GNUNET_OK !=
1491         GNUNET_CONFIGURATION_get_value_number (rc->cfg, "testbed",
1492                                                "OVERLAY_RANDOM_LINKS",
1493                                                &random_links))
1494     {
1495       /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS
1496        * option to be set to the number of random links to be established  */
1497       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "testbed",
1498                                  "OVERLAY_RANDOM_LINKS");
1499       goto error_cleanup;
1500     }
1501     if (random_links > UINT32_MAX)
1502     {
1503       GNUNET_break (0);         /* Too big number */
1504       goto error_cleanup;
1505     }
1506     rc->random_links = (unsigned int) random_links;
1507     break;
1508   case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1509     if (GNUNET_OK !=
1510         GNUNET_CONFIGURATION_get_value_string (rc->cfg, "testbed",
1511                                                "OVERLAY_TOPOLOGY_FILE",
1512                                                &rc->topo_file))
1513     {
1514       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, "testbed",
1515                                  "OVERLAY_TOPOLOGY_FILE");
1516       goto error_cleanup;
1517     }
1518   default:
1519     /* Warn if OVERLAY_RANDOM_LINKS is present that it will be ignored */
1520     if (GNUNET_YES ==
1521         GNUNET_CONFIGURATION_have_value (rc->cfg, "testbed",
1522                                          "OVERLAY_RANDOM_LINKS"))
1523       LOG (GNUNET_ERROR_TYPE_WARNING,
1524            "Ignoring value of `OVERLAY_RANDOM_LINKS' in given configuration\n");
1525     break;
1526   }
1527   if (0 != rc->num_hosts)
1528   {
1529     rc->hclist = GNUNET_malloc (sizeof (struct CompatibilityCheckContext)
1530                                 * rc->num_hosts);
1531     for (nhost = 0; nhost < rc->num_hosts; nhost++)
1532     {
1533       hc = &rc->hclist[nhost];
1534       hc->index = nhost;
1535       hc->rc = rc;
1536       hc->h = GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg,
1537                                                 &host_habitable_cb, hc);
1538       if (NULL == hc->h)
1539       {
1540         GNUNET_break (0);
1541         for (nhost = 0; nhost < rc->num_hosts; nhost++)
1542         {
1543           hc = &rc->hclist[nhost];
1544           if (NULL != hc->h)
1545             GNUNET_TESTBED_is_host_habitable_cancel (hc->h);
1546         }
1547         GNUNET_free (rc->hclist);
1548         rc->hclist = NULL;
1549         goto error_cleanup;
1550       }
1551     }
1552   }
1553   else
1554     rc->cproc =
1555         GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h,
1556                                          &controller_status_cb, rc);
1557   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_time (cfg, "TESTBED",
1558                                                         "SETUP_TIMEOUT",
1559                                                         &timeout))
1560   {
1561     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1562                                              DEFAULT_SETUP_TIMEOUT);
1563   }
1564   rc->rcop_map = GNUNET_CONTAINER_multihashmap32_create (256);
1565   rc->timeout_task =
1566       GNUNET_SCHEDULER_add_delayed (timeout, &timeout_task, rc);
1567   rc->interrupt_task =
1568       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &interrupt,
1569                                     rc);
1570   return;
1571
1572 error_cleanup:
1573   if (NULL != rc->h)
1574     GNUNET_TESTBED_host_destroy (rc->h);
1575   if (NULL != rc->hosts)
1576   {
1577     for (hid = 0; hid < rc->num_hosts; hid++)
1578       if (NULL != rc->hosts[hid])
1579         GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
1580     GNUNET_free (rc->hosts);
1581   }
1582   if (NULL != rc->cfg)
1583     GNUNET_CONFIGURATION_destroy (rc->cfg);
1584   GNUNET_free (rc);
1585 }
1586
1587
1588 /* end of testbed_api_testbed.c */