1e8d4eb550cc53b132c594f064e07c6528503614
[oweals/gnunet.git] / src / rps / test_rps.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2012 GNUnet e.V.
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.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 static 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 RPS service at the peer set this to 1 (start)
88    * or -1 (stop)
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 during the whole test
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  * Identifier for the churn task that runs periodically
261  */
262 static struct GNUNET_SCHEDULER_Task *churn_task;
263
264 /**
265  * Called to initialise the given RPSPeer
266  */
267 typedef void (*InitPeer) (struct RPSPeer *rps_peer);
268
269 /**
270  * Called directly after connecting to the service
271  */
272 typedef void (*PreTest) (void *cls, struct GNUNET_RPS_Handle *h);
273
274 /**
275  * @brief Executes functions to test the api/service for a given peer
276  *
277  * Called from within #rps_connect_complete_cb ()
278  * Implemented by #churn_test_cb, #profiler_cb, #mal_cb, #single_req_cb,
279  * #delay_req_cb, #seed_big_cb, #single_peer_seed_cb, #seed_cb, #req_cancel_cb
280  *
281  * @param rps_peer the peer the task runs on
282  */
283 typedef void (*MainTest) (struct RPSPeer *rps_peer);
284
285 /**
286  * Callback called once the requested random peers are available
287  */
288 typedef void (*ReplyHandle) (void *cls,
289                              uint64_t n,
290                              const struct GNUNET_PeerIdentity *recv_peers);
291
292 /**
293  * Called directly before disconnecting from the service
294  */
295 typedef void (*PostTest) (void *cls, struct GNUNET_RPS_Handle *h);
296
297 /**
298  * Function called after disconnect to evaluate test success
299  */
300 typedef int (*EvaluationCallback) (void);
301
302
303 /**
304  * Structure to define a single test
305  */
306 struct SingleTestRun
307 {
308   /**
309    * Name of the test
310    */
311   char *name;
312
313   /**
314    * Called with a single peer in order to initialise that peer
315    */
316   InitPeer init_peer;
317
318   /**
319    * Called directly after connecting to the service
320    */
321   PreTest pre_test;
322
323   /**
324    * Main function for each peer
325    */
326   MainTest main_test;
327
328   /**
329    * Callback called once the requested peers are available
330    */
331   ReplyHandle reply_handle;
332
333   /**
334    * Called directly before disconnecting from the service
335    */
336   PostTest post_test;
337
338   /**
339    * Function to evaluate the test results
340    */
341   EvaluationCallback eval_cb;
342
343   /**
344    * Request interval
345    */
346   uint32_t request_interval;
347
348   /**
349    * Number of Requests to make.
350    */
351   uint32_t num_requests;
352
353   /**
354    * Run with churn
355    */
356   int have_churn;
357 } cur_test_run;
358
359 /**
360  * Are we shutting down?
361  */
362 static int in_shutdown;
363
364 /**
365  * Append arguments to file
366  */
367 static void
368 tofile_ (const char *file_name, const char *line)
369 {
370   struct GNUNET_DISK_FileHandle *f;
371   /* char output_buffer[512]; */
372   size_t size;
373   /* int size; */
374   size_t size2;
375
376   if (NULL == (f = GNUNET_DISK_file_open (file_name,
377                                           GNUNET_DISK_OPEN_APPEND |
378                                           GNUNET_DISK_OPEN_WRITE |
379                                           GNUNET_DISK_OPEN_CREATE,
380                                           GNUNET_DISK_PERM_USER_READ |
381                                           GNUNET_DISK_PERM_USER_WRITE |
382                                           GNUNET_DISK_PERM_GROUP_READ |
383                                           GNUNET_DISK_PERM_OTHER_READ)))
384   {
385     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
386                 "Not able to open file %s\n",
387                 file_name);
388     return;
389   }
390   /* size = GNUNET_snprintf (output_buffer,
391                           sizeof (output_buffer),
392                           "%llu %s\n",
393                           GNUNET_TIME_absolute_get ().abs_value_us,
394                           line);
395   if (0 > size)
396   {
397     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
398                 "Failed to write string to buffer (size: %i)\n",
399                 size);
400     return;
401   } */
402
403   size = strlen (line) * sizeof (char);
404
405   size2 = GNUNET_DISK_file_write (f, line, size);
406   if (size != size2)
407   {
408     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
409                 "Unable to write to file! (Size: %lu, size2: %lu)\n",
410                 size,
411                 size2);
412     if (GNUNET_YES != GNUNET_DISK_file_close (f))
413     {
414       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
415                   "Unable to close file\n");
416     }
417     return;
418   }
419
420   if (GNUNET_YES != GNUNET_DISK_file_close (f))
421   {
422     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
423                 "Unable to close file\n");
424   }
425 }
426
427 /**
428  * This function is used to facilitate writing important information to disk
429  */
430 #define tofile(file_name, ...) do {\
431   char tmp_buf[512];\
432     int size;\
433     size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\
434     if (0 > size)\
435       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\
436                      "Failed to create tmp_buf\n");\
437     else\
438       tofile_(file_name,tmp_buf);\
439   } while (0);
440
441
442 /**
443  * Write the ids and their according index in the given array to a file
444  * Unused
445  */
446 /* static void
447 ids_to_file (char *file_name,
448              struct GNUNET_PeerIdentity *peer_ids,
449              unsigned int num_peer_ids)
450 {
451   unsigned int i;
452
453   for (i=0 ; i < num_peer_ids ; i++)
454   {
455     to_file (file_name,
456              "%u\t%s",
457              i,
458              GNUNET_i2s_full (&peer_ids[i]));
459   }
460 } */
461
462 /**
463  * Test the success of a single test
464  */
465 static int
466 evaluate (void)
467 {
468   unsigned int i;
469   int tmp_ok;
470
471   tmp_ok = 1;
472
473   for (i = 0; i < num_peers; i++)
474   {
475     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
476         "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
477         i,
478         GNUNET_i2s (rps_peers[i].peer_id),
479         rps_peers[i].num_recv_ids,
480         rps_peers[i].num_ids_to_request,
481         (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids));
482     tmp_ok &= (rps_peers[i].num_ids_to_request == rps_peers[i].num_recv_ids);
483   }
484   return tmp_ok? 0 : 1;
485 }
486
487
488 /**
489  * Creates an oplist entry and adds it to the oplist DLL
490  */
491 static struct OpListEntry *
492 make_oplist_entry ()
493 {
494   struct OpListEntry *entry;
495
496   entry = GNUNET_new (struct OpListEntry);
497   GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
498   return entry;
499 }
500
501
502 /**
503  * Task run on timeout to shut everything down.
504  */
505 static void
506 shutdown_op (void *cls)
507 {
508   unsigned int i;
509
510   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
511               "Shutdown task scheduled, going down.\n");
512   in_shutdown = GNUNET_YES;
513   if (NULL != churn_task)
514   {
515     GNUNET_SCHEDULER_cancel (churn_task);
516     churn_task = NULL;
517   }
518   for (i = 0; i < num_peers; i++)
519     if (NULL != rps_peers[i].op)
520       GNUNET_TESTBED_operation_done (rps_peers[i].op);
521   GNUNET_SCHEDULER_shutdown ();
522 }
523
524
525 /**
526  * Seed peers.
527  */
528 static void
529 seed_peers (void *cls)
530 {
531   struct RPSPeer *peer = cls;
532   unsigned int amount;
533   unsigned int i;
534
535   // TODO if malicious don't seed mal peers
536   amount = round (.5 * num_peers);
537
538   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
539   for (i = 0 ; i < amount ; i++)
540     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
541                 i,
542                 GNUNET_i2s (&rps_peer_ids[i]));
543
544   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
545 }
546
547
548 /**
549  * Seed peers.
550  */
551 static void
552 seed_peers_big (void *cls)
553 {
554   struct RPSPeer *peer = cls;
555   unsigned int seed_msg_size;
556   uint32_t num_peers_max;
557   unsigned int amount;
558   unsigned int i;
559
560   seed_msg_size = 8; /* sizeof (struct GNUNET_RPS_CS_SeedMessage) */
561   num_peers_max = (GNUNET_MAX_MESSAGE_SIZE - seed_msg_size) /
562     sizeof (struct GNUNET_PeerIdentity);
563   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
564       "Peers that fit in one seed msg; %u\n",
565       num_peers_max);
566   amount = num_peers_max + (0.5 * num_peers_max);
567   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
568       "Seeding many (%u) peers:\n",
569       amount);
570   struct GNUNET_PeerIdentity ids_to_seed[amount];
571   for (i = 0; i < amount; i++)
572   {
573     ids_to_seed[i] = *peer->peer_id;
574     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
575                 i,
576                 GNUNET_i2s (&ids_to_seed[i]));
577   }
578
579   GNUNET_RPS_seed_ids (peer->rps_handle, amount, ids_to_seed);
580 }
581
582 /**
583  * Get the id of peer i.
584  */
585   void
586 info_cb (void *cb_cls,
587          struct GNUNET_TESTBED_Operation *op,
588          const struct GNUNET_TESTBED_PeerInformation *pinfo,
589          const char *emsg)
590 {
591   struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
592
593   if (GNUNET_YES == in_shutdown)
594   {
595     return;
596   }
597
598   if (NULL == pinfo || NULL != emsg)
599   {
600     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
601     GNUNET_TESTBED_operation_done (entry->op);
602     return;
603   }
604
605   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
606               "Peer %u is %s\n",
607               entry->index,
608               GNUNET_i2s (pinfo->result.id));
609
610   rps_peer_ids[entry->index] = *(pinfo->result.id);
611   rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
612
613   GNUNET_assert (GNUNET_OK ==
614       GNUNET_CONTAINER_multipeermap_put (peer_map,
615         &rps_peer_ids[entry->index],
616         &rps_peers[entry->index],
617         GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY));
618   tofile ("/tmp/rps/peer_ids",
619            "%u\t%s\n",
620            entry->index,
621            GNUNET_i2s_full (&rps_peer_ids[entry->index]));
622
623   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
624   GNUNET_TESTBED_operation_done (entry->op);
625   GNUNET_free (entry);
626 }
627
628
629 /**
630  * Callback to be called when RPS service connect operation is completed
631  *
632  * @param cls the callback closure from functions generating an operation
633  * @param op the operation that has been finished
634  * @param ca_result the RPS service handle returned from rps_connect_adapter
635  * @param emsg error message in case the operation has failed; will be NULL if
636  *          operation has executed successfully.
637  */
638 static void
639 rps_connect_complete_cb (void *cls,
640                          struct GNUNET_TESTBED_Operation *op,
641                          void *ca_result,
642                          const char *emsg)
643 {
644   struct RPSPeer *rps_peer = cls;
645   struct GNUNET_RPS_Handle *rps = ca_result;
646
647   if (GNUNET_YES == in_shutdown)
648   {
649     return;
650   }
651
652   rps_peer->rps_handle = rps;
653   rps_peer->online = GNUNET_YES;
654   num_peers_online++;
655
656   GNUNET_assert (op == rps_peer->op);
657   if (NULL != emsg)
658   {
659     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
660                 "Failed to connect to RPS service: %s\n",
661                 emsg);
662     ok = 1;
663     GNUNET_SCHEDULER_shutdown ();
664     return;
665   }
666
667   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
668
669   cur_test_run.main_test (rps_peer);
670 }
671
672
673 /**
674  * Adapter function called to establish a connection to
675  * the RPS service.
676  *
677  * @param cls closure
678  * @param cfg configuration of the peer to connect to; will be available until
679  *          GNUNET_TESTBED_operation_done() is called on the operation returned
680  *          from GNUNET_TESTBED_service_connect()
681  * @return service handle to return in 'op_result', NULL on error
682  */
683 static void *
684 rps_connect_adapter (void *cls,
685                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
686 {
687   struct GNUNET_RPS_Handle *h;
688
689   h = GNUNET_RPS_connect (cfg);
690
691   if (NULL != cur_test_run.pre_test)
692     cur_test_run.pre_test (cls, h);
693
694   return h;
695 }
696
697
698 /**
699  * Adapter function called to destroy connection to
700  * RPS service.
701  *
702  * @param cls closure
703  * @param op_result service handle returned from the connect adapter
704  */
705 static void
706 rps_disconnect_adapter (void *cls,
707                                           void *op_result)
708 {
709   struct RPSPeer *peer = cls;
710   struct GNUNET_RPS_Handle *h = op_result;
711   GNUNET_assert (NULL != peer);
712   GNUNET_RPS_disconnect (h);
713   peer->rps_handle = NULL;
714 }
715
716
717 /***********************************************************************
718  * Definition of tests
719 ***********************************************************************/
720
721 // TODO check whether tests can be stopped earlier
722 static int
723 default_eval_cb (void)
724 {
725   return evaluate ();
726 }
727
728 static int
729 no_eval (void)
730 {
731   return 0;
732 }
733
734 /**
735  * Initialise given RPSPeer
736  */
737 static void default_init_peer (struct RPSPeer *rps_peer)
738 {
739   rps_peer->num_ids_to_request = 1;
740 }
741
742 /**
743  * Callback to call on receipt of a reply
744  *
745  * @param cls closure
746  * @param n number of peers
747  * @param recv_peers the received peers
748  */
749 static void
750 default_reply_handle (void *cls,
751                       uint64_t n,
752                       const struct GNUNET_PeerIdentity *recv_peers)
753 {
754   struct RPSPeer *rps_peer;
755   struct PendingReply *pending_rep = (struct PendingReply *) cls;
756   unsigned int i;
757
758   rps_peer = pending_rep->rps_peer;
759   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
760                                rps_peer->pending_rep_tail,
761                                pending_rep);
762   rps_peer->num_pending_reps--;
763   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
764               "[%s] got %" PRIu64 " peers:\n",
765               GNUNET_i2s (rps_peer->peer_id),
766               n);
767
768   for (i = 0; i < n; i++)
769   {
770     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
771                 "%u: %s\n",
772                 i,
773                 GNUNET_i2s (&recv_peers[i]));
774
775     rps_peer->num_recv_ids++;
776   }
777
778   if (0 == evaluate ())
779   {
780     GNUNET_SCHEDULER_shutdown ();
781   }
782 }
783
784 /**
785  * Request random peers.
786  */
787 static void
788 request_peers (void *cls)
789 {
790   struct PendingRequest *pending_req = cls;
791   struct RPSPeer *rps_peer;
792   struct PendingReply *pending_rep;
793
794   if (GNUNET_YES == in_shutdown)
795     return;
796   rps_peer = pending_req->rps_peer;
797   GNUNET_assert (1 <= rps_peer->num_pending_reqs);
798   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
799                                rps_peer->pending_req_tail,
800                                pending_req);
801   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
802               "Requesting one peer\n");
803   pending_rep = GNUNET_new (struct PendingReply);
804   pending_rep->rps_peer = rps_peer;
805   pending_rep->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle,
806       1,
807       cur_test_run.reply_handle,
808       pending_rep);
809   GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_rep_head,
810                                     rps_peer->pending_rep_tail,
811                                     pending_rep);
812   rps_peer->num_pending_reps++;
813   rps_peer->num_pending_reqs--;
814 }
815
816 static void
817 cancel_pending_req (struct PendingRequest *pending_req)
818 {
819   struct RPSPeer *rps_peer;
820
821   rps_peer = pending_req->rps_peer;
822   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_req_head,
823                                rps_peer->pending_req_tail,
824                                pending_req);
825   rps_peer->num_pending_reqs--;
826   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
827               "Cancelling pending request\n");
828   GNUNET_SCHEDULER_cancel (pending_req->request_task);
829   GNUNET_free (pending_req);
830 }
831
832 static void
833 cancel_request (struct PendingReply *pending_rep)
834 {
835   struct RPSPeer *rps_peer;
836
837   rps_peer = pending_rep->rps_peer;
838   GNUNET_CONTAINER_DLL_remove (rps_peer->pending_rep_head,
839                                rps_peer->pending_rep_tail,
840                                pending_rep);
841   rps_peer->num_pending_reps--;
842   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
843               "Cancelling request\n");
844   GNUNET_RPS_request_cancel (pending_rep->req_handle);
845   GNUNET_free (pending_rep);
846 }
847
848 /**
849  * Cancel a request.
850  */
851 static void
852 cancel_request_cb (void *cls)
853 {
854   struct RPSPeer *rps_peer = cls;
855   struct PendingReply *pending_rep;
856
857   if (GNUNET_YES == in_shutdown)
858     return;
859   pending_rep = rps_peer->pending_rep_head;
860   GNUNET_assert (1 <= rps_peer->num_pending_reps);
861   cancel_request (pending_rep);
862 }
863
864
865 /**
866  * Schedule requests for peer @a rps_peer that have neither been scheduled, nor
867  * issued, nor replied
868  */
869 void
870 schedule_missing_requests (struct RPSPeer *rps_peer)
871 {
872   unsigned int i;
873   struct PendingRequest *pending_req;
874
875   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
876       "Scheduling %u - %u missing requests\n",
877       rps_peer->num_ids_to_request,
878       rps_peer->num_pending_reqs + rps_peer->num_pending_reps);
879   GNUNET_assert (rps_peer->num_pending_reqs + rps_peer->num_pending_reps <=
880       rps_peer->num_ids_to_request);
881   for (i = rps_peer->num_pending_reqs + rps_peer->num_pending_reps;
882        i < rps_peer->num_ids_to_request; i++)
883   {
884     pending_req = GNUNET_new (struct PendingRequest);
885     pending_req->rps_peer = rps_peer;
886     pending_req->request_task = GNUNET_SCHEDULER_add_delayed (
887         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
888           cur_test_run.request_interval * i),
889         request_peers,
890         pending_req);
891     GNUNET_CONTAINER_DLL_insert_tail (rps_peer->pending_req_head,
892                                       rps_peer->pending_req_tail,
893                                       pending_req);
894     rps_peer->num_pending_reqs++;
895   }
896 }
897
898 void
899 cancel_pending_req_rep (struct RPSPeer *rps_peer)
900 {
901   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
902       "Cancelling all (pending) requests.\n");
903   while (NULL != rps_peer->pending_req_head)
904     cancel_pending_req (rps_peer->pending_req_head);
905   GNUNET_assert (0 == rps_peer->num_pending_reqs);
906   while (NULL != rps_peer->pending_rep_head)
907     cancel_request (rps_peer->pending_rep_head);
908   GNUNET_assert (0 == rps_peer->num_pending_reps);
909 }
910
911 /***********************************
912  * MALICIOUS
913 ***********************************/
914
915 /**
916  * Initialise only non-mal RPSPeers
917  */
918 static void mal_init_peer (struct RPSPeer *rps_peer)
919 {
920   if (rps_peer->index >= round (portion * num_peers))
921     rps_peer->num_ids_to_request = 1;
922 }
923
924 static void
925 mal_pre (void *cls, struct GNUNET_RPS_Handle *h)
926 {
927   #ifdef ENABLE_MALICIOUS
928   uint32_t num_mal_peers;
929   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
930
931   GNUNET_assert ( (1 >= portion) &&
932                   (0 <  portion) );
933   num_mal_peers = round (portion * num_peers);
934
935   if (rps_peer->index < num_mal_peers)
936   {
937     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
938                 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
939                 rps_peer->index,
940                 GNUNET_i2s (rps_peer->peer_id),
941                 num_mal_peers);
942
943     GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers,
944                               rps_peer_ids, target_peer);
945   }
946   #endif /* ENABLE_MALICIOUS */
947 }
948
949 static void
950 mal_cb (struct RPSPeer *rps_peer)
951 {
952   uint32_t num_mal_peers;
953
954   if (GNUNET_YES == in_shutdown)
955   {
956     return;
957   }
958
959   #ifdef ENABLE_MALICIOUS
960   GNUNET_assert ( (1 >= portion) &&
961                   (0 <  portion) );
962   num_mal_peers = round (portion * num_peers);
963
964   if (rps_peer->index >= num_mal_peers)
965   { /* It's useless to ask a malicious peer about a random sample -
966        it's not sampling */
967     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
968                                   seed_peers, rps_peer);
969     schedule_missing_requests (rps_peer);
970   }
971   #endif /* ENABLE_MALICIOUS */
972 }
973
974
975 /***********************************
976  * SINGLE_REQUEST
977 ***********************************/
978 static void
979 single_req_cb (struct RPSPeer *rps_peer)
980 {
981   if (GNUNET_YES == in_shutdown)
982   {
983     return;
984   }
985
986   schedule_missing_requests (rps_peer);
987 }
988
989 /***********************************
990  * DELAYED_REQUESTS
991 ***********************************/
992 static void
993 delay_req_cb (struct RPSPeer *rps_peer)
994 {
995   if (GNUNET_YES == in_shutdown)
996   {
997     return;
998   }
999
1000   schedule_missing_requests (rps_peer);
1001 }
1002
1003 /***********************************
1004  * SEED
1005 ***********************************/
1006 static void
1007 seed_cb (struct RPSPeer *rps_peer)
1008 {
1009   if (GNUNET_YES == in_shutdown)
1010   {
1011     return;
1012   }
1013
1014   GNUNET_SCHEDULER_add_delayed (
1015       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
1016       seed_peers, rps_peer);
1017 }
1018
1019 /***********************************
1020  * SEED_BIG
1021 ***********************************/
1022 static void
1023 seed_big_cb (struct RPSPeer *rps_peer)
1024 {
1025   if (GNUNET_YES == in_shutdown)
1026   {
1027     return;
1028   }
1029
1030   // TODO test seeding > GNUNET_MAX_MESSAGE_SIZE peers
1031   GNUNET_SCHEDULER_add_delayed (
1032       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1033       seed_peers_big, rps_peer);
1034 }
1035
1036 /***********************************
1037  * SINGLE_PEER_SEED
1038 ***********************************/
1039 static void
1040 single_peer_seed_cb (struct RPSPeer *rps_peer)
1041 {
1042   // TODO
1043 }
1044
1045 /***********************************
1046  * SEED_REQUEST
1047 ***********************************/
1048 static void
1049 seed_req_cb (struct RPSPeer *rps_peer)
1050 {
1051   if (GNUNET_YES == in_shutdown)
1052   {
1053     return;
1054   }
1055
1056   GNUNET_SCHEDULER_add_delayed (
1057       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1058       seed_peers, rps_peer);
1059   schedule_missing_requests (rps_peer);
1060 }
1061
1062 //TODO start big mal
1063
1064 /***********************************
1065  * REQUEST_CANCEL
1066 ***********************************/
1067 static void
1068 req_cancel_cb (struct RPSPeer *rps_peer)
1069 {
1070   if (GNUNET_YES == in_shutdown)
1071   {
1072     return;
1073   }
1074
1075   schedule_missing_requests (rps_peer);
1076   GNUNET_SCHEDULER_add_delayed (
1077       GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1078                                      (cur_test_run.request_interval + 1)),
1079       cancel_request_cb, rps_peer);
1080 }
1081
1082 /***********************************
1083  * CHURN
1084 ***********************************/
1085
1086 static void
1087 churn (void *cls);
1088
1089 /**
1090  * @brief Starts churn
1091  *
1092  * Has signature of #MainTest
1093  *
1094  * This is not implemented too nicely as this is called for each peer, but we
1095  * only need to call it once. (Yes we check that we only schedule the task
1096  * once.)
1097  *
1098  * @param rps_peer The peer it's called for
1099  */
1100 static void
1101 churn_test_cb (struct RPSPeer *rps_peer)
1102 {
1103   if (GNUNET_YES == in_shutdown)
1104   {
1105     return;
1106   }
1107
1108   /* Start churn */
1109   if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task)
1110   {
1111     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1112                 "Starting churn task\n");
1113     churn_task = GNUNET_SCHEDULER_add_delayed (
1114           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1115           churn,
1116           NULL);
1117   } else {
1118     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1119                 "Not starting churn task\n");
1120   }
1121
1122   schedule_missing_requests (rps_peer);
1123 }
1124
1125 /***********************************
1126  * PROFILER
1127 ***********************************/
1128
1129 /**
1130  * Callback to be called when RPS service is started or stopped at peers
1131  *
1132  * @param cls NULL
1133  * @param op the operation handle
1134  * @param emsg NULL on success; otherwise an error description
1135  */
1136 static void
1137 churn_cb (void *cls,
1138           struct GNUNET_TESTBED_Operation *op,
1139           const char *emsg)
1140 {
1141   // FIXME
1142   struct OpListEntry *entry = cls;
1143
1144   if (GNUNET_YES == in_shutdown)
1145   {
1146     return;
1147   }
1148
1149   GNUNET_TESTBED_operation_done (entry->op);
1150   if (NULL != emsg)
1151   {
1152     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n");
1153     GNUNET_SCHEDULER_shutdown ();
1154     return;
1155   }
1156   GNUNET_assert (0 != entry->delta);
1157
1158   num_peers_online += entry->delta;
1159
1160   if (0 > entry->delta)
1161   { /* Peer hopefully just went offline */
1162     if (GNUNET_YES != rps_peers[entry->index].online)
1163     {
1164       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1165                   "peer %s was expected to go offline but is still marked as online\n",
1166                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1167       GNUNET_break (0);
1168     }
1169     else
1170     {
1171       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1172                   "peer %s probably went offline as expected\n",
1173                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1174     }
1175     rps_peers[entry->index].online = GNUNET_NO;
1176   }
1177
1178   else if (0 < entry->delta)
1179   { /* Peer hopefully just went online */
1180     if (GNUNET_NO != rps_peers[entry->index].online)
1181     {
1182       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1183                   "peer %s was expected to go online but is still marked as offline\n",
1184                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1185       GNUNET_break (0);
1186     }
1187     else
1188     {
1189       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1190                   "peer %s probably went online as expected\n",
1191                   GNUNET_i2s (rps_peers[entry->index].peer_id));
1192       if (NULL != cur_test_run.pre_test)
1193       {
1194         cur_test_run.pre_test (&rps_peers[entry->index],
1195             rps_peers[entry->index].rps_handle);
1196         schedule_missing_requests (&rps_peers[entry->index]);
1197       }
1198     }
1199     rps_peers[entry->index].online = GNUNET_YES;
1200   }
1201
1202   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
1203   GNUNET_free (entry);
1204   //if (num_peers_in_round[current_round] == peers_running)
1205   //  run_round ();
1206 }
1207
1208 /**
1209  * @brief Set the rps-service up or down for a specific peer
1210  *
1211  * TODO use enum instead of 1/-1 for delta
1212  *
1213  * @param i index of action
1214  * @param j index of peer
1215  * @param delta down (-1) or up (1)
1216  * @param prob_go_on_off the probability of the action
1217  */
1218 static void
1219 manage_service_wrapper (unsigned int i, unsigned int j, int delta,
1220     double prob_go_on_off)
1221 {
1222   struct OpListEntry *entry;
1223   uint32_t prob;
1224
1225   prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
1226                                    UINT32_MAX);
1227   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1228               "%u. selected peer (%u: %s) is %s.\n",
1229               i,
1230               j,
1231               GNUNET_i2s (rps_peers[j].peer_id),
1232               (0 > delta) ? "online" : "offline");
1233   if (prob < prob_go_on_off * UINT32_MAX)
1234   {
1235     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1236                 "%s goes %s\n",
1237                 GNUNET_i2s (rps_peers[j].peer_id),
1238                 (0 > delta) ? "offline" : "online");
1239
1240     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1241                 "testbed_peers points to %p, peer 0 to %p\n",
1242                 testbed_peers, testbed_peers[0]);
1243
1244     if (0 > delta)
1245       cancel_pending_req_rep (&rps_peers[j]);
1246     entry = make_oplist_entry ();
1247     entry->delta = delta;
1248     entry->index = j;
1249     entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
1250                                                     testbed_peers[j],
1251                                                     "rps",
1252                                                     &churn_cb,
1253                                                     entry,
1254                                                     (0 > delta) ? 0 : 1);
1255   }
1256 }
1257
1258
1259 static void
1260 churn (void *cls)
1261 {
1262   unsigned int i;
1263   unsigned int j;
1264   double portion_online;
1265   unsigned int *permut;
1266   double prob_go_offline;
1267   double portion_go_online;
1268   double portion_go_offline;
1269
1270   if (GNUNET_YES == in_shutdown)
1271   {
1272     return;
1273   }
1274   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1275               "Churn function executing\n");
1276
1277   /* Compute the probability for an online peer to go offline
1278    * this round */
1279   portion_online = num_peers_online * 1.0 / num_peers;
1280   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1281               "Portion online: %f\n",
1282               portion_online);
1283   portion_go_online = ((1 - portion_online) * .5 * .66);
1284   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1285               "Portion that should go online: %f\n",
1286               portion_go_online);
1287   portion_go_offline = (portion_online + portion_go_online) - .75;
1288   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1289               "Portion that probably goes offline: %f\n",
1290               portion_go_offline);
1291   prob_go_offline = portion_go_offline / (portion_online * .5);
1292   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1293               "Probability of a selected online peer to go offline: %f\n",
1294               prob_go_offline);
1295
1296   permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
1297                                          (unsigned int) num_peers);
1298
1299   /* Go over 50% randomly chosen peers */
1300   for (i = 0; i < .5 * num_peers; i++)
1301   {
1302     j = permut[i];
1303
1304     /* If online, shut down with certain probability */
1305     if (GNUNET_YES == rps_peers[j].online)
1306     {
1307       manage_service_wrapper (i, j, -1, prob_go_offline);
1308     }
1309
1310     /* If offline, restart with certain probability */
1311     else if (GNUNET_NO == rps_peers[j].online)
1312     {
1313       manage_service_wrapper (i, j, 1, 0.66);
1314     }
1315   }
1316
1317   GNUNET_free (permut);
1318
1319   churn_task = GNUNET_SCHEDULER_add_delayed (
1320         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
1321         churn,
1322         NULL);
1323 }
1324
1325
1326 /**
1327  * Initialise given RPSPeer
1328  */
1329 static void profiler_init_peer (struct RPSPeer *rps_peer)
1330 {
1331   if (num_peers - 1 == rps_peer->index)
1332     rps_peer->num_ids_to_request = cur_test_run.num_requests;
1333 }
1334
1335
1336 /**
1337  * Callback to call on receipt of a reply
1338  *
1339  * @param cls closure
1340  * @param n number of peers
1341  * @param recv_peers the received peers
1342  */
1343 static void
1344 profiler_reply_handle (void *cls,
1345                       uint64_t n,
1346                       const struct GNUNET_PeerIdentity *recv_peers)
1347 {
1348   struct RPSPeer *rps_peer;
1349   struct RPSPeer *rcv_rps_peer;
1350   char *file_name;
1351   char *file_name_dh;
1352   unsigned int i;
1353   struct PendingReply *pending_rep = (struct PendingReply *) cls;
1354
1355   rps_peer = pending_rep->rps_peer;
1356   file_name = "/tmp/rps/received_ids";
1357   file_name_dh = "/tmp/rps/diehard_input";
1358   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1359               "[%s] got %" PRIu64 " peers:\n",
1360               GNUNET_i2s (rps_peer->peer_id),
1361               n);
1362   for (i = 0; i < n; i++)
1363   {
1364     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1365                 "%u: %s\n",
1366                 i,
1367                 GNUNET_i2s (&recv_peers[i]));
1368     tofile (file_name,
1369              "%s\n",
1370              GNUNET_i2s_full (&recv_peers[i]));
1371     rcv_rps_peer = GNUNET_CONTAINER_multipeermap_get (peer_map, &recv_peers[i]);
1372     GNUNET_assert (NULL != rcv_rps_peer);
1373     tofile (file_name_dh,
1374              "%" PRIu32 "\n",
1375              (uint32_t) rcv_rps_peer->index);
1376   }
1377   default_reply_handle (cls, n, recv_peers);
1378 }
1379
1380
1381 static void
1382 profiler_cb (struct RPSPeer *rps_peer)
1383 {
1384   if (GNUNET_YES == in_shutdown)
1385   {
1386     return;
1387   }
1388
1389   /* Start churn */
1390   if (GNUNET_YES == cur_test_run.have_churn && NULL == churn_task)
1391   {
1392     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1393                 "Starting churn task\n");
1394     churn_task = GNUNET_SCHEDULER_add_delayed (
1395           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1396           churn,
1397           NULL);
1398   } else {
1399     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1400                 "Not starting churn task\n");
1401   }
1402
1403   /* Only request peer ids at one peer.
1404    * (It's the before-last because last one is target of the focussed attack.)
1405    */
1406   if (eval_peer == rps_peer)
1407     schedule_missing_requests (rps_peer);
1408 }
1409
1410 /**
1411  * Function called from #profiler_eval with a filename.
1412  *
1413  * @param cls closure
1414  * @param filename complete filename (absolute path)
1415  * @return #GNUNET_OK to continue to iterate,
1416  *  #GNUNET_NO to stop iteration with no error,
1417  *  #GNUNET_SYSERR to abort iteration with error!
1418  */
1419 int
1420 file_name_cb (void *cls, const char *filename)
1421 {
1422   if (NULL != strstr (filename, "sampler_el"))
1423   {
1424     struct RPS_SamplerElement *s_elem;
1425     struct GNUNET_CRYPTO_AuthKey auth_key;
1426     const char *key_char;
1427     uint32_t i;
1428
1429     key_char = filename + 20; /* Length of "/tmp/rps/sampler_el-" */
1430     tofile (filename, "--------------------------\n");
1431
1432     auth_key = string_to_auth_key (key_char);
1433     s_elem = RPS_sampler_elem_create ();
1434     RPS_sampler_elem_set (s_elem, auth_key);
1435
1436     for (i = 0; i < num_peers; i++)
1437     {
1438       RPS_sampler_elem_next (s_elem, &rps_peer_ids[i]);
1439     }
1440     RPS_sampler_elem_destroy (s_elem);
1441   }
1442   return GNUNET_OK;
1443 }
1444
1445 /**
1446  * This is run after the test finished.
1447  *
1448  * Compute all perfect samples.
1449  */
1450 int
1451 profiler_eval (void)
1452 {
1453   /* Compute perfect sample for each sampler element */
1454   if (-1 == GNUNET_DISK_directory_scan ("/tmp/rps/", file_name_cb, NULL))
1455   {
1456     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Scan of directory failed\n");
1457   }
1458
1459   return evaluate ();
1460 }
1461
1462
1463 /***********************************************************************
1464  * /Definition of tests
1465 ***********************************************************************/
1466
1467
1468 /**
1469  * Actual "main" function for the testcase.
1470  *
1471  * @param cls closure
1472  * @param h the run handle
1473  * @param n_peers number of peers in 'peers'
1474  * @param peers handle to peers run in the testbed
1475  * @param links_succeeded the number of overlay link connection attempts that
1476  *          succeeded
1477  * @param links_failed the number of overlay link connection attempts that
1478  *          failed
1479  */
1480 static void
1481 run (void *cls,
1482      struct GNUNET_TESTBED_RunHandle *h,
1483      unsigned int n_peers,
1484      struct GNUNET_TESTBED_Peer **peers,
1485      unsigned int links_succeeded,
1486      unsigned int links_failed)
1487 {
1488   unsigned int i;
1489   struct OpListEntry *entry;
1490   uint32_t num_mal_peers;
1491
1492   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "RUN was called\n");
1493
1494   /* Check whether we timed out */
1495   if (n_peers != num_peers ||
1496       NULL == peers ||
1497       0 == links_succeeded)
1498   {
1499     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Going down due to args (eg. timeout)\n");
1500     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tn_peers: %u\n", n_peers);
1501     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tnum_peers: %" PRIu32 "\n", num_peers);
1502     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tpeers: %p\n", peers);
1503     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\tlinks_succeeded: %u\n", links_succeeded);
1504     GNUNET_SCHEDULER_shutdown ();
1505     return;
1506   }
1507
1508
1509   /* Initialize peers */
1510   testbed_peers = peers;
1511   num_peers_online = 0;
1512   for (i = 0; i < num_peers; i++)
1513   {
1514     entry = make_oplist_entry ();
1515     entry->index = i;
1516     rps_peers[i].index = i;
1517     if (NULL != cur_test_run.init_peer)
1518       cur_test_run.init_peer (&rps_peers[i]);
1519     entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
1520                                                      GNUNET_TESTBED_PIT_IDENTITY,
1521                                                      &info_cb,
1522                                                      entry);
1523   }
1524
1525   /* Bring peers up */
1526   num_mal_peers = round (portion * num_peers);
1527   GNUNET_assert (num_peers == n_peers);
1528   for (i = 0; i < n_peers; i++)
1529   {
1530     rps_peers[i].index = i;
1531     if ( (rps_peers[i].num_recv_ids < rps_peers[i].num_ids_to_request) ||
1532          (i < num_mal_peers) )
1533     {
1534       rps_peers[i].op =
1535         GNUNET_TESTBED_service_connect (&rps_peers[i],
1536                                         peers[i],
1537                                         "rps",
1538                                         &rps_connect_complete_cb,
1539                                         &rps_peers[i],
1540                                         &rps_connect_adapter,
1541                                         &rps_disconnect_adapter,
1542                                         &rps_peers[i]);
1543     }
1544   }
1545
1546   if (NULL != churn_task)
1547     GNUNET_SCHEDULER_cancel (churn_task);
1548   GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_op, NULL);
1549 }
1550
1551
1552 /**
1553  * Entry point for the testcase, sets up the testbed.
1554  *
1555  * @param argc unused
1556  * @param argv unused
1557  * @return 0 on success
1558  */
1559 int
1560 main (int argc, char *argv[])
1561 {
1562   int ret_value;
1563
1564   num_peers = 5;
1565   cur_test_run.name = "test-rps-default";
1566   cur_test_run.init_peer = default_init_peer;
1567   cur_test_run.pre_test = NULL;
1568   cur_test_run.reply_handle = default_reply_handle;
1569   cur_test_run.eval_cb = default_eval_cb;
1570   cur_test_run.have_churn = GNUNET_YES;
1571   churn_task = NULL;
1572   timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
1573
1574   if (strstr (argv[0], "malicious") != NULL)
1575   {
1576     cur_test_run.pre_test = mal_pre;
1577     cur_test_run.main_test = mal_cb;
1578     cur_test_run.init_peer = mal_init_peer;
1579
1580     if (strstr (argv[0], "_1") != NULL)
1581     {
1582       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 1\n");
1583       cur_test_run.name = "test-rps-malicious_1";
1584       mal_type = 1;
1585     }
1586     else if (strstr (argv[0], "_2") != NULL)
1587     {
1588       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 2\n");
1589       cur_test_run.name = "test-rps-malicious_2";
1590       mal_type = 2;
1591     }
1592     else if (strstr (argv[0], "_3") != NULL)
1593     {
1594       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 3\n");
1595       cur_test_run.name = "test-rps-malicious_3";
1596       mal_type = 3;
1597     }
1598   }
1599
1600   else if (strstr (argv[0], "_single_req") != NULL)
1601   {
1602     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
1603     cur_test_run.name = "test-rps-single-req";
1604     cur_test_run.main_test = single_req_cb;
1605     cur_test_run.have_churn = GNUNET_NO;
1606   }
1607
1608   else if (strstr (argv[0], "_delayed_reqs") != NULL)
1609   {
1610     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
1611     cur_test_run.name = "test-rps-delayed-reqs";
1612     cur_test_run.main_test = delay_req_cb;
1613     cur_test_run.have_churn = GNUNET_NO;
1614   }
1615
1616   else if (strstr (argv[0], "_seed_big") != NULL)
1617   {
1618     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding (num_peers > GNUNET_MAX_MESSAGE_SIZE)\n");
1619     num_peers = 1;
1620     cur_test_run.name = "test-rps-seed-big";
1621     cur_test_run.main_test = seed_big_cb;
1622     cur_test_run.eval_cb = no_eval;
1623     cur_test_run.have_churn = GNUNET_NO;
1624     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1625   }
1626
1627   else if (strstr (argv[0], "_single_peer_seed") != NULL)
1628   {
1629     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
1630     cur_test_run.name = "test-rps-single-peer-seed";
1631     cur_test_run.main_test = single_peer_seed_cb;
1632     cur_test_run.have_churn = GNUNET_NO;
1633   }
1634
1635   else if (strstr (argv[0], "_seed_request") != NULL)
1636   {
1637     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
1638     cur_test_run.name = "test-rps-seed-request";
1639     cur_test_run.main_test = seed_req_cb;
1640     cur_test_run.have_churn = GNUNET_NO;
1641   }
1642
1643   else if (strstr (argv[0], "_seed") != NULL)
1644   {
1645     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding\n");
1646     cur_test_run.name = "test-rps-seed";
1647     cur_test_run.main_test = seed_cb;
1648     cur_test_run.eval_cb = no_eval;
1649     cur_test_run.have_churn = GNUNET_NO;
1650   }
1651
1652   else if (strstr (argv[0], "_req_cancel") != NULL)
1653   {
1654     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test cancelling a request\n");
1655     cur_test_run.name = "test-rps-req-cancel";
1656     num_peers = 1;
1657     cur_test_run.main_test = req_cancel_cb;
1658     cur_test_run.eval_cb = no_eval;
1659     cur_test_run.have_churn = GNUNET_NO;
1660     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1661   }
1662
1663   else if (strstr (argv[0], "_churn") != NULL)
1664   {
1665     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test churn\n");
1666     cur_test_run.name = "test-rps-churn";
1667     num_peers = 5;
1668     cur_test_run.init_peer = default_init_peer;
1669     cur_test_run.main_test = churn_test_cb;
1670     cur_test_run.reply_handle = default_reply_handle;
1671     cur_test_run.eval_cb = default_eval_cb;
1672     cur_test_run.have_churn = GNUNET_YES;
1673     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10);
1674   }
1675
1676   else if (strstr (argv[0], "profiler") != NULL)
1677   {
1678     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
1679     cur_test_run.name = "test-rps-profiler";
1680     num_peers = 10;
1681     mal_type = 3;
1682     cur_test_run.init_peer = profiler_init_peer;
1683     cur_test_run.pre_test = mal_pre;
1684     cur_test_run.main_test = profiler_cb;
1685     cur_test_run.reply_handle = profiler_reply_handle;
1686     cur_test_run.eval_cb = profiler_eval;
1687     cur_test_run.request_interval = 2;
1688     cur_test_run.num_requests = 5;
1689     cur_test_run.have_churn = GNUNET_YES;
1690     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90);
1691
1692     /* 'Clean' directory */
1693     (void) GNUNET_DISK_directory_remove ("/tmp/rps/");
1694     GNUNET_DISK_directory_create ("/tmp/rps/");
1695   }
1696
1697   rps_peers = GNUNET_new_array (num_peers, struct RPSPeer);
1698   peer_map = GNUNET_CONTAINER_multipeermap_create (num_peers, GNUNET_NO);
1699   rps_peer_ids = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
1700   if ( (2 == mal_type) ||
1701        (3 == mal_type))
1702     target_peer = &rps_peer_ids[num_peers - 2];
1703   if (profiler_eval == cur_test_run.eval_cb)
1704     eval_peer = &rps_peers[num_peers - 1];    /* FIXME: eval_peer could be a
1705                                                  malicious peer if not careful
1706                                                  with the malicious portion */
1707
1708   ok = 1;
1709   ret_value = GNUNET_TESTBED_test_run (cur_test_run.name,
1710                                   "test_rps.conf",
1711                                   num_peers,
1712                                   0, NULL, NULL,
1713                                   &run, NULL);
1714   GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1715               "_test_run returned.\n");
1716   if (GNUNET_OK != ret_value)
1717   {
1718     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1719                 "Test did not run successfully!\n");
1720   }
1721
1722   ret_value = cur_test_run.eval_cb();
1723   GNUNET_free (rps_peers);
1724   GNUNET_free (rps_peer_ids);
1725   GNUNET_CONTAINER_multipeermap_destroy (peer_map);
1726   return ret_value;
1727 }
1728
1729 /* end of test_rps.c */