- extra includes to try fix w32
[oweals/gnunet.git] / src / mesh / mesh_test_lib.c
1 /*
2      This file is part of GNUnet.
3      (C) 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  * @file mesh/mesh_test_lib.c
22  * @author Bartlomiej Polot
23  * @brief library for writing MESH tests
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_testing_lib.h"
28 #include "mesh_test_lib.h"
29 #include "gnunet_mesh_service.h"
30
31 /**
32  * Test context for a MESH Test.
33  */
34 struct GNUNET_MESH_TEST_Context
35 {
36   /**
37    * Array of running peers.
38    */
39   struct GNUNET_TESTBED_Peer **peers;
40
41   /**
42    * Array of handles to the MESH for each peer.
43    */
44   struct GNUNET_MESH_Handle **meshes;
45
46   /**
47    * Operation associated with the connection to the MESH.
48    */
49   struct GNUNET_TESTBED_Operation **ops;
50
51   /**
52    * Main function of the test to run once all MESHs are available.
53    */
54   GNUNET_MESH_TEST_AppMain app_main;
55   
56   /**
57    * Closure for 'app_main'.
58    */
59   void *app_main_cls;
60
61   /**
62    * Number of peers running, size of the arrays above.
63    */
64   unsigned int num_peers;
65
66   /**
67    * Handler for incoming tunnels.
68    */
69   GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
70
71   /**
72    * Cleaner for destroyed incoming tunnels.
73    */
74   GNUNET_MESH_TunnelEndHandler *cleaner;
75
76   /**
77    * Message handlers.
78    */
79   struct GNUNET_MESH_MessageHandler* handlers;
80
81   /**
82    * Application types.
83    */
84   const GNUNET_MESH_ApplicationType* stypes;
85
86 };
87
88
89 /**
90  * Context for a mesh adapter callback.
91  */
92 struct GNUNET_MESH_TEST_AdapterContext
93 {
94   /**
95    * Peer number for the particular peer.
96    */
97   unsigned int peer;
98
99   /**
100    * General context.
101    */
102   struct GNUNET_MESH_TEST_Context *ctx;
103 };
104
105
106 /**
107  * Adapter function called to establish a connection to
108  * the MESH service.
109  *
110  * @param cls closure
111  * @param cfg configuration of the peer to connect to; will be available until
112  *          GNUNET_TESTBED_operation_done() is called on the operation returned
113  *          from GNUNET_TESTBED_service_connect()
114  * @return service handle to return in 'op_result', NULL on error
115  */
116 static void *
117 mesh_connect_adapter (void *cls,
118                       const struct GNUNET_CONFIGURATION_Handle *cfg)
119 {
120   struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
121   struct GNUNET_MESH_TEST_Context *ctx = actx->ctx;
122   struct GNUNET_MESH_Handle *h;
123
124   h = GNUNET_MESH_connect (cfg,
125                            (void *) (long) actx->peer,
126                            ctx->new_tunnel,
127                            ctx->cleaner,
128                            ctx->handlers,
129                            ctx->stypes);
130   return h;
131 }
132
133
134 /**
135  * Adapter function called to destroy a connection to
136  * the MESH service.
137  *
138  * @param cls closure
139  * @param op_result service handle returned from the connect adapter
140  */
141 static void 
142 mesh_disconnect_adapter (void *cls,
143                          void *op_result)
144 {
145   struct GNUNET_MESH_Handle *mesh = op_result;
146   struct GNUNET_MESH_TEST_AdapterContext *actx = cls;
147
148   GNUNET_free (actx);
149   GNUNET_MESH_disconnect (mesh);
150 }
151
152
153 /**
154  * Callback to be called when a service connect operation is completed.
155  *
156  * @param cls The callback closure from functions generating an operation.
157  * @param op The operation that has been finished.
158  * @param ca_result The service handle returned from 
159  *                  GNUNET_TESTBED_ConnectAdapter() (mesh handle).
160  * @param emsg Error message in case the operation has failed.
161  *             NULL if operation has executed successfully.
162  */
163 static void 
164 mesh_connect_cb (void *cls,
165                  struct GNUNET_TESTBED_Operation *op,
166                  void *ca_result,
167                  const char *emsg)
168 {
169   struct GNUNET_MESH_TEST_Context *ctx = cls;
170   unsigned int i;
171  
172   if (NULL != emsg)
173   {
174     fprintf (stderr, "Failed to connect to MESH service: %s\n",
175              emsg);
176     GNUNET_SCHEDULER_shutdown ();
177     return;
178   }
179   for (i = 0; i < ctx->num_peers; i++)
180     if (op == ctx->ops[i])
181       ctx->meshes[i] = ca_result;
182   for (i = 0; i < ctx->num_peers; i++)
183     if (NULL == ctx->meshes[i])
184       return; /* still some MESH connections missing */
185   /* all MESH connections ready! */
186   ctx->app_main (ctx->app_main_cls,
187                  ctx,
188                  ctx->num_peers,
189                  ctx->peers,
190                  ctx->meshes);
191 }
192
193
194 /**
195  * Clean up the testbed.
196  *
197  * @param ctx handle for the testbed
198  */
199 void
200 GNUNET_MESH_TEST_cleanup (struct GNUNET_MESH_TEST_Context *ctx)
201 {
202   unsigned int i;
203
204   for (i = 0; i < ctx->num_peers; i++)
205     GNUNET_TESTBED_operation_done (ctx->ops[i]);
206   GNUNET_free (ctx->ops);
207   GNUNET_free (ctx->meshes);
208   GNUNET_free (ctx);
209   GNUNET_SCHEDULER_shutdown ();
210 }
211
212
213 /**
214  * Callback run when the testbed is ready (peers running and connected to
215  * each other)
216  * 
217  * @param cls Closure (context).
218  * @param num_peers Number of peers that are running.
219  * @param peers Handles to each one of the @c num_peers peers.
220  */
221 static void
222 mesh_test_run (void *cls,
223                unsigned int num_peers,
224                struct GNUNET_TESTBED_Peer **peers)
225 {
226   struct GNUNET_MESH_TEST_Context *ctx = cls;
227   unsigned int i;
228
229   GNUNET_assert (num_peers == ctx->num_peers);
230   ctx->peers = peers;
231   for (i = 0; i < num_peers; i++)
232   {
233     struct GNUNET_MESH_TEST_AdapterContext *newctx;
234     newctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_AdapterContext));
235     newctx->peer = i;
236     newctx->ctx = ctx;
237     ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
238                                                   peers[i],
239                                                   "mesh",
240                                                   &mesh_connect_cb,
241                                                   ctx,
242                                                   &mesh_connect_adapter,
243                                                   &mesh_disconnect_adapter,
244                                                   newctx);
245   }
246 }
247
248
249 /**
250  * Run a test using the given name, configuration file and number of
251  * peers.
252  * All mesh callbacks will receive the peer number as the closure.
253  *
254  * @param testname Name of the test (for logging).
255  * @param cfgname Name of the configuration file.
256  * @param num_peers Number of peers to start.
257  * @param tmain Main function to run once the testbed is ready.
258  * @param tmain_cls Closure for 'tmain'.
259  * @param new_tunnel Handler for incoming tunnels.
260  * @param cleaner Cleaner for destroyed incoming tunnels.
261  * @param handlers Message handlers.
262  * @param stypes Application types.
263  */
264 void 
265 GNUNET_MESH_TEST_run (const char *testname,
266                       const char *cfgname,
267                       unsigned int num_peers,
268                       GNUNET_MESH_TEST_AppMain tmain,
269                       void *tmain_cls,
270                       GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
271                       GNUNET_MESH_TunnelEndHandler cleaner,
272                       struct GNUNET_MESH_MessageHandler* handlers,
273                       const GNUNET_MESH_ApplicationType* stypes)
274 {
275   struct GNUNET_MESH_TEST_Context *ctx;
276   
277   ctx = GNUNET_malloc (sizeof (struct GNUNET_MESH_TEST_Context));
278   ctx->num_peers = num_peers;
279   ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
280   ctx->meshes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_MESH_Handle *));
281   ctx->app_main = tmain;
282   ctx->app_main_cls = tmain_cls;
283   ctx->new_tunnel = new_tunnel;
284   ctx->cleaner = cleaner;
285   ctx->handlers = handlers;
286   ctx->stypes = stypes;
287   GNUNET_TESTBED_test_run (testname,
288                            cfgname,
289                            num_peers,
290                            0LL, NULL, NULL,
291                            &mesh_test_run, ctx);
292 }
293
294 /* end of mesh_test_lib.c */