d3b41801a7b99bcc18ccf337682800f90e030c35
[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    * Received PeerIDs
219    */
220   struct GNUNET_PeerIdentity *rec_ids;
221
222   /**
223    * Number of received PeerIDs
224    */
225   unsigned int num_rec_ids;
226 };
227
228
229 /**
230  * Information for all the peers.
231  */
232 static struct RPSPeer *rps_peers;
233
234 /**
235  * Peermap to get the index of a given peer ID quick.
236  */
237 static struct GNUNET_CONTAINER_MultiPeerMap *peer_map;
238
239 /**
240  * IDs of the peers.
241  */
242 static struct GNUNET_PeerIdentity *rps_peer_ids;
243
244 /**
245  * ID of the targeted peer.
246  */
247 static struct GNUNET_PeerIdentity *target_peer;
248
249 /**
250  * ID of the peer that requests for the evaluation.
251  */
252 static struct RPSPeer *eval_peer;
253
254 /**
255  * Number of online peers.
256  */
257 static unsigned int num_peers_online;
258
259 /**
260  * Return value from 'main'.
261  */
262 static int ok;
263
264
265 /**
266  * Identifier for the churn task that runs periodically
267  */
268 static struct GNUNET_SCHEDULER_Task *churn_task;
269
270 /**
271  * Identifier for the churn task that runs periodically
272  */
273 static struct GNUNET_SCHEDULER_Task *shutdown_task;
274
275
276 /**
277  * Called to initialise the given RPSPeer
278  */
279 typedef void (*InitPeer) (struct RPSPeer *rps_peer);
280
281 /**
282  * Called directly after connecting to the service
283  */
284 typedef void (*PreTest) (void *cls, struct GNUNET_RPS_Handle *h);
285
286 /**
287  * Called from within #rps_connect_complete_cb ()
288  * Executes functions to test the api/service
289  */
290 typedef void (*MainTest) (struct RPSPeer *rps_peer);
291
292 /**
293  * Callback called once the requested random peers are available
294  */
295 typedef void (*ReplyHandle) (void *cls,
296                              uint64_t n,
297                              const struct GNUNET_PeerIdentity *recv_peers);
298
299 /**
300  * Called directly before disconnecting from the service
301  */
302 typedef void (*PostTest) (void *cls, struct GNUNET_RPS_Handle *h);
303
304 /**
305  * Function called after disconnect to evaluate test success
306  */
307 typedef int (*EvaluationCallback) (void);
308
309
310 /**
311  * Structure to define a single test
312  */
313 struct SingleTestRun
314 {
315   /**
316    * Name of the test
317    */
318   char *name;
319
320   /**
321    * Called to initialise peer
322    */
323   InitPeer init_peer;
324
325   /**
326    * Called directly after connecting to the service
327    */
328   PreTest pre_test;
329
330   /**
331    * Function to execute the functions to be tested
332    */
333   MainTest main_test;
334
335   /**
336    * Callback called once the requested peers are available
337    */
338   ReplyHandle reply_handle;
339
340   /**
341    * Called directly before disconnecting from the service
342    */
343   PostTest post_test;
344
345   /**
346    * Function to evaluate the test results
347    */
348   EvaluationCallback eval_cb;
349
350   /**
351    * Request interval
352    */
353   uint32_t request_interval;
354
355   /**
356    * Number of Requests to make.
357    */
358   uint32_t num_requests;
359 } cur_test_run;
360
361 /**
362  * Are we shutting down?
363  */
364 static int in_shutdown;
365
366 /**
367  * Append arguments to file
368  */
369 static void
370 tofile_ (const char *file_name, char *line)
371 {
372   struct GNUNET_DISK_FileHandle *f;
373   /* char output_buffer[512]; */
374   size_t size;
375   /* int size; */
376   size_t size2;
377
378   if (NULL == (f = GNUNET_DISK_file_open (file_name,
379                                           GNUNET_DISK_OPEN_APPEND |
380                                           GNUNET_DISK_OPEN_WRITE |
381                                           GNUNET_DISK_OPEN_CREATE,
382                                           GNUNET_DISK_PERM_USER_READ |
383                                           GNUNET_DISK_PERM_USER_WRITE |
384                                           GNUNET_DISK_PERM_GROUP_READ |
385                                           GNUNET_DISK_PERM_OTHER_READ)))
386   {
387     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
388                 "Not able to open file %s\n",
389                 file_name);
390     return;
391   }
392   /* size = GNUNET_snprintf (output_buffer,
393                           sizeof (output_buffer),
394                           "%llu %s\n",
395                           GNUNET_TIME_absolute_get ().abs_value_us,
396                           line);
397   if (0 > size)
398   {
399     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
400                 "Failed to write string to buffer (size: %i)\n",
401                 size);
402     return;
403   } */
404
405   size = strlen (line) * sizeof (char);
406
407   size2 = GNUNET_DISK_file_write (f, line, size);
408   if (size != size2)
409   {
410     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
411                 "Unable to write to file! (Size: %u, size2: %u)\n",
412                 size,
413                 size2);
414     return;
415   }
416
417   if (GNUNET_YES != GNUNET_DISK_file_close (f))
418     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
419                 "Unable to close file\n");
420 }
421
422 /**
423  * This function is used to facilitate writing important information to disk
424  */
425 #define tofile(file_name, ...) do {\
426   char tmp_buf[512];\
427     int size;\
428     size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\
429     if (0 > size)\
430       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\
431                      "Failed to create tmp_buf\n");\
432     else\
433       tofile_(file_name,tmp_buf);\
434   } while (0);
435
436
437 /**
438  * Write the ids and their according index in the given array to a file 
439  * Unused
440  */
441 /* static void
442 ids_to_file (char *file_name,
443              struct GNUNET_PeerIdentity *peer_ids,
444              unsigned int num_peer_ids)
445 {
446   unsigned int i;
447
448   for (i=0 ; i < num_peer_ids ; i++)
449   {
450     to_file (file_name,
451              "%u\t%s",
452              i,
453              GNUNET_i2s_full (&peer_ids[i]));
454   }
455 } */
456
457 /**
458  * Test the success of a single test
459  */
460 static int
461 evaluate (void)
462 {
463   unsigned int i;
464   int tmp_ok;
465
466   tmp_ok = 1;
467
468   for (i = 0; i < num_peers; i++)
469   {
470     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
471         "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
472         i,
473         GNUNET_i2s (rps_peers[i].peer_id),
474         rps_peers[i].num_rec_ids,
475         rps_peers[i].num_ids_to_request,
476         (rps_peers[i].num_ids_to_request == rps_peers[i].num_rec_ids));
477     tmp_ok &= (rps_peers[i].num_ids_to_request == rps_peers[i].num_rec_ids);
478   }
479   return tmp_ok? 0 : 1;
480 }
481
482
483 /**
484  * Creates an oplist entry and adds it to the oplist DLL
485  */
486 static struct OpListEntry *
487 make_oplist_entry ()
488 {
489   struct OpListEntry *entry;
490
491   entry = GNUNET_new (struct OpListEntry);
492   GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
493   return entry;
494 }
495
496
497 /**
498  * Task run on timeout to shut everything down.
499  */
500 static void
501 shutdown_op (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
502 {
503   unsigned int i;
504
505   in_shutdown = GNUNET_YES;
506   if (NULL != churn_task)
507     GNUNET_SCHEDULER_cancel (churn_task);
508
509   for (i = 0 ; i < num_peers ; i++)
510     GNUNET_TESTBED_operation_done (rps_peers[i].op);
511   GNUNET_SCHEDULER_shutdown ();
512 }
513
514
515 /**
516  * Seed peers.
517  */
518   void
519 seed_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
520 {
521   unsigned int amount;
522   struct RPSPeer *peer = (struct RPSPeer *) cls;
523   unsigned int i;
524
525   // TODO if malicious don't seed mal peers
526   amount = round (.5 * num_peers);
527
528   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
529   for (i = 0 ; i < amount ; i++)
530     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
531                 i,
532                 GNUNET_i2s (&rps_peer_ids[i]));
533
534   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
535 }
536
537
538 /**
539  * Get the id of peer i.
540  */
541   void
542 info_cb (void *cb_cls,
543          struct GNUNET_TESTBED_Operation *op,
544          const struct GNUNET_TESTBED_PeerInformation *pinfo,
545          const char *emsg)
546 {
547   struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
548
549   if (NULL == pinfo || NULL != emsg)
550   {
551     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
552     return;
553   }
554
555   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
556               "Peer %u is %s\n",
557               entry->index,
558               GNUNET_i2s (pinfo->result.id));
559
560   rps_peer_ids[entry->index] = *(pinfo->result.id);
561   rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
562   rps_peers[entry->index].rec_ids = NULL;
563   rps_peers[entry->index].num_rec_ids = 0;
564
565   GNUNET_CONTAINER_multipeermap_put (peer_map,
566       &rps_peer_ids[entry->index],
567       &rps_peers[entry->index],
568       GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
569   tofile ("/tmp/rps/peer_ids",
570            "%u\t%s\n",
571            entry->index,
572            GNUNET_i2s_full (&rps_peer_ids[entry->index]));
573
574   if (NULL != cur_test_run.init_peer)
575     cur_test_run.init_peer (&rps_peers[entry->index]);
576
577   GNUNET_TESTBED_operation_done (entry->op);
578   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
579   GNUNET_free (entry);
580 }
581
582
583 /**
584  * Callback to be called when RPS service connect operation is completed
585  *
586  * @param cls the callback closure from functions generating an operation
587  * @param op the operation that has been finished
588  * @param ca_result the RPS service handle returned from rps_connect_adapter
589  * @param emsg error message in case the operation has failed; will be NULL if
590  *          operation has executed successfully.
591  */
592 static void
593 rps_connect_complete_cb (void *cls,
594                          struct GNUNET_TESTBED_Operation *op,
595                          void *ca_result,
596                          const char *emsg)
597 {
598   struct RPSPeer *rps_peer = cls;
599   struct GNUNET_RPS_Handle *rps = ca_result;
600
601   rps_peer->rps_handle = rps;
602   rps_peer->online = GNUNET_YES;
603   num_peers_online++;
604
605   GNUNET_assert (op == rps_peer->op);
606   if (NULL != emsg)
607   {
608     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
609                 "Failed to connect to RPS service: %s\n",
610                 emsg);
611     ok = 1;
612     GNUNET_SCHEDULER_shutdown ();
613     return;
614   }
615
616   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
617
618   cur_test_run.main_test (rps_peer);
619 }
620
621
622 /**
623  * Adapter function called to establish a connection to
624  * the RPS service.
625  *
626  * @param cls closure
627  * @param cfg configuration of the peer to connect to; will be available until
628  *          GNUNET_TESTBED_operation_done() is called on the operation returned
629  *          from GNUNET_TESTBED_service_connect()
630  * @return service handle to return in 'op_result', NULL on error
631  */
632 static void *
633 rps_connect_adapter (void *cls,
634                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
635 {
636   struct GNUNET_RPS_Handle *h;
637
638   h = GNUNET_RPS_connect (cfg);
639
640   if (NULL != cur_test_run.pre_test)
641     cur_test_run.pre_test (cls, h);
642
643   return h;
644 }
645
646
647 /**
648  * Adapter function called to destroy connection to
649  * RPS service.
650  *
651  * @param cls closure
652  * @param op_result service handle returned from the connect adapter
653  */
654 static void
655 rps_disconnect_adapter (void *cls,
656                                           void *op_result)
657 {
658   struct RPSPeer *peer = cls;
659   struct GNUNET_RPS_Handle *h = op_result;
660   GNUNET_assert (NULL != peer);
661   GNUNET_RPS_disconnect (h);
662   peer->rps_handle = NULL;
663 }
664
665
666 /***********************************************************************
667  * Definition of tests
668 ***********************************************************************/
669
670 // TODO check whether tests can be stopped earlier
671 static int
672 default_eval_cb (void)
673 {
674   return evaluate ();
675 }
676
677 static int
678 no_eval (void)
679 {
680   return 0;
681 }
682
683 /**
684  * Initialise given RPSPeer
685  */
686 static void default_init_peer (struct RPSPeer *rps_peer)
687 {
688   rps_peer->num_ids_to_request = 1;
689 }
690
691 /**
692  * Callback to call on receipt of a reply
693  *
694  * @param cls closure
695  * @param n number of peers
696  * @param recv_peers the received peers
697  */
698 static void
699 default_reply_handle (void *cls,
700                       uint64_t n,
701                       const struct GNUNET_PeerIdentity *recv_peers)
702 {
703   struct RPSPeer *rps_peer;
704   struct PendingReply *pending_rep = (struct PendingReply *) cls;
705   unsigned int i;
706
707   rps_peer = pending_rep->rps_peer;
708   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
709                                rps_peer->pending_rep_tail,
710                                pending_rep);
711   rps_peer->num_pending_reps--;
712   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
713               "[%s] got %" PRIu64 " peers:\n",
714               GNUNET_i2s (rps_peer->peer_id),
715               n);
716   
717   for (i = 0; i < n; i++)
718   {
719     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
720                 "%u: %s\n",
721                 i,
722                 GNUNET_i2s (&recv_peers[i]));
723
724     /* GNUNET_array_append (rps_peer->rec_ids, rps_peer->num_rec_ids, recv_peers[i]); */
725     rps_peer->num_rec_ids++;
726   }
727
728   if (0 == evaluate ())
729   {
730     GNUNET_SCHEDULER_cancel (shutdown_task);
731     shutdown_task = GNUNET_SCHEDULER_add_now (&shutdown_op, NULL);
732   }
733 }
734
735 /**
736  * Request random peers.
737  */
738 static void
739 request_peers (void *cls,
740                const struct GNUNET_SCHEDULER_TaskContext *tc)
741 {
742   struct RPSPeer *rps_peer;
743   struct PendingRequest *pending_req = (struct PendingRequest *) cls;
744   struct PendingReply *pending_rep;
745
746   if (GNUNET_YES == in_shutdown)
747     return;
748   rps_peer = pending_req->rps_peer;
749   GNUNET_assert (1 <= rps_peer->num_pending_reqs);
750   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
751                                rps_peer->pending_req_tail,
752                                pending_req);
753   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
754               "Requesting one peer\n");
755   pending_rep = GNUNET_new (struct PendingReply);
756   pending_rep->rps_peer = rps_peer;
757   pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
758       1,
759       cur_test_run.reply_handle,
760       pending_rep);
761   GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_rep_head,
762                                     rps_peer->pending_rep_tail,
763                                     pending_rep);
764   rps_peer->num_pending_reps++;
765   rps_peer->num_pending_reqs--;
766 }
767
768 static void
769 cancel_pending_req (struct PendingRequest *pending_req)
770 {
771   struct RPSPeer *rps_peer;
772
773   rps_peer = pending_req->rps_peer;
774   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
775                                rps_peer->pending_req_tail,
776                                pending_req);
777   rps_peer->num_pending_reqs--;
778   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
779               "Cancelling pending request\n");
780   GNUNET_SCHEDULER_cancel (pending_req->request_task);
781   GNUNET_free (pending_req);
782 }
783
784 static void
785 cancel_request (struct PendingReply *pending_rep)
786 {
787   struct RPSPeer *rps_peer;
788
789   rps_peer = pending_rep->rps_peer;
790   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
791                                rps_peer->pending_rep_tail,
792                                pending_rep);
793   rps_peer->num_pending_reps--;
794   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
795               "Cancelling request\n");
796   GNUNET_RPS_request_cancel (pending_rep->req_handle);
797   GNUNET_free (pending_rep);
798 }
799
800 /**
801  * Cancel a request.
802  */
803 static void
804 cancel_request_cb (void *cls,
805                 const struct GNUNET_SCHEDULER_TaskContext *tc)
806 {
807   struct PendingReply *pending_rep;
808   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
809
810   if (GNUNET_YES == in_shutdown)
811     return;
812   pending_rep = rps_peer->pending_rep_head;
813   GNUNET_assert (1 <= rps_peer->num_pending_reps);
814   cancel_request (pending_rep);
815 }
816
817
818 /**
819  * Schedule requests for peer @a rps_peer that have neither been scheduled, nor
820  * issued, nor replied
821  */
822 void
823 schedule_missing_requests (struct RPSPeer *rps_peer)
824 {
825   unsigned int i;
826   struct PendingRequest *pending_req;
827
828   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
829       "Scheduling %u - %u missing requests\n",
830       rps_peer->num_ids_to_request,
831       rps_peer->num_pending_reqs + rps_peer->num_pending_reps);
832   GNUNET_assert (rps_peer->num_pending_reqs + rps_peer->num_pending_reps <=
833       rps_peer->num_ids_to_request);
834   for (i = rps_peer->num_pending_reqs + rps_peer->num_pending_reps;
835        i < rps_peer->num_ids_to_request; i++)
836   {
837     pending_req = GNUNET_new (struct PendingRequest);
838     pending_req->rps_peer = rps_peer;
839     pending_req->request_task = GNUNET_SCHEDULER_add_delayed (
840         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
841           cur_test_run.request_interval * i),
842         request_peers,
843         pending_req);
844     GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_req_head,
845                                       rps_peer->pending_req_tail,
846                                       pending_req);
847     rps_peer->num_pending_reqs++;
848   }
849 }
850
851 void
852 cancel_pending_req_rep (struct RPSPeer *rps_peer)
853 {
854   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
855       "Cancelling all (pending) requests.\n");
856   while (NULL != rps_peer->pending_req_head)
857     cancel_pending_req (rps_peer->pending_req_head);
858   GNUNET_assert (0 == rps_peer->num_pending_reqs);
859   while (NULL != rps_peer->pending_rep_head)
860     cancel_request (rps_peer->pending_rep_head);
861   GNUNET_assert (0 == rps_peer->num_pending_reps);
862 }
863
864 /***********************************
865  * MALICIOUS
866 ***********************************/
867
868 /**
869  * Initialise only non-mal RPSPeers
870  */
871 static void mal_init_peer (struct RPSPeer *rps_peer)
872 {
873   if (rps_peer->index >= round (portion * num_peers))
874     rps_peer->num_ids_to_request = 1;
875 }
876
877 static void
878 mal_pre (void *cls, struct GNUNET_RPS_Handle *h)
879 {
880   #ifdef ENABLE_MALICIOUS
881   uint32_t num_mal_peers;
882   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
883
884   GNUNET_assert ( (1 >= portion) &&
885                   (0 <  portion) );
886   num_mal_peers = round (portion * num_peers);
887
888   if (rps_peer->index < num_mal_peers)
889   {
890     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
891                 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
892                 rps_peer->index,
893                 GNUNET_i2s (rps_peer->peer_id),
894                 num_mal_peers);
895
896     GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers,
897                               rps_peer_ids, target_peer);
898   }
899   #endif /* ENABLE_MALICIOUS */
900 }
901
902 static void
903 mal_cb (struct RPSPeer *rps_peer)
904 {
905   uint32_t num_mal_peers;
906
907   #ifdef ENABLE_MALICIOUS
908   GNUNET_assert ( (1 >= portion) &&
909                   (0 <  portion) );
910   num_mal_peers = round (portion * num_peers);
911
912   if (rps_peer->index >= num_mal_peers)
913   { /* It's useless to ask a malicious peer about a random sample -
914        it's not sampling */
915     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
916                                   seed_peers, rps_peer);
917     schedule_missing_requests (rps_peer);
918   }
919   #endif /* ENABLE_MALICIOUS */
920 }
921
922
923 /***********************************
924  * SINGLE_REQUEST
925 ***********************************/
926 static void
927 single_req_cb (struct RPSPeer *rps_peer)
928 {
929   schedule_missing_requests (rps_peer);
930 }
931
932 /***********************************
933  * DELAYED_REQUESTS
934 ***********************************/
935 static void
936 delay_req_cb (struct RPSPeer *rps_peer)
937 {
938   schedule_missing_requests (rps_peer);
939 }
940
941 /***********************************
942  * SEED
943 ***********************************/
944 static void
945 seed_cb (struct RPSPeer *rps_peer)
946 {
947   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
948                                 seed_peers, rps_peer);
949 }
950
951 /***********************************
952  * SEED_BIG
953 ***********************************/
954 static void
955 seed_big_cb (struct RPSPeer *rps_peer)
956 {
957   // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
958 }
959
960 /***********************************
961  * SINGLE_PEER_SEED
962 ***********************************/
963 static void
964 single_peer_seed_cb (struct RPSPeer *rps_peer)
965 {
966   // TODO
967 }
968
969 /***********************************
970  * SEED_REQUEST
971 ***********************************/
972 static void
973 seed_req_cb (struct RPSPeer *rps_peer)
974 {
975   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
976                                 seed_peers, rps_peer);
977   schedule_missing_requests (rps_peer);
978 }
979
980 //TODO start big mal
981
982 /***********************************
983  * REQUEST_CANCEL
984 ***********************************/
985 static void
986 req_cancel_cb (struct RPSPeer *rps_peer)
987 {
988   schedule_missing_requests (rps_peer);
989   GNUNET_SCHEDULER_add_delayed (
990       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
991                                      (cur_test_run.request_interval + 1)),
992       cancel_request_cb, rps_peer);
993 }
994
995 /***********************************
996  * PROFILER
997 ***********************************/
998
999 /**
1000  * Callback to be called when RPS service is started or stopped at peers
1001  *
1002  * @param cls NULL
1003  * @param op the operation handle
1004  * @param emsg NULL on success; otherwise an error description
1005  */
1006 static void
1007 churn_cb (void *cls,
1008           struct GNUNET_TESTBED_Operation *op,
1009           const char *emsg)
1010 {
1011   // FIXME
1012   struct OpListEntry *entry = cls;
1013
1014   GNUNET_TESTBED_operation_done (entry->op);
1015   if (NULL != emsg)
1016   {
1017     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n");
1018     GNUNET_SCHEDULER_shutdown ();
1019     return;
1020   }
1021   GNUNET_assert (0 != entry->delta);
1022
1023   num_peers_online += entry->delta;
1024
1025   if (0 > entry->delta)
1026   { /* Peer hopefully just went offline */
1027     if (GNUNET_YES != rps_peers[entry->index].online)
1028     {
1029       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1030                   "peer %s was expected to go offline but is still marked as online\n",
1031                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1032       GNUNET_break (0);
1033     }
1034     else
1035     {
1036       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1037                   "peer %s probably went offline as expected\n",
1038                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1039     }
1040     rps_peers[entry->index].online = GNUNET_NO;
1041   }
1042
1043   else if (0 < entry->delta)
1044   { /* Peer hopefully just went online */
1045     if (GNUNET_NO != rps_peers[entry->index].online)
1046     {
1047       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1048                   "peer %s was expected to go online but is still marked as offline\n",
1049                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1050       GNUNET_break (0);
1051     }
1052     else
1053     {
1054       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1055                   "peer %s probably went online as expected\n",
1056                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1057       if (NULL != cur_test_run.pre_test)
1058       {
1059         cur_test_run.pre_test (&rps_peers[entry->index],
1060             rps_peers[entry->index].rps_handle);
1061         schedule_missing_requests (&rps_peers[entry->index]);
1062       }
1063     }
1064     rps_peers[entry->index].online = GNUNET_YES;
1065   }
1066
1067   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1068   GNUNET_free (entry);
1069   //if (num_peers_in_round[current_round] == peers_running)
1070   //  run_round ();
1071 }
1072
1073 static void
1074 manage_service_wrapper (unsigned int i, unsigned int j, int delta,
1075     double prob_go_on_off)
1076 {
1077   struct OpListEntry *entry;
1078   uint32_t prob;
1079
1080   prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1081                                    UINT32_MAX);
1082   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1083               "%u. selected peer (%u: %s) is %s.\n",
1084               i,
1085               j,
1086               GNUNET_i2s (rps_peers[j].peer_id),
1087               (0 > delta) ? "online" : "offline");
1088   if (prob < prob_go_on_off * UINT32_MAX)
1089   {
1090     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1091                 "%s goes %s\n",
1092                 GNUNET_i2s (rps_peers[j].peer_id),
1093                 (0 > delta) ? "offline" : "online");
1094
1095     if (0 > delta)
1096       cancel_pending_req_rep (&rps_peers[j]);
1097     entry = make_oplist_entry ();
1098     entry->delta = delta;
1099     entry->index = j;
1100     entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
1101                                                     testbed_peers[j],
1102                                                     "rps",
1103                                                     &churn_cb,
1104                                                     entry,
1105                                                     (0 > delta) ? 0 : 1);
1106   }
1107 }
1108
1109 static void
1110 churn (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1111 {
1112   unsigned int i;
1113   unsigned int j;
1114   double portion_online;
1115   unsigned int *permut;
1116   double prob_go_offline;
1117   double portion_go_online;
1118   double portion_go_offline;
1119
1120   /* Compute the probability for an online peer to go offline
1121    * this round */
1122   portion_online = num_peers_online * 1.0 / num_peers;
1123   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1124               "Portion online: %f\n",
1125               portion_online);
1126   portion_go_online = ((1 - portion_online) * .5 * .66);
1127   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1128               "Portion that should go online: %f\n",
1129               portion_go_online);
1130   portion_go_offline = (portion_online + portion_go_online) - .75;
1131   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1132               "Portion that probably goes offline: %f\n",
1133               portion_go_offline);
1134   prob_go_offline = portion_go_offline / (portion_online * .5);
1135   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1136               "Probability of a selected online peer to go offline: %f\n",
1137               prob_go_offline);
1138
1139   permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
1140                                          (unsigned int) num_peers);
1141
1142   /* Go over 50% randomly chosen peers */
1143   for (i = 0; i < .5 * num_peers; i++)
1144   {
1145     j = permut[i];
1146
1147     /* If online, shut down with certain probability */
1148     if (GNUNET_YES == rps_peers[j].online)
1149     {
1150       manage_service_wrapper (i, j, -1, prob_go_offline);
1151     }
1152
1153     /* If offline, restart with certain probability */
1154     else if (GNUNET_NO == rps_peers[j].online)
1155     {
1156       manage_service_wrapper (i, j, 1, 0.66);
1157     }
1158   }
1159
1160   GNUNET_free (permut);
1161
1162   churn_task = GNUNET_SCHEDULER_add_delayed (
1163         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1164         churn,
1165         NULL);
1166 }
1167
1168
1169 /**
1170  * Initialise given RPSPeer
1171  */
1172 static void profiler_init_peer (struct RPSPeer *rps_peer)
1173 {
1174   if (num_peers - 1 == rps_peer->index)
1175     rps_peer->num_ids_to_request = cur_test_run.num_requests;
1176 }
1177
1178
1179 /**
1180  * Callback to call on receipt of a reply
1181  *
1182  * @param cls closure
1183  * @param n number of peers
1184  * @param recv_peers the received peers
1185  */
1186 static void
1187 profiler_reply_handle (void *cls,
1188                       uint64_t n,
1189                       const struct GNUNET_PeerIdentity *recv_peers)
1190 {
1191   struct RPSPeer *rps_peer;
1192   struct RPSPeer *rcv_rps_peer;
1193   char *file_name;
1194   char *file_name_dh;
1195   unsigned int i;
1196   struct PendingReply *pending_rep = (struct PendingReply *) cls;
1197
1198   rps_peer = pending_rep->rps_peer;
1199   file_name = "/tmp/rps/received_ids";
1200   file_name_dh = "/tmp/rps/diehard_input";
1201   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1202               "[%s] got %" PRIu64 " peers:\n",
1203               GNUNET_i2s (rps_peer->peer_id),
1204               n);
1205   for (i = 0; i < n; i++)
1206   {
1207     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1208                 "%u: %s\n",
1209                 i,
1210                 GNUNET_i2s (&recv_peers[i]));
1211     tofile (file_name,
1212              "%s\n",
1213              GNUNET_i2s_full (&recv_peers[i]));
1214     rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, &recv_peers[i]);
1215     tofile (file_name_dh,
1216              "%" PRIu32 "\n",
1217              (uint32_t) rcv_rps_peer->index);
1218   }
1219   default_reply_handle (cls, n, recv_peers);
1220 }
1221
1222
1223 static void
1224 profiler_cb (struct RPSPeer *rps_peer)
1225 {
1226   /* Start churn */
1227   if (NULL == churn_task)
1228   {
1229     churn_task = GNUNET_SCHEDULER_add_delayed (
1230           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1231           churn,
1232           NULL);
1233   }
1234
1235   /* Only request peer ids at one peer.
1236    * (It's the before-last because last one is target of the focussed attack.)
1237    */
1238   if (eval_peer == rps_peer)
1239     schedule_missing_requests (rps_peer);
1240 }
1241
1242 /**
1243  * Function called from #profiler_eval with a filename.
1244  *
1245  * @param cls closure
1246  * @param filename complete filename (absolute path)
1247  * @return #GNUNET_OK to continue to iterate,
1248  *  #GNUNET_NO to stop iteration with no error,
1249  *  #GNUNET_SYSERR to abort iteration with error!
1250  */
1251 int
1252 file_name_cb (void *cls, const char *filename)
1253 {
1254   if (NULL != strstr (filename, "sampler_el"))
1255   {
1256     struct RPS_SamplerElement *s_elem;
1257     struct GNUNET_CRYPTO_AuthKey auth_key;
1258     const char *key_char;
1259     uint32_t i;
1260
1261     key_char = filename + 20; /* Length of "/tmp/rps/sampler_el-" */
1262     tofile (filename, "--------------------------\n");
1263
1264     auth_key = string_to_auth_key (key_char);
1265     s_elem = RPS_sampler_elem_create ();
1266     RPS_sampler_elem_set (s_elem, auth_key);
1267
1268     for (i = 0; i < num_peers; i++)
1269     {
1270       RPS_sampler_elem_next (s_elem, &rps_peer_ids[i]);
1271     }
1272   }
1273   return GNUNET_OK;
1274 }
1275
1276 /**
1277  * This is run after the test finished.
1278  *
1279  * Compute all perfect samples.
1280  */
1281 int
1282 profiler_eval (void)
1283 {
1284   /* Compute perfect sample for each sampler element */
1285   if (-1 == GNUNET_DISK_directory_scan ("/tmp/rps/", file_name_cb, NULL))
1286   {
1287     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scan of directory failed\n");
1288   }
1289
1290   return evaluate ();
1291 }
1292
1293
1294 /***********************************************************************
1295  * /Definition of tests
1296 ***********************************************************************/
1297
1298
1299 /**
1300  * Actual "main" function for the testcase.
1301  *
1302  * @param cls closure
1303  * @param h the run handle
1304  * @param n_peers number of peers in 'peers'
1305  * @param peers handle to peers run in the testbed
1306  * @param links_succeeded the number of overlay link connection attempts that
1307  *          succeeded
1308  * @param links_failed the number of overlay link connection attempts that
1309  *          failed
1310  */
1311 static void
1312 run (void *cls,
1313      struct GNUNET_TESTBED_RunHandle *h,
1314      unsigned int n_peers,
1315      struct GNUNET_TESTBED_Peer **peers,
1316      unsigned int links_succeeded,
1317      unsigned int links_failed)
1318 {
1319   unsigned int i;
1320   struct OpListEntry *entry;
1321
1322   testbed_peers = peers;
1323   num_peers_online = 0;
1324   for (i = 0 ; i < num_peers ; i++)
1325   {
1326     entry = make_oplist_entry ();
1327     entry->index = i;
1328     entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
1329                                                      GNUNET_TESTBED_PIT_IDENTITY,
1330                                                      &info_cb,
1331                                                      entry);
1332   }
1333
1334   GNUNET_assert (num_peers == n_peers);
1335   for (i = 0 ; i < n_peers ; i++)
1336   {
1337     rps_peers[i].index = i;
1338     rps_peers[i].op =
1339       GNUNET_TESTBED_service_connect (&rps_peers[i],
1340                                       peers[i],
1341                                       "rps",
1342                                       &rps_connect_complete_cb,
1343                                       &rps_peers[i],
1344                                       &rps_connect_adapter,
1345                                       &rps_disconnect_adapter,
1346                                       &rps_peers[i]);
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 */