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