use precomputed zonekeys
[oweals/gnunet.git] / src / gns / test_gns_dht_three_peers.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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 gns/test_gns_dht_threepeer.c
22  * @brief tests dht lookup over 3 peers
23  *
24  * topology:
25  * alice <----> bob <-----> dave
26  *
27  * alice queries for www.buddy.bob.gnunet
28  *
29  */
30 #include "platform.h"
31 #include "gnunet_common.h"
32 #include "gnunet_disk_lib.h"
33 #include "gnunet_testing_lib-new.h"
34 #include "gnunet_testbed_service.h"
35 #include "gnunet_core_service.h"
36 #include "gnunet_dht_service.h"
37 #include "block_dns.h"
38 #include "gnunet_signatures.h"
39 #include "gnunet_namestore_service.h"
40 #include "gnunet_dnsparser_lib.h"
41 #include "gnunet_gns_service.h"
42
43 #define ZONE_PUT_WAIT_TIME GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 30)
44
45 /* If number of peers not in config file, use this number */
46 #define DEFAULT_NUM_PEERS 2
47
48 #define TEST_DOMAIN "www.buddy.bob.gnunet"
49 #define TEST_IP "1.1.1.1"
50 #define TEST_DAVE_PSEU "hagbard"
51 #define TEST_NUM_PEERS 3
52 #define TEST_NUM_CON 3
53
54
55 /* Timeout for entire testcase */
56 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_MINUTES, 5)
57
58 /* Global return value (0 for success, anything else for failure) */
59 static int ok;
60
61 /* Task handle to use to schedule test failure */
62 GNUNET_SCHEDULER_TaskIdentifier die_task;
63 GNUNET_SCHEDULER_TaskIdentifier wait_task;
64
65 struct GNUNET_CRYPTO_ShortHashCode dave_hash;
66
67 struct GNUNET_CRYPTO_ShortHashCode bob_hash;
68
69 const struct GNUNET_CONFIGURATION_Handle *alice_cfg;
70
71 struct GNUNET_TESTBED_Peer **cpeers;
72
73 struct GNUNET_GNS_Handle *gh;
74
75 struct GNUNET_TESTBED_Operation *get_cfg_ops[3];
76 struct GNUNET_TESTBED_Operation *connect_ops[3];
77
78 /**
79  * Check if the get_handle is being used, if so stop the request.  Either
80  * way, schedule the end_badly_cont function which actually shuts down the
81  * test.
82  */
83 static void
84 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
85 {
86   die_task = GNUNET_SCHEDULER_NO_TASK;
87   int c;
88
89   if (GNUNET_SCHEDULER_NO_TASK != wait_task)
90   {
91       GNUNET_SCHEDULER_cancel (wait_task);
92       wait_task = GNUNET_SCHEDULER_NO_TASK;
93   }
94
95   for (c = 0; c < 3; c++)
96   {
97     if (NULL != get_cfg_ops[c])
98     {
99         GNUNET_TESTBED_operation_cancel(get_cfg_ops[c]);
100         get_cfg_ops[c] = NULL;
101     }
102     if (NULL != connect_ops[c])
103     {
104         GNUNET_TESTBED_operation_cancel(connect_ops[c]);
105         connect_ops[c] = NULL;
106     }
107   }
108
109   if (NULL != gh)
110   {
111      GNUNET_GNS_disconnect (gh);
112      gh = NULL;
113   }
114
115   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed \n");
116   GNUNET_break (0);
117   GNUNET_SCHEDULER_shutdown ();
118   ok = 1;
119 }
120
121 static void
122 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
123 {
124   if (GNUNET_SCHEDULER_NO_TASK != die_task)
125   {
126       GNUNET_SCHEDULER_cancel (die_task);
127       die_task = GNUNET_SCHEDULER_NO_TASK;
128   }
129
130   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test successful \n");
131   GNUNET_break (0);
132   GNUNET_SCHEDULER_shutdown ();
133   ok = 0;
134 }
135
136 static void
137 end_now ()
138 {
139   GNUNET_SCHEDULER_add_now (&end, NULL);
140 }
141
142
143 static void
144 disconnect_ns (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
145 {
146   GNUNET_NAMESTORE_disconnect (cls);
147 }
148
149
150 static void
151 cont_ns (void* cls, int32_t s, const char* emsg)
152 {
153   GNUNET_SCHEDULER_add_now (&disconnect_ns, cls);
154 }
155
156 static void
157 on_lookup_result(void *cls, uint32_t rd_count,
158                  const struct GNUNET_NAMESTORE_RecordData *rd)
159 {
160   int i;
161   char* string_val;
162
163   if (rd_count == 0)
164   {
165     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
166                 "Lookup failed!\n");
167     ok = 2;
168   }
169   else
170   {
171     ok = 1;
172     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
173     for (i=0; i<rd_count; i++)
174     {
175       string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
176                                                     rd[i].data,
177                                                     rd[i].data_size);
178       if (0 == strcmp(string_val, TEST_IP))
179       {
180         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
181                     "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val);
182         ok = 0;
183       }
184     }
185   }
186   GNUNET_GNS_disconnect(gh);
187   gh = NULL;
188   end_now ();
189 }
190
191 static void
192 commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
193 {
194   static int wait = 0;
195   wait++;
196   if ((ZONE_PUT_WAIT_TIME.rel_value / 1000) == wait)
197   {
198     fprintf (stderr, "\n");
199     wait_task = GNUNET_SCHEDULER_NO_TASK;
200     gh = GNUNET_GNS_connect(alice_cfg);
201
202     GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_A,
203                       GNUNET_NO,
204                       NULL,
205                       &on_lookup_result, TEST_DOMAIN);
206     if (GNUNET_SCHEDULER_NO_TASK != die_task)
207       GNUNET_SCHEDULER_cancel(die_task);
208     die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup");
209   }
210   else
211   {
212       fprintf (stderr, ".");
213       wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL);
214   }
215 }
216
217 void
218 all_connected ()
219 {
220   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created all connections! Waiting for PUTs\n");
221   wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL);
222 }
223
224
225 static void connect_peers ()
226 {
227   static int started;
228   started ++;
229
230   if (3 == started)
231   {
232       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started\n");
233
234       connect_ops[0] = GNUNET_TESTBED_overlay_connect (NULL,
235           cpeers[0],
236           cpeers[1]);
237
238       connect_ops[1] = GNUNET_TESTBED_overlay_connect (NULL,
239           cpeers[1],
240           cpeers[2]);
241
242       connect_ops[2] = GNUNET_TESTBED_overlay_connect (NULL,
243           cpeers[0],
244           cpeers[2]);
245   }
246 }
247
248 static int
249 setup_dave (const struct GNUNET_CONFIGURATION_Handle * cfg)
250 {
251   struct GNUNET_NAMESTORE_Handle *ns;
252   char* keyfile;
253   char* source;
254   struct GNUNET_CRYPTO_RsaPrivateKey *key;
255   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
256   struct in_addr *web;
257   struct GNUNET_NAMESTORE_RecordData rd;
258
259   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave\n");
260   GNUNET_assert (NULL != cfg);
261   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
262                                                             "ZONEKEY",
263                                                             &keyfile))
264   {
265     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
266     return GNUNET_SYSERR;
267   }
268
269   GNUNET_asprintf (&source, "zonefiles%s%s", DIR_SEPARATOR_STR, "test_zonekey");
270   GNUNET_break (GNUNET_OK == GNUNET_DISK_file_copy (source, keyfile));
271   GNUNET_free (source);
272
273   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
274   if (NULL == key)
275   {
276
277     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
278     GNUNET_free (keyfile);
279     return GNUNET_SYSERR;
280   }
281
282   ns = GNUNET_NAMESTORE_connect (cfg);
283   if (NULL == ns)
284   {
285     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
286     GNUNET_CRYPTO_rsa_key_free (key);
287     GNUNET_free (keyfile);
288     return GNUNET_SYSERR;
289   }
290
291   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
292   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash);
293
294   web = GNUNET_malloc(sizeof(struct in_addr));
295   GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web));
296   rd.data_size = sizeof(struct in_addr);
297   rd.data = web;
298   rd.record_type = GNUNET_GNS_RECORD_A;
299   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
300
301   GNUNET_NAMESTORE_record_create (ns, key, "www", &rd, NULL, NULL);
302
303   rd.data_size = strlen(TEST_DAVE_PSEU);
304   rd.data = TEST_DAVE_PSEU;
305   rd.record_type = GNUNET_GNS_RECORD_PSEU;
306
307   GNUNET_NAMESTORE_record_create (ns, key, "+", &rd, &cont_ns, ns);
308
309   GNUNET_CRYPTO_rsa_key_free(key);
310   GNUNET_free(keyfile);
311   GNUNET_free(web);
312   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave done\n");
313   return GNUNET_OK;
314 }
315
316 static int
317 setup_bob (const struct GNUNET_CONFIGURATION_Handle * cfg)
318 {
319   struct GNUNET_NAMESTORE_Handle *ns;
320   char* keyfile;
321   char* source;
322   struct GNUNET_CRYPTO_RsaPrivateKey *key;
323   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
324   struct GNUNET_NAMESTORE_RecordData rd;
325
326   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob\n");
327   GNUNET_assert (NULL != cfg);
328   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
329                                                             "ZONEKEY",
330                                                             &keyfile))
331   {
332     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
333     return GNUNET_SYSERR;
334   }
335
336   GNUNET_asprintf (&source, "zonefiles%s%s", DIR_SEPARATOR_STR, "OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey");
337   GNUNET_break (GNUNET_OK == GNUNET_DISK_file_copy (source, keyfile));
338   GNUNET_free (source);
339
340   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
341   if (NULL == key)
342   {
343
344     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
345     GNUNET_free (keyfile);
346     return GNUNET_SYSERR;
347   }
348
349   ns = GNUNET_NAMESTORE_connect (cfg);
350   if (NULL == ns)
351   {
352     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
353     GNUNET_CRYPTO_rsa_key_free (key);
354     GNUNET_free (keyfile);
355     return GNUNET_SYSERR;
356   }
357
358   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
359   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash);
360
361   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
362   rd.data = &dave_hash;
363   rd.record_type = GNUNET_GNS_RECORD_PKEY;
364   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
365
366   GNUNET_NAMESTORE_record_create (ns, key, "buddy", &rd, &cont_ns, ns);
367
368   GNUNET_CRYPTO_rsa_key_free(key);
369   GNUNET_free(keyfile);
370   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob done\n");
371   return GNUNET_OK;
372 }
373
374 static int
375 setup_alice (const struct GNUNET_CONFIGURATION_Handle * cfg)
376 {
377   struct GNUNET_NAMESTORE_Handle *ns;
378   char* keyfile;
379   char* source;
380   struct GNUNET_CRYPTO_RsaPrivateKey *key;
381   struct GNUNET_NAMESTORE_RecordData rd;
382
383
384   GNUNET_assert (NULL != cfg);
385   alice_cfg = cfg;
386   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
387                                                             "ZONEKEY",
388                                                             &keyfile))
389   {
390     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
391     return GNUNET_SYSERR;
392   }
393
394   GNUNET_asprintf (&source, "zonefiles%s%s", DIR_SEPARATOR_STR, "188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey");
395   GNUNET_break (GNUNET_OK == GNUNET_DISK_file_copy (source, keyfile));
396   GNUNET_free (source);
397
398   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
399   if (NULL == key)
400   {
401
402     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
403     GNUNET_free (keyfile);
404     return GNUNET_SYSERR;
405   }
406
407   ns = GNUNET_NAMESTORE_connect (cfg);
408   if (NULL == ns)
409   {
410     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
411     GNUNET_CRYPTO_rsa_key_free (key);
412     GNUNET_free (keyfile);
413     return GNUNET_SYSERR;
414   }
415
416   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
417   rd.data = &bob_hash;
418   rd.record_type = GNUNET_GNS_RECORD_PKEY;
419   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
420
421   GNUNET_NAMESTORE_record_create (ns, key, "bob", &rd, &cont_ns, ns);
422
423   GNUNET_CRYPTO_rsa_key_free (key);
424   GNUNET_free (keyfile);
425   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice  done\n");
426   return GNUNET_OK;
427 }
428
429 static void
430 end_badly_now ()
431 {
432   if (GNUNET_SCHEDULER_NO_TASK != die_task)
433     GNUNET_SCHEDULER_cancel (die_task);
434   die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
435 }
436
437 void testbed_master (void *cls,
438                      unsigned int num_peers,
439                      struct GNUNET_TESTBED_Peer **peers)
440 {
441   GNUNET_assert (NULL != peers);
442   cpeers = peers;
443
444   /* peer 0: dave */
445   GNUNET_assert (NULL != peers[0]);
446   get_cfg_ops[0] = GNUNET_TESTBED_peer_get_information (peers[0], GNUNET_TESTBED_PIT_CONFIGURATION);
447
448   /* peer 1: bob */
449   GNUNET_assert (NULL != peers[1]);
450   get_cfg_ops[1] = GNUNET_TESTBED_peer_get_information (peers[1], GNUNET_TESTBED_PIT_CONFIGURATION);
451
452   /* peer 2: alice */
453   GNUNET_assert (NULL != peers[2]);
454   get_cfg_ops[2] = GNUNET_TESTBED_peer_get_information (peers[2], GNUNET_TESTBED_PIT_CONFIGURATION);
455
456 }
457
458 void testbed_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
459 {
460   static int connections = 0;
461   int res;
462
463   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback of type: %u %p \n", event->type, cls);
464   switch (event->type)
465   {
466     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
467       if (get_cfg_ops[0] == event->details.operation_finished.operation)
468       {
469           res = setup_dave (event->details.operation_finished.op_result.cfg);
470           get_cfg_ops[0] = NULL;
471           if (GNUNET_SYSERR == res)
472           {
473               GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
474               end_badly_now();
475           }
476           else
477           {
478               connect_peers ();
479           }
480       }
481       else if (get_cfg_ops[1] ==  event->details.operation_finished.operation)
482       {
483          res = setup_bob (event->details.operation_finished.op_result.cfg);
484          get_cfg_ops[1] = NULL;
485          if (GNUNET_SYSERR == res)
486          {
487              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
488              end_badly_now();
489          }
490          else
491          {
492              connect_peers ();
493          }
494       }
495       else if (get_cfg_ops[2] ==  event->details.operation_finished.operation)
496       {
497          res = setup_alice (event->details.operation_finished.op_result.cfg);
498          get_cfg_ops[2] = NULL;
499          if (GNUNET_SYSERR == res)
500          {
501              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
502              end_badly_now();
503          }
504          else
505          {
506              connect_peers ();
507          }
508       }
509       break;
510     case GNUNET_TESTBED_ET_CONNECT:
511       connections ++;
512       if (connections == 3)
513       {
514           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers connected\n");
515           connect_ops[0] = NULL;
516           connect_ops[1] = NULL;
517           connect_ops[2] = NULL;
518           all_connected ();
519       }
520       break;
521     default:
522       /* whatever ... */
523       break;
524   }
525 }
526
527 int
528 main (int argc, char *argv[])
529 {
530   uint64_t event_mask;
531
532   ok = 0;
533   event_mask = 0;
534   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
535   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
536   GNUNET_TESTBED_test_run ("test_gns_dht_three_peers", "test_gns_dht_default.conf",
537                            3, event_mask,
538                            &testbed_controller_cb, NULL,
539                            &testbed_master, NULL);
540   if (GNUNET_SYSERR == ok)
541     return 1;
542   return 0;
543 }
544
545 /* end of test_gns_dht_three_peers.c */