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