test working, but fails
[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 struct GNUNET_TESTBED_Peer **cpeers;
70
71 struct GNUNET_GNS_Handle *gh;
72
73 struct GNUNET_TESTBED_Operation *get_cfg_ops[3];
74 struct GNUNET_TESTBED_Operation *connect_ops[3];
75 struct GNUNET_CONFIGURATION_Handle *cfg_handles[3];
76 struct GNUNET_NAMESTORE_Handle *nh[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 != nh[c])
98     {
99       GNUNET_NAMESTORE_disconnect(nh[c]);
100       nh[c] = NULL;
101     }
102     if (NULL != get_cfg_ops[c])
103     {
104         GNUNET_TESTBED_operation_cancel(get_cfg_ops[c]);
105         get_cfg_ops[c] = NULL;
106     }
107     if (NULL != connect_ops[c])
108     {
109         GNUNET_TESTBED_operation_cancel(connect_ops[c]);
110         connect_ops[c] = NULL;
111     }
112     if (NULL != cfg_handles[c])
113     {
114       GNUNET_CONFIGURATION_destroy (cfg_handles[c]);
115       cfg_handles[c] = NULL;
116     }
117   }
118
119   if (NULL != gh)
120   {
121      GNUNET_GNS_disconnect (gh);
122      gh = NULL;
123   }
124
125   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed \n");
126   GNUNET_break (0);
127   GNUNET_SCHEDULER_shutdown ();
128   ok = 1;
129 }
130
131 static void
132 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
133 {
134   int c;
135   if (GNUNET_SCHEDULER_NO_TASK != die_task)
136   {
137       GNUNET_SCHEDULER_cancel (die_task);
138       die_task = GNUNET_SCHEDULER_NO_TASK;
139   }
140
141   for (c = 0; c < 3; c++)
142   {
143     if (NULL != nh[c])
144     {
145       GNUNET_NAMESTORE_disconnect(nh[c]);
146       nh[c] = NULL;
147     }
148     if (NULL != cfg_handles[c])
149     {
150       GNUNET_CONFIGURATION_destroy (cfg_handles[c]);
151       cfg_handles[c] = NULL;
152     }
153   }
154
155   if (0 == ok)
156     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test ended successful\n");
157   else
158     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed\n");
159   GNUNET_SCHEDULER_shutdown ();
160 }
161
162 static void
163 end_now ()
164 {
165   GNUNET_SCHEDULER_add_now (&end, NULL);
166 }
167
168
169 static void
170 disconnect_ns (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
171 {
172
173   GNUNET_NAMESTORE_disconnect (cls);
174   if (cls == nh[0])
175     nh[0] = NULL;
176   if (cls == nh[1])
177     nh[1] = NULL;
178   if (cls == nh[2])
179     nh[2] = NULL;
180 }
181
182
183 static void
184 cont_ns (void* cls, int32_t s, const char* emsg)
185 {
186   GNUNET_SCHEDULER_add_now (&disconnect_ns, cls);
187 }
188
189 static void
190 on_lookup_result(void *cls, uint32_t rd_count,
191                  const struct GNUNET_NAMESTORE_RecordData *rd)
192 {
193   int i;
194   char* string_val;
195
196   if (rd_count == 0)
197   {
198     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
199                 "Lookup failed!\n");
200     ok = 2;
201   }
202   else
203   {
204     ok = 1;
205     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
206     for (i=0; i<rd_count; i++)
207     {
208       string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
209                                                     rd[i].data,
210                                                     rd[i].data_size);
211       if (0 == strcmp(string_val, TEST_IP))
212       {
213         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
214                     "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val);
215         ok = 0;
216       }
217     }
218   }
219   GNUNET_GNS_disconnect(gh);
220   gh = NULL;
221   end_now ();
222 }
223
224 static void
225 commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
226 {
227   static int wait = 0;
228   wait++;
229   if ((ZONE_PUT_WAIT_TIME.rel_value / 1000) == wait)
230   {
231     fprintf (stderr, "\n");
232     wait_task = GNUNET_SCHEDULER_NO_TASK;
233     GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_A,
234                       GNUNET_NO,
235                       NULL,
236                       &on_lookup_result, TEST_DOMAIN);
237     if (GNUNET_SCHEDULER_NO_TASK != die_task)
238       GNUNET_SCHEDULER_cancel(die_task);
239     die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup");
240   }
241   else
242   {
243       fprintf (stderr, ".");
244       wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL);
245   }
246 }
247
248 void
249 all_connected ()
250 {
251   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created all connections! Waiting for PUTs\n");
252   wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL);
253 }
254
255
256 static void connect_peers ()
257 {
258   static int started;
259   started ++;
260
261   if (3 == started)
262   {
263       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started\n");
264
265       connect_ops[0] = GNUNET_TESTBED_overlay_connect (NULL,
266           cpeers[0],
267           cpeers[1]);
268
269       connect_ops[1] = GNUNET_TESTBED_overlay_connect (NULL,
270           cpeers[1],
271           cpeers[2]);
272
273       connect_ops[2] = GNUNET_TESTBED_overlay_connect (NULL,
274           cpeers[0],
275           cpeers[2]);
276   }
277 }
278
279 static int
280 setup_dave (const struct GNUNET_CONFIGURATION_Handle * cfg)
281 {
282   char* keyfile;
283   char* source;
284   struct GNUNET_CRYPTO_RsaPrivateKey *key;
285   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
286   struct in_addr *web;
287   struct GNUNET_NAMESTORE_RecordData rd;
288
289   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave\n");
290   cfg_handles[0] = GNUNET_CONFIGURATION_dup (cfg);
291   GNUNET_assert (NULL != cfg_handles[0]);
292   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg_handles[0], "gns",
293                                                             "ZONEKEY",
294                                                             &keyfile))
295   {
296     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
297     return GNUNET_SYSERR;
298   }
299
300   GNUNET_asprintf (&source, "zonefiles%s%s", DIR_SEPARATOR_STR, "test_zonekey");
301   if (GNUNET_OK == GNUNET_DISK_file_test (source))
302   {
303       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Copy `%s' to `%s'\n", source, keyfile);
304       GNUNET_DISK_file_copy (source, keyfile);
305   }
306   else
307     GNUNET_break (0);
308   GNUNET_free (source);
309
310   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
311   if (NULL == key)
312   {
313
314     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
315     GNUNET_free (keyfile);
316     return GNUNET_SYSERR;
317   }
318
319   nh[0] = GNUNET_NAMESTORE_connect (cfg_handles[0]);
320   if (NULL == nh[0])
321   {
322     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
323     GNUNET_CRYPTO_rsa_key_free (key);
324     GNUNET_free (keyfile);
325     return GNUNET_SYSERR;
326   }
327
328   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
329   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash);
330
331   web = GNUNET_malloc(sizeof(struct in_addr));
332   GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web));
333   rd.data_size = sizeof(struct in_addr);
334   rd.data = web;
335   rd.record_type = GNUNET_GNS_RECORD_A;
336   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
337
338   GNUNET_NAMESTORE_record_create (nh[0], key, "www", &rd, NULL, NULL);
339
340   rd.data_size = strlen(TEST_DAVE_PSEU);
341   rd.data = TEST_DAVE_PSEU;
342   rd.record_type = GNUNET_GNS_RECORD_PSEU;
343
344   GNUNET_NAMESTORE_record_create (nh[0], key, "+", &rd, &cont_ns, nh[0]);
345
346   GNUNET_CRYPTO_rsa_key_free(key);
347   GNUNET_free(keyfile);
348   GNUNET_free(web);
349   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave done\n");
350   return GNUNET_OK;
351 }
352
353 static int
354 setup_bob (const struct GNUNET_CONFIGURATION_Handle * cfg)
355 {
356   char* keyfile;
357   char* source;
358   struct GNUNET_CRYPTO_RsaPrivateKey *key;
359   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
360   struct GNUNET_NAMESTORE_RecordData rd;
361
362   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob\n");
363   GNUNET_assert (NULL != cfg);
364   cfg_handles[1] = GNUNET_CONFIGURATION_dup (cfg);
365   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg_handles[1], "gns",
366                                                             "ZONEKEY",
367                                                             &keyfile))
368   {
369     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
370     return GNUNET_SYSERR;
371   }
372
373   GNUNET_asprintf (&source, "zonefiles%s%s", DIR_SEPARATOR_STR, "OEFL7A4VEF1B40QLEMTG5D8G1CN6EN16QUSG5R2DT71GRJN34LSG.zkey");
374   if (GNUNET_OK == GNUNET_DISK_file_test (source))
375   {
376       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Copy `%s' to `%s'\n", source, keyfile);
377       GNUNET_DISK_file_copy (source, keyfile);
378   }
379   else
380     GNUNET_break (0);
381   GNUNET_free (source);
382
383
384   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
385   if (NULL == key)
386   {
387
388     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
389     GNUNET_free (keyfile);
390     return GNUNET_SYSERR;
391   }
392
393   nh[1] = GNUNET_NAMESTORE_connect (cfg_handles[1]);
394   if (NULL == nh[1])
395   {
396     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
397     GNUNET_CRYPTO_rsa_key_free (key);
398     GNUNET_free (keyfile);
399     return GNUNET_SYSERR;
400   }
401
402   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
403   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash);
404
405   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
406   rd.data = &dave_hash;
407   rd.record_type = GNUNET_GNS_RECORD_PKEY;
408   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
409
410   GNUNET_NAMESTORE_record_create (nh[1], key, "buddy", &rd, &cont_ns, nh[1]);
411
412   GNUNET_CRYPTO_rsa_key_free(key);
413   GNUNET_free(keyfile);
414   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob done\n");
415   return GNUNET_OK;
416 }
417
418 static int
419 setup_alice (const struct GNUNET_CONFIGURATION_Handle * cfg)
420 {
421   char* keyfile;
422   char* source;
423   struct GNUNET_CRYPTO_RsaPrivateKey *key;
424   struct GNUNET_NAMESTORE_RecordData rd;
425
426
427   GNUNET_assert (NULL != cfg);
428   cfg_handles[2] = GNUNET_CONFIGURATION_dup (cfg);
429   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg_handles[2], "gns",
430                                                             "ZONEKEY",
431                                                             &keyfile))
432   {
433     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
434     return GNUNET_SYSERR;
435   }
436
437   GNUNET_asprintf (&source, "zonefiles%s%s", DIR_SEPARATOR_STR, "188JSUMKEF25GVU8TTV0PBNNN8JVCPUEDFV1UHJJU884JD25V0T0.zkey");
438   if (GNUNET_OK == GNUNET_DISK_file_test (source))
439   {
440       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Copy `%s' to `%s'\n", source, keyfile);
441       GNUNET_DISK_file_copy (source, keyfile);
442   }
443   else
444     GNUNET_break (0);
445   GNUNET_free (source);
446
447   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
448   if (NULL == key)
449   {
450
451     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
452     GNUNET_free (keyfile);
453     return GNUNET_SYSERR;
454   }
455
456   nh[2] = GNUNET_NAMESTORE_connect (cfg_handles[2]);
457   if (NULL == nh[2])
458   {
459     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
460     GNUNET_CRYPTO_rsa_key_free (key);
461     GNUNET_free (keyfile);
462     return GNUNET_SYSERR;
463   }
464
465   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
466   rd.data = &bob_hash;
467   rd.record_type = GNUNET_GNS_RECORD_PKEY;
468   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
469
470   GNUNET_NAMESTORE_record_create (nh[2], key, "bob", &rd, &cont_ns, nh[2]);
471
472   gh = GNUNET_GNS_connect (cfg_handles[2]);
473   if (NULL == gh)
474   {
475     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
476     GNUNET_CRYPTO_rsa_key_free (key);
477     GNUNET_free (keyfile);
478     return GNUNET_SYSERR;
479   }
480
481   GNUNET_CRYPTO_rsa_key_free (key);
482   GNUNET_free (keyfile);
483   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice  done\n");
484   return GNUNET_OK;
485 }
486
487 static void
488 end_badly_now ()
489 {
490   if (GNUNET_SCHEDULER_NO_TASK != die_task)
491     GNUNET_SCHEDULER_cancel (die_task);
492   die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
493 }
494
495 void testbed_master (void *cls,
496                      unsigned int num_peers,
497                      struct GNUNET_TESTBED_Peer **peers)
498 {
499   GNUNET_assert (NULL != peers);
500   cpeers = peers;
501
502   /* peer 0: dave */
503   GNUNET_assert (NULL != peers[0]);
504   get_cfg_ops[0] = GNUNET_TESTBED_peer_get_information (peers[0], GNUNET_TESTBED_PIT_CONFIGURATION);
505
506   /* peer 1: bob */
507   GNUNET_assert (NULL != peers[1]);
508   get_cfg_ops[1] = GNUNET_TESTBED_peer_get_information (peers[1], GNUNET_TESTBED_PIT_CONFIGURATION);
509
510   /* peer 2: alice */
511   GNUNET_assert (NULL != peers[2]);
512   get_cfg_ops[2] = GNUNET_TESTBED_peer_get_information (peers[2], GNUNET_TESTBED_PIT_CONFIGURATION);
513
514 }
515
516 void testbed_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
517 {
518   static int connections = 0;
519   int res;
520
521   switch (event->type)
522   {
523     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
524       if (get_cfg_ops[0] == event->details.operation_finished.operation)
525       {
526           res = setup_dave (event->details.operation_finished.op_result.cfg);
527           GNUNET_TESTBED_operation_done (get_cfg_ops[0]);
528           get_cfg_ops[0] = NULL;
529           if (GNUNET_SYSERR == res)
530           {
531               GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
532               end_badly_now();
533           }
534           else
535           {
536               connect_peers ();
537           }
538       }
539       else if (get_cfg_ops[1] ==  event->details.operation_finished.operation)
540       {
541          res = setup_bob (event->details.operation_finished.op_result.cfg);
542          GNUNET_TESTBED_operation_done (get_cfg_ops[1]);
543          get_cfg_ops[1] = NULL;
544          if (GNUNET_SYSERR == res)
545          {
546              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
547              end_badly_now();
548          }
549          else
550          {
551              connect_peers ();
552          }
553       }
554       else if (get_cfg_ops[2] ==  event->details.operation_finished.operation)
555       {
556          res = setup_alice (event->details.operation_finished.op_result.cfg);
557          GNUNET_TESTBED_operation_done (get_cfg_ops[2]);
558          get_cfg_ops[2] = NULL;
559          if (GNUNET_SYSERR == res)
560          {
561              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
562              end_badly_now();
563          }
564          else
565          {
566              connect_peers ();
567          }
568       }
569       break;
570     case GNUNET_TESTBED_ET_CONNECT:
571       connections ++;
572       if (connections == 3)
573       {
574           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers connected\n");
575           GNUNET_TESTBED_operation_done (connect_ops[0]);
576           connect_ops[0] = NULL;
577           GNUNET_TESTBED_operation_done (connect_ops[1]);
578           connect_ops[1] = NULL;
579           GNUNET_TESTBED_operation_done (connect_ops[2]);
580           connect_ops[2] = NULL;
581           all_connected ();
582       }
583       break;
584     default:
585       /* whatever ... */
586       break;
587   }
588 }
589
590 int
591 main (int argc, char *argv[])
592 {
593   uint64_t event_mask;
594   ok = 0;
595   event_mask = 0;
596   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
597   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
598   GNUNET_TESTBED_test_run ("test_gns_dht_three_peers", "test_gns_dht_default.conf",
599                            3, event_mask,
600                            &testbed_controller_cb, NULL,
601                            &testbed_master, NULL);
602   if (GNUNET_SYSERR == ok)
603     return 1;
604   return 0;
605 }
606
607 /* end of test_gns_dht_three_peers.c */
608