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