57cea80072c68939762b565c44a6c14c3e4b7ee1
[oweals/gnunet.git] / src / testing / testing_group.c
1 /*
2       This file is part of GNUnet
3       (C) 2008, 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 2, 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 /**
22  * @file testing/testing_group.c
23  * @brief convenience API for writing testcases for GNUnet
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_arm_service.h"
28 #include "gnunet_testing_lib.h"
29
30 #define VERBOSE_TESTING GNUNET_YES
31
32 /**
33  * Lowest port used for GNUnet testing.  Should be high enough to not
34  * conflict with other applications running on the hosts but be low
35  * enough to not conflict with client-ports (typically starting around
36  * 32k).
37  */
38 #define LOW_PORT 10000
39
40 /**
41  * Highest port used for GNUnet testing.  Should be low enough to not
42  * conflict with the port range for "local" ports (client apps; see
43  * /proc/sys/net/ipv4/ip_local_port_range on Linux for example).
44  */
45 #define HIGH_PORT 32000
46
47 #define MAX_OUTSTANDING_CONNECTIONS 50
48
49 #define CONNECT_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 160)
50
51 #define CONNECT_ATTEMPTS 8
52
53 /**
54  * Prototype of a function called whenever two peers would be connected
55  * in a certain topology.
56  */
57 typedef int (*GNUNET_TESTING_ConnectionProcessor)
58 (struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second);
59
60 struct RestartContext
61 {
62   /**
63    * The group of peers being restarted
64    */
65   struct GNUNET_TESTING_PeerGroup *peer_group;
66
67   /**
68    * How many peers have been restarted thus far
69    */
70   unsigned int peers_restarted;
71
72   /**
73    * How many peers got an error when restarting
74    */
75   unsigned int peers_restart_failed;
76
77   /**
78    * The function to call once all peers have been restarted
79    */
80   GNUNET_TESTING_NotifyCompletion callback;
81
82   /**
83    * Closure for callback function
84    */
85   void *callback_cls;
86
87 };
88
89 struct CreateTopologyContext
90 {
91
92   /**
93    * Function to call with number of connections
94    */
95   GNUNET_TESTING_NotifyConnections cont;
96
97   /**
98    * Closure for connection notification
99    */
100   void *cls;
101 };
102
103 #if OLD
104 struct PeerConnection
105 {
106   /*
107    * Linked list
108    */
109   struct PeerConnection *next;
110
111   /*
112    * Pointer to daemon handle
113    */
114   struct GNUNET_TESTING_Daemon *daemon;
115
116 };
117 #endif
118
119 /**
120  * Data we keep per peer.
121  */
122 struct PeerData
123 {
124   /**
125    * (Initial) configuration of the host.
126    * (initial because clients could change
127    *  it and we would not know about those
128    *  updates).
129    */
130   struct GNUNET_CONFIGURATION_Handle *cfg;
131
132   /**
133    * Handle for controlling the daemon.
134    */
135   struct GNUNET_TESTING_Daemon *daemon;
136
137   /**
138    * The peergroup this peer belongs to.
139    */
140   struct GNUNET_TESTING_PeerGroup *pg;
141
142   /**
143    * Linked list of peer connections (pointers)
144    */
145   //struct PeerConnection *connected_peers;
146   /**
147    * Hash map of allowed peer connections (F2F created topology)
148    */
149   struct GNUNET_CONTAINER_MultiHashMap *allowed_peers;
150
151   /**
152    * Hash map of blacklisted peers
153    */
154   struct GNUNET_CONTAINER_MultiHashMap *blacklisted_peers;
155
156   /**
157    * Hash map of peer connections
158    */
159   struct GNUNET_CONTAINER_MultiHashMap *connect_peers;
160
161   /**
162    * Temporary hash map of peer connections
163    */
164   struct GNUNET_CONTAINER_MultiHashMap *connect_peers_working_set;
165
166   /**
167    * Temporary variable for topology creation, should be reset before
168    * creating any topology so the count is valid once finished.
169    */
170   int num_connections;
171 };
172
173
174 /**
175  * Data we keep per host.
176  */
177 struct HostData
178 {
179   /**
180    * Name of the host.
181    */
182   char *hostname;
183
184   /**
185    * Lowest port that we have not yet used
186    * for GNUnet.
187    */
188   uint16_t minport;
189 };
190
191
192 /**
193  * Handle to a group of GNUnet peers.
194  */
195 struct GNUNET_TESTING_PeerGroup
196 {
197   /**
198    * Our scheduler.
199    */
200   struct GNUNET_SCHEDULER_Handle *sched;
201
202   /**
203    * Configuration template.
204    */
205   const struct GNUNET_CONFIGURATION_Handle *cfg;
206
207   /**
208    * Function to call on each started daemon.
209    */
210   GNUNET_TESTING_NotifyDaemonRunning cb;
211
212   /**
213    * Closure for cb.
214    */
215   void *cb_cls;
216
217   /*
218    * Function to call on each topology connection created
219    */
220   GNUNET_TESTING_NotifyConnection notify_connection;
221
222   /*
223    * Callback for notify_connection
224    */
225   void *notify_connection_cls;
226
227   /**
228    * NULL-terminated array of information about
229    * hosts.
230    */
231   struct HostData *hosts;
232
233   /**
234    * Array of "total" peers.
235    */
236   struct PeerData *peers;
237
238   /**
239    * Number of peers in this group.
240    */
241   unsigned int total;
242
243 };
244
245 /**
246  * Convert unique ID to hash code.
247  *
248  * @param uid unique ID to convert
249  * @param hash set to uid (extended with zeros)
250  */
251 static void
252 hash_from_uid (uint32_t uid,
253                GNUNET_HashCode *hash)
254 {
255   memset (hash, 0, sizeof(GNUNET_HashCode));
256   *((uint32_t*)hash) = uid;
257 }
258
259 /**
260  * Convert hash code to unique ID.
261  *
262  * @param uid unique ID to convert
263  * @param hash set to uid (extended with zeros)
264  */
265 static void
266 uid_from_hash (const GNUNET_HashCode *hash, uint32_t *uid)
267 {
268   memcpy (uid, hash, sizeof(uint32_t));
269 }
270
271 struct UpdateContext
272 {
273   struct GNUNET_CONFIGURATION_Handle *ret;
274   unsigned int nport;
275   const char *hostname;
276 };
277
278
279 struct ConnectContext
280 {
281   struct GNUNET_TESTING_Daemon *first;
282
283   struct GNUNET_TESTING_Daemon *second;
284
285   struct GNUNET_TESTING_PeerGroup *pg;
286 };
287
288 /**
289  * Number of connects we are waiting on, allows us to rate limit
290  * connect attempts.
291  */
292 static int outstanding_connects;
293
294
295 /**
296  * Function to iterate over options.  Copies
297  * the options to the target configuration,
298  * updating PORT values as needed.
299  *
300  * @param cls closure
301  * @param section name of the section
302  * @param option name of the option
303  * @param value value of the option
304  */
305 static void
306 update_config (void *cls,
307                const char *section, const char *option, const char *value)
308 {
309   struct UpdateContext *ctx = cls;
310   unsigned int ival;
311   char cval[12];
312
313   if ((0 == strcmp (option, "PORT")) && (1 == sscanf (value, "%u", &ival)))
314     {
315       GNUNET_snprintf (cval, sizeof (cval), "%u", ctx->nport++);
316       value = cval;
317     }
318
319   if ((0 == strcmp (option, "HOSTNAME")) && (ctx->hostname != NULL))
320     {
321       value = ctx->hostname;
322     }
323
324   GNUNET_CONFIGURATION_set_value_string (ctx->ret, section, option, value);
325 }
326
327
328 /**
329  * Create a new configuration using the given configuration
330  * as a template; however, each PORT in the existing cfg
331  * must be renumbered by incrementing "*port".  If we run
332  * out of "*port" numbers, return NULL.
333  *
334  * @param cfg template configuration
335  * @param port port numbers to use, update to reflect
336  *             port numbers that were used
337  * @param hostname hostname of the controlling host, to allow control connections from
338  *
339  * @return new configuration, NULL on error
340  */
341 static struct GNUNET_CONFIGURATION_Handle *
342 make_config (const struct GNUNET_CONFIGURATION_Handle *cfg, uint16_t * port, const char *hostname)
343 {
344   struct UpdateContext uc;
345   uint16_t orig;
346   char *control_host;
347   char *allowed_hosts;
348
349   orig = *port;
350   uc.nport = *port;
351   uc.ret = GNUNET_CONFIGURATION_create ();
352   uc.hostname = hostname;
353
354   GNUNET_CONFIGURATION_iterate (cfg, &update_config, &uc);
355   if (uc.nport >= HIGH_PORT)
356     {
357       *port = orig;
358       GNUNET_CONFIGURATION_destroy (uc.ret);
359       return NULL;
360     }
361
362   if (GNUNET_CONFIGURATION_get_value_string(cfg, "testing", "control_host", &control_host) == GNUNET_OK)
363     {
364       GNUNET_asprintf(&allowed_hosts, "%s; 127.0.0.1;", control_host);
365       GNUNET_CONFIGURATION_set_value_string(uc.ret, "core", "ACCEPT_FROM", allowed_hosts);
366       GNUNET_free_non_null(control_host);
367       GNUNET_free(allowed_hosts);
368     }
369
370
371   /* arm needs to know to allow connections from the host on which it is running,
372    * otherwise gnunet-arm is unable to connect to it in some instances */
373   if (hostname != NULL)
374     {
375       GNUNET_asprintf(&allowed_hosts, "%s; 127.0.0.1;", hostname);
376       GNUNET_CONFIGURATION_set_value_string(uc.ret, "arm", "ACCEPT_FROM", allowed_hosts);
377       GNUNET_free(allowed_hosts);
378     }
379
380   *port = (uint16_t) uc.nport;
381   return uc.ret;
382 }
383
384
385 /*
386  * Add entries to the peers connect list
387  *
388  * @param pg the peer group we are working with
389  * @param first index of the first peer
390  * @param second index of the second peer
391  *
392  * @return the number of connections added (can be 0, 1 or 2)
393  *         technically should only be 0 or 2, but the small price
394  *         of iterating over the lists (hashmaps in the future)
395  *         for being sure doesn't bother me!
396  *
397  */
398 static int
399 add_actual_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
400 {
401   int added;
402   int add_first;
403   int add_second;
404
405   GNUNET_HashCode hash_first;
406   GNUNET_HashCode hash_second;
407
408   hash_from_uid(first, &hash_first);
409   hash_from_uid(second, &hash_second);
410
411   add_first = GNUNET_NO;
412   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].connect_peers, &hash_second))
413     {
414       add_first = GNUNET_YES;
415     }
416
417   add_second = GNUNET_NO;
418   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].connect_peers, &hash_first))
419     {
420       add_second = GNUNET_YES;
421     }
422
423   added = 0;
424   if (add_first)
425     {
426       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].connect_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
427       pg->peers[first].num_connections++;
428       added++;
429     }
430
431   if (add_second)
432     {
433       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].connect_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
434       pg->peers[second].num_connections++;
435       added++;
436     }
437
438   return added;
439 }
440
441
442 /*
443  * Add entries to the peers allowed connections list
444  *
445  * @param pg the peer group we are working with
446  * @param first index of the first peer
447  * @param second index of the second peer
448  *
449  * @return the number of connections added (can be 0, 1 or 2)
450  *         technically should only be 0 or 2, but the small price
451  *         of iterating over the lists (hashmaps in the future)
452  *         for being sure doesn't bother me!
453  *
454  */
455 static int
456 add_allowed_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
457 {
458   int added;
459 #if OLD
460   struct PeerConnection *first_iter;
461   struct PeerConnection *second_iter;
462   struct PeerConnection *new_first;
463   struct PeerConnection *new_second;
464 #endif
465   int add_first;
466   int add_second;
467
468   GNUNET_HashCode hash_first;
469   GNUNET_HashCode hash_second;
470
471   hash_from_uid(first, &hash_first);
472   hash_from_uid(second, &hash_second);
473
474   add_first = GNUNET_NO;
475   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].allowed_peers, &hash_second))
476     {
477       add_first = GNUNET_YES;
478     }
479
480   add_second = GNUNET_NO;
481   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].allowed_peers, &hash_first))
482     {
483       add_second = GNUNET_YES;
484     }
485 #if OLD
486   first_iter = pg->peers[first].connected_peers;
487   while (first_iter != NULL)
488     {
489       if (first_iter->daemon == pg->peers[second].daemon)
490         add_first = GNUNET_NO;
491       first_iter = first_iter->next;
492     }
493
494   second_iter = pg->peers[second].connected_peers;
495   add_second = GNUNET_YES;
496   while (second_iter != NULL)
497     {
498       if (second_iter->daemon == pg->peers[first].daemon)
499         add_second = GNUNET_NO;
500       second_iter = second_iter->next;
501     }
502 #endif
503
504   added = 0;
505   if (add_first)
506     {
507       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].allowed_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
508 #if OLD
509       new_first = GNUNET_malloc(sizeof(struct PeerConnection));
510       new_first->daemon = pg->peers[second].daemon;
511       new_first->next = pg->peers[first].connected_peers;
512       pg->peers[first].connected_peers = new_first;
513 #endif
514       pg->peers[first].num_connections++;
515       added++;
516     }
517
518   if (add_second)
519     {
520       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].allowed_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
521 #if OLD
522       new_second = GNUNET_malloc(sizeof(struct PeerConnection));
523       new_second->daemon = pg->peers[first].daemon;
524       new_second->next = pg->peers[second].connected_peers;
525       pg->peers[second].connected_peers = new_second;
526       pg->peers[first].num_connections++;
527 #endif
528       pg->peers[second].num_connections++;
529       added++;
530     }
531
532   return added;
533 }
534
535 /*
536  * Add entries to the peers blacklisted list
537  *
538  * @param pg the peer group we are working with
539  * @param first index of the first peer
540  * @param second index of the second peer
541  *
542  * @return the number of connections added (can be 0, 1 or 2)
543  *
544  */
545 static int
546 blacklist_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
547 {
548   int added;
549   int add_first;
550   int add_second;
551   GNUNET_HashCode hash_first;
552   GNUNET_HashCode hash_second;
553
554   hash_from_uid(first, &hash_first);
555   hash_from_uid(second, &hash_second);
556
557   add_first = GNUNET_NO;
558   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].blacklisted_peers, &hash_second))
559     {
560       add_first = GNUNET_YES;
561     }
562
563   add_second = GNUNET_NO;
564   if (GNUNET_NO == GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].blacklisted_peers, &hash_first))
565     {
566       add_second = GNUNET_YES;
567     }
568
569   added = 0;
570   if (add_first)
571     {
572       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[first].blacklisted_peers, &hash_second, pg->peers[second].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
573       pg->peers[first].num_connections++;
574       added++;
575     }
576
577   if (add_second)
578     {
579       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(pg->peers[second].blacklisted_peers, &hash_first, pg->peers[first].daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
580       pg->peers[second].num_connections++;
581       added++;
582     }
583
584   return added;
585 }
586
587 /*
588  * Remove entries from the peers blacklisted list
589  *
590  * @param pg the peer group we are working with
591  * @param first index of the first peer
592  * @param second index of the second peer
593  *
594  * @return the number of connections removed (can be 0, 1 or 2)
595  *
596  */
597 static int
598 unblacklist_connections(struct GNUNET_TESTING_PeerGroup *pg, unsigned int first, unsigned int second)
599 {
600   int removed;
601   int remove_first;
602   int remove_second;
603   GNUNET_HashCode hash_first;
604   GNUNET_HashCode hash_second;
605
606   hash_from_uid(first, &hash_first);
607   hash_from_uid(second, &hash_second);
608
609   remove_first = GNUNET_CONTAINER_multihashmap_contains(pg->peers[first].blacklisted_peers, &hash_second);
610   remove_second = GNUNET_CONTAINER_multihashmap_contains(pg->peers[second].blacklisted_peers, &hash_first);
611
612   removed = 0;
613   if (remove_first)
614     {
615       GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[first].blacklisted_peers, &hash_second, pg->peers[second].daemon));
616       removed++;
617     }
618
619   if (remove_second)
620     {
621       GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[second].blacklisted_peers, &hash_first, pg->peers[first].daemon));
622       removed++;
623     }
624
625   return removed;
626 }
627
628 /**
629  * Scale free network construction as described in:
630  *
631  * "Emergence of Scaling in Random Networks." Science 286, 509-512, 1999.
632  *
633  * Start with a network of "one" peer, then progressively add
634  * peers up to the total number.  At each step, iterate over
635  * all possible peers and connect new peer based on number of
636  * existing connections of the target peer.
637  *
638  * @param pg the peer group we are dealing with
639  *
640  * @return the number of connections created
641  */
642 static int
643 create_scale_free (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
644 {
645
646   unsigned int total_connections;
647   unsigned int outer_count;
648   unsigned int i;
649   unsigned int previous_total_connections;
650   double random;
651   double probability;
652
653   GNUNET_assert(pg->total > 1);
654
655   /* Add a connection between the first two nodes */
656   total_connections = proc(pg, 0, 1);
657
658   for (outer_count = 1; outer_count < pg->total; outer_count++)
659     {
660       previous_total_connections = total_connections;
661       for (i = 0; i < outer_count; i++)
662         {
663           probability = pg->peers[i].num_connections / (double)previous_total_connections;
664           random = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
665                                                       (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
666 #if VERBOSE_TESTING
667           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
668                       "Considering connecting peer %d to peer %d\n",
669                       outer_count, i);
670 #endif
671           if (random < probability)
672             {
673 #if VERBOSE_TESTING
674               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
675                           "Connecting peer %d to peer %d\n",
676                           outer_count, i);
677 #endif
678               total_connections += proc(pg, outer_count, i);
679             }
680         }
681     }
682
683   return total_connections;
684 }
685
686 int
687 create_small_world_ring(struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
688 {
689   unsigned int i, j;
690   int nodeToConnect;
691   unsigned int natLog;
692   unsigned int randomPeer;
693   double random, logNModifier, percentage;
694   unsigned int smallWorldConnections;
695   int connsPerPeer;
696   char *p_string;
697   int max;
698   int min;
699   unsigned int useAnd;
700   int connect_attempts;
701
702   logNModifier = 0.5; /* FIXME: default value? */
703   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(pg->cfg,
704                                                          "TESTING",
705                                                          "LOGNMODIFIER",
706                                                          &p_string))
707     {
708       if (sscanf(p_string, "%lf", &logNModifier) != 1)
709         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
710                     _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
711                     p_string,
712                     "LOGNMODIFIER",
713                     "TESTING");
714       GNUNET_free (p_string);
715     }
716   percentage = 0.5; /* FIXME: default percentage? */
717   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(pg->cfg,
718                                                          "TESTING",
719                                                          "PERCENTAGE",
720                                                          &p_string))
721     {
722       if (sscanf(p_string, "%lf", &percentage) != 1)
723         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
724                     _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
725                     p_string,
726                     "PERCENTAGE",
727                     "TESTING");
728       GNUNET_free (p_string);
729     }
730   natLog = log (pg->total);
731   connsPerPeer = ceil (natLog * logNModifier);
732
733   if (connsPerPeer % 2 == 1)
734     connsPerPeer += 1;
735
736   smallWorldConnections = 0;
737   connect_attempts = 0;
738   for (i = 0; i < pg->total; i++)
739     {
740       useAnd = 0;
741       max = i + connsPerPeer / 2;
742       min = i - connsPerPeer / 2;
743
744       if (max > pg->total - 1)
745         {
746           max = max - pg->total;
747           useAnd = 1;
748         }
749
750       if (min < 0)
751         {
752           min = pg->total - 1 + min;
753           useAnd = 1;
754         }
755
756       for (j = 0; j < connsPerPeer / 2; j++)
757         {
758           random = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
759                                                       (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
760           if (random < percentage)
761             {
762               /* Connect to uniformly selected random peer */
763               randomPeer =
764                 GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
765                                    pg->total);
766               while ((((randomPeer < max) && (randomPeer > min))
767                       && (useAnd == 0)) || (((randomPeer > min)
768                                              || (randomPeer < max))
769                                             && (useAnd == 1)))
770                 {
771                   randomPeer =
772                       GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
773                                                          pg->total);
774                 }
775               smallWorldConnections +=
776                 proc (pg, i, randomPeer);
777             }
778           else
779             {
780               nodeToConnect = i + j + 1;
781               if (nodeToConnect > pg->total - 1)
782                 {
783                   nodeToConnect = nodeToConnect - pg->total;
784                 }
785               connect_attempts +=
786                 proc (pg, i, nodeToConnect);
787             }
788         }
789
790     }
791
792   connect_attempts += smallWorldConnections;
793
794   return connect_attempts;
795 }
796
797
798 static int
799 create_nated_internet (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
800 {
801   unsigned int outer_count, inner_count;
802   unsigned int cutoff;
803   int connect_attempts;
804   double nat_percentage;
805   char *p_string;
806
807   nat_percentage = 0.6; /* FIXME: default percentage? */
808   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(pg->cfg,
809                                                          "TESTING",
810                                                          "NATPERCENTAGE",
811                                                          &p_string))
812     {
813       if (sscanf(p_string, "%lf", &nat_percentage) != 1)
814         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
815                     _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
816                     p_string,
817                     "NATPERCENTAGE",
818                     "TESTING");
819       GNUNET_free (p_string);
820     }
821
822
823
824   cutoff = (unsigned int) (nat_percentage * pg->total);
825
826   connect_attempts = 0;
827
828   for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
829     {
830       for (inner_count = outer_count + 1; inner_count < pg->total;
831            inner_count++)
832         {
833           if ((outer_count > cutoff) || (inner_count > cutoff))
834             {
835 #if VERBOSE_TESTING
836               GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
837                           "Connecting peer %d to peer %d\n",
838                           outer_count, inner_count);
839 #endif
840               connect_attempts += proc(pg, outer_count, inner_count);
841             }
842         }
843     }
844
845   return connect_attempts;
846
847 }
848
849
850
851 static int
852 create_small_world (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
853 {
854   unsigned int i, j, k;
855   unsigned int square;
856   unsigned int rows;
857   unsigned int cols;
858   unsigned int toggle = 1;
859   unsigned int nodeToConnect;
860   unsigned int natLog;
861   unsigned int node1Row;
862   unsigned int node1Col;
863   unsigned int node2Row;
864   unsigned int node2Col;
865   unsigned int distance;
866   double probability, random, percentage;
867   unsigned int smallWorldConnections;
868   char *p_string;
869   int connect_attempts;
870   square = floor (sqrt (pg->total));
871   rows = square;
872   cols = square;
873
874   percentage = 0.5; /* FIXME: default percentage? */
875   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(pg->cfg,
876                                                          "TESTING",
877                                                          "PERCENTAGE",
878                                                          &p_string))
879     {
880       if (sscanf(p_string, "%lf", &percentage) != 1)
881         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
882                     _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
883                     p_string,
884                     "PERCENTAGE",
885                     "TESTING");
886       GNUNET_free (p_string);
887     }
888   probability = 0.5; /* FIXME: default percentage? */
889   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(pg->cfg,
890                                                          "TESTING",
891                                                          "PROBABILITY",
892                                                          &p_string))
893     {
894       if (sscanf(p_string, "%lf", &probability) != 1)
895         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
896                     _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
897                     p_string,
898                     "PROBABILITY",
899                     "TESTING");
900       GNUNET_free (p_string);
901     }
902   if (square * square != pg->total)
903     {
904       while (rows * cols < pg->total)
905         {
906           if (toggle % 2 == 0)
907             rows++;
908           else
909             cols++;
910
911           toggle++;
912         }
913     }
914 #if VERBOSE_TESTING
915       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
916                   _("Connecting nodes in 2d torus topology: %u rows %u columns\n"),
917                   rows, cols);
918 #endif
919
920   connect_attempts = 0;
921   /* Rows and columns are all sorted out, now iterate over all nodes and connect each
922    * to the node to its right and above.  Once this is over, we'll have our torus!
923    * Special case for the last node (if the rows and columns are not equal), connect
924    * to the first in the row to maintain topology.
925    */
926   for (i = 0; i < pg->total; i++)
927     {
928       /* First connect to the node to the right */
929       if (((i + 1) % cols != 0) && (i + 1 != pg->total))
930         nodeToConnect = i + 1;
931       else if (i + 1 == pg->total)
932         nodeToConnect = rows * cols - cols;
933       else
934         nodeToConnect = i - cols + 1;
935
936       connect_attempts += proc (pg, i, nodeToConnect);
937
938       if (i < cols)
939         nodeToConnect = (rows * cols) - cols + i;
940       else
941         nodeToConnect = i - cols;
942
943       if (nodeToConnect < pg->total)
944         connect_attempts += proc (pg, i, nodeToConnect);
945     }
946   natLog = log (pg->total);
947 #if VERBOSE_TESTING > 2
948   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
949               _("natural log of %d is %d, will run %d iterations\n"),
950              pg->total, natLog, (int) (natLog * percentage));
951   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, _("Total connections added thus far: %u!\n"), connect_attempts);
952 #endif
953   smallWorldConnections = 0;
954   for (i = 0; i < (int) (natLog * percentage); i++)
955     {
956       for (j = 0; j < pg->total; j++)
957         {
958           /* Determine the row and column of node at position j on the 2d torus */
959           node1Row = j / cols;
960           node1Col = j - (node1Row * cols);
961           for (k = 0; k < pg->total; k++)
962             {
963               /* Determine the row and column of node at position k on the 2d torus */
964               node2Row = k / cols;
965               node2Col = k - (node2Row * cols);
966               /* Simple Cartesian distance */
967               distance = abs (node1Row - node2Row) + abs (node1Col - node2Col);
968               if (distance > 1)
969                 {
970                   /* Calculate probability as 1 over the square of the distance */
971                   probability = 1.0 / (distance * distance);
972                   /* Choose a random value between 0 and 1 */
973                   random = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
974                                                               (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
975                   /* If random < probability, then connect the two nodes */
976                   if (random < probability)
977                     smallWorldConnections += proc (pg, j, k);
978
979                 }
980             }
981         }
982     }
983   connect_attempts += smallWorldConnections;
984 #if VERBOSE_TESTING > 2
985           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
986                       _("Total connections added for small world: %d!\n"),
987                       smallWorldConnections);
988 #endif
989   return connect_attempts;
990 }
991
992
993
994 static int
995 create_erdos_renyi (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
996 {
997   double temp_rand;
998   unsigned int outer_count;
999   unsigned int inner_count;
1000   int connect_attempts;
1001   double probability;
1002   char *p_string;
1003
1004   probability = 0.5; /* FIXME: default percentage? */
1005   if (GNUNET_OK == GNUNET_CONFIGURATION_get_value_string(pg->cfg,
1006                                                          "TESTING",
1007                                                          "PROBABILITY",
1008                                                          &p_string))
1009     {
1010       if (sscanf(p_string, "%lf", &probability) != 1)
1011         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1012                     _("Invalid value `%s' for option `%s' in section `%s': expected float\n"),
1013                     p_string,
1014                     "PROBABILITY",
1015                     "TESTING");
1016       GNUNET_free (p_string);
1017     }
1018   connect_attempts = 0;
1019   for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
1020     {
1021       for (inner_count = outer_count + 1; inner_count < pg->total;
1022            inner_count++)
1023         {
1024           temp_rand = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
1025                                                          (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
1026 #if VERBOSE_TESTING
1027           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1028                       _("rand is %f probability is %f\n"), temp_rand,
1029                       probability);
1030 #endif
1031           if (temp_rand < probability)
1032             {
1033               connect_attempts += proc (pg, outer_count, inner_count);
1034             }
1035         }
1036     }
1037
1038   return connect_attempts;
1039 }
1040
1041 static int
1042 create_2d_torus (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
1043 {
1044   unsigned int i;
1045   unsigned int square;
1046   unsigned int rows;
1047   unsigned int cols;
1048   unsigned int toggle = 1;
1049   unsigned int nodeToConnect;
1050   int connect_attempts;
1051
1052   connect_attempts = 0;
1053
1054   square = floor (sqrt (pg->total));
1055   rows = square;
1056   cols = square;
1057
1058   if (square * square != pg->total)
1059     {
1060       while (rows * cols < pg->total)
1061         {
1062           if (toggle % 2 == 0)
1063             rows++;
1064           else
1065             cols++;
1066
1067           toggle++;
1068         }
1069     }
1070 #if VERBOSE_TESTING
1071       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1072                   _("Connecting nodes in 2d torus topology: %u rows %u columns\n"),
1073                   rows, cols);
1074 #endif
1075   /* Rows and columns are all sorted out, now iterate over all nodes and connect each
1076    * to the node to its right and above.  Once this is over, we'll have our torus!
1077    * Special case for the last node (if the rows and columns are not equal), connect
1078    * to the first in the row to maintain topology.
1079    */
1080   for (i = 0; i < pg->total; i++)
1081     {
1082       /* First connect to the node to the right */
1083       if (((i + 1) % cols != 0) && (i + 1 != pg->total))
1084         nodeToConnect = i + 1;
1085       else if (i + 1 == pg->total)
1086         nodeToConnect = rows * cols - cols;
1087       else
1088         nodeToConnect = i - cols + 1;
1089 #if VERBOSE_TESTING
1090           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1091                       "Connecting peer %d to peer %d\n",
1092                       i, nodeToConnect);
1093 #endif
1094       connect_attempts += proc(pg, i, nodeToConnect);
1095
1096       /* Second connect to the node immediately above */
1097       if (i < cols)
1098         nodeToConnect = (rows * cols) - cols + i;
1099       else
1100         nodeToConnect = i - cols;
1101
1102       if (nodeToConnect < pg->total)
1103         {
1104 #if VERBOSE_TESTING
1105           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1106                       "Connecting peer %d to peer %d\n",
1107                       i, nodeToConnect);
1108 #endif
1109           connect_attempts += proc(pg, i, nodeToConnect);
1110         }
1111
1112     }
1113
1114   return connect_attempts;
1115 }
1116
1117
1118
1119 static int
1120 create_clique (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
1121 {
1122   unsigned int outer_count;
1123   unsigned int inner_count;
1124   int connect_attempts;
1125
1126   connect_attempts = 0;
1127
1128   for (outer_count = 0; outer_count < pg->total - 1; outer_count++)
1129     {
1130       for (inner_count = outer_count + 1; inner_count < pg->total;
1131            inner_count++)
1132         {
1133 #if VERBOSE_TESTING
1134           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1135                       "Connecting peer %d to peer %d\n",
1136                       outer_count, inner_count);
1137 #endif
1138           connect_attempts += proc(pg, outer_count, inner_count);
1139         }
1140     }
1141
1142   return connect_attempts;
1143 }
1144
1145
1146 static int
1147 create_ring (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_ConnectionProcessor proc)
1148 {
1149   unsigned int count;
1150   int connect_attempts;
1151
1152   connect_attempts = 0;
1153
1154   /* Connect each peer to the next highest numbered peer */
1155   for (count = 0; count < pg->total - 1; count++)
1156     {
1157 #if VERBOSE_TESTING
1158           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1159                       "Connecting peer %d to peer %d\n",
1160                       count, count + 1);
1161 #endif
1162       connect_attempts += proc(pg, count, count + 1);
1163     }
1164
1165   /* Connect the last peer to the first peer */
1166   connect_attempts += proc(pg, pg->total - 1, 0);
1167
1168   return connect_attempts;
1169 }
1170
1171
1172 /**
1173  * Iterator for writing friends of a peer to a file.
1174  *
1175  * @param cls closure, an open writable file handle
1176  * @param key the key the daemon was stored under
1177  * @param value the GNUNET_TESTING_Daemon that needs to be written.
1178  *
1179  * @return GNUNET_YES to continue iteration
1180  *
1181  * TODO: Could replace friend_file_iterator and blacklist_file_iterator
1182  *       with a single file_iterator that takes a closure which contains
1183  *       the prefix to write before the peer.  Then this could be used
1184  *       for blacklisting multiple transports and writing the friend
1185  *       file.  I'm sure *someone* will complain loudly about other
1186  *       things that negate these functions even existing so no point in
1187  *       "fixing" now.
1188  */
1189 static int
1190 friend_file_iterator (void *cls,
1191                   const GNUNET_HashCode * key,
1192                   void *value)
1193 {
1194   FILE *temp_friend_handle = cls;
1195   struct GNUNET_TESTING_Daemon *peer = value;
1196   struct GNUNET_PeerIdentity *temppeer;
1197   struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
1198
1199   temppeer = &peer->id;
1200   GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc);
1201   fprintf(temp_friend_handle, "%s\n", (char *)&peer_enc);
1202
1203   return GNUNET_YES;
1204 }
1205
1206
1207 /**
1208  * Iterator for writing blacklist data to appropriate files.
1209  *
1210  * @param cls closure, an open writable file handle
1211  * @param key the key the daemon was stored under
1212  * @param value the GNUNET_TESTING_Daemon that needs to be written.
1213  *
1214  * @return GNUNET_YES to continue iteration
1215  */
1216 static int
1217 blacklist_file_iterator (void *cls,
1218                          const GNUNET_HashCode * key,
1219                          void *value)
1220 {
1221   FILE *temp_blacklist_handle = cls;
1222   struct GNUNET_TESTING_Daemon *peer = value;
1223   struct GNUNET_PeerIdentity *temppeer;
1224   struct GNUNET_CRYPTO_HashAsciiEncoded peer_enc;
1225
1226   temppeer = &peer->id;
1227   GNUNET_CRYPTO_hash_to_enc(&temppeer->hashPubKey, &peer_enc);
1228   fprintf(temp_blacklist_handle, "tcp:%s\n", (char *)&peer_enc);
1229
1230   return GNUNET_YES;
1231 }
1232
1233 /*
1234  * Create the friend files based on the PeerConnection's
1235  * of each peer in the peer group, and copy the files
1236  * to the appropriate place
1237  *
1238  * @param pg the peer group we are dealing with
1239  */
1240 static int
1241 create_and_copy_friend_files (struct GNUNET_TESTING_PeerGroup *pg)
1242 {
1243   FILE *temp_friend_handle;
1244   unsigned int pg_iter;
1245   char *temp_service_path;
1246   pid_t *pidarr;
1247   char *arg;
1248   char * mytemp;
1249   enum GNUNET_OS_ProcessStatusType type;
1250   unsigned long return_code;
1251   int count;
1252   int ret;
1253   int max_wait = 10;
1254
1255   pidarr = GNUNET_malloc(sizeof(pid_t) * pg->total);
1256   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1257     {
1258       mytemp = GNUNET_DISK_mktemp("friends");
1259       GNUNET_assert(mytemp != NULL);
1260       temp_friend_handle = fopen (mytemp, "wt");
1261       GNUNET_assert(temp_friend_handle != NULL);
1262       GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].allowed_peers, &friend_file_iterator, temp_friend_handle);
1263       fclose(temp_friend_handle);
1264
1265       if (GNUNET_OK !=
1266           GNUNET_CONFIGURATION_get_value_string(pg->peers[pg_iter].daemon->cfg, "PATHS", "SERVICEHOME", &temp_service_path))
1267         {
1268           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1269                       _("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
1270                       "SERVICEHOME",
1271                       "PATHS");
1272           if (UNLINK (mytemp) != 0)
1273             GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
1274           GNUNET_free (mytemp);
1275           break;
1276         }
1277
1278       if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */
1279         {
1280           GNUNET_asprintf (&arg, "%s/friends", temp_service_path);
1281           pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "mv",
1282                                          "mv", mytemp, arg, NULL);
1283 #if VERBOSE_TESTING
1284           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1285                       _("Copying file with command cp %s %s\n"), mytemp, arg);
1286 #endif
1287
1288           GNUNET_free(arg);
1289         }
1290       else /* Remote, scp the file to the correct place */
1291         {
1292           if (NULL != pg->peers[pg_iter].daemon->username)
1293             GNUNET_asprintf (&arg, "%s@%s:%s/friends", pg->peers[pg_iter].daemon->username, pg->peers[pg_iter].daemon->hostname, temp_service_path);
1294           else
1295             GNUNET_asprintf (&arg, "%s:%s/friends", pg->peers[pg_iter].daemon->hostname, temp_service_path);
1296           pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp",
1297                                          "scp", mytemp, arg, NULL);
1298
1299 #if VERBOSE_TESTING
1300           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1301                       _("Copying file with command scp %s %s\n"), mytemp, arg);
1302 #endif
1303           GNUNET_free(arg);
1304         }
1305       GNUNET_free (temp_service_path);
1306       GNUNET_free (mytemp);
1307     }
1308
1309   count = 0;
1310   ret = GNUNET_SYSERR;
1311   while ((count < max_wait) && (ret != GNUNET_OK))
1312     {
1313       ret = GNUNET_OK;
1314       for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1315         {
1316 #if VERBOSE_TESTING
1317           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1318                       _("Checking copy status of file %d\n"), pg_iter);
1319 #endif
1320           if (pidarr[pg_iter] != 0) /* Check for already completed! */
1321             {
1322               if (GNUNET_OS_process_status(pidarr[pg_iter], &type, &return_code) != GNUNET_OK)
1323                 {
1324                   ret = GNUNET_SYSERR;
1325                 }
1326               else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
1327                 {
1328                   ret = GNUNET_SYSERR;
1329                 }
1330               else
1331                 {
1332                   pidarr[pg_iter] = 0;
1333 #if VERBOSE_TESTING
1334             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1335                       _("File %d copied\n"), pg_iter);
1336 #endif
1337                 }
1338             }
1339         }
1340       count++;
1341       if (ret == GNUNET_SYSERR)
1342         {
1343           sleep(1);
1344         }
1345     }
1346
1347 #if VERBOSE_TESTING
1348     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1349                 _("Finished copying all friend files!\n"));
1350 #endif
1351   GNUNET_free(pidarr);
1352   return ret;
1353 }
1354
1355
1356 /*
1357  * Create the blacklist files based on the PeerConnection's
1358  * of each peer in the peer group, and copy the files
1359  * to the appropriate place.
1360  *
1361  * @param pg the peer group we are dealing with
1362  */
1363 static int
1364 create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg)
1365 {
1366   FILE *temp_friend_handle;
1367   unsigned int pg_iter;
1368   char *temp_service_path;
1369   pid_t *pidarr;
1370   char *arg;
1371   char *mytemp;
1372   enum GNUNET_OS_ProcessStatusType type;
1373   unsigned long return_code;
1374   int count;
1375   int ret;
1376   int max_wait = 10;
1377
1378   pidarr = GNUNET_malloc(sizeof(pid_t) * pg->total);
1379   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1380     {
1381       mytemp = GNUNET_DISK_mktemp("blacklist");
1382       GNUNET_assert(mytemp != NULL);
1383       temp_friend_handle = fopen (mytemp, "wt");
1384       GNUNET_assert(temp_friend_handle != NULL);
1385       GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].blacklisted_peers, &blacklist_file_iterator, temp_friend_handle);
1386       fclose(temp_friend_handle);
1387
1388       if (GNUNET_OK !=
1389           GNUNET_CONFIGURATION_get_value_string(pg->peers[pg_iter].daemon->cfg, "PATHS", "SERVICEHOME", &temp_service_path))
1390         {
1391           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1392                       _("No `%s' specified in peer configuration in section `%s', cannot copy friends file!\n"),
1393                       "SERVICEHOME",
1394                       "PATHS");
1395           if (UNLINK (mytemp) != 0)
1396             GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, "unlink", mytemp);
1397           GNUNET_free (mytemp);
1398           break;
1399         }
1400
1401       if (pg->peers[pg_iter].daemon->hostname == NULL) /* Local, just copy the file */
1402         {
1403           GNUNET_asprintf (&arg, "%s/blacklist", temp_service_path);
1404           pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "mv",
1405                                          "mv", mytemp, arg, NULL);
1406 #if VERBOSE_TESTING
1407           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1408                       _("Copying file with command cp %s %s\n"), mytemp, arg);
1409 #endif
1410
1411           GNUNET_free(arg);
1412         }
1413       else /* Remote, scp the file to the correct place */
1414         {
1415           if (NULL != pg->peers[pg_iter].daemon->username)
1416             GNUNET_asprintf (&arg, "%s@%s:%s/blacklist", pg->peers[pg_iter].daemon->username, pg->peers[pg_iter].daemon->hostname, temp_service_path);
1417           else
1418             GNUNET_asprintf (&arg, "%s:%s/blacklist", pg->peers[pg_iter].daemon->hostname, temp_service_path);
1419           pidarr[pg_iter] = GNUNET_OS_start_process (NULL, NULL, "scp",
1420                                          "scp", mytemp, arg, NULL);
1421
1422 #if VERBOSE_TESTING
1423           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1424                       _("Copying file with command scp %s %s\n"), mytemp, arg);
1425 #endif
1426           GNUNET_free(arg);
1427         }
1428       GNUNET_free (temp_service_path);
1429       GNUNET_free (mytemp);
1430     }
1431
1432   count = 0;
1433   ret = GNUNET_SYSERR;
1434   while ((count < max_wait) && (ret != GNUNET_OK))
1435     {
1436       ret = GNUNET_OK;
1437       for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1438         {
1439 #if VERBOSE_TESTING
1440           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1441                       _("Checking copy status of file %d\n"), pg_iter);
1442 #endif
1443           if (pidarr[pg_iter] != 0) /* Check for already completed! */
1444             {
1445               if (GNUNET_OS_process_status(pidarr[pg_iter], &type, &return_code) != GNUNET_OK)
1446                 {
1447                   ret = GNUNET_SYSERR;
1448                 }
1449               else if ((type != GNUNET_OS_PROCESS_EXITED) || (return_code != 0))
1450                 {
1451                   ret = GNUNET_SYSERR;
1452                 }
1453               else
1454                 {
1455                   pidarr[pg_iter] = 0;
1456 #if VERBOSE_TESTING
1457             GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1458                       _("File %d copied\n"), pg_iter);
1459 #endif
1460                 }
1461             }
1462         }
1463       count++;
1464       if (ret == GNUNET_SYSERR)
1465         {
1466           sleep(1);
1467         }
1468     }
1469
1470 #if VERBOSE_TESTING
1471     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1472                 _("Finished copying all blacklist files!\n"));
1473 #endif
1474   GNUNET_free(pidarr);
1475   return ret;
1476 }
1477
1478
1479 /**
1480  * Internal notification of a connection, kept so that we can ensure some connections
1481  * happen instead of flooding all testing daemons with requests to connect.
1482  */
1483 static void internal_connect_notify (void *cls,
1484                                      const struct GNUNET_PeerIdentity *first,
1485                                      const struct GNUNET_PeerIdentity *second,
1486                                      const struct GNUNET_CONFIGURATION_Handle *first_cfg,
1487                                      const struct GNUNET_CONFIGURATION_Handle *second_cfg,
1488                                      struct GNUNET_TESTING_Daemon *first_daemon,
1489                                      struct GNUNET_TESTING_Daemon *second_daemon,
1490                                      const char *emsg)
1491 {
1492   struct GNUNET_TESTING_PeerGroup *pg = cls;
1493   outstanding_connects--;
1494
1495   pg->notify_connection(pg->notify_connection_cls, first, second, first_cfg, second_cfg, first_daemon, second_daemon, emsg);
1496
1497 }
1498
1499 static void schedule_connect(void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1500 {
1501   struct ConnectContext *connect_context = cls;
1502
1503   if (tc->reason == GNUNET_SCHEDULER_REASON_SHUTDOWN)
1504     return;
1505
1506   if (outstanding_connects > MAX_OUTSTANDING_CONNECTIONS)
1507     {
1508 #if VERBOSE_TESTING > 2
1509           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1510                       _("Delaying connect, we have too many outstanding connections!\n"));
1511 #endif
1512       GNUNET_SCHEDULER_add_delayed(connect_context->pg->sched, GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 3), &schedule_connect, connect_context);
1513     }
1514   else
1515     {
1516 #if VERBOSE_TESTING > 2
1517           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1518                       _("Creating connection, outstanding_connections is %d\n"), outstanding_connects);
1519 #endif
1520       outstanding_connects++;
1521       GNUNET_TESTING_daemons_connect (connect_context->first,
1522                                       connect_context->second,
1523                                       CONNECT_TIMEOUT,
1524                                       CONNECT_ATTEMPTS,
1525                                       &internal_connect_notify,
1526                                       connect_context->pg);
1527       GNUNET_free(connect_context);
1528     }
1529 }
1530
1531 /**
1532  * Iterator for actually scheduling connections to be created
1533  * between two peers.
1534  *
1535  * @param cls closure, a GNUNET_TESTING_Daemon
1536  * @param key the key the second Daemon was stored under
1537  * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1538  *
1539  * @return GNUNET_YES to continue iteration
1540  */
1541 static int
1542 connect_iterator (void *cls,
1543                   const GNUNET_HashCode * key,
1544                   void *value)
1545 {
1546   struct PeerData *first = cls;
1547   struct GNUNET_TESTING_Daemon *second = value;
1548   struct ConnectContext *connect_context;
1549
1550   connect_context = GNUNET_malloc(sizeof(struct ConnectContext));
1551   connect_context->pg = first->pg;
1552   connect_context->first = first->daemon;
1553   connect_context->second = second;
1554   GNUNET_SCHEDULER_add_now(first->pg->sched, &schedule_connect, connect_context);
1555
1556   return GNUNET_YES;
1557 }
1558
1559 /**
1560  * Iterator for copying all entries in the allowed hashmap to the
1561  * connect hashmap.
1562  *
1563  * @param cls closure, a GNUNET_TESTING_Daemon
1564  * @param key the key the second Daemon was stored under
1565  * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1566  *
1567  * @return GNUNET_YES to continue iteration
1568  */
1569 static int
1570 copy_topology_iterator (void *cls,
1571                   const GNUNET_HashCode * key,
1572                   void *value)
1573 {
1574   struct PeerData *first = cls;
1575
1576   GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(first->connect_peers, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1577
1578   return GNUNET_YES;
1579 }
1580
1581 /**
1582  * Make the peers to connect the same as those that are allowed to be
1583  * connected.
1584  *
1585  * @param pg the peer group
1586  */
1587 static int
1588 copy_allowed_topology (struct GNUNET_TESTING_PeerGroup *pg)
1589 {
1590   unsigned int pg_iter;
1591   int ret;
1592   int total;
1593
1594   total = 0;
1595   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1596     {
1597       ret = GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].allowed_peers, &copy_topology_iterator, &pg->peers[pg_iter]);
1598       if (GNUNET_SYSERR == ret)
1599         return GNUNET_SYSERR;
1600
1601       total = total + ret;
1602     }
1603
1604   return total;
1605 }
1606
1607
1608 /*
1609  * Connect the topology as specified by the PeerConnection's
1610  * of each peer in the peer group
1611  *
1612  * @param pg the peer group we are dealing with
1613  *
1614  * @return the number of connections that will be attempted
1615  */
1616 static int
1617 connect_topology (struct GNUNET_TESTING_PeerGroup *pg)
1618 {
1619   unsigned int pg_iter;
1620   int ret;
1621   int total;
1622 #if OLD
1623   struct PeerConnection *connection_iter;
1624   struct ConnectContext *connect_context;
1625 #endif
1626
1627   total = 0;
1628   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
1629     {
1630       ret = GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &connect_iterator, &pg->peers[pg_iter]);
1631       if (GNUNET_SYSERR == ret)
1632         return GNUNET_SYSERR;
1633
1634       total = total + ret;
1635
1636 #if OLD
1637       connection_iter = ;
1638       while (connection_iter != NULL)
1639         {
1640           connect_context = GNUNET_malloc(sizeof(struct ConnectContext));
1641           connect_context->pg = pg;
1642           connect_context->first = ;
1643           connect_context->second = connection_iter->daemon;
1644           GNUNET_SCHEDULER_add_now(pg->sched, &schedule_connect, connect_context);
1645           connection_iter = connection_iter->next;
1646         }
1647 #endif
1648     }
1649   return total;
1650 }
1651
1652
1653 /*
1654  * Takes a peer group and creates a topology based on the
1655  * one specified.  Creates a topology means generates friend
1656  * files for the peers so they can only connect to those allowed
1657  * by the topology.  This will only have an effect once peers
1658  * are started if the FRIENDS_ONLY option is set in the base
1659  * config.  Also takes an optional restrict topology which
1660  * disallows direct TCP connections UNLESS they are specified in
1661  * the restricted topology.
1662  *
1663  * @param pg the peer group struct representing the running peers
1664  * @param topology which topology to connect the peers in
1665  * @param restrict_topology allow only direct TCP connections in this topology
1666  *                          use GNUNET_TESTING_TOPOLOGY_NONE for no restrictions
1667  *
1668  * @return the maximum number of connections were all allowed peers
1669  *         connected to each other
1670  */
1671 int
1672 GNUNET_TESTING_create_topology (struct GNUNET_TESTING_PeerGroup *pg,
1673                                 enum GNUNET_TESTING_Topology topology,
1674                                 enum GNUNET_TESTING_Topology restrict_topology)
1675 {
1676   int ret;
1677   int num_connections;
1678   int unblacklisted_connections;
1679
1680   GNUNET_assert (pg->notify_connection != NULL);
1681   ret = GNUNET_OK;
1682
1683   switch (topology)
1684     {
1685     case GNUNET_TESTING_TOPOLOGY_CLIQUE:
1686 #if VERBOSE_TESTING
1687       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1688                   _("Creating clique topology\n"));
1689 #endif
1690       num_connections = create_clique (pg, &add_allowed_connections);
1691       break;
1692     case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
1693 #if VERBOSE_TESTING
1694       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695                   _("Creating small world (ring) topology\n"));
1696 #endif
1697       num_connections = create_small_world_ring (pg, &add_allowed_connections);
1698       break;
1699     case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
1700 #if VERBOSE_TESTING
1701       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1702                   _("Creating small world (2d-torus) topology\n"));
1703 #endif
1704       num_connections = create_small_world (pg, &add_allowed_connections);
1705       break;
1706     case GNUNET_TESTING_TOPOLOGY_RING:
1707 #if VERBOSE_TESTING
1708       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1709                   _("Creating ring topology\n"));
1710 #endif
1711       num_connections = create_ring (pg, &add_allowed_connections);
1712       break;
1713     case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
1714 #if VERBOSE_TESTING
1715       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1716                   _("Creating 2d torus topology\n"));
1717 #endif
1718       num_connections = create_2d_torus (pg, &add_allowed_connections);
1719       break;
1720     case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
1721 #if VERBOSE_TESTING
1722       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1723                   _("Creating Erdos-Renyi topology\n"));
1724 #endif
1725       num_connections = create_erdos_renyi (pg, &add_allowed_connections);
1726       break;
1727     case GNUNET_TESTING_TOPOLOGY_INTERNAT:
1728 #if VERBOSE_TESTING
1729       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1730                   _("Creating InterNAT topology\n"));
1731 #endif
1732       num_connections = create_nated_internet (pg, &add_allowed_connections);
1733       break;
1734     case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
1735 #if VERBOSE_TESTING
1736       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1737                   _("Creating Scale Free topology\n"));
1738 #endif
1739       num_connections = create_scale_free (pg, &add_allowed_connections);
1740       break;
1741     case GNUNET_TESTING_TOPOLOGY_NONE:
1742       num_connections = 0;
1743       break;
1744     default:
1745       num_connections = 0;
1746       break;
1747     }
1748   if (num_connections < 1)
1749     return GNUNET_SYSERR;
1750
1751   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_yesno (pg->cfg, "TESTING", "F2F"))
1752     {
1753       ret = create_and_copy_friend_files(pg);
1754     }
1755
1756   if (ret != GNUNET_OK)
1757     {
1758 #if VERBOSE_TESTING
1759       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1760                   _("Failed during friend file copying!\n"));
1761 #endif
1762       return GNUNET_SYSERR;
1763     }
1764   else
1765     {
1766 #if VERBOSE_TESTING
1767           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1768                       _("Friend files created/copied successfully!\n"));
1769 #endif
1770     }
1771
1772   /**
1773    * Use the create clique method to initially set all connections
1774    * as blacklisted.
1775    */
1776   create_clique (pg, &blacklist_connections);
1777   unblacklisted_connections = 0;
1778   /**
1779    * Un-blacklist connections as per the topology specified
1780    */
1781   switch (restrict_topology)
1782     {
1783     case GNUNET_TESTING_TOPOLOGY_CLIQUE:
1784 #if VERBOSE_TESTING
1785       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1786                   _("Blacklisting all but clique topology\n"));
1787 #endif
1788       unblacklisted_connections = create_clique (pg, &unblacklist_connections);
1789       break;
1790     case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
1791 #if VERBOSE_TESTING
1792       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1793                   _("Blacklisting all but small world (ring) topology\n"));
1794 #endif
1795       unblacklisted_connections = create_small_world_ring (pg, &unblacklist_connections);
1796       break;
1797     case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
1798 #if VERBOSE_TESTING
1799       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1800                   _("Blacklisting all but small world (2d-torus) topology\n"));
1801 #endif
1802       unblacklisted_connections = create_small_world (pg, &unblacklist_connections);
1803       break;
1804     case GNUNET_TESTING_TOPOLOGY_RING:
1805 #if VERBOSE_TESTING
1806       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1807                   _("Blacklisting all but ring topology\n"));
1808 #endif
1809       unblacklisted_connections = create_ring (pg, &unblacklist_connections);
1810       break;
1811     case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
1812 #if VERBOSE_TESTING
1813       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1814                   _("Blacklisting all but 2d torus topology\n"));
1815 #endif
1816       unblacklisted_connections = create_2d_torus (pg, &unblacklist_connections);
1817       break;
1818     case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
1819 #if VERBOSE_TESTING
1820       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1821                   _("Blacklisting all but Erdos-Renyi topology\n"));
1822 #endif
1823       unblacklisted_connections = create_erdos_renyi (pg, &unblacklist_connections);
1824       break;
1825     case GNUNET_TESTING_TOPOLOGY_INTERNAT:
1826 #if VERBOSE_TESTING
1827       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1828                   _("Blacklisting all but InterNAT topology\n"));
1829 #endif
1830       unblacklisted_connections = create_nated_internet (pg, &unblacklist_connections);
1831       break;
1832     case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
1833 #if VERBOSE_TESTING
1834       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1835                   _("Blacklisting all but Scale Free topology\n"));
1836 #endif
1837       unblacklisted_connections = create_scale_free (pg, &unblacklist_connections);
1838       break;
1839     case GNUNET_TESTING_TOPOLOGY_NONE:
1840       /* Fall through */
1841     default:
1842       break;
1843     }
1844
1845   if (unblacklisted_connections > 0)
1846   {
1847     ret = create_and_copy_blacklist_files(pg);
1848     if (ret != GNUNET_OK)
1849       {
1850 #if VERBOSE_TESTING
1851         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1852                     _("Failed during blacklist file copying!\n"));
1853 #endif
1854         return GNUNET_SYSERR;
1855       }
1856     else
1857       {
1858 #if VERBOSE_TESTING
1859         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1860                     _("Blacklist files created/copied successfully!\n"));
1861 #endif
1862       }
1863   }
1864
1865
1866   return num_connections;
1867 }
1868
1869 struct RandomContext
1870 {
1871   /**
1872    * The peergroup
1873    */
1874   struct GNUNET_TESTING_PeerGroup *pg;
1875
1876   /**
1877    * uid of the first peer
1878    */
1879   uint32_t first_uid;
1880
1881   /**
1882    * Peer data for first peer.
1883    */
1884   struct PeerData *first;
1885
1886   /**
1887    * Random percentage to use
1888    */
1889   double percentage;
1890 };
1891
1892 struct MinimumContext
1893 {
1894   /**
1895    * The peergroup
1896    */
1897   struct GNUNET_TESTING_PeerGroup *pg;
1898
1899   /**
1900    * uid of the first peer
1901    */
1902   uint32_t first_uid;
1903
1904   /**
1905    * Peer data for first peer.
1906    */
1907   struct PeerData *first;
1908
1909   /**
1910    * Number of conns per peer
1911    */
1912   unsigned int num_to_add;
1913
1914   /**
1915    * Permuted array of all possible connections.  Only add the Nth
1916    * peer if it's in the Nth position.
1917    */
1918   unsigned int *pg_array;
1919
1920   /**
1921    * What number is the current element we are iterating over?
1922    */
1923   unsigned int current;
1924 };
1925
1926 struct DFSContext
1927 {
1928   /**
1929    * The peergroup
1930    */
1931   struct GNUNET_TESTING_PeerGroup *pg;
1932
1933   /**
1934    * uid of the first peer
1935    */
1936   uint32_t first_uid;
1937
1938   /**
1939    * uid of the second peer
1940    */
1941   uint32_t second_uid;
1942
1943   /**
1944    * Peer data for first peer.
1945    */
1946   struct PeerData *first;
1947
1948   /**
1949    * Which peer has been chosen as the one to add?
1950    */
1951   unsigned int chosen;
1952
1953   /**
1954    * What number is the current element we are iterating over?
1955    */
1956   unsigned int current;
1957 };
1958
1959 /**
1960  * Iterator for choosing random peers to connect.
1961  *
1962  * @param cls closure, a RandomContext
1963  * @param key the key the second Daemon was stored under
1964  * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1965  *
1966  * @return GNUNET_YES to continue iteration
1967  */
1968 static int
1969 random_connect_iterator (void *cls,
1970                   const GNUNET_HashCode * key,
1971                   void *value)
1972 {
1973   struct RandomContext *random_ctx = cls;
1974   double random_number;
1975   uint32_t second_pos;
1976   GNUNET_HashCode first_hash;
1977   random_number = ((double) GNUNET_CRYPTO_random_u64(GNUNET_CRYPTO_QUALITY_WEAK,
1978                    (uint64_t)-1LL)) / ( (double) (uint64_t) -1LL);
1979   if (random_number < random_ctx->percentage)
1980   {
1981     GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(random_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
1982   }
1983   /* Now we have considered this particular connection, remove it from the second peer so it's not double counted */
1984   uid_from_hash(key, &second_pos);
1985   hash_from_uid(random_ctx->first_uid, &first_hash);
1986   GNUNET_assert(random_ctx->pg->total > second_pos);
1987   GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(random_ctx->pg->peers[second_pos].connect_peers, &first_hash, random_ctx->first->daemon));
1988
1989   return GNUNET_YES;
1990 }
1991
1992 /**
1993  * Iterator for adding at least X peers to a peers connection set.
1994  *
1995  * @param cls closure, MinimumContext
1996  * @param key the key the second Daemon was stored under
1997  * @param value the GNUNET_TESTING_Daemon that the first is to connect to
1998  *
1999  * @return GNUNET_YES to continue iteration
2000  */
2001 static int
2002 minimum_connect_iterator (void *cls,
2003                   const GNUNET_HashCode * key,
2004                   void *value)
2005 {
2006   struct MinimumContext *min_ctx = cls;
2007   uint32_t second_pos;
2008   GNUNET_HashCode first_hash;
2009   unsigned int i;
2010
2011   if (GNUNET_CONTAINER_multihashmap_size(min_ctx->first->connect_peers_working_set) < min_ctx->num_to_add)
2012   {
2013     for (i = 0; i < min_ctx->num_to_add; i++)
2014     {
2015       if (min_ctx->pg_array[i] == min_ctx->current)
2016       {
2017         GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(min_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2018         uid_from_hash(key, &second_pos);
2019         hash_from_uid(min_ctx->first_uid, &first_hash);
2020         GNUNET_assert(min_ctx->pg->total > second_pos);
2021         GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(min_ctx->pg->peers[second_pos].connect_peers_working_set, &first_hash, min_ctx->first->daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2022         /* Now we have added this particular connection, remove it from the second peer's map so it's not double counted */
2023         GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(min_ctx->pg->peers[second_pos].connect_peers, &first_hash, min_ctx->first->daemon));
2024       }
2025     }
2026     min_ctx->current++;
2027     return GNUNET_YES;
2028   }
2029   else
2030     return GNUNET_NO; /* We can stop iterating, we have enough peers! */
2031
2032 }
2033
2034
2035 /**
2036  * Iterator for adding peers to a connection set based on a depth first search.
2037  *
2038  * @param cls closure, MinimumContext
2039  * @param key the key the second daemon was stored under
2040  * @param value the GNUNET_TESTING_Daemon that the first is to connect to
2041  *
2042  * @return GNUNET_YES to continue iteration
2043  */
2044 static int
2045 dfs_connect_iterator (void *cls,
2046                   const GNUNET_HashCode * key,
2047                   void *value)
2048 {
2049   struct DFSContext *dfs_ctx = cls;
2050   GNUNET_HashCode first_hash;
2051
2052   if (dfs_ctx->current == dfs_ctx->chosen)
2053     {
2054       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(dfs_ctx->first->connect_peers_working_set, key, value, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2055       uid_from_hash(key, &dfs_ctx->second_uid);
2056       hash_from_uid(dfs_ctx->first_uid, &first_hash);
2057       GNUNET_assert(GNUNET_OK == GNUNET_CONTAINER_multihashmap_put(dfs_ctx->pg->peers[dfs_ctx->second_uid].connect_peers_working_set, &first_hash, dfs_ctx->first->daemon, GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
2058       GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(dfs_ctx->pg->peers[dfs_ctx->second_uid].connect_peers, &first_hash, dfs_ctx->first->daemon));
2059       /* Can't remove second from first yet because we are currently iterating, hence the return value in the DFSContext! */
2060       return GNUNET_NO; /* We have found our peer, don't iterate more */
2061     }
2062
2063   dfs_ctx->current++;
2064   return GNUNET_YES;
2065 }
2066
2067
2068 /**
2069  * From the set of connections possible, choose percentage percent of connections
2070  * to actually connect.
2071  *
2072  * @param pg the peergroup we are dealing with
2073  * @param percentage what percent of total connections to make
2074  */
2075 void
2076 choose_random_connections(struct GNUNET_TESTING_PeerGroup *pg, double percentage)
2077 {
2078   struct RandomContext random_ctx;
2079   uint32_t pg_iter;
2080
2081   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2082     {
2083       random_ctx.first_uid = pg_iter;
2084       random_ctx.first = &pg->peers[pg_iter];
2085       random_ctx.percentage = percentage;
2086       random_ctx.pg = pg;
2087       pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total);
2088       GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &random_connect_iterator, &random_ctx);
2089       /* Now remove the old connections */
2090       GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
2091       /* And replace with the random set */
2092       pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
2093     }
2094 }
2095
2096 /**
2097  * From the set of connections possible, choose at least num connections per
2098  * peer.
2099  *
2100  * @param pg the peergroup we are dealing with
2101  * @param num how many connections at least should each peer have (if possible)?
2102  */
2103 void
2104 choose_minimum(struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
2105 {
2106   struct MinimumContext minimum_ctx;
2107   uint32_t pg_iter;
2108
2109   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2110     {
2111       pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(num);
2112     }
2113
2114   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2115     {
2116       minimum_ctx.first_uid = pg_iter;
2117       minimum_ctx.pg_array = GNUNET_CRYPTO_random_permute(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
2118       minimum_ctx.first = &pg->peers[pg_iter];
2119       minimum_ctx.pg = pg;
2120       minimum_ctx.num_to_add = num;
2121       minimum_ctx.current = 0;
2122       pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(pg->total);
2123       GNUNET_CONTAINER_multihashmap_iterate(pg->peers[pg_iter].connect_peers, &minimum_connect_iterator, &minimum_ctx);
2124     }
2125
2126   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2127     {
2128       /* Remove the "old" connections */
2129       GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
2130       /* And replace with the working set */
2131       pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
2132       fprintf(stderr, "Finished! Hashmap size %u\n", GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
2133     }
2134
2135 }
2136
2137
2138 static unsigned int count_workingset_connections(struct GNUNET_TESTING_PeerGroup *pg)
2139 {
2140   unsigned int count;
2141   unsigned int pg_iter;
2142
2143   count = 0;
2144
2145   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2146     {
2147       count += GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers_working_set);
2148     }
2149
2150   return count;
2151 }
2152
2153
2154 static unsigned int count_allowed_connections(struct GNUNET_TESTING_PeerGroup *pg)
2155 {
2156   unsigned int count;
2157   unsigned int pg_iter;
2158
2159   count = 0;
2160
2161   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2162     {
2163       count += GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers);
2164     }
2165
2166   return count;
2167 }
2168
2169 /**
2170  * From the set of connections possible, choose at least num connections per
2171  * peer based on depth first traversal of peer connections.  If DFS leaves
2172  * peers unconnected, ensure those peers get connections.
2173  *
2174  * @param pg the peergroup we are dealing with
2175  * @param num how many connections at least should each peer have (if possible)?
2176  */
2177 void
2178 perform_dfs (struct GNUNET_TESTING_PeerGroup *pg, unsigned int num)
2179 {
2180   struct DFSContext dfs_ctx;
2181   uint32_t pg_iter;
2182   uint32_t dfs_count;
2183   uint32_t starting_peer;
2184   uint32_t least_connections;
2185   GNUNET_HashCode second_hash;
2186
2187   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2188     {
2189       pg->peers[pg_iter].connect_peers_working_set = GNUNET_CONTAINER_multihashmap_create(num);
2190     }
2191
2192   starting_peer = 0;
2193   dfs_count = 0;
2194   while ((count_workingset_connections(pg) < num * pg->total) && (count_allowed_connections(pg) > 0))
2195     {
2196       if (dfs_count % pg->total == 0) /* Restart the DFS at some weakly connected peer */
2197         {
2198           least_connections = -1; /* Set to very high number */
2199           for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2200             {
2201               if (GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers_working_set) < least_connections)
2202                 {
2203                   starting_peer = pg_iter;
2204                   least_connections = GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers_working_set);
2205                 }
2206             }
2207         }
2208
2209       if (GNUNET_CONTAINER_multihashmap_size(pg->peers[starting_peer].connect_peers) == 0)  /* Ensure there is at least one peer left to connect! */
2210         {
2211           dfs_count = 0;
2212           continue;
2213         }
2214
2215       /* Choose a random peer from the chosen peers set of connections to add */
2216       dfs_ctx.chosen = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, GNUNET_CONTAINER_multihashmap_size(pg->peers[starting_peer].connect_peers));
2217       dfs_ctx.first_uid = starting_peer;
2218       dfs_ctx.first = &pg->peers[starting_peer];
2219       dfs_ctx.pg = pg;
2220       dfs_ctx.current = 0;
2221
2222       GNUNET_CONTAINER_multihashmap_iterate(pg->peers[starting_peer].connect_peers, &dfs_connect_iterator, &dfs_ctx);
2223       /* Remove the second from the first, since we will be continuing the search and may encounter the first peer again! */
2224       hash_from_uid(dfs_ctx.second_uid, &second_hash);
2225       GNUNET_assert(GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove(pg->peers[starting_peer].connect_peers, &second_hash, pg->peers[dfs_ctx.second_uid].daemon));
2226       starting_peer = dfs_ctx.second_uid;
2227     }
2228
2229   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2230     {
2231
2232     }
2233
2234   for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
2235     {
2236       /* Remove the "old" connections */
2237       GNUNET_CONTAINER_multihashmap_destroy(pg->peers[pg_iter].connect_peers);
2238       /* And replace with the working set */
2239       pg->peers[pg_iter].connect_peers = pg->peers[pg_iter].connect_peers_working_set;
2240       fprintf(stderr, "Finished! Hashmap size %u\n", GNUNET_CONTAINER_multihashmap_size(pg->peers[pg_iter].connect_peers));
2241     }
2242
2243 }
2244
2245 /*
2246  * @param pg the peer group struct representing the running peers
2247  * @param topology which topology to connect the peers in
2248  * @param options options for connecting the topology
2249  * @param option_modifier modifier for options that take a parameter
2250  *
2251  * There are many ways to connect peers that are supported by this function.
2252  * To connect peers in the same topology that was created via the
2253  * GNUNET_TESTING_create_topology, the topology variable must be set to
2254  * GNUNET_TESTING_TOPOLOGY_NONE.  If the topology variable is specified,
2255  * a new instance of that topology will be generated and attempted to be
2256  * connected.  This could result in some connections being impossible,
2257  * because some topologies are non-deterministic.
2258  *
2259  */
2260 int
2261 GNUNET_TESTING_connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
2262                                  enum GNUNET_TESTING_Topology topology,
2263                                  enum GNUNET_TESTING_TopologyOption options,
2264                                  double option_modifier)
2265 {
2266   int num_connections;
2267
2268   switch (topology)
2269       {
2270       case GNUNET_TESTING_TOPOLOGY_CLIQUE:
2271   #if VERBOSE_TESTING
2272         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2273                     _("Creating clique topology\n"));
2274   #endif
2275         num_connections = create_clique (pg, &add_actual_connections);
2276         break;
2277       case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD_RING:
2278   #if VERBOSE_TESTING
2279         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2280                     _("Creating small world (ring) topology\n"));
2281   #endif
2282         num_connections = create_small_world_ring (pg, &add_actual_connections);
2283         break;
2284       case GNUNET_TESTING_TOPOLOGY_SMALL_WORLD:
2285   #if VERBOSE_TESTING
2286         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2287                     _("Creating small world (2d-torus) topology\n"));
2288   #endif
2289         num_connections = create_small_world (pg, &add_actual_connections);
2290         break;
2291       case GNUNET_TESTING_TOPOLOGY_RING:
2292   #if VERBOSE_TESTING
2293         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2294                     _("Creating ring topology\n"));
2295   #endif
2296         num_connections = create_ring (pg, &add_actual_connections);
2297         break;
2298       case GNUNET_TESTING_TOPOLOGY_2D_TORUS:
2299   #if VERBOSE_TESTING
2300         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2301                     _("Creating 2d torus topology\n"));
2302   #endif
2303         num_connections = create_2d_torus (pg, &add_actual_connections);
2304         break;
2305       case GNUNET_TESTING_TOPOLOGY_ERDOS_RENYI:
2306   #if VERBOSE_TESTING
2307         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2308                     _("Creating Erdos-Renyi topology\n"));
2309   #endif
2310         num_connections = create_erdos_renyi (pg, &add_actual_connections);
2311         break;
2312       case GNUNET_TESTING_TOPOLOGY_INTERNAT:
2313   #if VERBOSE_TESTING
2314         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2315                     _("Creating InterNAT topology\n"));
2316   #endif
2317         num_connections = create_nated_internet (pg, &add_actual_connections);
2318         break;
2319       case GNUNET_TESTING_TOPOLOGY_SCALE_FREE:
2320   #if VERBOSE_TESTING
2321         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2322                     _("Creating Scale Free topology\n"));
2323   #endif
2324         num_connections = create_scale_free (pg, &add_actual_connections);
2325         break;
2326       case GNUNET_TESTING_TOPOLOGY_NONE:
2327         num_connections = copy_allowed_topology(pg);
2328         break;
2329       default:
2330         GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Unknown topology specification, can't connect peers!\n");
2331         return GNUNET_SYSERR;
2332       }
2333
2334   switch (options)
2335     {
2336     case GNUNET_TESTING_TOPOLOGY_OPTION_RANDOM: /* Create a random subset of total connections based on parameter */
2337       choose_random_connections(pg, option_modifier);
2338       break;
2339     case GNUNET_TESTING_TOPOLOGY_OPTION_MINIMUM: /* Create at least X connections per peer (if possible!) */
2340       choose_minimum(pg, (unsigned int)option_modifier);
2341       break;
2342     case GNUNET_TESTING_TOPOLOGY_OPTION_DFS: /* Choose a random starting point, randomly walk graph, try to get each peer X connections */
2343       perform_dfs(pg, (int)option_modifier);
2344       break;
2345     case GNUNET_TESTING_TOPOLOGY_OPTION_NONE:
2346       /* Fall through */
2347     case GNUNET_TESTING_TOPOLOGY_OPTION_ALL:
2348       /* Fall through */
2349     default:
2350       break;
2351     }
2352
2353   return connect_topology(pg);
2354 }
2355
2356 /**
2357  * Function which continues a peer group starting up
2358  * after successfully generating hostkeys for each peer.
2359  *
2360  * @param pg the peer group to continue starting
2361  *
2362  */
2363 void
2364 GNUNET_TESTING_daemons_continue_startup(struct GNUNET_TESTING_PeerGroup *pg)
2365 {
2366   unsigned int i;
2367
2368   for (i = 0; i < pg->total; i++)
2369     {
2370       GNUNET_TESTING_daemon_continue_startup(pg->peers[i].daemon);
2371     }
2372 }
2373
2374 /**
2375  * Start count gnunetd processes with the same set of transports and
2376  * applications.  The port numbers (any option called "PORT") will be
2377  * adjusted to ensure that no two peers running on the same system
2378  * have the same port(s) in their respective configurations.
2379  *
2380  * @param sched scheduler to use
2381  * @param cfg configuration template to use
2382  * @param total number of daemons to start
2383  * @param hostkey_callback function to call on each peers hostkey generation
2384  *        if NULL, peers will be started by this call, if non-null,
2385  *        GNUNET_TESTING_daemons_continue_startup must be called after
2386  *        successful hostkey generation
2387  * @param hostkey_cls closure for hostkey callback
2388  * @param cb function to call on each daemon that was started
2389  * @param cb_cls closure for cb
2390  * @param connect_callback function to call each time two hosts are connected
2391  * @param connect_callback_cls closure for connect_callback
2392  * @param hostnames space-separated list of hostnames to use; can be NULL (to run
2393  *        everything on localhost).
2394  * @return NULL on error, otherwise handle to control peer group
2395  */
2396 struct GNUNET_TESTING_PeerGroup *
2397 GNUNET_TESTING_daemons_start (struct GNUNET_SCHEDULER_Handle *sched,
2398                               const struct GNUNET_CONFIGURATION_Handle *cfg,
2399                               unsigned int total,
2400                               GNUNET_TESTING_NotifyHostkeyCreated hostkey_callback,
2401                               void *hostkey_cls,
2402                               GNUNET_TESTING_NotifyDaemonRunning cb,
2403                               void *cb_cls,
2404                               GNUNET_TESTING_NotifyConnection
2405                               connect_callback, void *connect_callback_cls,
2406                               const char *hostnames)
2407 {
2408   struct GNUNET_TESTING_PeerGroup *pg;
2409   const char *rpos;
2410   char *pos;
2411   char *start;
2412   const char *hostname;
2413   char *baseservicehome;
2414   char *newservicehome;
2415   char *tmpdir;
2416   struct GNUNET_CONFIGURATION_Handle *pcfg;
2417   unsigned int off;
2418   unsigned int hostcnt;
2419   uint16_t minport;
2420
2421   if (0 == total)
2422     {
2423       GNUNET_break (0);
2424       return NULL;
2425     }
2426
2427   pg = GNUNET_malloc (sizeof (struct GNUNET_TESTING_PeerGroup));
2428   pg->sched = sched;
2429   pg->cfg = cfg;
2430   pg->cb = cb;
2431   pg->cb_cls = cb_cls;
2432   pg->notify_connection = connect_callback;
2433   pg->notify_connection_cls = connect_callback_cls;
2434   pg->total = total;
2435   pg->peers = GNUNET_malloc (total * sizeof (struct PeerData));
2436   if (NULL != hostnames)
2437     {
2438       off = 2;
2439       /* skip leading spaces */
2440       while ((0 != *hostnames) && (isspace (*hostnames)))
2441         hostnames++;
2442       rpos = hostnames;
2443       while ('\0' != *rpos)
2444         {
2445           if (isspace (*rpos))
2446             off++;
2447           rpos++;
2448         }
2449       pg->hosts = GNUNET_malloc (off * sizeof (struct HostData));
2450       off = 0;
2451       start = GNUNET_strdup (hostnames);
2452       pos = start;
2453       while ('\0' != *pos)
2454         {
2455           if (isspace (*pos))
2456             {
2457               *pos = '\0';
2458               if (strlen (start) > 0)
2459                 {
2460                   pg->hosts[off].minport = LOW_PORT;
2461                   pg->hosts[off++].hostname = start;
2462                 }
2463               start = pos + 1;
2464             }
2465           pos++;
2466         }
2467       if (strlen (start) > 0)
2468         {
2469           pg->hosts[off].minport = LOW_PORT;
2470           pg->hosts[off++].hostname = start;
2471         }
2472       if (off == 0)
2473         {
2474           GNUNET_free (start);
2475           GNUNET_free (pg->hosts);
2476           pg->hosts = NULL;
2477         }
2478       hostcnt = off;
2479       minport = 0;              /* make gcc happy */
2480     }
2481   else
2482     {
2483       hostcnt = 0;
2484       minport = LOW_PORT;
2485     }
2486   for (off = 0; off < total; off++)
2487     {
2488       if (hostcnt > 0)
2489         {
2490           hostname = pg->hosts[off % hostcnt].hostname;
2491           pcfg = make_config (cfg, &pg->hosts[off % hostcnt].minport, hostname);
2492         }
2493       else
2494         {
2495           hostname = NULL;
2496           pcfg = make_config (cfg, &minport, hostname);
2497         }
2498
2499       if (NULL == pcfg)
2500         {
2501           GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2502                       _
2503                       ("Could not create configuration for peer number %u on `%s'!\n"),
2504                       off, hostname == NULL ? "localhost" : hostname);
2505           continue;
2506         }
2507
2508       if (GNUNET_YES ==
2509           GNUNET_CONFIGURATION_get_value_string (pcfg, "PATHS", "SERVICEHOME",
2510                                                  &baseservicehome))
2511         {
2512           GNUNET_asprintf (&newservicehome,
2513                            "%s/%d/", baseservicehome, off);
2514           GNUNET_free (baseservicehome);
2515         }
2516       else
2517         {
2518           tmpdir = getenv ("TMPDIR");
2519           tmpdir = tmpdir ? tmpdir : "/tmp";
2520           GNUNET_asprintf (&newservicehome,
2521                            "%s/%s/%d/",
2522                            tmpdir,
2523                            "gnunet-testing-test-test", off);
2524         }
2525       GNUNET_CONFIGURATION_set_value_string (pcfg,
2526                                              "PATHS",
2527                                              "SERVICEHOME", newservicehome);
2528       GNUNET_free (newservicehome);
2529       pg->peers[off].cfg = pcfg;
2530       pg->peers[off].allowed_peers = GNUNET_CONTAINER_multihashmap_create(total);
2531       pg->peers[off].connect_peers = GNUNET_CONTAINER_multihashmap_create(total);
2532       pg->peers[off].blacklisted_peers = GNUNET_CONTAINER_multihashmap_create(total);
2533       pg->peers[off].pg = pg;
2534       pg->peers[off].daemon = GNUNET_TESTING_daemon_start (sched,
2535                                                            pcfg,
2536                                                            hostname,
2537                                                            hostkey_callback,
2538                                                            hostkey_cls,
2539                                                            cb, cb_cls);
2540       if (NULL == pg->peers[off].daemon)
2541         GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
2542                     _("Could not start peer number %u!\n"), off);
2543
2544     }
2545   return pg;
2546 }
2547
2548 /*
2549  * Get a daemon by number, so callers don't have to do nasty
2550  * offsetting operation.
2551  */
2552 struct GNUNET_TESTING_Daemon *
2553 GNUNET_TESTING_daemon_get (struct GNUNET_TESTING_PeerGroup *pg, unsigned int position)
2554 {
2555   if (position < pg->total)
2556     return pg->peers[position].daemon;
2557   else
2558     return NULL;
2559 }
2560
2561 /**
2562  * Prototype of a function that will be called when a
2563  * particular operation was completed the testing library.
2564  *
2565  * @param cls closure
2566  * @param emsg NULL on success
2567  */
2568 void restart_callback (void *cls,
2569                        const struct GNUNET_PeerIdentity *id,
2570                        const struct GNUNET_CONFIGURATION_Handle *cfg,
2571                        struct GNUNET_TESTING_Daemon *d,
2572                        const char *emsg)
2573 {
2574   struct RestartContext *restart_context = cls;
2575
2576   if (emsg == NULL)
2577     {
2578       restart_context->peers_restarted++;
2579     }
2580   else
2581     {
2582       restart_context->peers_restart_failed++;
2583     }
2584
2585   if (restart_context->peers_restarted == restart_context->peer_group->total)
2586     {
2587       restart_context->callback(restart_context->callback_cls, NULL);
2588       GNUNET_free(restart_context);
2589     }
2590   else if (restart_context->peers_restart_failed + restart_context->peers_restarted == restart_context->peer_group->total)
2591     {
2592       restart_context->callback(restart_context->callback_cls, "Failed to restart peers!");
2593       GNUNET_free(restart_context);
2594     }
2595
2596 }
2597
2598 /**
2599  * Restart all peers in the given group.
2600  *
2601  * @param pg the handle to the peer group
2602  * @param timeout how long to wait on failure
2603  * @param callback function to call on completion (or failure)
2604  * @param callback_cls closure for the callback function
2605  */
2606 void
2607 GNUNET_TESTING_daemons_restart (struct GNUNET_TESTING_PeerGroup *pg, GNUNET_TESTING_NotifyCompletion callback, void *callback_cls)
2608 {
2609   struct RestartContext *restart_context;
2610   unsigned int off;
2611
2612   if (pg->total > 0)
2613     {
2614       restart_context = GNUNET_malloc(sizeof(struct RestartContext));
2615       restart_context->peer_group = pg;
2616       restart_context->peers_restarted = 0;
2617       restart_context->callback = callback;
2618       restart_context->callback_cls = callback_cls;
2619
2620       for (off = 0; off < pg->total; off++)
2621         {
2622           GNUNET_TESTING_daemon_restart (pg->peers[off].daemon, &restart_callback, restart_context);
2623         }
2624     }
2625 }
2626
2627 /**
2628  * Shutdown all peers started in the given group.
2629  *
2630  * @param pg handle to the peer group
2631  */
2632 void
2633 GNUNET_TESTING_daemons_stop (struct GNUNET_TESTING_PeerGroup *pg)
2634 {
2635   unsigned int off;
2636
2637   for (off = 0; off < pg->total; off++)
2638     {
2639       /* FIXME: should we wait for our
2640          continuations to be called here? This
2641          would require us to take a continuation
2642          as well... */
2643
2644       if (NULL != pg->peers[off].daemon)
2645         GNUNET_TESTING_daemon_stop (pg->peers[off].daemon, NULL, NULL, GNUNET_YES);
2646       if (NULL != pg->peers[off].cfg)
2647         GNUNET_CONFIGURATION_destroy (pg->peers[off].cfg);
2648
2649       if (pg->peers[off].allowed_peers != NULL)
2650         GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].allowed_peers);
2651       if (pg->peers[off].connect_peers != NULL)
2652         GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].connect_peers);
2653       if (pg->peers[off].blacklisted_peers != NULL)
2654         GNUNET_CONTAINER_multihashmap_destroy(pg->peers[off].blacklisted_peers);
2655
2656     }
2657   GNUNET_free (pg->peers);
2658   if (NULL != pg->hosts)
2659     {
2660       GNUNET_free (pg->hosts[0].hostname);
2661       GNUNET_free (pg->hosts);
2662     }
2663   GNUNET_free (pg);
2664 }
2665
2666
2667 /* end of testing_group.c */