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