-generate nicer error message
[oweals/gnunet.git] / src / testbed / testbed_api_testbed.c
1 /*
2   This file is part of GNUnet
3   (C) 2008--2012 Christian Grothoff (and other contributing authors)
4
5   GNUnet is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published
7   by the Free Software Foundation; either version 3, or (at your
8   option) any later version.
9
10   GNUnet is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with GNUnet; see the file COPYING.  If not, write to the
17   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18   Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file testbed/testbed_api_testbed.c
23  * @brief high-level testbed management
24  * @author Christian Grothoff
25  * @author Sree Harsha Totakura
26  */
27
28 #include "platform.h"
29 #include "gnunet_testbed_service.h"
30 #include "testbed_api_peers.h"
31 #include "testbed_api_hosts.h"
32 #include "testbed_api_topology.h"
33
34 /**
35  * Generic loggins shorthand
36  */
37 #define LOG(kind,...)                                           \
38   GNUNET_log_from (kind, "testbed-api-testbed", __VA_ARGS__)
39
40 /**
41  * Opaque handle to an abstract operation to be executed by the testing framework.
42  */
43 struct GNUNET_TESTBED_Testbed
44 {
45   /**
46    * The array of hosts
47    */
48   struct GNUNET_TESTBED_Host **hosts;
49
50   /**
51    * The number of hosts in the hosts array
52    */
53   unsigned int num_hosts;
54
55   /**
56    * The controller handle
57    */
58   struct GNUNET_TESTBED_Controller *c;
59 };
60
61
62 /**
63  * DLL of operations
64  */
65 struct DLLOperation
66 {
67   /**
68    * The testbed operation handle
69    */
70   struct GNUNET_TESTBED_Operation *op;
71
72   /**
73    * Context information for GNUNET_TESTBED_run()
74    */
75   struct RunContext *rc;
76
77   /**
78    * Closure
79    */
80   void *cls;
81
82   /**
83    * The next pointer for DLL
84    */
85   struct DLLOperation *next;
86
87   /**
88    * The prev pointer for DLL
89    */
90   struct DLLOperation *prev;
91 };
92
93
94 /**
95  * States of RunContext
96  */
97 enum State
98 {
99   /**
100    * Initial state
101    */
102   RC_INIT = 0,
103
104   /**
105    * Controllers on given hosts started and linked
106    */
107   RC_LINKED,
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
128 /**
129  * Testbed Run Handle
130  */
131 struct RunContext
132 {
133   /**
134    * The controller handle
135    */
136   struct GNUNET_TESTBED_Controller *c;
137
138   /**
139    * The configuration of the controller. This is based on the cfg given to the
140    * function GNUNET_TESTBED_run(). We also use this config as a template while
141    * for peers
142    */
143   struct GNUNET_CONFIGURATION_Handle *cfg;
144
145   /**
146    * Handle to the host on which the controller runs
147    */
148   struct GNUNET_TESTBED_Host *h;
149
150   /**
151    * The handle to the controller process
152    */
153   struct GNUNET_TESTBED_ControllerProc *cproc;
154
155   /**
156    * The callback to use as controller callback
157    */
158   GNUNET_TESTBED_ControllerCallback cc;
159
160   /**
161    * The pointer to the controller callback
162    */
163   void *cc_cls;
164
165   /**
166    * TestMaster callback to call when testbed initialization is done
167    */
168   GNUNET_TESTBED_TestMaster test_master;
169   
170   /**
171    * The closure for the TestMaster callback
172    */
173   void *test_master_cls;
174
175   /**
176    * The head element of DLL operations
177    */
178   struct DLLOperation *dll_op_head;
179
180   /**
181    * The tail element of DLL operations
182    */
183   struct DLLOperation *dll_op_tail;
184
185   /**
186    * An array of hosts loaded from the hostkeys file
187    */
188   struct GNUNET_TESTBED_Host **hosts;
189
190   /**
191    * The handle for whether a host is habitable or not
192    */
193   struct GNUNET_TESTBED_HostHabitableCheckHandle **hc_handles;
194
195   /**
196    * Array of peers which we create
197    */
198   struct GNUNET_TESTBED_Peer **peers;
199
200   /**
201    * The topology generation operation. Will be null if no topology is set in
202    * the configuration
203    */
204   struct GNUNET_TESTBED_Operation *topology_operation;
205
206   /**
207    * The file containing topology data. Only used if the topology is set to 'FROM_FILE'
208    */
209   char *topo_file;
210
211   /**
212    * Host registration handle
213    */
214   struct GNUNET_TESTBED_HostRegistrationHandle *reg_handle;
215
216   /**
217    * Host registration task
218    */
219   GNUNET_SCHEDULER_TaskIdentifier register_hosts_task;
220
221   /**
222    * Task to be run while shutting down
223    */
224   GNUNET_SCHEDULER_TaskIdentifier shutdown_run_task;
225
226   /**
227    * The event mask for the controller
228    */
229   uint64_t event_mask;
230
231   /**
232    * State of this context
233    */
234   enum State state;
235
236   /**
237    * The topology which has to be achieved with the peers started in this context
238    */
239   enum GNUNET_TESTBED_TopologyOption topology;
240
241   /**
242    * Number of hosts in the given host file
243    */
244   unsigned int num_hosts;
245
246   /**
247    * Number of registered hosts. Also used as a counter while checking
248    * habitabillity of hosts
249    */
250   unsigned int reg_hosts;
251
252   /**
253    * Current peer count for an operation; Set this to 0 and increment for each
254    * successful operation on a peer
255    */
256   unsigned int peer_count;
257
258   /**
259    * number of peers to start
260    */
261   unsigned int num_peers;
262
263   /**
264    * counter to count overlay connect attempts. This counter includes both
265    * successful and failed overlay connects
266    */
267   unsigned int oc_count;
268
269   /**
270    * Expected overlay connects. Should be zero if no topology is relavant
271    */
272   unsigned int num_oc;
273
274   /**
275    * Number of random links to established
276    */
277   unsigned int random_links;
278   
279 };
280
281
282 /**
283  * Task for starting peers
284  *
285  * @param cls the RunHandle
286  * @param tc the task context from scheduler
287  */
288 static void
289 start_peers_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
290 {
291   struct RunContext *rc = cls;
292   struct DLLOperation *dll_op;
293   unsigned int peer;
294
295   LOG (GNUNET_ERROR_TYPE_DEBUG, "Starting Peers\n");
296   for (peer = 0; peer < rc->num_peers; peer++)
297   {
298     dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
299     dll_op->op = GNUNET_TESTBED_peer_start (NULL, rc->peers[peer], NULL, NULL);
300     dll_op->cls = rc->peers[peer];
301     GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);
302   }
303   rc->peer_count = 0;
304 }
305
306
307 /**
308  * Functions of this signature are called when a peer has been successfully
309  * created
310  *
311  * @param cls the closure from GNUNET_TESTBED_peer_create()
312  * @param peer the handle for the created peer; NULL on any error during
313  *          creation
314  * @param emsg NULL if peer is not NULL; else MAY contain the error description
315  */
316 static void
317 peer_create_cb (void *cls, struct GNUNET_TESTBED_Peer *peer, const char *emsg)
318 {
319   struct DLLOperation *dll_op = cls;
320   struct RunContext *rc;
321
322   GNUNET_assert (NULL != dll_op);
323   rc = dll_op->rc;
324   GNUNET_assert (NULL != rc);
325   GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
326   GNUNET_TESTBED_operation_done (dll_op->op);
327   GNUNET_free (dll_op);
328   if (NULL == peer)
329   {
330     if (NULL != emsg)
331       LOG (GNUNET_ERROR_TYPE_WARNING, "Error while creating a peer: %s\n",
332            emsg);
333     /* FIXME: GNUNET_TESTBED_shutdown_run()? */
334     return;
335   }
336   rc->peers[rc->peer_count] = peer;
337   rc->peer_count++;
338   if (rc->peer_count < rc->num_peers)
339     return;
340   LOG (GNUNET_ERROR_TYPE_DEBUG, "Required peers created successfully\n");
341   GNUNET_SCHEDULER_add_now (&start_peers_task, rc);
342 }
343
344
345 /**
346  * Assuming all peers have been destroyed cleanup run handle
347  *
348  * @param cls the run handle
349  * @param tc the task context from scheduler
350  */
351 static void
352 cleanup_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
353 {
354   struct RunContext *rc = cls;
355   struct DLLOperation *dll_op;
356   unsigned int hid;
357
358   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == rc->register_hosts_task);
359   GNUNET_assert (NULL == rc->reg_handle);
360   GNUNET_assert (NULL == rc->peers);
361   GNUNET_assert (NULL == rc->hc_handles);
362   GNUNET_assert (RC_PEERS_DESTROYED == rc->state);
363   if (NULL != rc->c)
364     GNUNET_TESTBED_controller_disconnect (rc->c);
365   if (NULL != rc->cproc)
366     GNUNET_TESTBED_controller_stop (rc->cproc);
367   if (NULL != rc->h)
368     GNUNET_TESTBED_host_destroy (rc->h);
369   for (hid = 0; hid < rc->num_hosts; hid++)
370         GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
371   GNUNET_free_non_null (rc->hosts);
372   if (NULL != rc->dll_op_head)
373   {
374     LOG (GNUNET_ERROR_TYPE_WARNING,
375          _("Some operations are still pending. Cancelling them\n"));
376     while (NULL != (dll_op = rc->dll_op_head))
377     {
378       GNUNET_TESTBED_operation_done (dll_op->op);
379       GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
380       GNUNET_free (dll_op);
381     }
382   }
383   if (NULL != rc->cfg)
384     GNUNET_CONFIGURATION_destroy (rc->cfg);
385   GNUNET_free_non_null (rc->topo_file);
386   GNUNET_free (rc);
387 }
388
389
390 /**
391  * Stops the testbed run and releases any used resources
392  *
393  * @param cls the tesbed run handle
394  * @param tc the task context from scheduler
395  */
396 static void
397 shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
398
399
400 /**
401  * Function to shutdown now
402  *
403  * @param rc the RunContext
404  */
405 static void
406 shutdown_now (struct RunContext *rc)
407 {
408   if (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task)
409     GNUNET_SCHEDULER_cancel (rc->shutdown_run_task);
410   rc->shutdown_run_task = GNUNET_SCHEDULER_add_now (&shutdown_run, rc);
411 }
412
413
414 /**
415  * Stops the testbed run and releases any used resources
416  *
417  * @param cls the tesbed run handle
418  * @param tc the task context from scheduler
419  */
420 static void
421 shutdown_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
422 {
423   struct RunContext *rc = cls;
424   struct DLLOperation *dll_op;
425   unsigned int peer;
426   unsigned int nhost;
427
428   GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != rc->shutdown_run_task);
429   rc->shutdown_run_task = GNUNET_SCHEDULER_NO_TASK;
430   if (NULL != rc->hc_handles)
431   {
432     for (nhost = 0; nhost < rc->num_hosts; nhost++)
433       if (NULL != rc->hc_handles[nhost])
434         GNUNET_TESTBED_is_host_habitable_cancel (rc->hc_handles[nhost]);
435     GNUNET_free (rc->hc_handles);
436     rc->hc_handles = NULL;
437   }
438   /* Stop register hosts task if it is running */
439   if (GNUNET_SCHEDULER_NO_TASK != rc->register_hosts_task)
440   {
441     GNUNET_SCHEDULER_cancel (rc->register_hosts_task);
442     rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
443   }
444   if (NULL != rc->reg_handle)
445   {
446     GNUNET_TESTBED_cancel_registration (rc->reg_handle);
447     rc->reg_handle = NULL;
448   }
449   if (NULL != rc->c)
450   {
451     if (NULL != rc->peers)
452     {
453       if (NULL != rc->topology_operation)
454       {
455         GNUNET_TESTBED_operation_done (rc->topology_operation);
456         rc->topology_operation = NULL;
457       }
458       if (RC_INIT == rc->state)
459         rc->state = RC_READY;   /* Even though we haven't called the master callback */
460       rc->peer_count = 0;
461       /* Check if some peers are stopped */
462       for (peer = 0; peer < rc->num_peers; peer++)
463       {
464         if (PS_STOPPED != rc->peers[peer]->state)
465           break;
466       }
467       if (peer == rc->num_peers)
468       {
469         /* All peers are stopped */
470         rc->state = RC_PEERS_STOPPED;
471         for (peer = 0; peer < rc->num_peers; peer++)
472         {
473           dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
474           dll_op->op = GNUNET_TESTBED_peer_destroy (rc->peers[peer]);
475           GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
476                                             dll_op);
477         }
478         return;
479       }
480       /* Some peers are stopped */
481       for (peer = 0; peer < rc->num_peers; peer++)
482       {
483         if (PS_STARTED != rc->peers[peer]->state)
484         {
485           rc->peer_count++;
486           continue;
487         }
488         dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
489         dll_op->op = GNUNET_TESTBED_peer_stop (rc->peers[peer], NULL, NULL);
490         dll_op->cls = rc->peers[peer];
491         GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
492                                           dll_op);
493       }
494       if (rc->peer_count != rc->num_peers)
495         return;
496     }
497   }
498   rc->state = RC_PEERS_DESTROYED;       /* No peers are present so we consider the
499                                          * state where all peers are destroyed  */
500   GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
501 }
502
503
504 /**
505  * Task to call master task
506  *
507  * @param cls the run context
508  * @param tc the task context
509  */
510 static void
511 call_master (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
512 {
513   struct RunContext *rc = cls;
514   
515   if (NULL != rc->topology_operation)
516   {
517     GNUNET_TESTBED_operation_done (rc->topology_operation);
518     rc->topology_operation = NULL;
519   }
520   if (NULL != rc->test_master)
521     rc->test_master (rc->test_master_cls, rc->num_peers, rc->peers);
522 }
523
524
525 /**
526  * Function to create peers
527  *
528  * @param rc the RunContext
529  */
530 static void
531 create_peers (struct RunContext *rc)
532 {
533   struct DLLOperation *dll_op;
534   unsigned int peer;
535
536   rc->peers =
537       GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Peer *) * rc->num_peers);
538   GNUNET_assert (NULL != rc->c);
539   rc->peer_count = 0;
540   for (peer = 0; peer < rc->num_peers; peer++)
541   {
542     dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
543     dll_op->rc = rc;
544     dll_op->op =
545         GNUNET_TESTBED_peer_create (rc->c, 
546                                     (0 == rc->num_hosts)
547                                     ? rc->h : rc->hosts[peer % rc->num_hosts],
548                                     rc->cfg,
549                                     peer_create_cb, dll_op);
550     GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);
551   }
552 }
553
554
555 /**
556  * Signature of the event handler function called by the
557  * respective event controller.
558  *
559  * @param cls closure
560  * @param event information about the event
561  */
562 static void
563 event_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
564 {
565   struct RunContext *rc = cls;
566   struct DLLOperation *dll_op;
567   unsigned int peer_id;
568
569   if (RC_INIT == rc->state)
570   {
571     switch (event->type)
572     {
573     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
574       dll_op = event->details.operation_finished.op_cls;
575       if (NULL != event->details.operation_finished.emsg)
576       {
577         LOG (GNUNET_ERROR_TYPE_ERROR,
578              _("Linking controllers failed. Exiting"));
579         shutdown_now (rc);
580       }
581       else
582         rc->reg_hosts++;
583       GNUNET_assert (event->details.operation_finished.operation == dll_op->op);
584       GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
585       GNUNET_TESTBED_operation_done (dll_op->op);
586       GNUNET_free (dll_op);
587       if (rc->reg_hosts == rc->num_hosts)
588       {
589         rc->state = RC_LINKED;
590         create_peers (rc);
591       }
592       return;
593     default:
594       GNUNET_break (0);
595       shutdown_now (rc);
596       return;
597     }
598   }
599   if (NULL != rc->topology_operation)
600   {
601     switch (event->type)
602     {
603     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
604     case GNUNET_TESTBED_ET_CONNECT:
605       rc->oc_count++;
606       break;
607     default:
608       GNUNET_break (0);
609       shutdown_now (rc);
610       return;
611     }
612     if (rc->oc_count == rc->num_oc)
613     {
614       rc->state = RC_READY;
615       GNUNET_SCHEDULER_add_continuation (&call_master, rc,
616                                          GNUNET_SCHEDULER_REASON_PREREQ_DONE);
617     }
618     return;
619   }
620   if ((RC_LINKED < rc->state) &&
621       ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) ||
622        (GNUNET_TESTBED_ET_PEER_STOP == event->type)))
623   {
624     for (dll_op = rc->dll_op_head; NULL != dll_op; dll_op = dll_op->next)
625     {
626       if ((GNUNET_TESTBED_ET_OPERATION_FINISHED == event->type) &&
627           (event->details.operation_finished.operation == dll_op->op))
628         break;
629       if ((GNUNET_TESTBED_ET_PEER_STOP == event->type) &&
630           (event->details.peer_stop.peer == dll_op->cls))
631         break;
632     }
633     if (NULL == dll_op)
634       goto call_cc;
635     GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
636     GNUNET_TESTBED_operation_done (dll_op->op);
637     GNUNET_free (dll_op);
638     rc->peer_count++;
639     if (rc->peer_count < rc->num_peers)
640       return;
641     switch (rc->state)
642     {
643     case RC_READY:
644       rc->state = RC_PEERS_STOPPED;
645       rc->peer_count = 0;
646       for (peer_id = 0; peer_id < rc->num_peers; peer_id++)
647       {
648         dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
649         dll_op->op = GNUNET_TESTBED_peer_destroy (rc->peers[peer_id]);
650         GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail,
651                                           dll_op);
652       }
653       break;
654     case RC_PEERS_STOPPED:
655       rc->state = RC_PEERS_DESTROYED;
656       GNUNET_free (rc->peers);
657       rc->peers = NULL;
658       LOG (GNUNET_ERROR_TYPE_DEBUG, "All peers successfully destroyed\n");
659       GNUNET_SCHEDULER_add_now (&cleanup_task, rc);
660       break;
661     default:
662       GNUNET_assert (0);
663     }
664     return;
665   }
666
667 call_cc:
668   if ((0 != (rc->event_mask & (1LL << event->type))) && (NULL != rc->cc))
669     rc->cc (rc->cc_cls, event);
670   if (GNUNET_TESTBED_ET_PEER_START != event->type)
671     return;
672   for (dll_op = rc->dll_op_head; NULL != dll_op; dll_op = dll_op->next)
673     if ((NULL != dll_op->cls) &&
674         (event->details.peer_start.peer == dll_op->cls))
675       break;
676   GNUNET_assert (NULL != dll_op);
677   GNUNET_CONTAINER_DLL_remove (rc->dll_op_head, rc->dll_op_tail, dll_op);
678   GNUNET_TESTBED_operation_done (dll_op->op);
679   GNUNET_free (dll_op);
680   rc->peer_count++;
681   if (rc->peer_count < rc->num_peers)
682     return;
683   LOG (GNUNET_ERROR_TYPE_DEBUG, "Peers started successfully\n");
684   if (GNUNET_TESTBED_TOPOLOGY_NONE != rc->topology)
685   {
686     if ( (GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI == rc->topology)
687          || (GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING == rc->topology)
688          || (GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD == rc->topology))
689     {
690       rc->topology_operation =
691           GNUNET_TESTBED_overlay_configure_topology (NULL,
692                                                      rc->num_peers,
693                                                      rc->peers,
694                                                      &rc->num_oc,
695                                                      rc->topology,
696                                                      rc->random_links,
697                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
698     }
699     else if (GNUNET_TESTBED_TOPOLOGY_FROM_FILE == rc->topology)
700     {
701       GNUNET_assert (NULL != rc->topo_file);
702       rc->topology_operation =
703           GNUNET_TESTBED_overlay_configure_topology (NULL,
704                                                      rc->num_peers,
705                                                      rc->peers,
706                                                      &rc->num_oc,
707                                                      rc->topology,
708                                                      rc->topo_file,
709                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
710     }
711     else
712       rc->topology_operation =
713           GNUNET_TESTBED_overlay_configure_topology (NULL,
714                                                      rc->num_peers,
715                                                      rc->peers,
716                                                      &rc->num_oc,
717                                                      rc->topology,
718                                                      GNUNET_TESTBED_TOPOLOGY_OPTION_END);
719     if (NULL == rc->topology_operation)
720       LOG (GNUNET_ERROR_TYPE_WARNING,
721            "Not generating topology. Check number of peers\n");
722     else
723       return;
724   }
725   rc->state = RC_READY;
726   GNUNET_SCHEDULER_add_continuation (&call_master, rc,
727                                      GNUNET_SCHEDULER_REASON_PREREQ_DONE);
728 }
729
730
731 /**
732  * Task to register all hosts available in the global host list
733  *
734  * @param cls the RunContext
735  * @param tc the scheduler task context
736  */
737 static void
738 register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
739
740
741 /**
742  * Callback which will be called to after a host registration succeeded or failed
743  *
744  * @param cls the closure
745  * @param emsg the error message; NULL if host registration is successful
746  */
747 static void
748 host_registration_completion (void *cls, const char *emsg)
749 {
750   struct RunContext *rc = cls;
751
752   rc->reg_handle = NULL;
753   if (NULL != emsg)
754   {
755     LOG (GNUNET_ERROR_TYPE_WARNING,
756          _("Host registration failed for a host. Error: %s\n"), emsg);
757     shutdown_now (rc);
758     return;
759   }
760   rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
761 }
762
763
764 /**
765  * Task to register all hosts available in the global host list
766  *
767  * @param cls RunContext
768  * @param tc the scheduler task context
769  */
770 static void
771 register_hosts (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
772 {
773   struct RunContext *rc = cls;
774   struct DLLOperation *dll_op;
775   unsigned int slave;
776
777   rc->register_hosts_task = GNUNET_SCHEDULER_NO_TASK;
778   if (rc->reg_hosts == rc->num_hosts)
779   {
780     LOG (GNUNET_ERROR_TYPE_DEBUG,
781          "All hosts successfully registered\n");
782     /* Start slaves */
783     for (slave = 0; slave < rc->num_hosts; slave++)
784     {
785       dll_op = GNUNET_malloc (sizeof (struct DLLOperation));
786       dll_op->rc = rc;
787       dll_op->op = GNUNET_TESTBED_controller_link (dll_op,
788                                                    rc->c,
789                                                    rc->hosts[slave],
790                                                    rc->h,
791                                                    rc->cfg,
792                                                    GNUNET_YES);
793       GNUNET_CONTAINER_DLL_insert_tail (rc->dll_op_head, rc->dll_op_tail, dll_op);
794     }
795     rc->reg_hosts = 0;
796     return;
797   }
798   rc->reg_handle = GNUNET_TESTBED_register_host (rc->c,
799                                                  rc->hosts[rc->reg_hosts++],
800                                                  host_registration_completion,
801                                                  rc);
802 }
803
804
805 /**
806  * Callback to signal successfull startup of the controller process
807  *
808  * @param cls the closure from GNUNET_TESTBED_controller_start()
809  * @param cfg the configuration with which the controller has been started;
810  *          NULL if status is not GNUNET_OK
811  * @param status GNUNET_OK if the startup is successfull; GNUNET_SYSERR if not,
812  *          GNUNET_TESTBED_controller_stop() shouldn't be called in this case
813  */
814 static void
815 controller_status_cb (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg,
816                       int status)
817 {
818   struct RunContext *rc = cls;
819   uint64_t event_mask;
820
821   if (status != GNUNET_OK)
822   {
823     switch (rc->state)
824     {
825     case RC_INIT:
826       GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Testbed startup failed\n");
827       return;
828     default:
829       shutdown_now (rc);
830       return;
831     }
832   }
833   GNUNET_CONFIGURATION_destroy (rc->cfg);
834   rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
835   event_mask = rc->event_mask;
836   event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_STOP);
837   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
838   event_mask |= (1LL << GNUNET_TESTBED_ET_PEER_START);
839   if (rc->topology < GNUNET_TESTBED_TOPOLOGY_NONE)
840     event_mask |= GNUNET_TESTBED_ET_CONNECT;
841   rc->c =
842       GNUNET_TESTBED_controller_connect (rc->cfg, rc->h, event_mask, &event_cb, rc);
843   if (0 < rc->num_hosts)
844   {
845     rc->register_hosts_task = GNUNET_SCHEDULER_add_now (&register_hosts, rc);
846     return;
847   }
848   rc->state = RC_LINKED;
849   create_peers (rc);
850 }
851
852
853 /**
854  * Callbacks of this type are called by GNUNET_TESTBED_is_host_habitable to
855  * inform whether the given host is habitable or not. The Handle returned by
856  * GNUNET_TESTBED_is_host_habitable() is invalid after this callback is called
857  *
858  * @param cls NULL
859  * @param host the host whose status is being reported; will be NULL if the host
860  *          given to GNUNET_TESTBED_is_host_habitable() is NULL
861  * @param status GNUNET_YES if it is habitable; GNUNET_NO if not
862  */
863 static void 
864 host_habitable_cb (void *cls, const struct GNUNET_TESTBED_Host *host, int status)
865 {
866   struct RunContext *rc = cls;
867   unsigned int nhost;
868   
869   for (nhost = 0; nhost < rc->num_hosts; nhost++)
870   {
871     if (host == rc->hosts[nhost])
872       break;
873   }
874   GNUNET_assert (nhost != rc->num_hosts);
875   rc->hc_handles[nhost] = NULL;
876   if (GNUNET_NO == status)
877   {
878     if ((NULL != host) && (NULL != GNUNET_TESTBED_host_get_hostname (host)))
879       LOG (GNUNET_ERROR_TYPE_ERROR, _("Host %s cannot start testbed\n"),
880            GNUNET_TESTBED_host_get_hostname (host));
881     else
882       LOG (GNUNET_ERROR_TYPE_ERROR, _("Testbed cannot be started on localhost\n"));
883     shutdown_now (rc);
884     return;
885   }
886   rc->reg_hosts++;
887   if (rc->reg_hosts < rc->num_hosts)
888     return;
889   GNUNET_free (rc->hc_handles);
890   rc->hc_handles = NULL;
891   rc->h = rc->hosts[0];
892   rc->num_hosts--;
893   if (0 < rc->num_hosts)
894     rc->hosts = &rc->hosts[1];
895   else
896   {
897     GNUNET_free (rc->hosts);
898     rc->hosts = NULL;
899   }
900   /* FIXME: If we are starting controller on different host 127.0.0.1 may not ab
901   correct */
902   rc->cproc =
903       GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, rc->cfg,
904                                        &controller_status_cb, rc);
905   if (NULL == rc->cproc)
906   {
907     LOG (GNUNET_ERROR_TYPE_ERROR, _("Cannot start the master controller"));
908     shutdown_now (rc);
909   }
910 }
911
912
913 /**
914  * Convenience method for running a testbed with
915  * a single call.  Underlay and overlay topology
916  * are configured using the "UNDERLAY" and "OVERLAY"
917  * options in the "[testbed]" section of the configuration\
918  * (with possible options given in "UNDERLAY_XXX" and/or
919  * "OVERLAY_XXX").
920  *
921  * The testbed is to be terminated using a call to
922  * "GNUNET_SCHEDULER_shutdown".
923  *
924  * @param host_filename name of the file with the 'hosts', NULL
925  *        to run everything on 'localhost'
926  * @param cfg configuration to use (for testbed, controller and peers)
927  * @param num_peers number of peers to start; FIXME: maybe put that ALSO into cfg?
928  * @param event_mask bit mask with set of events to call 'cc' for;
929  *                   or-ed values of "1LL" shifted by the
930  *                   respective 'enum GNUNET_TESTBED_EventType'
931  *                   (i.e.  "(1LL << GNUNET_TESTBED_ET_CONNECT) || ...")
932  * @param cc controller callback to invoke on events; This callback is called
933  *          for all peer start events even if GNUNET_TESTBED_ET_PEER_START isn't
934  *          set in the event_mask as this is the only way get access to the
935  *          handle of each peer
936  * @param cc_cls closure for cc
937  * @param test_master this callback will be called once the test is ready
938  * @param test_master_cls closure for 'test_master'.
939  */
940 void
941 GNUNET_TESTBED_run (const char *host_filename,
942                     const struct GNUNET_CONFIGURATION_Handle *cfg,
943                     unsigned int num_peers, uint64_t event_mask,
944                     GNUNET_TESTBED_ControllerCallback cc, void *cc_cls,
945                     GNUNET_TESTBED_TestMaster test_master,
946                     void *test_master_cls)
947 {
948   struct RunContext *rc;
949   char *topology;
950   unsigned long long random_links;
951   unsigned int hid;
952   unsigned int nhost;
953   
954   GNUNET_assert (num_peers > 0);
955   rc = GNUNET_malloc (sizeof (struct RunContext));
956   if (NULL != host_filename)
957   {
958     rc->num_hosts =
959         GNUNET_TESTBED_hosts_load_from_file (host_filename, &rc->hosts);
960     if (0 == rc->num_hosts)
961     {
962       LOG (GNUNET_ERROR_TYPE_WARNING,
963            _("No hosts loaded. Need at least one host\n"));
964       goto error_cleanup;
965     }
966   }
967   else
968     rc->h = GNUNET_TESTBED_host_create (NULL, NULL, 0);
969   rc->cfg = GNUNET_CONFIGURATION_dup (cfg);
970   rc->num_peers = num_peers;
971   rc->event_mask = event_mask;
972   rc->cc = cc;
973   rc->cc_cls = cc_cls;
974   rc->test_master = test_master;
975   rc->test_master_cls = test_master_cls;
976   rc->state = RC_INIT;
977   rc->topology = GNUNET_TESTBED_TOPOLOGY_NONE;  
978   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string (rc->cfg, "testbed",
979                                                           "OVERLAY_TOPOLOGY",
980                                                           &topology))
981   {
982     if (GNUNET_NO == GNUNET_TESTBED_topology_get_ (&rc->topology,
983                                                     topology))
984     {
985       GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
986                                  "testbed", "OVERLAY_TOPLOGY",
987                                  _("Specified topology must be supported by testbed"));
988     }
989     GNUNET_free (topology);
990   }
991   switch (rc->topology)
992   {
993   case GNUNET_TESTBED_TOPOLOGY_ERDOS_RENYI:
994   case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD_RING:
995   case GNUNET_TESTBED_TOPOLOGY_SMALL_WORLD:
996     if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (rc->cfg, "testbed",
997                                                             "OVERLAY_RANDOM_LINKS",
998                                                             &random_links))
999     {
1000       /* OVERLAY option RANDOM & SMALL_WORLD_RING requires OVERLAY_RANDOM_LINKS
1001          option to be set to the number of random links to be established  */
1002       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1003                                  "testbed", "OVERLAY_RANDOM_LINKS");
1004       goto error_cleanup;
1005     }
1006     if (random_links > UINT32_MAX)
1007     {
1008       GNUNET_break (0);       /* Too big number */
1009       goto error_cleanup;
1010     }
1011     rc->random_links = (unsigned int) random_links;
1012     break;
1013   case GNUNET_TESTBED_TOPOLOGY_FROM_FILE:
1014     if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (rc->cfg, "testbed",
1015                                                             "TOPOLOGY_FILE",
1016                                                             &rc->topo_file))
1017     {
1018       GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
1019                                  "testbed", "TOPOLOGY_FILE");
1020       goto error_cleanup;
1021     }
1022     break;
1023   default:   
1024     /* Do nothing */
1025     break;
1026   }
1027   if (NULL != host_filename)
1028   {
1029     rc->hc_handles = GNUNET_malloc (sizeof (struct
1030                                             GNUNET_TESTBED_HostHabitableCheckHandle *) 
1031                                     * rc->num_hosts);
1032     for (nhost = 0; nhost < rc->num_hosts; nhost++) 
1033     {    
1034       if (NULL == (rc->hc_handles[nhost] = 
1035                    GNUNET_TESTBED_is_host_habitable (rc->hosts[nhost], rc->cfg,
1036                                                      &host_habitable_cb,
1037                                                      rc)))
1038       {
1039         GNUNET_break (0);
1040         for (nhost = 0; nhost < rc->num_hosts; nhost++)
1041           if (NULL != rc->hc_handles[nhost])
1042             GNUNET_TESTBED_is_host_habitable_cancel (rc->hc_handles[nhost]);
1043         GNUNET_free (rc->hc_handles);
1044         rc->hc_handles = NULL;
1045         goto error_cleanup;
1046       }
1047     }
1048   }
1049   else
1050     rc->cproc =
1051       GNUNET_TESTBED_controller_start ("127.0.0.1", rc->h, rc->cfg,
1052                                        &controller_status_cb, rc);
1053   rc->shutdown_run_task =
1054       GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
1055                                     &shutdown_run, rc);
1056   return;
1057
1058  error_cleanup:
1059   if (NULL != rc->h)
1060     GNUNET_TESTBED_host_destroy (rc->h);
1061   if (NULL != rc->hosts)
1062   {
1063     for (hid = 0; hid < rc->num_hosts; hid++)
1064       if (NULL != rc->hosts[hid])
1065         GNUNET_TESTBED_host_destroy (rc->hosts[hid]);
1066     GNUNET_free (rc->hosts);
1067   }
1068   GNUNET_free (rc);
1069 }
1070
1071
1072 /**
1073  * Configure and run a testbed using the given
1074  * master controller on 'num_hosts' starting
1075  * 'num_peers' using the given peer configuration.
1076  *
1077  * @param controller master controller for the testbed
1078  *                   (must not be destroyed until after the
1079  *                    testbed is destroyed).
1080  * @param num_hosts number of hosts in 'hosts', 0 to only
1081  *        use 'localhost'
1082  * @param hosts list of hosts to use for the testbed
1083  * @param num_peers number of peers to start
1084  * @param cfg the configuration to use as a template for peers and also for
1085  *         checking the value of testbed helper binary
1086  * @param underlay_topology underlay topology to create
1087  * @param va topology-specific options
1088  * @return handle to the testbed; NULL upon error (error messaage will be printed)
1089  */
1090 struct GNUNET_TESTBED_Testbed *
1091 GNUNET_TESTBED_create_va (struct GNUNET_TESTBED_Controller *controller,
1092                           unsigned int num_hosts,
1093                           struct GNUNET_TESTBED_Host **hosts,
1094                           unsigned int num_peers,
1095                           const struct GNUNET_CONFIGURATION_Handle *cfg,
1096                           enum GNUNET_TESTBED_TopologyOption underlay_topology,
1097                           va_list va)
1098 {
1099   /* unsigned int nhost; */
1100
1101   /* GNUNET_assert (underlay_topology < GNUNET_TESTBED_TOPOLOGY_NONE); */
1102   /* if (num_hosts != 0) */
1103   /* { */
1104   /*   for (nhost = 0; nhost < num_hosts; nhost++) */
1105   /*   { */
1106   /*     if (GNUNET_YES != GNUNET_TESTBED_is_host_habitable (hosts[nhost], cfg)) */
1107   /*     { */
1108   /*       LOG (GNUNET_ERROR_TYPE_ERROR, _("Host %s cannot start testbed\n"), */
1109   /*            GNUNET_TESTBED_host_get_hostname_ (hosts[nhost])); */
1110   /*       break; */
1111   /*     } */
1112   /*   } */
1113   /*   if (num_hosts != nhost) */
1114   /*     return NULL; */
1115   /* } */
1116   /* We need controller callback here to get operation done events while
1117      linking hosts */
1118   GNUNET_break (0);
1119   return NULL;
1120 }
1121
1122
1123 /**
1124  * Configure and run a testbed using the given
1125  * master controller on 'num_hosts' starting
1126  * 'num_peers' using the given peer configuration.
1127  *
1128  * @param controller master controller for the testbed
1129  *                   (must not be destroyed until after the
1130  *                    testbed is destroyed).
1131  * @param num_hosts number of hosts in 'hosts', 0 to only
1132  *        use 'localhost'
1133  * @param hosts list of hosts to use for the testbed
1134  * @param num_peers number of peers to start
1135  * @param cfg the configuration to use as a template for peers and also for
1136  *         checking the value of testbed helper binary
1137  * @param underlay_topology underlay topology to create
1138  * @param ... topology-specific options
1139  */
1140 struct GNUNET_TESTBED_Testbed *
1141 GNUNET_TESTBED_create (struct GNUNET_TESTBED_Controller *controller,
1142                        unsigned int num_hosts,
1143                        struct GNUNET_TESTBED_Host **hosts,
1144                        unsigned int num_peers,
1145                        const struct GNUNET_CONFIGURATION_Handle *cfg,
1146                        enum GNUNET_TESTBED_TopologyOption underlay_topology,
1147                        ...)
1148 {
1149   struct GNUNET_TESTBED_Testbed *testbed;
1150   va_list vargs;
1151   
1152   va_start (vargs, underlay_topology);
1153   testbed = GNUNET_TESTBED_create_va (controller, num_hosts, hosts, num_peers,
1154                                       cfg, underlay_topology, vargs);
1155   va_end (vargs);
1156   return testbed;
1157 }
1158
1159
1160 /**
1161  * Destroy a testbed.  Stops all running peers and then
1162  * destroys all peers.  Does NOT destroy the master controller.
1163  *
1164  * @param testbed testbed to destroy
1165  */
1166 void
1167 GNUNET_TESTBED_destroy (struct GNUNET_TESTBED_Testbed *testbed)
1168 {
1169   GNUNET_break (0);
1170 }
1171
1172
1173 /* end of testbed_api_testbed.c */