-add option for future use
[oweals/gnunet.git] / doc / testbed_test.c
1 #include <unistd.h>
2 #include <gnunet/platform.h>
3 #include <gnunet/gnunet_util_lib.h>
4 #include <gnunet/gnunet_testbed_service.h>
5 #include <gnunet/gnunet_dht_service.h>
6
7 /* Number of peers we want to start */
8 #define NUM_PEERS 20
9
10 static struct GNUNET_TESTBED_Operation *dht_op;
11
12 static struct GNUNET_DHT_Handle *dht_handle;
13
14 static GNUNET_SCHEDULER_TaskIdentifier shutdown_tid;
15
16
17 /**
18  * Closure to 'dht_ca' and 'dht_da' DHT adapters.
19  */
20 struct MyContext
21 {
22   /**
23    * Argument we pass to GNUNET_DHT_connect.
24    */
25   int ht_len;
26 } ctxt;
27
28
29 /**
30  * Global result for testcase.
31  */
32 static int result;
33
34
35 /**
36  * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
37  * Cleans up.
38  */
39 static void 
40 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
41 {
42   shutdown_tid = GNUNET_SCHEDULER_NO_TASK;
43   if (NULL != dht_op)
44   {  
45     GNUNET_TESTBED_operation_done (dht_op); /* indirectly calls the dht_da() for closing
46                                                down the connection to the DHT */
47     dht_op = NULL;
48     dht_handle = NULL;
49   }
50   result = GNUNET_OK;
51   GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
52 }
53
54
55 /**
56  * This is where the test logic should be, at least that
57  * part of it that uses the DHT of peer "0".
58  *
59  * @param cls closure, for the example: NULL
60  * @param op should be equal to "dht_op"
61  * @param ca_result result of the connect operation, the
62  *        connection to the DHT service
63  * @param emsg error message, if testbed somehow failed to
64  *        connect to the DHT.
65  */
66 static void
67 service_connect_comp (void *cls,
68                       struct GNUNET_TESTBED_Operation *op,
69                       void *ca_result,
70                       const char *emsg)
71 {    
72   GNUNET_assert (op == dht_op);
73   dht_handle = ca_result;
74   /* Service to DHT successful; here we'd usually do something 
75      with the DHT (ok, if successful) */
76
77   /* for now, just indiscriminately terminate after 10s */
78   GNUNET_SCHEDULER_cancel (shutdown_tid);
79   shutdown_tid = GNUNET_SCHEDULER_add_delayed 
80       (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
81        &shutdown_task, NULL);
82 }
83
84
85 /**
86  * Testbed has provided us with the configuration to access one
87  * of the peers and it is time to do "some" connect operation to
88  * "some" subsystem of the peer.  For this example, we connect
89  * to the DHT subsystem.  Testbed doesn't know which subsystem,
90  * so we need these adapters to do the actual connecting (and
91  * possibly pass additional options to the subsystem connect
92  * function, such as the "ht_len" argument for the DHT).
93  *
94  * @param cls closure
95  * @param cfg peer configuration (here: peer[0]
96  * @return NULL on error, otherwise some handle to access the
97  *         subsystem
98  */
99 static void *
100 dht_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
101 {
102   struct MyContext *ctxt = cls;
103
104   /* Use the provided configuration to connect to service */
105   dht_handle = GNUNET_DHT_connect (cfg, ctxt->ht_len);  
106   return dht_handle;
107 }
108
109
110 /**
111  * Dual of 'dht_ca' to perform the 'disconnect'/cleanup operation
112  * once we no longer need to access this subsystem.
113  *
114  * @param op_result whatever we returned from 'dht_ca'
115  */
116 static void 
117 dht_da (void *cls, void *op_result)
118 {
119   struct MyContext *ctxt = cls;
120   
121   /* Disconnect from DHT service */  
122   GNUNET_DHT_disconnect ((struct GNUNET_DHT_Handle *) op_result);
123   dht_handle = NULL;
124 }
125
126
127 /**
128  * Main function inovked from TESTBED once all of the
129  * peers are up and running.  This one then connects
130  * just to the DHT service of peer 0.
131  *
132  * @param cls closure
133  * @param num_peers size of the 'peers' array
134  * @param links_succeeded number of links between peers that were created
135  * @param links_failed number of links testbed was unable to establish
136  */
137 static void
138 test_master (void *cls, unsigned int num_peers,
139              struct GNUNET_TESTBED_Peer **peers,
140              unsigned int links_succeeeded,
141              unsigned int links_failed)
142 {
143   /* Testbed is ready with peers running and connected in a pre-defined overlay
144      topology  */
145
146   /* do something */
147   ctxt.ht_len = 10;
148
149   /* connect to a peers service */
150   dht_op = GNUNET_TESTBED_service_connect 
151       (NULL,                    /* Closure for operation */
152        peers[0],                /* The peer whose service to connect to */
153        "dht",                   /* The name of the service */
154        service_connect_comp,    /* callback to call after a handle to service
155                                    is opened */
156        NULL,                    /* closure for the above callback */
157        dht_ca,                  /* callback to call with peer's configuration;
158                                    this should open the needed service connection */
159        dht_da,                  /* callback to be called when closing the
160                                    opened service connection */
161        &ctxt);                  /* closure for the above two callbacks */
162   shutdown_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
163                                                &shutdown_task, NULL);
164 }
165
166
167 int
168 main (int argc, char **argv)
169 {
170   int ret;
171
172   result = GNUNET_SYSERR;
173   ret = GNUNET_TESTBED_test_run 
174       ("awesome-test",  /* test case name */
175        "template.conf", /* template configuration */
176        NUM_PEERS,       /* number of peers to start */
177        0LL, /* Event mask - set to 0 for no event notifications */
178        NULL, /* Controller event callback */
179        NULL, /* Closure for controller event callback */
180        &test_master, /* continuation callback to be called when testbed setup is
181                         complete */
182        NULL); /* Closure for the test_master callback */
183   if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
184     return 1;
185   return 0;
186 }