fix
[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, NULL, NULL,
266                                                        cpeers[0],
267                                                        cpeers[1]);
268
269       connect_ops[1] = GNUNET_TESTBED_overlay_connect (NULL, NULL, NULL,
270                                                        cpeers[1],
271                                                        cpeers[2]);
272
273       connect_ops[2] = GNUNET_TESTBED_overlay_connect (NULL, NULL, 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
496 /**
497  * Callback to be called when the requested peer information is available
498  *
499  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
500  * @param op the operation this callback corresponds to
501  * @param pinfo the result; will be NULL if the operation has failed
502  * @param emsg error message if the operation has failed; will be NULL if the
503  *          operation is successfull
504  */
505 static void 
506 peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
507              const struct GNUNET_TESTBED_PeerInformation *pinfo,
508              const char *emsg)
509 {
510   int res;
511
512   if (get_cfg_ops[0] == op)
513   {
514     GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
515     res = setup_dave (pinfo->result.cfg);
516     GNUNET_TESTBED_operation_done (get_cfg_ops[0]);
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] == op)
529   {
530     GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
531     res = setup_bob (pinfo->result.cfg);
532     GNUNET_TESTBED_operation_done (get_cfg_ops[1]);
533     get_cfg_ops[1] = NULL;
534     if (GNUNET_SYSERR == res)
535     {
536       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
537       end_badly_now();
538     }
539     else
540     {
541       connect_peers ();
542     }
543   }
544   else if (get_cfg_ops[2] == op)
545   {
546     GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
547     res = setup_alice (pinfo->result.cfg);
548     GNUNET_TESTBED_operation_done (get_cfg_ops[2]);
549     get_cfg_ops[2] = NULL;
550     if (GNUNET_SYSERR == res)
551     {
552       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
553       end_badly_now();
554     }
555     else
556     {
557       connect_peers ();
558     }
559   }
560 }
561
562
563 void testbed_master (void *cls,
564                      unsigned int num_peers,
565                      struct GNUNET_TESTBED_Peer **peers)
566 {
567   GNUNET_assert (NULL != peers);
568   cpeers = peers;
569
570   /* peer 0: dave */
571   GNUNET_assert (NULL != peers[0]);
572   get_cfg_ops[0] = GNUNET_TESTBED_peer_get_information (peers[0],
573                                                         GNUNET_TESTBED_PIT_CONFIGURATION,
574                                                         &peerinfo_cb, NULL);
575
576   /* peer 1: bob */
577   GNUNET_assert (NULL != peers[1]);
578   get_cfg_ops[1] = GNUNET_TESTBED_peer_get_information (peers[1],
579                                                         GNUNET_TESTBED_PIT_CONFIGURATION,
580                                                         &peerinfo_cb, NULL );
581
582   /* peer 2: alice */
583   GNUNET_assert (NULL != peers[2]);
584   get_cfg_ops[2] = GNUNET_TESTBED_peer_get_information (peers[2],
585                                                         GNUNET_TESTBED_PIT_CONFIGURATION,
586                                                         &peerinfo_cb, NULL);
587
588 }
589
590 void testbed_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
591 {
592   static int connections = 0;
593
594   switch (event->type)
595   {
596     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
597       /* This part will still be called when
598          GNUNET_TESTBED_peer_get_information() succeeds. However, the code is
599          now more relevant in operation completion callback */
600       break;
601     case GNUNET_TESTBED_ET_CONNECT:
602       connections ++;
603       if (connections == 3)
604       {
605           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers connected\n");
606           GNUNET_TESTBED_operation_done (connect_ops[0]);
607           connect_ops[0] = NULL;
608           GNUNET_TESTBED_operation_done (connect_ops[1]);
609           connect_ops[1] = NULL;
610           GNUNET_TESTBED_operation_done (connect_ops[2]);
611           connect_ops[2] = NULL;
612           all_connected ();
613       }
614       break;
615     default:
616       /* whatever ... */
617       break;
618   }
619 }
620
621 int
622 main (int argc, char *argv[])
623 {
624   uint64_t event_mask;
625   ok = 0;
626   event_mask = 0;
627   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
628   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
629   GNUNET_TESTBED_test_run ("test_gns_dht_three_peers", "test_gns_dht_default.conf",
630                            3, event_mask,
631                            &testbed_controller_cb, NULL,
632                            &testbed_master, NULL);
633   if (GNUNET_SYSERR == ok)
634     return 1;
635   return 0;
636 }
637
638 /* end of test_gns_dht_three_peers.c */
639