f6c7ec205de7ebc8b116ee0bd40c96177f08353f
[oweals/gnunet.git] / src / rps / test_rps.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20 /**
21  * @file rps/test_rps_multipeer.c
22  * @brief Testcase for the random peer sampling service.  Starts
23  *        a peergroup with a given number of peers, then waits to
24  *        receive size pushes/pulls from each peer.  Expects to wait
25  *        for one message from each peer.
26  */
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_testbed_service.h"
30
31 #include "gnunet_rps_service.h"
32 #include "rps-test_util.h"
33 #include "gnunet-service-rps_sampler_elem.h"
34
35 #include <inttypes.h>
36
37
38 /**
39  * How many peers do we start?
40  */
41 uint32_t num_peers;
42
43 /**
44  * How long do we run the test?
45  */
46 //#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
47 static struct GNUNET_TIME_Relative timeout;
48
49
50 /**
51  * Portion of malicious peers
52  */
53 static double portion = .1;
54
55 /**
56  * Type of malicious peer to test
57  */
58 static unsigned int mal_type = 0;
59
60 /**
61  * Handles to all of the running peers
62  */
63 static struct GNUNET_TESTBED_Peer **testbed_peers;
64
65
66 /**
67  * Operation map entry
68  */
69 struct OpListEntry
70 {
71   /**
72    * DLL next ptr
73    */
74   struct OpListEntry *next;
75
76   /**
77    * DLL prev ptr
78    */
79   struct OpListEntry *prev;
80
81   /**
82    * The testbed operation
83    */
84   struct GNUNET_TESTBED_Operation *op;
85
86   /**
87    * Depending on whether we start or stop NSE service at the peer set this to 1
88    * or -1
89    */
90   int delta;
91
92   /**
93    * Index of the regarding peer
94    */
95   unsigned int index;
96 };
97
98 /**
99  * OpList DLL head
100  */
101 static struct OpListEntry *oplist_head;
102
103 /**
104  * OpList DLL tail
105  */
106 static struct OpListEntry *oplist_tail;
107
108
109 /**
110  * A pending reply: A request was sent and the reply is pending.
111  */
112 struct PendingReply
113 {
114   /**
115    * DLL next,prev ptr
116    */
117   struct PendingReply *next;
118   struct PendingReply *prev;
119
120   /**
121    * Handle to the request we are waiting for
122    */
123   struct GNUNET_RPS_Request_Handle *req_handle;
124
125   /**
126    * The peer that requested
127    */
128   struct RPSPeer *rps_peer;
129 };
130
131
132 /**
133  * A pending request: A request was not made yet but is scheduled for later.
134  */
135 struct PendingRequest
136 {
137   /**
138    * DLL next,prev ptr
139    */
140   struct PendingRequest *next;
141   struct PendingRequest *prev;
142
143   /**
144    * Handle to the request we are waiting for
145    */
146   struct GNUNET_SCHEDULER_Task *request_task;
147
148   /**
149    * The peer that requested
150    */
151   struct RPSPeer *rps_peer;
152 };
153
154
155 /**
156  * Information we track for each peer.
157  */
158 struct RPSPeer
159 {
160   /**
161    * Index of the peer.
162    */
163   unsigned int index;
164
165   /**
166    * Handle for RPS connect operation.
167    */
168   struct GNUNET_TESTBED_Operation *op;
169
170   /**
171    * Handle to RPS service.
172    */
173   struct GNUNET_RPS_Handle *rps_handle;
174
175   /**
176    * ID of the peer.
177    */
178   struct GNUNET_PeerIdentity *peer_id;
179
180   /**
181    * A request handle to check for an request
182    */
183   //struct GNUNET_RPS_Request_Handle *req_handle;
184
185   /**
186    * Peer on- or offline?
187    */
188   int online;
189
190   /**
191    * Number of Peer IDs to request
192    */
193   unsigned int num_ids_to_request;
194
195   /**
196    * Pending requests DLL
197    */
198   struct PendingRequest *pending_req_head;
199   struct PendingRequest *pending_req_tail;
200
201   /**
202    * Number of pending requests
203    */
204   unsigned int num_pending_reqs;
205
206   /**
207    * Pending replies DLL
208    */
209   struct PendingReply *pending_rep_head;
210   struct PendingReply *pending_rep_tail;
211
212   /**
213    * Number of pending replies
214    */
215   unsigned int num_pending_reps;
216
217   /**
218    * Number of received PeerIDs
219    */
220   unsigned int num_recv_ids;
221 };
222
223
224 /**
225  * Information for all the peers.
226  */
227 static struct RPSPeer *rps_peers;
228
229 /**
230  * Peermap to get the index of a given peer ID quick.
231  */
232 static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
233
234 /**
235  * IDs of the peers.
236  */
237 static struct GNUNET_PeerIdentity *rps_peer_ids;
238
239 /**
240  * ID of the targeted peer.
241  */
242 static struct GNUNET_PeerIdentity *target_peer;
243
244 /**
245  * ID of the peer that requests for the evaluation.
246  */
247 static struct RPSPeer *eval_peer;
248
249 /**
250  * Number of online peers.
251  */
252 static unsigned int num_peers_online;
253
254 /**
255  * Return value from 'main'.
256  */
257 static int ok;
258
259
260 /**
261  * Identifier for the churn task that runs periodically
262  */
263 static struct GNUNET_SCHEDULER_Task *churn_task;
264
265 /**
266  * Identifier for the churn task that runs periodically
267  */
268 static struct GNUNET_SCHEDULER_Task *shutdown_task;
269
270
271 /**
272  * Called to initialise the given RPSPeer
273  */
274 typedef void (*InitPeer) (struct RPSPeer *rps_peer);
275
276 /**
277  * Called directly after connecting to the service
278  */
279 typedef void (*PreTest) (void *cls, struct GNUNET_RPS_Handle *h);
280
281 /**
282  * Called from within #rps_connect_complete_cb ()
283  * Executes functions to test the api/service
284  */
285 typedef void (*MainTest) (struct RPSPeer *rps_peer);
286
287 /**
288  * Callback called once the requested random peers are available
289  */
290 typedef void (*ReplyHandle) (void *cls,
291                              uint64_t n,
292                              const struct GNUNET_PeerIdentity *recv_peers);
293
294 /**
295  * Called directly before disconnecting from the service
296  */
297 typedef void (*PostTest) (void *cls, struct GNUNET_RPS_Handle *h);
298
299 /**
300  * Function called after disconnect to evaluate test success
301  */
302 typedef int (*EvaluationCallback) (void);
303
304
305 /**
306  * Structure to define a single test
307  */
308 struct SingleTestRun
309 {
310   /**
311    * Name of the test
312    */
313   char *name;
314
315   /**
316    * Called to initialise peer
317    */
318   InitPeer init_peer;
319
320   /**
321    * Called directly after connecting to the service
322    */
323   PreTest pre_test;
324
325   /**
326    * Function to execute the functions to be tested
327    */
328   MainTest main_test;
329
330   /**
331    * Callback called once the requested peers are available
332    */
333   ReplyHandle reply_handle;
334
335   /**
336    * Called directly before disconnecting from the service
337    */
338   PostTest post_test;
339
340   /**
341    * Function to evaluate the test results
342    */
343   EvaluationCallback eval_cb;
344
345   /**
346    * Request interval
347    */
348   uint32_t request_interval;
349
350   /**
351    * Number of Requests to make.
352    */
353   uint32_t num_requests;
354 } cur_test_run;
355
356 /**
357  * Are we shutting down?
358  */
359 static int in_shutdown;
360
361 /**
362  * Append arguments to file
363  */
364 static void
365 tofile_ (const char *file_name, char *line)
366 {
367   struct GNUNET_DISK_FileHandle *f;
368   /* char output_buffer[512]; */
369   size_t size;
370   /* int size; */
371   size_t size2;
372
373   if (NULL == (f = GNUNET_DISK_file_open (file_name,
374                                           GNUNET_DISK_OPEN_APPEND |
375                                           GNUNET_DISK_OPEN_WRITE |
376                                           GNUNET_DISK_OPEN_CREATE,
377                                           GNUNET_DISK_PERM_USER_READ |
378                                           GNUNET_DISK_PERM_USER_WRITE |
379                                           GNUNET_DISK_PERM_GROUP_READ |
380                                           GNUNET_DISK_PERM_OTHER_READ)))
381   {
382     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
383                 "Not able to open file %s\n",
384                 file_name);
385     return;
386   }
387   /* size = GNUNET_snprintf (output_buffer,
388                           sizeof (output_buffer),
389                           "%llu %s\n",
390                           GNUNET_TIME_absolute_get ().abs_value_us,
391                           line);
392   if (0 > size)
393   {
394     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
395                 "Failed to write string to buffer (size: %i)\n",
396                 size);
397     return;
398   } */
399
400   size = strlen (line) * sizeof (char);
401
402   size2 = GNUNET_DISK_file_write (f, line, size);
403   if (size != size2)
404   {
405     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
406                 "Unable to write to file! (Size: %u, size2: %u)\n",
407                 size,
408                 size2);
409     return;
410   }
411
412   if (GNUNET_YES != GNUNET_DISK_file_close (f))
413     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
414                 "Unable to close file\n");
415 }
416
417 /**
418  * This function is used to facilitate writing important information to disk
419  */
420 #define tofile(file_name, ...) do {\
421   char tmp_buf[512];\
422     int size;\
423     size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\
424     if (0 > size)\
425       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\
426                      "Failed to create tmp_buf\n");\
427     else\
428       tofile_(file_name,tmp_buf);\
429   } while (0);
430
431
432 /**
433  * Write the ids and their according index in the given array to a file 
434  * Unused
435  */
436 /* static void
437 ids_to_file (char *file_name,
438              struct GNUNET_PeerIdentity *peer_ids,
439              unsigned int num_peer_ids)
440 {
441   unsigned int i;
442
443   for (i=0 ; i < num_peer_ids ; i++)
444   {
445     to_file (file_name,
446              "%u\t%s",
447              i,
448              GNUNET_i2s_full (&peer_ids[i]));
449   }
450 } */
451
452 /**
453  * Test the success of a single test
454  */
455 static int
456 evaluate (void)
457 {
458   unsigned int i;
459   int tmp_ok;
460
461   tmp_ok = 1;
462
463   for (i = 0; i < num_peers; i++)
464   {
465     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
466         "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
467         i,
468         GNUNET_i2s (rps_peers[i].peer_id),
469         rps_peers[i].num_recv_ids,
470         rps_peers[i].num_ids_to_request,
471         (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids));
472     tmp_ok &= (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids);
473   }
474   return tmp_ok? 0 : 1;
475 }
476
477
478 /**
479  * Creates an oplist entry and adds it to the oplist DLL
480  */
481 static struct OpListEntry *
482 make_oplist_entry ()
483 {
484   struct OpListEntry *entry;
485
486   entry = GNUNET_new (struct OpListEntry);
487   GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
488   return entry;
489 }
490
491
492 /**
493  * Task run on timeout to shut everything down.
494  */
495 static void
496 shutdown_op (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
497 {
498   unsigned int i;
499
500   in_shutdown = GNUNET_YES;
501   if (NULL != churn_task)
502     GNUNET_SCHEDULER_cancel (churn_task);
503
504   for (i = 0; i < num_peers; i++)
505     if (NULL != rps_peers[i].op)
506       GNUNET_TESTBED_operation_done (rps_peers[i].op);
507   GNUNET_SCHEDULER_shutdown ();
508 }
509
510
511 /**
512  * Seed peers.
513  */
514   void
515 seed_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
516 {
517   unsigned int amount;
518   struct RPSPeer *peer = (struct RPSPeer *) cls;
519   unsigned int i;
520
521   // TODO if malicious don't seed mal peers
522   amount = round (.5 * num_peers);
523
524   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
525   for (i = 0 ; i < amount ; i++)
526     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
527                 i,
528                 GNUNET_i2s (&rps_peer_ids[i]));
529
530   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
531 }
532
533
534 /**
535  * Get the id of peer i.
536  */
537   void
538 info_cb (void *cb_cls,
539          struct GNUNET_TESTBED_Operation *op,
540          const struct GNUNET_TESTBED_PeerInformation *pinfo,
541          const char *emsg)
542 {
543   struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
544
545   if (NULL == pinfo || NULL != emsg)
546   {
547     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
548     GNUNET_TESTBED_operation_done (entry->op);
549     return;
550   }
551
552   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
553               "Peer %u is %s\n",
554               entry->index,
555               GNUNET_i2s (pinfo->result.id));
556
557   rps_peer_ids[entry->index] = *(pinfo->result.id);
558   rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
559
560   GNUNET_CONTAINER_multipeermap_put (peer_map,
561       &rps_peer_ids[entry->index],
562       &rps_peers[entry->index],
563       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
564   tofile ("/tmp/rps/peer_ids",
565            "%u\t%s\n",
566            entry->index,
567            GNUNET_i2s_full (&rps_peer_ids[entry->index]));
568
569   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
570   GNUNET_TESTBED_operation_done (entry->op);
571   GNUNET_free (entry);
572 }
573
574
575 /**
576  * Callback to be called when RPS service connect operation is completed
577  *
578  * @param cls the callback closure from functions generating an operation
579  * @param op the operation that has been finished
580  * @param ca_result the RPS service handle returned from rps_connect_adapter
581  * @param emsg error message in case the operation has failed; will be NULL if
582  *          operation has executed successfully.
583  */
584 static void
585 rps_connect_complete_cb (void *cls,
586                          struct GNUNET_TESTBED_Operation *op,
587                          void *ca_result,
588                          const char *emsg)
589 {
590   struct RPSPeer *rps_peer = cls;
591   struct GNUNET_RPS_Handle *rps = ca_result;
592
593   rps_peer->rps_handle = rps;
594   rps_peer->online = GNUNET_YES;
595   num_peers_online++;
596
597   GNUNET_assert (op == rps_peer->op);
598   if (NULL != emsg)
599   {
600     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
601                 "Failed to connect to RPS service: %s\n",
602                 emsg);
603     ok = 1;
604     GNUNET_SCHEDULER_shutdown ();
605     return;
606   }
607
608   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
609
610   cur_test_run.main_test (rps_peer);
611 }
612
613
614 /**
615  * Adapter function called to establish a connection to
616  * the RPS service.
617  *
618  * @param cls closure
619  * @param cfg configuration of the peer to connect to; will be available until
620  *          GNUNET_TESTBED_operation_done() is called on the operation returned
621  *          from GNUNET_TESTBED_service_connect()
622  * @return service handle to return in 'op_result', NULL on error
623  */
624 static void *
625 rps_connect_adapter (void *cls,
626                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
627 {
628   struct GNUNET_RPS_Handle *h;
629
630   h = GNUNET_RPS_connect (cfg);
631
632   if (NULL != cur_test_run.pre_test)
633     cur_test_run.pre_test (cls, h);
634
635   return h;
636 }
637
638
639 /**
640  * Adapter function called to destroy connection to
641  * RPS service.
642  *
643  * @param cls closure
644  * @param op_result service handle returned from the connect adapter
645  */
646 static void
647 rps_disconnect_adapter (void *cls,
648                                           void *op_result)
649 {
650   struct RPSPeer *peer = cls;
651   struct GNUNET_RPS_Handle *h = op_result;
652   GNUNET_assert (NULL != peer);
653   GNUNET_RPS_disconnect (h);
654   peer->rps_handle = NULL;
655 }
656
657
658 /***********************************************************************
659  * Definition of tests
660 ***********************************************************************/
661
662 // TODO check whether tests can be stopped earlier
663 static int
664 default_eval_cb (void)
665 {
666   return evaluate ();
667 }
668
669 static int
670 no_eval (void)
671 {
672   return 0;
673 }
674
675 /**
676  * Initialise given RPSPeer
677  */
678 static void default_init_peer (struct RPSPeer *rps_peer)
679 {
680   rps_peer->num_ids_to_request = 1;
681 }
682
683 /**
684  * Callback to call on receipt of a reply
685  *
686  * @param cls closure
687  * @param n number of peers
688  * @param recv_peers the received peers
689  */
690 static void
691 default_reply_handle (void *cls,
692                       uint64_t n,
693                       const struct GNUNET_PeerIdentity *recv_peers)
694 {
695   struct RPSPeer *rps_peer;
696   struct PendingReply *pending_rep = (struct PendingReply *) cls;
697   unsigned int i;
698
699   rps_peer = pending_rep->rps_peer;
700   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
701                                rps_peer->pending_rep_tail,
702                                pending_rep);
703   rps_peer->num_pending_reps--;
704   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705               "[%s] got %" PRIu64 " peers:\n",
706               GNUNET_i2s (rps_peer->peer_id),
707               n);
708   
709   for (i = 0; i < n; i++)
710   {
711     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
712                 "%u: %s\n",
713                 i,
714                 GNUNET_i2s (&recv_peers[i]));
715
716     rps_peer->num_recv_ids++;
717   }
718
719   if (0 == evaluate ())
720   {
721     GNUNET_SCHEDULER_cancel (shutdown_task);
722     shutdown_task = GNUNET_SCHEDULER_add_now (&shutdown_op, NULL);
723   }
724 }
725
726 /**
727  * Request random peers.
728  */
729 static void
730 request_peers (void *cls,
731                const struct GNUNET_SCHEDULER_TaskContext *tc)
732 {
733   struct RPSPeer *rps_peer;
734   struct PendingRequest *pending_req = (struct PendingRequest *) cls;
735   struct PendingReply *pending_rep;
736
737   if (GNUNET_YES == in_shutdown)
738     return;
739   rps_peer = pending_req->rps_peer;
740   GNUNET_assert (1 <= rps_peer->num_pending_reqs);
741   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
742                                rps_peer->pending_req_tail,
743                                pending_req);
744   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
745               "Requesting one peer\n");
746   pending_rep = GNUNET_new (struct PendingReply);
747   pending_rep->rps_peer = rps_peer;
748   pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
749       1,
750       cur_test_run.reply_handle,
751       pending_rep);
752   GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_rep_head,
753                                     rps_peer->pending_rep_tail,
754                                     pending_rep);
755   rps_peer->num_pending_reps++;
756   rps_peer->num_pending_reqs--;
757 }
758
759 static void
760 cancel_pending_req (struct PendingRequest *pending_req)
761 {
762   struct RPSPeer *rps_peer;
763
764   rps_peer = pending_req->rps_peer;
765   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
766                                rps_peer->pending_req_tail,
767                                pending_req);
768   rps_peer->num_pending_reqs--;
769   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
770               "Cancelling pending request\n");
771   GNUNET_SCHEDULER_cancel (pending_req->request_task);
772   GNUNET_free (pending_req);
773 }
774
775 static void
776 cancel_request (struct PendingReply *pending_rep)
777 {
778   struct RPSPeer *rps_peer;
779
780   rps_peer = pending_rep->rps_peer;
781   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
782                                rps_peer->pending_rep_tail,
783                                pending_rep);
784   rps_peer->num_pending_reps--;
785   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
786               "Cancelling request\n");
787   GNUNET_RPS_request_cancel (pending_rep->req_handle);
788   GNUNET_free (pending_rep);
789 }
790
791 /**
792  * Cancel a request.
793  */
794 static void
795 cancel_request_cb (void *cls,
796                 const struct GNUNET_SCHEDULER_TaskContext *tc)
797 {
798   struct PendingReply *pending_rep;
799   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
800
801   if (GNUNET_YES == in_shutdown)
802     return;
803   pending_rep = rps_peer->pending_rep_head;
804   GNUNET_assert (1 <= rps_peer->num_pending_reps);
805   cancel_request (pending_rep);
806 }
807
808
809 /**
810  * Schedule requests for peer @a rps_peer that have neither been scheduled, nor
811  * issued, nor replied
812  */
813 void
814 schedule_missing_requests (struct RPSPeer *rps_peer)
815 {
816   unsigned int i;
817   struct PendingRequest *pending_req;
818
819   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
820       "Scheduling %u - %u missing requests\n",
821       rps_peer->num_ids_to_request,
822       rps_peer->num_pending_reqs + rps_peer->num_pending_reps);
823   GNUNET_assert (rps_peer->num_pending_reqs + rps_peer->num_pending_reps <=
824       rps_peer->num_ids_to_request);
825   for (i = rps_peer->num_pending_reqs + rps_peer->num_pending_reps;
826        i < rps_peer->num_ids_to_request; i++)
827   {
828     pending_req = GNUNET_new (struct PendingRequest);
829     pending_req->rps_peer = rps_peer;
830     pending_req->request_task = GNUNET_SCHEDULER_add_delayed (
831         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
832           cur_test_run.request_interval * i),
833         request_peers,
834         pending_req);
835     GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_req_head,
836                                       rps_peer->pending_req_tail,
837                                       pending_req);
838     rps_peer->num_pending_reqs++;
839   }
840 }
841
842 void
843 cancel_pending_req_rep (struct RPSPeer *rps_peer)
844 {
845   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
846       "Cancelling all (pending) requests.\n");
847   while (NULL != rps_peer->pending_req_head)
848     cancel_pending_req (rps_peer->pending_req_head);
849   GNUNET_assert (0 == rps_peer->num_pending_reqs);
850   while (NULL != rps_peer->pending_rep_head)
851     cancel_request (rps_peer->pending_rep_head);
852   GNUNET_assert (0 == rps_peer->num_pending_reps);
853 }
854
855 /***********************************
856  * MALICIOUS
857 ***********************************/
858
859 /**
860  * Initialise only non-mal RPSPeers
861  */
862 static void mal_init_peer (struct RPSPeer *rps_peer)
863 {
864   if (rps_peer->index >= round (portion * num_peers))
865     rps_peer->num_ids_to_request = 1;
866 }
867
868 static void
869 mal_pre (void *cls, struct GNUNET_RPS_Handle *h)
870 {
871   #ifdef ENABLE_MALICIOUS
872   uint32_t num_mal_peers;
873   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
874
875   GNUNET_assert ( (1 >= portion) &&
876                   (0 <  portion) );
877   num_mal_peers = round (portion * num_peers);
878
879   if (rps_peer->index < num_mal_peers)
880   {
881     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
882                 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
883                 rps_peer->index,
884                 GNUNET_i2s (rps_peer->peer_id),
885                 num_mal_peers);
886
887     GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers,
888                               rps_peer_ids, target_peer);
889   }
890   #endif /* ENABLE_MALICIOUS */
891 }
892
893 static void
894 mal_cb (struct RPSPeer *rps_peer)
895 {
896   uint32_t num_mal_peers;
897
898   #ifdef ENABLE_MALICIOUS
899   GNUNET_assert ( (1 >= portion) &&
900                   (0 <  portion) );
901   num_mal_peers = round (portion * num_peers);
902
903   if (rps_peer->index >= num_mal_peers)
904   { /* It's useless to ask a malicious peer about a random sample -
905        it's not sampling */
906     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
907                                   seed_peers, rps_peer);
908     schedule_missing_requests (rps_peer);
909   }
910   #endif /* ENABLE_MALICIOUS */
911 }
912
913
914 /***********************************
915  * SINGLE_REQUEST
916 ***********************************/
917 static void
918 single_req_cb (struct RPSPeer *rps_peer)
919 {
920   schedule_missing_requests (rps_peer);
921 }
922
923 /***********************************
924  * DELAYED_REQUESTS
925 ***********************************/
926 static void
927 delay_req_cb (struct RPSPeer *rps_peer)
928 {
929   schedule_missing_requests (rps_peer);
930 }
931
932 /***********************************
933  * SEED
934 ***********************************/
935 static void
936 seed_cb (struct RPSPeer *rps_peer)
937 {
938   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
939                                 seed_peers, rps_peer);
940 }
941
942 /***********************************
943  * SEED_BIG
944 ***********************************/
945 static void
946 seed_big_cb (struct RPSPeer *rps_peer)
947 {
948   // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
949 }
950
951 /***********************************
952  * SINGLE_PEER_SEED
953 ***********************************/
954 static void
955 single_peer_seed_cb (struct RPSPeer *rps_peer)
956 {
957   // TODO
958 }
959
960 /***********************************
961  * SEED_REQUEST
962 ***********************************/
963 static void
964 seed_req_cb (struct RPSPeer *rps_peer)
965 {
966   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
967                                 seed_peers, rps_peer);
968   schedule_missing_requests (rps_peer);
969 }
970
971 //TODO start big mal
972
973 /***********************************
974  * REQUEST_CANCEL
975 ***********************************/
976 static void
977 req_cancel_cb (struct RPSPeer *rps_peer)
978 {
979   schedule_missing_requests (rps_peer);
980   GNUNET_SCHEDULER_add_delayed (
981       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
982                                      (cur_test_run.request_interval + 1)),
983       cancel_request_cb, rps_peer);
984 }
985
986 /***********************************
987  * PROFILER
988 ***********************************/
989
990 /**
991  * Callback to be called when RPS service is started or stopped at peers
992  *
993  * @param cls NULL
994  * @param op the operation handle
995  * @param emsg NULL on success; otherwise an error description
996  */
997 static void
998 churn_cb (void *cls,
999           struct GNUNET_TESTBED_Operation *op,
1000           const char *emsg)
1001 {
1002   // FIXME
1003   struct OpListEntry *entry = cls;
1004
1005   GNUNET_TESTBED_operation_done (entry->op);
1006   if (NULL != emsg)
1007   {
1008     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n");
1009     GNUNET_SCHEDULER_shutdown ();
1010     return;
1011   }
1012   GNUNET_assert (0 != entry->delta);
1013
1014   num_peers_online += entry->delta;
1015
1016   if (0 > entry->delta)
1017   { /* Peer hopefully just went offline */
1018     if (GNUNET_YES != rps_peers[entry->index].online)
1019     {
1020       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1021                   "peer %s was expected to go offline but is still marked as online\n",
1022                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1023       GNUNET_break (0);
1024     }
1025     else
1026     {
1027       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1028                   "peer %s probably went offline as expected\n",
1029                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1030     }
1031     rps_peers[entry->index].online = GNUNET_NO;
1032   }
1033
1034   else if (0 < entry->delta)
1035   { /* Peer hopefully just went online */
1036     if (GNUNET_NO != rps_peers[entry->index].online)
1037     {
1038       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1039                   "peer %s was expected to go online but is still marked as offline\n",
1040                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1041       GNUNET_break (0);
1042     }
1043     else
1044     {
1045       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1046                   "peer %s probably went online as expected\n",
1047                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1048       if (NULL != cur_test_run.pre_test)
1049       {
1050         cur_test_run.pre_test (&rps_peers[entry->index],
1051             rps_peers[entry->index].rps_handle);
1052         schedule_missing_requests (&rps_peers[entry->index]);
1053       }
1054     }
1055     rps_peers[entry->index].online = GNUNET_YES;
1056   }
1057
1058   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1059   GNUNET_free (entry);
1060   //if (num_peers_in_round[current_round] == peers_running)
1061   //  run_round ();
1062 }
1063
1064 static void
1065 manage_service_wrapper (unsigned int i, unsigned int j, int delta,
1066     double prob_go_on_off)
1067 {
1068   struct OpListEntry *entry;
1069   uint32_t prob;
1070
1071   prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1072                                    UINT32_MAX);
1073   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1074               "%u. selected peer (%u: %s) is %s.\n",
1075               i,
1076               j,
1077               GNUNET_i2s (rps_peers[j].peer_id),
1078               (0 > delta) ? "online" : "offline");
1079   if (prob < prob_go_on_off * UINT32_MAX)
1080   {
1081     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1082                 "%s goes %s\n",
1083                 GNUNET_i2s (rps_peers[j].peer_id),
1084                 (0 > delta) ? "offline" : "online");
1085
1086     if (0 > delta)
1087       cancel_pending_req_rep (&rps_peers[j]);
1088     entry = make_oplist_entry ();
1089     entry->delta = delta;
1090     entry->index = j;
1091     entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
1092                                                     testbed_peers[j],
1093                                                     "rps",
1094                                                     &churn_cb,
1095                                                     entry,
1096                                                     (0 > delta) ? 0 : 1);
1097   }
1098 }
1099
1100 static void
1101 churn (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1102 {
1103   unsigned int i;
1104   unsigned int j;
1105   double portion_online;
1106   unsigned int *permut;
1107   double prob_go_offline;
1108   double portion_go_online;
1109   double portion_go_offline;
1110
1111   /* Compute the probability for an online peer to go offline
1112    * this round */
1113   portion_online = num_peers_online * 1.0 / num_peers;
1114   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1115               "Portion online: %f\n",
1116               portion_online);
1117   portion_go_online = ((1 - portion_online) * .5 * .66);
1118   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119               "Portion that should go online: %f\n",
1120               portion_go_online);
1121   portion_go_offline = (portion_online + portion_go_online) - .75;
1122   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1123               "Portion that probably goes offline: %f\n",
1124               portion_go_offline);
1125   prob_go_offline = portion_go_offline / (portion_online * .5);
1126   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1127               "Probability of a selected online peer to go offline: %f\n",
1128               prob_go_offline);
1129
1130   permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
1131                                          (unsigned int) num_peers);
1132
1133   /* Go over 50% randomly chosen peers */
1134   for (i = 0; i < .5 * num_peers; i++)
1135   {
1136     j = permut[i];
1137
1138     /* If online, shut down with certain probability */
1139     if (GNUNET_YES == rps_peers[j].online)
1140     {
1141       manage_service_wrapper (i, j, -1, prob_go_offline);
1142     }
1143
1144     /* If offline, restart with certain probability */
1145     else if (GNUNET_NO == rps_peers[j].online)
1146     {
1147       manage_service_wrapper (i, j, 1, 0.66);
1148     }
1149   }
1150
1151   GNUNET_free (permut);
1152
1153   churn_task = GNUNET_SCHEDULER_add_delayed (
1154         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1155         churn,
1156         NULL);
1157 }
1158
1159
1160 /**
1161  * Initialise given RPSPeer
1162  */
1163 static void profiler_init_peer (struct RPSPeer *rps_peer)
1164 {
1165   if (num_peers - 1 == rps_peer->index)
1166     rps_peer->num_ids_to_request = cur_test_run.num_requests;
1167 }
1168
1169
1170 /**
1171  * Callback to call on receipt of a reply
1172  *
1173  * @param cls closure
1174  * @param n number of peers
1175  * @param recv_peers the received peers
1176  */
1177 static void
1178 profiler_reply_handle (void *cls,
1179                       uint64_t n,
1180                       const struct GNUNET_PeerIdentity *recv_peers)
1181 {
1182   struct RPSPeer *rps_peer;
1183   struct RPSPeer *rcv_rps_peer;
1184   char *file_name;
1185   char *file_name_dh;
1186   unsigned int i;
1187   struct PendingReply *pending_rep = (struct PendingReply *) cls;
1188
1189   rps_peer = pending_rep->rps_peer;
1190   file_name = "/tmp/rps/received_ids";
1191   file_name_dh = "/tmp/rps/diehard_input";
1192   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1193               "[%s] got %" PRIu64 " peers:\n",
1194               GNUNET_i2s (rps_peer->peer_id),
1195               n);
1196   for (i = 0; i < n; i++)
1197   {
1198     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1199                 "%u: %s\n",
1200                 i,
1201                 GNUNET_i2s (&recv_peers[i]));
1202     tofile (file_name,
1203              "%s\n",
1204              GNUNET_i2s_full (&recv_peers[i]));
1205     rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, &recv_peers[i]);
1206     tofile (file_name_dh,
1207              "%" PRIu32 "\n",
1208              (uint32_t) rcv_rps_peer->index);
1209   }
1210   default_reply_handle (cls, n, recv_peers);
1211 }
1212
1213
1214 static void
1215 profiler_cb (struct RPSPeer *rps_peer)
1216 {
1217   /* Start churn */
1218   if (NULL == churn_task)
1219   {
1220     churn_task = GNUNET_SCHEDULER_add_delayed (
1221           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1222           churn,
1223           NULL);
1224   }
1225
1226   /* Only request peer ids at one peer.
1227    * (It's the before-last because last one is target of the focussed attack.)
1228    */
1229   if (eval_peer == rps_peer)
1230     schedule_missing_requests (rps_peer);
1231 }
1232
1233 /**
1234  * Function called from #profiler_eval with a filename.
1235  *
1236  * @param cls closure
1237  * @param filename complete filename (absolute path)
1238  * @return #GNUNET_OK to continue to iterate,
1239  *  #GNUNET_NO to stop iteration with no error,
1240  *  #GNUNET_SYSERR to abort iteration with error!
1241  */
1242 int
1243 file_name_cb (void *cls, const char *filename)
1244 {
1245   if (NULL != strstr (filename, "sampler_el"))
1246   {
1247     struct RPS_SamplerElement *s_elem;
1248     struct GNUNET_CRYPTO_AuthKey auth_key;
1249     const char *key_char;
1250     uint32_t i;
1251
1252     key_char = filename + 20; /* Length of "/tmp/rps/sampler_el-" */
1253     tofile (filename, "--------------------------\n");
1254
1255     auth_key = string_to_auth_key (key_char);
1256     s_elem = RPS_sampler_elem_create ();
1257     RPS_sampler_elem_set (s_elem, auth_key);
1258
1259     for (i = 0; i < num_peers; i++)
1260     {
1261       RPS_sampler_elem_next (s_elem, &rps_peer_ids[i]);
1262     }
1263   }
1264   return GNUNET_OK;
1265 }
1266
1267 /**
1268  * This is run after the test finished.
1269  *
1270  * Compute all perfect samples.
1271  */
1272 int
1273 profiler_eval (void)
1274 {
1275   /* Compute perfect sample for each sampler element */
1276   if (-1 == GNUNET_DISK_directory_scan ("/tmp/rps/", file_name_cb, NULL))
1277   {
1278     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scan of directory failed\n");
1279   }
1280
1281   return evaluate ();
1282 }
1283
1284
1285 /***********************************************************************
1286  * /Definition of tests
1287 ***********************************************************************/
1288
1289
1290 /**
1291  * Actual "main" function for the testcase.
1292  *
1293  * @param cls closure
1294  * @param h the run handle
1295  * @param n_peers number of peers in 'peers'
1296  * @param peers handle to peers run in the testbed
1297  * @param links_succeeded the number of overlay link connection attempts that
1298  *          succeeded
1299  * @param links_failed the number of overlay link connection attempts that
1300  *          failed
1301  */
1302 static void
1303 run (void *cls,
1304      struct GNUNET_TESTBED_RunHandle *h,
1305      unsigned int n_peers,
1306      struct GNUNET_TESTBED_Peer **peers,
1307      unsigned int links_succeeded,
1308      unsigned int links_failed)
1309 {
1310   unsigned int i;
1311   struct OpListEntry *entry;
1312   uint32_t num_mal_peers;
1313
1314   testbed_peers = peers;
1315   num_peers_online = 0;
1316   for (i = 0; i < num_peers; i++)
1317   {
1318     entry = make_oplist_entry ();
1319     entry->index = i;
1320     rps_peers[i].index = i;
1321     if (NULL != cur_test_run.init_peer)
1322       cur_test_run.init_peer (&rps_peers[i]);
1323     entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
1324                                                      GNUNET_TESTBED_PIT_IDENTITY,
1325                                                      &info_cb,
1326                                                      entry);
1327   }
1328
1329   num_mal_peers = round (portion * num_peers);
1330   GNUNET_assert (num_peers == n_peers);
1331   for (i = 0; i < n_peers; i++)
1332   {
1333     rps_peers[i].index = i;
1334     if ( (rps_peers[i].num_recv_ids < rps_peers[i].num_ids_to_request) ||
1335          (i < num_mal_peers) )
1336     {
1337       rps_peers[i].op =
1338         GNUNET_TESTBED_service_connect (&rps_peers[i],
1339                                         peers[i],
1340                                         "rps",
1341                                         &rps_connect_complete_cb,
1342                                         &rps_peers[i],
1343                                         &rps_connect_adapter,
1344                                         &rps_disconnect_adapter,
1345                                         &rps_peers[i]);
1346     }
1347   }
1348
1349   if (NULL != churn_task)
1350     GNUNET_SCHEDULER_cancel (churn_task);
1351   shutdown_task = GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL);
1352 }
1353
1354
1355 /**
1356  * Entry point for the testcase, sets up the testbed.
1357  *
1358  * @param argc unused
1359  * @param argv unused
1360  * @return 0 on success
1361  */
1362 int
1363 main (int argc, char *argv[])
1364 {
1365   int ret_value;
1366
1367   num_peers = 5;
1368   cur_test_run.name = "test-rps-default";
1369   cur_test_run.init_peer = default_init_peer;
1370   cur_test_run.pre_test = NULL;
1371   cur_test_run.reply_handle = default_reply_handle;
1372   cur_test_run.eval_cb = default_eval_cb;
1373   churn_task = NULL;
1374   timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
1375
1376   if (strstr (argv[0], "malicious") != NULL)
1377   {
1378     cur_test_run.pre_test = mal_pre;
1379     cur_test_run.main_test = mal_cb;
1380     cur_test_run.init_peer = mal_init_peer;
1381
1382     if (strstr (argv[0], "_1") != NULL)
1383     {
1384       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 1\n");
1385       cur_test_run.name = "test-rps-malicious_1";
1386       mal_type = 1;
1387     }
1388     else if (strstr (argv[0], "_2") != NULL)
1389     {
1390       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 2\n");
1391       cur_test_run.name = "test-rps-malicious_2";
1392       mal_type = 2;
1393     }
1394     else if (strstr (argv[0], "_3") != NULL)
1395     {
1396       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 3\n");
1397       cur_test_run.name = "test-rps-malicious_3";
1398       mal_type = 3;
1399     }
1400   }
1401
1402   else if (strstr (argv[0], "_single_req") != NULL)
1403   {
1404     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
1405     cur_test_run.name = "test-rps-single-req";
1406     cur_test_run.main_test = single_req_cb;
1407   }
1408
1409   else if (strstr (argv[0], "_delayed_reqs") != NULL)
1410   {
1411     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
1412     cur_test_run.name = "test-rps-delayed-reqs";
1413     cur_test_run.main_test = delay_req_cb;
1414   }
1415
1416   else if (strstr (argv[0], "_seed_big") != NULL)
1417   {
1418     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding (num_peers > GNUNET_SERVER_MAX_MESSAGE_SIZE)\n");
1419     cur_test_run.name = "test-rps-seed-big";
1420     cur_test_run.main_test = seed_big_cb;
1421   }
1422
1423   else if (strstr (argv[0], "_single_peer_seed") != NULL)
1424   {
1425     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
1426     cur_test_run.name = "test-rps-single-peer-seed";
1427     cur_test_run.main_test = single_peer_seed_cb;
1428   }
1429
1430   else if (strstr (argv[0], "_seed_request") != NULL)
1431   {
1432     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
1433     cur_test_run.name = "test-rps-seed-request";
1434     cur_test_run.main_test = seed_req_cb;
1435   }
1436
1437   else if (strstr (argv[0], "_seed") != NULL)
1438   {
1439     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding\n");
1440     cur_test_run.name = "test-rps-seed";
1441     cur_test_run.main_test = seed_cb;
1442     cur_test_run.eval_cb = no_eval;
1443   }
1444
1445   else if (strstr (argv[0], "_req_cancel") != NULL)
1446   {
1447     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test cancelling a request\n");
1448     cur_test_run.name = "test-rps-req-cancel";
1449     num_peers = 1;
1450     cur_test_run.main_test = req_cancel_cb;
1451     cur_test_run.eval_cb = no_eval;
1452     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1453   }
1454
1455   else if (strstr (argv[0], "profiler") != NULL)
1456   {
1457     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
1458     cur_test_run.name = "test-rps-profiler";
1459     num_peers = 10;
1460     mal_type = 3;
1461     cur_test_run.init_peer = profiler_init_peer;
1462     cur_test_run.pre_test = mal_pre;
1463     cur_test_run.main_test = profiler_cb;
1464     cur_test_run.reply_handle = profiler_reply_handle;
1465     cur_test_run.eval_cb = profiler_eval;
1466     cur_test_run.request_interval = 2;
1467     cur_test_run.num_requests = 5;
1468     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90);
1469
1470     /* 'Clean' directory */
1471     (void) GNUNET_DISK_directory_remove ("/tmp/rps/");
1472     GNUNET_DISK_directory_create ("/tmp/rps/");
1473   }
1474
1475   rps_peers = GNUNET_new_array (num_peers, struct RPSPeer);
1476   peer_map = GNUNET_CONTAINER_multipeermap_create (num_peers, GNUNET_NO);
1477   rps_peer_ids = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
1478   if ( (2 == mal_type) ||
1479        (3 == mal_type))
1480     target_peer = &rps_peer_ids[num_peers - 2];
1481   if (profiler_eval == cur_test_run.eval_cb)
1482     eval_peer = &rps_peers[num_peers - 1];
1483
1484   ok = 1;
1485   (void) GNUNET_TESTBED_test_run (cur_test_run.name,
1486                                   "test_rps.conf",
1487                                   num_peers,
1488                                   0, NULL, NULL,
1489                                   &run, NULL);
1490
1491   ret_value = cur_test_run.eval_cb();
1492   GNUNET_free (rps_peers );
1493   GNUNET_free (rps_peer_ids);
1494   GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1495   return ret_value;
1496 }
1497
1498 /* end of test_rps_multipeer.c */