-add missing includes for FreeBSD
[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.gads
28  *
29  */
30 #include "platform.h"
31 #include "gnunet_common.h"
32 #include "gnunet_disk_lib.h"
33 #include "gnunet_testing_lib.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, 10)
44
45 #define TEST_DOMAIN "www.buddy.bob.gads"
46 #define TEST_IP "1.1.1.1"
47 #define TEST_DAVE_PSEU "hagbard"
48
49
50 /* Timeout for entire testcase */
51 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 60)
52 #define SETUP_TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 60)
53
54 /* Global return value (0 for success, anything else for failure) */
55 static int ok;
56
57 /* Task handle to use to schedule test failure */
58 static GNUNET_SCHEDULER_TaskIdentifier die_task;
59
60 static GNUNET_SCHEDULER_TaskIdentifier wait_task;
61
62 static GNUNET_SCHEDULER_TaskIdentifier setup_task;
63
64 static struct GNUNET_CRYPTO_ShortHashCode dave_hash;
65
66 static struct GNUNET_CRYPTO_ShortHashCode bob_hash;
67
68 static struct GNUNET_TESTBED_Peer **cpeers;
69
70 static struct GNUNET_GNS_Handle *gh;
71 static struct GNUNET_GNS_LookupRequest *lookup_handle;
72
73 static struct GNUNET_TESTBED_Operation *get_cfg_ops[3];
74 static struct GNUNET_TESTBED_Operation *topology_op;
75 static struct GNUNET_CONFIGURATION_Handle *cfg_handles[3];
76 static struct GNUNET_NAMESTORE_Handle *nh[3];
77
78 static int dave_is_setup;
79 static int bob_is_setup;
80 static int alice_is_setup;
81
82 /**
83  * Check if the get_handle is being used, if so stop the request.  Either
84  * way, schedule the end_badly_cont function which actually shuts down the
85  * test.
86  */
87 static void
88 end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
89 {
90   die_task = GNUNET_SCHEDULER_NO_TASK;
91   int c;
92
93   if (GNUNET_SCHEDULER_NO_TASK != wait_task)
94   {
95       GNUNET_SCHEDULER_cancel (wait_task);
96       wait_task = GNUNET_SCHEDULER_NO_TASK;
97   }
98
99   for (c = 0; c < 3; c++)
100   {
101     if (NULL != nh[c])
102     {
103       GNUNET_NAMESTORE_disconnect(nh[c]);
104       nh[c] = NULL;
105     }
106
107     if (NULL != get_cfg_ops[c])
108     {
109         GNUNET_TESTBED_operation_done(get_cfg_ops[c]);
110         get_cfg_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   if (NULL != topology_op)
119   {
120     GNUNET_TESTBED_operation_done (topology_op);
121     topology_op = NULL;
122   }
123   if (NULL != lookup_handle)
124   {
125     GNUNET_GNS_cancel_lookup_request (lookup_handle);
126     lookup_handle = NULL;
127   }
128   if (NULL != gh)
129   {
130     GNUNET_GNS_disconnect(gh);
131     gh = NULL;
132   }
133   
134   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed \n");
135   GNUNET_SCHEDULER_shutdown ();
136   ok = 1;
137 }
138
139 static void
140 end (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
141 {
142   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Finished\n");
143   int c;
144   if (GNUNET_SCHEDULER_NO_TASK != die_task)
145   {
146       GNUNET_SCHEDULER_cancel (die_task);
147       die_task = GNUNET_SCHEDULER_NO_TASK;
148   }
149
150   for (c = 0; c < 3; c++)
151   {
152     if (NULL != nh[c])
153     {
154       GNUNET_NAMESTORE_disconnect(nh[c]);
155       nh[c] = NULL;
156     }
157     if (NULL != cfg_handles[c])
158     {
159       GNUNET_CONFIGURATION_destroy (cfg_handles[c]);
160       cfg_handles[c] = NULL;
161     }
162   }
163
164   if (NULL != gh)
165   {
166     GNUNET_GNS_disconnect(gh);
167     gh = NULL;
168   }
169
170   if (0 == ok)
171     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test ended successful\n");
172   else
173     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Test failed\n");
174   GNUNET_SCHEDULER_shutdown ();
175 }
176
177 static void
178 setup_end_badly (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
179 {
180   setup_task = GNUNET_SCHEDULER_NO_TASK;
181   GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Timeout during setup, test failed\n");
182
183   if (NULL != topology_op)
184   {
185     GNUNET_TESTBED_operation_done (topology_op);
186     topology_op = NULL;
187   }
188   GNUNET_SCHEDULER_shutdown ();
189   ok = GNUNET_SYSERR;
190 }
191
192 static void
193 end_now ()
194 {
195   GNUNET_SCHEDULER_add_now (&end, NULL);
196 }
197
198
199 static void
200 disconnect_ns (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
201 {
202
203   GNUNET_NAMESTORE_disconnect (cls);
204   if (cls == nh[0])
205     nh[0] = NULL;
206   if (cls == nh[1])
207     nh[1] = NULL;
208   if (cls == nh[2])
209     nh[2] = NULL;
210 }
211
212
213 static void
214 cont_ns (void* cls, int32_t s, const char* emsg)
215 {
216   GNUNET_SCHEDULER_add_now (&disconnect_ns, cls);
217 }
218
219 static void
220 on_lookup_result(void *cls, uint32_t rd_count,
221                  const struct GNUNET_NAMESTORE_RecordData *rd)
222 {
223   int i;
224   char* string_val;
225
226   if (rd_count == 0)
227   {
228     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
229                 "Lookup failed!\n");
230     ok = 2;
231   }
232   else
233   {
234     ok = 1;
235     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "name: %s\n", (char*)cls);
236     for (i=0; i<rd_count; i++)
237     {
238       string_val = GNUNET_NAMESTORE_value_to_string(rd[i].record_type,
239                                                     rd[i].data,
240                                                     rd[i].data_size);
241       if (0 == strcmp(string_val, TEST_IP))
242       {
243         GNUNET_log (GNUNET_ERROR_TYPE_INFO,
244                     "%s correctly resolved to %s!\n", TEST_DOMAIN, string_val);
245         ok = 0;
246       }
247       GNUNET_free (string_val);
248     }
249   }
250   end_now ();
251 }
252
253 static void
254 commence_testing(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
255 {
256   static int wait = 0;
257   wait++;
258   if ((ZONE_PUT_WAIT_TIME.rel_value / 1000) == wait)
259   {
260     fprintf (stderr, "\n");
261     wait_task = GNUNET_SCHEDULER_NO_TASK;
262     lookup_handle = GNUNET_GNS_lookup(gh, TEST_DOMAIN, GNUNET_GNS_RECORD_A,
263                       GNUNET_NO,
264                       NULL,
265                       &on_lookup_result, TEST_DOMAIN);
266     if (GNUNET_SCHEDULER_NO_TASK != die_task)
267       GNUNET_SCHEDULER_cancel(die_task);
268     die_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT, &end_badly, "from lookup");
269   }
270   else
271   {
272       fprintf (stderr, ".");
273       wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL);
274   }
275 }
276
277 void
278 all_connected ()
279 {
280   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Created all connections! Waiting for PUTs\n");
281   if (GNUNET_SCHEDULER_NO_TASK != setup_task)
282   {
283       GNUNET_SCHEDULER_cancel (setup_task);
284       setup_task = GNUNET_SCHEDULER_NO_TASK;
285   }
286   wait_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &commence_testing, NULL);
287 }
288
289
290 static void connect_peers ()
291 {
292   static int started;
293   started ++;
294   if (3 == started)
295   {
296       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers started\n");
297
298       topology_op = 
299           GNUNET_TESTBED_overlay_configure_topology  (NULL, 3, cpeers, NULL,
300                                                       NULL,
301                                                       NULL,
302                                                       GNUNET_TESTBED_TOPOLOGY_RING,
303                                                       GNUNET_TESTBED_TOPOLOGY_OPTION_END);
304   }
305 }
306
307 static int
308 setup_dave (const struct GNUNET_CONFIGURATION_Handle * cfg)
309 {
310   char* keyfile;
311   struct GNUNET_CRYPTO_EccPrivateKey *key;
312   struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pkey;
313   struct in_addr *web;
314   struct GNUNET_NAMESTORE_RecordData rd;
315
316   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave\n");
317   cfg_handles[0] = GNUNET_CONFIGURATION_dup (cfg);
318   GNUNET_assert (NULL != cfg_handles[0]);
319   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
320                                                             "ZONEKEY",
321                                                             &keyfile))
322   {
323     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
324     return GNUNET_SYSERR;
325   }
326
327   key = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
328   if (NULL == key)
329   {
330
331     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
332     GNUNET_free (keyfile);
333     return GNUNET_SYSERR;
334   }
335   nh[0] = GNUNET_NAMESTORE_connect (cfg_handles[0]);
336   if (NULL == nh[0])
337   {
338     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
339     GNUNET_CRYPTO_ecc_key_free (key);
340     GNUNET_free (keyfile);
341     return GNUNET_SYSERR;
342   }
343
344   GNUNET_CRYPTO_ecc_key_get_public (key, &pkey);
345   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &dave_hash);
346
347   rd.expiration_time = UINT64_MAX;
348
349   web = GNUNET_malloc(sizeof(struct in_addr));
350   GNUNET_assert(1 == inet_pton (AF_INET, TEST_IP, web));
351   rd.data_size = sizeof(struct in_addr);
352   rd.data = web;
353   rd.record_type = GNUNET_GNS_RECORD_A;
354   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
355
356   GNUNET_NAMESTORE_record_put_by_authority (nh[0], key, "www", 
357                                             1, &rd,
358                                             NULL, NULL);
359
360   rd.data_size = strlen(TEST_DAVE_PSEU);
361   rd.data = TEST_DAVE_PSEU;
362   rd.record_type = GNUNET_GNS_RECORD_PSEU;
363
364
365   GNUNET_NAMESTORE_record_put_by_authority (nh[0], key, 
366                                             GNUNET_GNS_MASTERZONE_STR, 
367                                             1, &rd, 
368                                             &cont_ns, nh[0]);
369
370   GNUNET_CRYPTO_ecc_key_free(key);
371   GNUNET_free(keyfile);
372   GNUNET_free(web);
373   dave_is_setup = GNUNET_YES;
374   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up dave done\n");
375   return GNUNET_OK;
376 }
377
378 static int
379 setup_bob (const struct GNUNET_CONFIGURATION_Handle * cfg)
380 {
381   char* keyfile;
382   struct GNUNET_CRYPTO_EccPrivateKey *key;
383   struct GNUNET_CRYPTO_EccPublicKeyBinaryEncoded pkey;
384   struct GNUNET_NAMESTORE_RecordData rd;
385
386   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob\n");
387   cfg_handles[1] = GNUNET_CONFIGURATION_dup (cfg);
388   GNUNET_assert (NULL != cfg_handles[1]);
389   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
390                                                             "ZONEKEY",
391                                                             &keyfile))
392   {
393     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
394     return GNUNET_SYSERR;
395   }
396
397   key = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
398   if (NULL == key)
399   {
400
401     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
402     GNUNET_free (keyfile);
403     return GNUNET_SYSERR;
404   }
405
406   nh[1] = GNUNET_NAMESTORE_connect (cfg_handles[1]);
407   if (NULL == nh[1])
408   {
409     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
410     GNUNET_CRYPTO_ecc_key_free (key);
411     GNUNET_free (keyfile);
412     return GNUNET_SYSERR;
413   }
414   
415   GNUNET_CRYPTO_ecc_key_get_public (key, &pkey);
416   GNUNET_CRYPTO_short_hash(&pkey, sizeof(pkey), &bob_hash);
417
418   rd.expiration_time = UINT64_MAX;
419   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
420   rd.data = &dave_hash;
421   rd.record_type = GNUNET_GNS_RECORD_PKEY;
422   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
423
424   GNUNET_NAMESTORE_record_put_by_authority (nh[1], key, "buddy",
425                                             1, &rd,
426                                             &cont_ns, nh[1]);
427
428   GNUNET_CRYPTO_ecc_key_free(key);
429   GNUNET_free(keyfile);
430   bob_is_setup = GNUNET_YES;
431   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up bob done\n");
432   return GNUNET_OK;
433 }
434
435 static int
436 setup_alice (const struct GNUNET_CONFIGURATION_Handle * cfg)
437 {
438   char* keyfile;
439   struct GNUNET_CRYPTO_EccPrivateKey *key;
440   struct GNUNET_NAMESTORE_RecordData rd;
441
442   cfg_handles[2] = GNUNET_CONFIGURATION_dup (cfg);
443   GNUNET_assert (NULL != cfg);
444   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, "gns",
445                                                             "ZONEKEY",
446                                                             &keyfile))
447   {
448     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
449     return GNUNET_SYSERR;
450   }
451
452   key = GNUNET_CRYPTO_ecc_key_create_from_file (keyfile);
453   if (NULL == key)
454   {
455
456     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to get key from cfg\n");
457     GNUNET_free (keyfile);
458     return GNUNET_SYSERR;
459   }
460
461   nh[2] = GNUNET_NAMESTORE_connect (cfg_handles[2]);
462   if (NULL == nh[2])
463   {
464     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to namestore\n");
465     GNUNET_CRYPTO_ecc_key_free (key);
466     GNUNET_free (keyfile);
467     return GNUNET_SYSERR;
468   }
469
470   rd.expiration_time = UINT64_MAX;
471   rd.data_size = sizeof(struct GNUNET_CRYPTO_ShortHashCode);
472   rd.data = &bob_hash;
473   rd.record_type = GNUNET_GNS_RECORD_PKEY;
474   rd.flags = GNUNET_NAMESTORE_RF_AUTHORITY;
475
476   GNUNET_NAMESTORE_record_put_by_authority (nh[2], key, "bob", 
477                                             1, &rd, 
478                                             &cont_ns, nh[2]);
479
480   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice gns\n");
481   gh = GNUNET_GNS_connect (cfg_handles[2]);
482   if (NULL == gh)
483   {
484     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Failed to connect to gns\n");
485     GNUNET_CRYPTO_ecc_key_free (key);
486     GNUNET_free (keyfile);
487     return GNUNET_SYSERR;
488   }
489
490   GNUNET_CRYPTO_ecc_key_free (key);
491   GNUNET_free (keyfile);
492   alice_is_setup = GNUNET_YES;
493   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Setting up alice  done\n");
494   return GNUNET_OK;
495 }
496
497 static void
498 end_badly_now ()
499 {
500   if (GNUNET_SCHEDULER_NO_TASK != die_task)
501     GNUNET_SCHEDULER_cancel (die_task);
502   die_task = GNUNET_SCHEDULER_add_now (&end_badly, NULL);
503 }
504
505
506 /**
507  * Callback to be called when the requested peer information is available
508  *
509  * @param cb_cls the closure from GNUNET_TETSBED_peer_get_information()
510  * @param op the operation this callback corresponds to
511  * @param pinfo the result; will be NULL if the operation has failed
512  * @param emsg error message if the operation has failed; will be NULL if the
513  *          operation is successfull
514  */
515 static void 
516 peerinfo_cb (void *cb_cls, struct GNUNET_TESTBED_Operation *op,
517              const struct GNUNET_TESTBED_PeerInformation *pinfo,
518              const char *emsg)
519 {
520   int res;
521   GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
522   if (GNUNET_NO == dave_is_setup)
523     res = setup_dave (pinfo->result.cfg);
524   else if (GNUNET_NO == bob_is_setup)
525     res = setup_bob (pinfo->result.cfg);
526   else
527     res = setup_alice (pinfo->result.cfg);
528   
529   if (get_cfg_ops[0] == op)
530     get_cfg_ops[0] = NULL;
531   else if (get_cfg_ops[1] == op)
532     get_cfg_ops[1] = NULL;
533   else
534     get_cfg_ops[2] = NULL;
535   GNUNET_TESTBED_operation_done (op);
536   op = NULL;
537   if (GNUNET_SYSERR == res)
538   {
539     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup peer \n");
540     end_badly_now();
541   }
542   else
543     connect_peers ();
544   /*if (get_cfg_ops[0] == op)
545   {
546     GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
547     res = setup_dave (pinfo->result.cfg);
548     GNUNET_TESTBED_operation_done (get_cfg_ops[0]);
549     get_cfg_ops[0] = 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   else if (get_cfg_ops[1] == op)
561   {
562     GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
563     res = setup_bob (pinfo->result.cfg);
564     GNUNET_TESTBED_operation_done (get_cfg_ops[1]);
565     get_cfg_ops[1] = NULL;
566     if (GNUNET_SYSERR == res)
567     {
568       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
569       end_badly_now();
570     }
571     else
572     {
573       connect_peers ();
574     }
575   }
576   else if (get_cfg_ops[2] == op)
577   {
578     GNUNET_assert (GNUNET_TESTBED_PIT_CONFIGURATION == pinfo->pit);
579     res = setup_alice (pinfo->result.cfg);
580     GNUNET_TESTBED_operation_done (get_cfg_ops[2]);
581     get_cfg_ops[2] = NULL;
582     if (GNUNET_SYSERR == res)
583     {
584       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to setup dave \n");
585       end_badly_now();
586     }
587     else
588     {
589       connect_peers ();
590     }
591   }*/
592 }
593
594
595 void testbed_master (void *cls,
596                      unsigned int num_peers,
597                      struct GNUNET_TESTBED_Peer **peers,
598                      unsigned int links_succeeded,
599                      unsigned int links_failed)
600 {
601   GNUNET_assert (NULL != peers);
602   cpeers = peers;
603
604   setup_task = GNUNET_SCHEDULER_add_delayed (SETUP_TIMEOUT, &setup_end_badly, NULL);
605
606   /* peer 0: dave */
607   GNUNET_assert (NULL != peers[0]);
608   get_cfg_ops[0] = GNUNET_TESTBED_peer_get_information (peers[0],
609                                                         GNUNET_TESTBED_PIT_CONFIGURATION,
610                                                         &peerinfo_cb, NULL);
611
612   /* peer 1: bob */
613   GNUNET_assert (NULL != peers[1]);
614   get_cfg_ops[1] = GNUNET_TESTBED_peer_get_information (peers[1],
615                                                         GNUNET_TESTBED_PIT_CONFIGURATION,
616                                                         &peerinfo_cb, NULL );
617
618   /* peer 2: alice */
619   GNUNET_assert (NULL != peers[2]);
620   get_cfg_ops[2] = GNUNET_TESTBED_peer_get_information (peers[2],
621                                                         GNUNET_TESTBED_PIT_CONFIGURATION,
622                                                         &peerinfo_cb, NULL);
623
624 }
625
626 void testbed_controller_cb (void *cls, const struct GNUNET_TESTBED_EventInformation *event)
627 {
628   static int connections = 0;
629
630   switch (event->type)
631   {
632     case GNUNET_TESTBED_ET_OPERATION_FINISHED:
633       /* This part will still be called when
634          GNUNET_TESTBED_peer_get_information() succeeds. However, the code is
635          now more relevant in operation completion callback */
636       break;
637     case GNUNET_TESTBED_ET_CONNECT:
638       connections ++;
639       if (connections == 3)
640       {
641           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "All peers connected\n");
642           GNUNET_TESTBED_operation_done (topology_op);
643           topology_op = NULL;
644           all_connected ();
645       }
646       break;
647     default:
648       /* whatever ... */
649       break;
650   }
651 }
652
653 int
654 main (int argc, char *argv[])
655 {
656   uint64_t event_mask;
657   ok = 0;
658   event_mask = 0;
659   event_mask |= (1LL << GNUNET_TESTBED_ET_CONNECT);
660   event_mask |= (1LL << GNUNET_TESTBED_ET_OPERATION_FINISHED);
661   (void) GNUNET_TESTBED_test_run ("test_gns_dht_three_peers", "test_gns_dht_default.conf",
662                                   3, event_mask,
663                                   &testbed_controller_cb, NULL,
664                                   &testbed_master, NULL);
665   if (GNUNET_SYSERR == ok)
666     return 1;
667   return 0;
668 }
669
670 /* end of test_gns_dht_three_peers.c */
671