- finally the last test
[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   struct GNUNET_CRYPTO_RsaPrivateKey *key;
254   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
255   struct in_addr *web;
256   struct GNUNET_NAMESTORE_RecordData rd;
257
258   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave\n");
259   GNUNET_assert (NULL != cfg);
260   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
261                                                             "ZONEKEY",
262                                                             &keyfile))
263   {
264     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
265     return GNUNET_SYSERR;
266   }
267
268   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
269   if (NULL == key)
270   {
271
272     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
273     GNUNET_free (keyfile);
274     return GNUNET_SYSERR;
275   }
276
277   ns = GNUNET_NAMESTORE_connect (cfg);
278   if (NULL == ns)
279   {
280     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
281     GNUNET_CRYPTO_rsa_key_free (key);
282     GNUNET_free (keyfile);
283     return GNUNET_SYSERR;
284   }
285
286   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
287   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash);
288
289   web = GNUNET_malloc(sizeof(struct in_addr));
290   GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web));
291   rd.data_size = sizeof(struct in_addr);
292   rd.data = web;
293   rd.record_type = GNUNET_GNS_RECORD_A;
294   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
295
296   GNUNET_NAMESTORE_record_create (ns, key, "www", &rd, NULL, NULL);
297
298   rd.data_size = strlen(TEST_DAVE_PSEU);
299   rd.data = TEST_DAVE_PSEU;
300   rd.record_type = GNUNET_GNS_RECORD_PSEU;
301
302   GNUNET_NAMESTORE_record_create (ns, key, "+", &rd, &cont_ns, ns);
303
304   GNUNET_CRYPTO_rsa_key_free(key);
305   GNUNET_free(keyfile);
306   GNUNET_free(web);
307   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave done\n");
308   return GNUNET_OK;
309 }
310
311 static int
312 setup_bob (const struct GNUNET_CONFIGURATION_Handle * cfg)
313 {
314   struct GNUNET_NAMESTORE_Handle *ns;
315   char* keyfile;
316   struct GNUNET_CRYPTO_RsaPrivateKey *key;
317   struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey;
318   struct GNUNET_NAMESTORE_RecordData rd;
319
320   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob\n");
321   GNUNET_assert (NULL != cfg);
322   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
323                                                             "ZONEKEY",
324                                                             &keyfile))
325   {
326     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
327     return GNUNET_SYSERR;
328   }
329
330   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
331   if (NULL == key)
332   {
333
334     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
335     GNUNET_free (keyfile);
336     return GNUNET_SYSERR;
337   }
338
339   ns = GNUNET_NAMESTORE_connect (cfg);
340   if (NULL == ns)
341   {
342     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
343     GNUNET_CRYPTO_rsa_key_free (key);
344     GNUNET_free (keyfile);
345     return GNUNET_SYSERR;
346   }
347
348   GNUNET_CRYPTO_rsa_key_get_public (key, &pkey);
349   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash);
350
351   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
352   rd.data = &dave_hash;
353   rd.record_type = GNUNET_GNS_RECORD_PKEY;
354   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
355
356   GNUNET_NAMESTORE_record_create (ns, key, "buddy", &rd, &cont_ns, ns);
357
358   GNUNET_CRYPTO_rsa_key_free(key);
359   GNUNET_free(keyfile);
360   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob done\n");
361   return GNUNET_OK;
362 }
363
364 static int
365 setup_alice (const struct GNUNET_CONFIGURATION_Handle * cfg)
366 {
367   struct GNUNET_NAMESTORE_Handle *ns;
368   char* keyfile;
369   struct GNUNET_CRYPTO_RsaPrivateKey *key;
370   struct GNUNET_NAMESTORE_RecordData rd;
371
372
373   GNUNET_assert (NULL != cfg);
374   alice_cfg = cfg;
375   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
376                                                             "ZONEKEY",
377                                                             &keyfile))
378   {
379     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
380     return GNUNET_SYSERR;
381   }
382
383   key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
384   if (NULL == key)
385   {
386
387     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
388     GNUNET_free (keyfile);
389     return GNUNET_SYSERR;
390   }
391
392   ns = GNUNET_NAMESTORE_connect (cfg);
393   if (NULL == ns)
394   {
395     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
396     GNUNET_CRYPTO_rsa_key_free (key);
397     GNUNET_free (keyfile);
398     return GNUNET_SYSERR;
399   }
400
401   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
402   rd.data = &bob_hash;
403   rd.record_type = GNUNET_GNS_RECORD_PKEY;
404   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
405
406   GNUNET_NAMESTORE_record_create (ns, key, "bob", &rd, &cont_ns, ns);
407
408   GNUNET_CRYPTO_rsa_key_free(key);
409   GNUNET_free(keyfile);
410   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice  done\n");
411   return GNUNET_OK;
412 }
413
414 static void
415 end_badly_now ()
416 {
417   if (GNUNET_SCHEDULER_NO_TASK != die_task)
418     GNUNET_SCHEDULER_cancel (die_task);
419   die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
420 }
421
422 void testbed_master (void *cls,
423                      unsigned int num_peers,
424                      struct GNUNET_TESTBED_Peer **peers)
425 {
426   GNUNET_assert (NULL != peers);
427   cpeers = peers;
428
429   /* peer 0: dave */
430   GNUNET_assert (NULL != peers[0]);
431   get_cfg_ops[0] = GNUNET_TESTBED_peer_get_information (peers[0], GNUNET_TESTBED_PIT_CONFIGURATION);
432
433   /* peer 1: bob */
434   GNUNET_assert (NULL != peers[1]);
435   get_cfg_ops[1] = GNUNET_TESTBED_peer_get_information (peers[1], GNUNET_TESTBED_PIT_CONFIGURATION);
436
437   /* peer 2: alice */
438   GNUNET_assert (NULL != peers[2]);
439   get_cfg_ops[2] = GNUNET_TESTBED_peer_get_information (peers[2], GNUNET_TESTBED_PIT_CONFIGURATION);
440
441 }
442
443 void testbed_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
444 {
445   static int connections = 0;
446   int res;
447
448   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Callback of type: %u %p \n", event->type, cls);
449   switch (event->type)
450   {
451     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
452       if (get_cfg_ops[0] == event->details.operation_finished.operation)
453       {
454           res = setup_dave (event->details.operation_finished.op_result.cfg);
455           get_cfg_ops[0] = NULL;
456           if (GNUNET_SYSERR == res)
457           {
458               GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
459               end_badly_now();
460           }
461           else
462           {
463               connect_peers ();
464           }
465       }
466       else if (get_cfg_ops[1] ==  event->details.operation_finished.operation)
467       {
468          res = setup_bob (event->details.operation_finished.op_result.cfg);
469          get_cfg_ops[1] = NULL;
470          if (GNUNET_SYSERR == res)
471          {
472              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
473              end_badly_now();
474          }
475          else
476          {
477              connect_peers ();
478          }
479       }
480       else if (get_cfg_ops[2] ==  event->details.operation_finished.operation)
481       {
482          res = setup_alice (event->details.operation_finished.op_result.cfg);
483          get_cfg_ops[2] = NULL;
484          if (GNUNET_SYSERR == res)
485          {
486              GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
487              end_badly_now();
488          }
489          else
490          {
491              connect_peers ();
492          }
493       }
494       break;
495     case GNUNET_TESTBED_ET_CONNECT:
496       connections ++;
497       if (connections == 3)
498       {
499           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers connected\n");
500           connect_ops[0] = NULL;
501           connect_ops[1] = NULL;
502           connect_ops[2] = NULL;
503           all_connected ();
504       }
505       break;
506     default:
507       /* whatever ... */
508       break;
509   }
510 }
511
512 int
513 main (int argc, char *argv[])
514 {
515   uint64_t event_mask;
516
517   ok = 0;
518   event_mask = 0;
519   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
520   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
521   GNUNET_TESTBED_test_run ("test_gns_dht_three_peers", "test_gns_dht_default.conf",
522                            3, event_mask,
523                            &testbed_controller_cb, NULL,
524                            &testbed_master, NULL);
525   if (GNUNET_SYSERR == ok)
526     return 1;
527   return 0;
528 }
529
530 /* end of test_gns_dht_three_peers.c */