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