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