converting conversation to use new CADET API
[oweals/gnunet.git] / src / cadet / cadet_test_lib.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2012 GNUnet e.V.
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., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file cadet/cadet_test_lib.c
22  * @author Bartlomiej Polot
23  * @brief library for writing CADET tests
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "cadet_test_lib.h"
28 #include "gnunet_cadet_service.h"
29
30 /**
31  * Test context for a CADET Test.
32  */
33 struct GNUNET_CADET_TEST_Context
34 {
35   /**
36    * Array of running peers.
37    */
38   struct GNUNET_TESTBED_Peer **peers;
39
40   /**
41    * Array of handles to the CADET for each peer.
42    */
43   struct GNUNET_CADET_Handle **cadetes;
44
45   /**
46    * Operation associated with the connection to the CADET.
47    */
48   struct GNUNET_TESTBED_Operation **ops;
49
50   /**
51    * Main function of the test to run once all CADETs are available.
52    */
53   GNUNET_CADET_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_CADET_InboundChannelNotificationHandler *new_channel;
69
70   /**
71    * Cleaner for destroyed incoming tunnels.
72    */
73   GNUNET_CADET_ChannelEndHandler *cleaner;
74
75   /**
76    * Message handlers.
77    */
78   struct GNUNET_CADET_MessageHandler* handlers;
79
80   /**
81    * Application ports.
82    */
83   const struct GNUNET_HashCode **ports;
84
85 };
86
87
88 /**
89  * Context for a cadet adapter callback.
90  */
91 struct GNUNET_CADET_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_CADET_TEST_Context *ctx;
102 };
103
104
105 /**
106  * Adapter function called to establish a connection to
107  * the CADET 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 cadet_connect_adapter (void *cls,
117                       const struct GNUNET_CONFIGURATION_Handle *cfg)
118 {
119   struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
120   struct GNUNET_CADET_TEST_Context *ctx = actx->ctx;
121   struct GNUNET_CADET_Handle *h;
122
123   h = GNUNET_CADET_connect (cfg,
124                            (void *) (long) actx->peer,
125                            ctx->cleaner,
126                            ctx->handlers);
127   if (NULL == ctx->ports)
128     return h;
129
130   for (int i = 0; NULL != ctx->ports[i]; i++)
131   {
132     (void ) GNUNET_CADET_open_port (h, ctx->ports[i],
133                                     ctx->new_channel,
134                                     (void *) (long) actx->peer);
135   }
136
137   return h;
138 }
139
140
141 /**
142  * Adapter function called to destroy a connection to
143  * the CADET service.
144  *
145  * @param cls closure
146  * @param op_result service handle returned from the connect adapter
147  */
148 static void
149 cadet_disconnect_adapter (void *cls,
150                          void *op_result)
151 {
152   struct GNUNET_CADET_Handle *cadet = op_result;
153   struct GNUNET_CADET_TEST_AdapterContext *actx = cls;
154
155   GNUNET_free (actx);
156   GNUNET_CADET_disconnect (cadet);
157 }
158
159
160 /**
161  * Callback to be called when a service connect operation is completed.
162  *
163  * @param cls The callback closure from functions generating an operation.
164  * @param op The operation that has been finished.
165  * @param ca_result The service handle returned from
166  *                  GNUNET_TESTBED_ConnectAdapter() (cadet handle).
167  * @param emsg Error message in case the operation has failed.
168  *             NULL if operation has executed successfully.
169  */
170 static void
171 cadet_connect_cb (void *cls,
172                  struct GNUNET_TESTBED_Operation *op,
173                  void *ca_result,
174                  const char *emsg)
175 {
176   struct GNUNET_CADET_TEST_Context *ctx = cls;
177   unsigned int i;
178
179   if (NULL != emsg)
180   {
181     fprintf (stderr, "Failed to connect to CADET service: %s\n",
182              emsg);
183     GNUNET_SCHEDULER_shutdown ();
184     return;
185   }
186   for (i = 0; i < ctx->num_peers; i++)
187     if (op == ctx->ops[i])
188     {
189       ctx->cadetes[i] = ca_result;
190       GNUNET_log (GNUNET_ERROR_TYPE_INFO, "...cadet %u connected\n", i);
191     }
192   for (i = 0; i < ctx->num_peers; i++)
193     if (NULL == ctx->cadetes[i])
194       return; /* still some CADET connections missing */
195   /* all CADET connections ready! */
196   ctx->app_main (ctx->app_main_cls,
197                  ctx,
198                  ctx->num_peers,
199                  ctx->peers,
200                  ctx->cadetes);
201 }
202
203
204 void
205 GNUNET_CADET_TEST_cleanup (struct GNUNET_CADET_TEST_Context *ctx)
206 {
207   unsigned int i;
208
209   for (i = 0; i < ctx->num_peers; i++)
210   {
211     GNUNET_assert (NULL != ctx->ops[i]);
212     GNUNET_TESTBED_operation_done (ctx->ops[i]);
213     ctx->ops[i] = NULL;
214   }
215   GNUNET_free (ctx->ops);
216   GNUNET_free (ctx->cadetes);
217   GNUNET_free (ctx);
218   GNUNET_SCHEDULER_shutdown ();
219 }
220
221
222 /**
223  * Callback run when the testbed is ready (peers running and connected to
224  * each other)
225  *
226  * @param cls Closure (context).
227  * @param h the run handle
228  * @param num_peers Number of peers that are running.
229  * @param peers Handles to each one of the @c num_peers peers.
230  * @param links_succeeded the number of overlay link connection attempts that
231  *          succeeded
232  * @param links_failed the number of overlay link connection attempts that
233  *          failed
234  */
235 static void
236 cadet_test_run (void *cls,
237                struct GNUNET_TESTBED_RunHandle *h,
238                unsigned int num_peers,
239                struct GNUNET_TESTBED_Peer **peers,
240                unsigned int links_succeeded,
241                unsigned int links_failed)
242 {
243   struct GNUNET_CADET_TEST_Context *ctx = cls;
244   unsigned int i;
245
246   if  (num_peers != ctx->num_peers)
247   {
248     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Peers started %u/%u, ending\n",
249                 num_peers, ctx->num_peers);
250     exit (1);
251   }
252   ctx->peers = peers;
253   for (i = 0; i < num_peers; i++)
254   {
255     struct GNUNET_CADET_TEST_AdapterContext *newctx;
256     newctx = GNUNET_new (struct GNUNET_CADET_TEST_AdapterContext);
257     newctx->peer = i;
258     newctx->ctx = ctx;
259     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to cadet %u\n", i);
260     ctx->ops[i] = GNUNET_TESTBED_service_connect (ctx,
261                                                   peers[i],
262                                                   "cadet",
263                                                   &cadet_connect_cb,
264                                                   ctx,
265                                                   &cadet_connect_adapter,
266                                                   &cadet_disconnect_adapter,
267                                                   newctx);
268     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "op handle %p\n", ctx->ops[i]);
269   }
270 }
271
272
273 void
274 GNUNET_CADET_TEST_run (const char *testname,
275                       const char *cfgname,
276                       unsigned int num_peers,
277                       GNUNET_CADET_TEST_AppMain tmain,
278                       void *tmain_cls,
279                       GNUNET_CADET_InboundChannelNotificationHandler new_channel,
280                       GNUNET_CADET_ChannelEndHandler cleaner,
281                       struct GNUNET_CADET_MessageHandler* handlers,
282                       const struct GNUNET_HashCode **ports)
283 {
284   struct GNUNET_CADET_TEST_Context *ctx;
285
286   ctx = GNUNET_new (struct GNUNET_CADET_TEST_Context);
287   ctx->num_peers = num_peers;
288   ctx->ops = GNUNET_malloc (num_peers * sizeof (struct GNUNET_TESTBED_Operation *));
289   ctx->cadetes = GNUNET_malloc (num_peers * sizeof (struct GNUNET_CADET_Handle *));
290   ctx->app_main = tmain;
291   ctx->app_main_cls = tmain_cls;
292   ctx->new_channel = new_channel;
293   ctx->cleaner = cleaner;
294   ctx->handlers = handlers;
295   ctx->ports = ports;
296   GNUNET_TESTBED_test_run (testname,
297                            cfgname,
298                            num_peers,
299                            0LL, NULL, NULL,
300                            &cadet_test_run, ctx);
301 }
302
303 /* end of cadet_test_lib.c */