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