Check return value of GNUNET_STATISTICS_get
[oweals/gnunet.git] / src / revocation / test_revocation.c
1 /*
2    This file is part of GNUnet.
3    (C) 2009, 2013 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 revocation/test_revocation.c
22  * @brief base testcase for revocation exchange
23  * @author Matthias Wachs
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_core_service.h"
28 #include "gnunet_identity_service.h"
29 #include "gnunet_revocation_service.h"
30 #include "gnunet_testbed_service.h"
31
32 #define NUM_TEST_PEERS 2
33
34 struct TestPeer
35 {
36   struct GNUNET_TESTBED_Peer *p;
37   struct GNUNET_TESTBED_Operation *identity_op;
38   struct GNUNET_TESTBED_Operation *core_op;
39   struct GNUNET_IDENTITY_Handle *idh;
40   const struct GNUNET_CONFIGURATION_Handle *cfg;
41   const struct GNUNET_CRYPTO_EcdsaPrivateKey *privkey;
42   struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
43   struct GNUNET_CRYPTO_EcdsaSignature sig;
44   struct GNUNET_IDENTITY_Operation *create_id_op;
45   struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
46   struct GNUNET_REVOCATION_Handle *revok_handle;
47   struct GNUNET_CORE_Handle *ch;
48   uint64_t pow;
49 };
50
51 static struct TestPeer testpeers[2];
52
53 /**
54  * Return value from main, set to 0 on success.
55  */
56 static int ok;
57
58
59 static void
60 do_shutdown (void *cls,
61              const struct GNUNET_SCHEDULER_TaskContext *tc)
62 {
63   unsigned int c;
64
65   for (c = 0; c < NUM_TEST_PEERS; c++)
66   {
67     if (NULL != testpeers[c].create_id_op)
68     {
69       GNUNET_IDENTITY_cancel (testpeers[c].create_id_op);
70       testpeers[c].create_id_op = NULL;
71     }
72     if (NULL != testpeers[c].ego_lookup)
73     {
74       GNUNET_IDENTITY_ego_lookup_cancel (testpeers[c].ego_lookup);
75       testpeers[c].ego_lookup = NULL;
76     }
77     if (NULL != testpeers[c].revok_handle)
78     {
79       GNUNET_REVOCATION_revoke_cancel (testpeers[c].revok_handle);
80       testpeers[c].revok_handle = NULL;
81     }
82     if (NULL != testpeers[c].identity_op)
83     {
84       GNUNET_TESTBED_operation_done (testpeers[c].identity_op);
85       testpeers[c].identity_op = NULL;
86     }
87     if (NULL != testpeers[c].core_op)
88     {
89       GNUNET_TESTBED_operation_done (testpeers[c].core_op);
90       testpeers[c].core_op = NULL;
91     }
92   }
93 }
94
95
96 static void
97 check_revocation (void *cls,
98                   const struct GNUNET_SCHEDULER_TaskContext *tc);
99
100
101 static void
102 revocation_remote_cb (void *cls,
103                       int is_valid)
104 {
105   static int repeat = 0;
106
107   if (GNUNET_NO == is_valid)
108   {
109     fprintf (stderr,
110              "Local revocation successful\n");
111     ok = 0;
112     GNUNET_SCHEDULER_shutdown ();
113     return;
114   }
115   if (repeat < 10)
116   {
117     repeat++;
118     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
119                                   &check_revocation,
120                                   NULL);
121     return;
122   }
123   fprintf (stderr,
124            "Flooding of revocation failed\n");
125   ok = 2;
126   GNUNET_SCHEDULER_shutdown ();
127 }
128
129
130 static void
131 check_revocation (void *cls,
132                   const struct GNUNET_SCHEDULER_TaskContext *tc)
133 {
134   GNUNET_REVOCATION_query (testpeers[0].cfg,
135                            &testpeers[1].pubkey,
136                            &revocation_remote_cb, NULL);
137 }
138
139
140 static void
141 revocation_cb (void *cls,
142                int is_valid)
143 {
144   testpeers[1].revok_handle = NULL;
145   if (GNUNET_NO == is_valid)
146   {
147     fprintf (stderr,
148              "Revocation successful\n");
149     check_revocation (NULL, NULL);
150   }
151 }
152
153
154 static void
155 ego_cb (void *cls,
156         const struct GNUNET_IDENTITY_Ego *ego)
157 {
158   static int completed = 0;
159
160   if ((NULL != ego) && (cls == &testpeers[0]))
161   {
162     testpeers[0].ego_lookup = NULL;
163     testpeers[0].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
164     GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[0].pubkey);
165     completed++;
166   }
167   if ((NULL != ego) && (cls == &testpeers[1]))
168   {
169     testpeers[1].ego_lookup = NULL;
170     testpeers[1].privkey = GNUNET_IDENTITY_ego_get_private_key (ego);
171     GNUNET_IDENTITY_ego_get_public_key (ego, &testpeers[1].pubkey);
172     GNUNET_REVOCATION_sign_revocation (testpeers[1].privkey, &testpeers[1].sig);
173
174     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
175                "Calculating proof of work...\n");
176     testpeers[1].pow = 0;
177     int res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey,
178         testpeers[1].pow, 5);
179     while (GNUNET_OK != res)
180     {
181       testpeers[1].pow++;
182       res = GNUNET_REVOCATION_check_pow (&testpeers[1].pubkey,
183                                          testpeers[1].pow,
184                                          5);
185     }
186     fprintf (stderr,
187              "Done calculating proof of work\n");
188     completed++;
189   }
190   if (2 == completed)
191   {
192     GNUNET_log(GNUNET_ERROR_TYPE_INFO,
193                "Egos retrieved\n");
194     testpeers[1].revok_handle
195       = GNUNET_REVOCATION_revoke (testpeers[1].cfg,
196                                   &testpeers[1].pubkey,
197                                   &testpeers[1].sig,
198                                   testpeers[1].pow,
199                                   &revocation_cb, NULL);
200   }
201 }
202
203
204 static void
205 identity_create_cb (void *cls,
206                     const char *emsg)
207 {
208   static int completed = 0;
209
210   if ((NULL == emsg) && (cls == &testpeers[0]))
211   {
212     testpeers[0].create_id_op = NULL;
213     completed++;
214   }
215   if ((NULL == emsg) && (cls == &testpeers[1]))
216   {
217     testpeers[1].create_id_op = NULL;
218     completed++;
219   }
220   if (2 != completed)
221     return;
222   fprintf (stderr,
223            "Identities created\n");
224   testpeers[0].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[0].cfg,
225                                                         "client",
226                                                         &ego_cb,
227                                                         &testpeers[0]);
228   testpeers[1].ego_lookup = GNUNET_IDENTITY_ego_lookup (testpeers[1].cfg,
229                                                         "toberevoked",
230                                                         &ego_cb,
231                                                         &testpeers[1]);
232 }
233
234
235 static void
236 identity_completion_cb (void *cls,
237                         struct GNUNET_TESTBED_Operation *op,
238                         void *ca_result,
239                         const char *emsg)
240 {
241   static int completed = 0;
242
243   completed++;
244   if (NUM_TEST_PEERS != completed)
245     return;
246   fprintf (stderr,
247            "All peers connected @ IDENTITY ...\n");
248   testpeers[0].create_id_op
249     = GNUNET_IDENTITY_create (testpeers[0].idh,
250                               "client",
251                               &identity_create_cb,
252                               &testpeers[0]);
253   testpeers[1].create_id_op
254     = GNUNET_IDENTITY_create (testpeers[1].idh,
255                               "toberevoked",
256                               &identity_create_cb,
257                               &testpeers[1]);
258 }
259
260
261 static void *
262 identity_connect_adapter (void *cls,
263                           const struct GNUNET_CONFIGURATION_Handle *cfg)
264 {
265   struct TestPeer *me = cls;
266   me->cfg = cfg;
267   me->idh = GNUNET_IDENTITY_connect (cfg, NULL, NULL );
268   if (NULL == me->idh)
269     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
270                "Failed to create IDENTITY handle \n");
271   return me->idh;
272 }
273
274
275 static void
276 identity_disconnect_adapter (void *cls,
277                              void *op_result)
278 {
279   struct TestPeer *me = cls;
280   GNUNET_IDENTITY_disconnect (me->idh);
281   me->idh = NULL;
282 }
283
284
285 static void
286 connect_cb (void *cls,
287             const struct GNUNET_PeerIdentity *peer)
288 {
289   static int connects = 0;
290
291   connects++;
292   if (NUM_TEST_PEERS * NUM_TEST_PEERS == connects)
293   {
294     fprintf (stderr,
295              "All peers connected @ CORE ...\n");
296
297     /* Connect to identity service */
298     testpeers[0].identity_op
299       = GNUNET_TESTBED_service_connect (NULL,
300                                         testpeers[0].p, "identity",
301                                         &identity_completion_cb, NULL,
302                                         &identity_connect_adapter,
303                                         &identity_disconnect_adapter,
304                                         &testpeers[0]);
305     testpeers[1].identity_op
306       = GNUNET_TESTBED_service_connect (NULL,
307                                         testpeers[1].p, "identity",
308                                         *identity_completion_cb, NULL,
309                                         &identity_connect_adapter,
310                                         &identity_disconnect_adapter,
311                                         &testpeers[1]);
312   }
313 }
314
315
316 static void
317 core_completion_cb (void *cls,
318                     struct GNUNET_TESTBED_Operation *op,
319                     void *ca_result,
320                     const char *emsg)
321 {
322   static int completed = 0;
323
324   completed++;
325   if (NUM_TEST_PEERS == completed)
326   {
327     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
328                 "Connected to CORE\n");
329   }
330 }
331
332
333 static void *
334 core_connect_adapter (void *cls,
335                       const struct GNUNET_CONFIGURATION_Handle *cfg)
336 {
337   struct TestPeer *me = cls;
338
339   me->cfg = cfg;
340   me->ch = GNUNET_CORE_connect (cfg, me, NULL,
341                                 &connect_cb, NULL,
342                                 NULL, GNUNET_NO,
343                                 NULL, GNUNET_NO,
344                                 NULL);
345   if (NULL == me->ch)
346     GNUNET_log(GNUNET_ERROR_TYPE_ERROR,
347                "Failed to create CORE handle \n");
348   return me->ch;
349 }
350
351
352 static void
353 core_disconnect_adapter (void *cls,
354                          void *op_result)
355 {
356   struct TestPeer *me = cls;
357
358   GNUNET_CORE_disconnect (me->ch);
359   me->ch = NULL;
360 }
361
362
363 static void
364 test_connection (void *cls,
365                  struct GNUNET_TESTBED_RunHandle *h,
366                  unsigned int num_peers,
367                  struct GNUNET_TESTBED_Peer **peers,
368                  unsigned int links_succeeded,
369                  unsigned int links_failed)
370 {
371   unsigned int c;
372
373   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MINUTES,
374                                 &do_shutdown, NULL);
375
376   if (NUM_TEST_PEERS != num_peers)
377   {
378     ok = 4;
379     fprintf (stderr,
380              "Only %u out of %u peers were started ...\n",
381              num_peers,
382              NUM_TEST_PEERS);
383     GNUNET_SCHEDULER_shutdown ();
384     return;
385   }
386    /* We are generating a CLIQUE */
387   if (NUM_TEST_PEERS * (NUM_TEST_PEERS -1) == links_succeeded)
388   {
389     fprintf (stderr,
390              "Testbed connected peers, initializing test\n");
391     for (c = 0; c < num_peers; c++)
392     {
393       testpeers[c].p = peers[c];
394       testpeers[c].core_op
395         = GNUNET_TESTBED_service_connect (NULL,
396                                           testpeers[c].p,
397                                           "core",
398                                           &core_completion_cb, NULL,
399                                           &core_connect_adapter,
400                                           &core_disconnect_adapter,
401                                           &testpeers[c]);
402     }
403   }
404   else
405   {
406     fprintf (stderr,
407              "Testbed failed to connect peers\n");
408     ok = 5;
409     GNUNET_SCHEDULER_shutdown ();
410     return;
411   }
412 }
413
414
415 int
416 main (int argc,
417       char *argv[])
418 {
419   ok = 1;
420   /* Connecting initial topology */
421   (void) GNUNET_TESTBED_test_run ("test-revocation",
422                                   "test_revocation.conf",
423                                   NUM_TEST_PEERS, 0,
424                                   NULL, NULL,
425                                   &test_connection, NULL);
426   return ok;
427 }
428
429 /* end of test_revocation.c */