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