-clean logging dir before running profiler
[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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, 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 #include "gnunet_rps_service.h"
31
32 #include <inttypes.h>
33
34
35 /**
36  * How many peers do we start?
37  */
38 uint32_t num_peers;
39
40 /**
41  * How long do we run the test?
42  */
43 //#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
44 static struct GNUNET_TIME_Relative timeout;
45
46
47 /**
48  * Portion of malicious peers
49  */
50 static double portion = .1;
51
52 /**
53  * Type of malicious peer to test
54  */
55 static unsigned int mal_type = 0;
56
57 /**
58  * Handles to all of the running peers
59  */
60 static struct GNUNET_TESTBED_Peer **testbed_peers;
61
62
63 /**
64  * Operation map entry
65  */
66 struct OpListEntry
67 {
68   /**
69    * DLL next ptr
70    */
71   struct OpListEntry *next;
72
73   /**
74    * DLL prev ptr
75    */
76   struct OpListEntry *prev;
77
78   /**
79    * The testbed operation
80    */
81   struct GNUNET_TESTBED_Operation *op;
82
83   /**
84    * Depending on whether we start or stop NSE service at the peer set this to 1
85    * or -1
86    */
87   int delta;
88
89   /**
90    * Index of the regarding peer
91    */
92   unsigned int index;
93 };
94
95 /**
96  * OpList DLL head
97  */
98 static struct OpListEntry *oplist_head;
99
100 /**
101  * OpList DLL tail
102  */
103 static struct OpListEntry *oplist_tail;
104
105
106 /**
107  * Information we track for each peer.
108  */
109 struct RPSPeer
110 {
111   /**
112    * Index of the peer.
113    */
114   unsigned int index;
115
116   /**
117    * Handle for RPS connect operation.
118    */
119   struct GNUNET_TESTBED_Operation *op;
120
121   /**
122    * Handle to RPS service.
123    */
124   struct GNUNET_RPS_Handle *rps_handle;
125
126   /**
127    * ID of the peer.
128    */
129   struct GNUNET_PeerIdentity *peer_id;
130
131   /**
132    * A request handle to check for an request
133    */
134   //struct GNUNET_RPS_Request_Handle *req_handle;
135
136   /**
137    * Peer on- or offline?
138    */
139   int online;
140
141   /**
142    * Received PeerIDs
143    */
144   struct GNUNET_PeerIdentity *rec_ids;
145
146   /**
147    * Number of received PeerIDs
148    */
149   unsigned int num_rec_ids;
150 };
151
152
153 /**
154  * Information for all the peers.
155  */
156 static struct RPSPeer *rps_peers;
157
158 /**
159  * IDs of the peers.
160  */
161 static struct GNUNET_PeerIdentity *rps_peer_ids;
162
163 /**
164  * Number of online peers.
165  */
166 static unsigned int num_peers_online;
167
168 /**
169  * Return value from 'main'.
170  */
171 static int ok;
172
173
174 /**
175  * Identifier for the churn task that runs periodically
176  */
177 static struct GNUNET_SCHEDULER_Task *churn_task;
178
179
180 /**
181  * Called directly after connecting to the service
182  */
183 typedef void (*PreTest) (void *cls, struct GNUNET_RPS_Handle *h);
184
185 /**
186  * Called from within #rps_connect_complete_cb ()
187  * Executes functions to test the api/service
188  */
189 typedef void (*MainTest) (struct RPSPeer *rps_peer);
190
191 /**
192  * Callback called once the requested random peers are available
193  */
194 typedef void (*ReplyHandle) (void *cls,
195                              uint64_t n,
196                              const struct GNUNET_PeerIdentity *recv_peers);
197
198 /**
199  * Called directly before disconnecting from the service
200  */
201 typedef void (*PostTest) (void *cls, struct GNUNET_RPS_Handle *h);
202
203 /**
204  * Function called after disconnect to evaluate test success
205  */
206 typedef int (*EvaluationCallback) (void);
207
208
209 /**
210  * Structure to define a single test
211  */
212 struct SingleTestRun
213 {
214   /**
215    * Name of the test
216    */
217   char *name;
218
219   /**
220    * Called directly after connecting to the service
221    */
222   PreTest pre_test;
223
224   /**
225    * Function to execute the functions to be tested
226    */
227   MainTest main_test;
228
229   /**
230    * Callback called once the requested peers are available
231    */
232   ReplyHandle reply_handle;
233
234   /**
235    * Called directly before disconnecting from the service
236    */
237   PostTest post_test;
238
239   /**
240    * Function to evaluate the test results
241    */
242   EvaluationCallback eval_cb;
243
244   /**
245    * Request interval
246    */
247   uint32_t request_interval;
248
249   /**
250    * Number of Requests to make.
251    */
252   uint32_t num_requests;
253 } cur_test_run;
254
255
256 /**
257  * Append arguments to file
258  */
259 static void
260 to_file_ (char *file_name, char *line)
261 {
262   struct GNUNET_DISK_FileHandle *f;
263   /* char output_buffer[512]; */
264   size_t size;
265   /* int size; */
266   size_t size2;
267
268   if (NULL == (f = GNUNET_DISK_file_open (file_name,
269                                           GNUNET_DISK_OPEN_APPEND |
270                                           GNUNET_DISK_OPEN_WRITE |
271                                           GNUNET_DISK_OPEN_CREATE,
272                                           GNUNET_DISK_PERM_USER_READ |
273                                           GNUNET_DISK_PERM_USER_WRITE |
274                                           GNUNET_DISK_PERM_GROUP_READ |
275                                           GNUNET_DISK_PERM_OTHER_READ)))
276   {
277     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
278                 "Not able to open file %s\n",
279                 file_name);
280     return;
281   }
282   /* size = GNUNET_snprintf (output_buffer,
283                           sizeof (output_buffer),
284                           "%llu %s\n",
285                           GNUNET_TIME_absolute_get ().abs_value_us,
286                           line);
287   if (0 > size)
288   {
289     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
290                 "Failed to write string to buffer (size: %i)\n",
291                 size);
292     return;
293   } */
294
295   size = strlen (line) * sizeof (char);
296
297   size2 = GNUNET_DISK_file_write (f, line, size);
298   if (size != size2)
299   {
300     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
301                 "Unable to write to file! (Size: %u, size2: %u)\n",
302                 size,
303                 size2);
304     return;
305   }
306
307   if (GNUNET_YES != GNUNET_DISK_file_close (f))
308     GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
309                 "Unable to close file\n");
310 }
311
312 /**
313  * This function is used to facilitate writing important information to disk
314  */
315 #define to_file(file_name, ...) do {\
316   char tmp_buf[512];\
317     int size;\
318     size = GNUNET_snprintf(tmp_buf,sizeof(tmp_buf),__VA_ARGS__);\
319     if (0 > size)\
320       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,\
321                      "Failed to create tmp_buf\n");\
322     else\
323       to_file_(file_name,tmp_buf);\
324   } while (0);
325
326 /**
327  * Write the ids and their according index in the given array to a file 
328  * Unused
329  */
330 /* static void
331 ids_to_file (char *file_name,
332              struct GNUNET_PeerIdentity *peer_ids,
333              unsigned int num_peer_ids)
334 {
335   unsigned int i;
336
337   for (i=0 ; i < num_peer_ids ; i++)
338   {
339     to_file (file_name,
340              "%u\t%s",
341              i,
342              GNUNET_i2s_full (&peer_ids[i]));
343   }
344 } */
345
346 /**
347  * Test the success of a single test
348  */
349 static int
350 evaluate (struct RPSPeer *loc_rps_peers,
351           unsigned int num_loc_rps_peers,
352           unsigned int expected_recv)
353 {
354   unsigned int i;
355   int tmp_ok;
356
357   tmp_ok = (1 == loc_rps_peers[0].num_rec_ids);
358
359   for (i = 0 ; i < num_loc_rps_peers ; i++)
360   {
361     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
362                 "%u. peer [%s] received %u of %u expected peer_ids: %i\n",
363                 i,
364                 GNUNET_i2s (loc_rps_peers[i].peer_id),
365                 loc_rps_peers[i].num_rec_ids,
366                 expected_recv,
367                 (1 == loc_rps_peers[i].num_rec_ids));
368     tmp_ok &= (1 == loc_rps_peers[i].num_rec_ids);
369   }
370   return tmp_ok? 0 : 1;
371 }
372
373
374 /**
375  * Creates an oplist entry and adds it to the oplist DLL
376  */
377 static struct OpListEntry *
378 make_oplist_entry ()
379 {
380   struct OpListEntry *entry;
381
382   entry = GNUNET_new (struct OpListEntry);
383   GNUNET_CONTAINER_DLL_insert_tail (oplist_head, oplist_tail, entry);
384   return entry;
385 }
386
387
388 /**
389  * Callback to be called when NSE service is started or stopped at peers
390  *
391  * @param cls NULL
392  * @param op the operation handle
393  * @param emsg NULL on success; otherwise an error description
394  */
395 static void
396 churn_cb (void *cls,
397           struct GNUNET_TESTBED_Operation *op,
398           const char *emsg)
399 {
400   // FIXME
401   struct OpListEntry *entry = cls;
402
403   GNUNET_TESTBED_operation_done (entry->op);
404   if (NULL != emsg)
405   {
406     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Failed to start/stop RPS at a peer\n");
407     GNUNET_SCHEDULER_shutdown ();
408     return;
409   }
410   GNUNET_assert (0 != entry->delta);
411
412   num_peers_online += entry->delta;
413
414   if (0 > entry->delta)
415   { /* Peer hopefully just went offline */
416     if (GNUNET_YES != rps_peers[entry->index].online)
417     {
418       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
419                   "peer %s was expected to go offline but is still marked as online\n",
420                   GNUNET_i2s (rps_peers[entry->index].peer_id));
421       GNUNET_break (0);
422     }
423     else
424     {
425       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
426                   "peer %s probably went offline as expected\n",
427                   GNUNET_i2s (rps_peers[entry->index].peer_id));
428     }
429     rps_peers[entry->index].online = GNUNET_NO;
430   }
431
432   else if (0 < entry->delta)
433   { /* Peer hopefully just went online */
434     if (GNUNET_NO != rps_peers[entry->index].online)
435     {
436       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
437                   "peer %s was expected to go online but is still marked as offline\n",
438                   GNUNET_i2s (rps_peers[entry->index].peer_id));
439       GNUNET_break (0);
440     }
441     else
442     {
443       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
444                   "peer %s probably went online as expected\n",
445                   GNUNET_i2s (rps_peers[entry->index].peer_id));
446     }
447     rps_peers[entry->index].online = GNUNET_YES;
448   }
449
450   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
451   GNUNET_free (entry);
452   //if (num_peers_in_round[current_round] == peers_running)
453   //  run_round ();
454 }
455
456
457 /**
458  * Task run on timeout to shut everything down.
459  */
460 static void
461 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
462 {
463   unsigned int i;
464
465   if (NULL != churn_task)
466     GNUNET_SCHEDULER_cancel (churn_task);
467
468   for (i = 0 ; i < num_peers ; i++)
469     GNUNET_TESTBED_operation_done (rps_peers[i].op);
470   GNUNET_SCHEDULER_shutdown ();
471 }
472
473
474 /**
475  * Seed peers.
476  */
477   void
478 seed_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
479 {
480   unsigned int amount;
481   struct RPSPeer *peer = (struct RPSPeer *) cls;
482   unsigned int i;
483
484   // TODO if malicious don't seed mal peers
485   amount = round (.5 * num_peers);
486
487   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
488   for (i = 0 ; i < amount ; i++)
489     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
490                 i,
491                 GNUNET_i2s (&rps_peer_ids[i]));
492
493   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
494 }
495
496
497 /**
498  * Get the id of peer i.
499  */
500   void
501 info_cb (void *cb_cls,
502          struct GNUNET_TESTBED_Operation *op,
503          const struct GNUNET_TESTBED_PeerInformation *pinfo,
504          const char *emsg)
505 {
506   struct OpListEntry *entry = (struct OpListEntry *) cb_cls;
507
508   if (NULL == pinfo || NULL != emsg)
509   {
510     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
511     return;
512   }
513
514   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
515               "Peer %u is %s\n",
516               entry->index,
517               GNUNET_i2s (pinfo->result.id));
518
519   rps_peer_ids[entry->index] = *(pinfo->result.id);
520   rps_peers[entry->index].peer_id = &rps_peer_ids[entry->index];
521   rps_peers[entry->index].rec_ids = NULL;
522   rps_peers[entry->index].num_rec_ids = 0;
523
524   to_file ("/tmp/rps/peer_ids",
525            "%u\t%s\n",
526            entry->index,
527            GNUNET_i2s_full (&rps_peer_ids[entry->index]));
528
529   GNUNET_TESTBED_operation_done (entry->op);
530
531   GNUNET_CONTAINER_DLL_remove (oplist_head, oplist_tail, entry);
532   GNUNET_free (entry);
533 }
534
535
536 /**
537  * Callback to be called when RPS service connect operation is completed
538  *
539  * @param cls the callback closure from functions generating an operation
540  * @param op the operation that has been finished
541  * @param ca_result the RPS service handle returned from rps_connect_adapter
542  * @param emsg error message in case the operation has failed; will be NULL if
543  *          operation has executed successfully.
544  */
545 static void
546 rps_connect_complete_cb (void *cls,
547                          struct GNUNET_TESTBED_Operation *op,
548                          void *ca_result,
549                          const char *emsg)
550 {
551   struct RPSPeer *rps_peer = cls;
552   struct GNUNET_RPS_Handle *rps = ca_result;
553
554   rps_peer->rps_handle = rps;
555   rps_peer->online = GNUNET_YES;
556   num_peers_online++;
557
558   GNUNET_assert (op == rps_peer->op);
559   if (NULL != emsg)
560   {
561     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
562                 "Failed to connect to RPS service: %s\n",
563                 emsg);
564     ok = 1;
565     GNUNET_SCHEDULER_shutdown ();
566     return;
567   }
568
569   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
570
571   cur_test_run.main_test (rps_peer);
572 }
573
574
575 /**
576  * Adapter function called to establish a connection to
577  * the RPS service.
578  *
579  * @param cls closure
580  * @param cfg configuration of the peer to connect to; will be available until
581  *          GNUNET_TESTBED_operation_done() is called on the operation returned
582  *          from GNUNET_TESTBED_service_connect()
583  * @return service handle to return in 'op_result', NULL on error
584  */
585 static void *
586 rps_connect_adapter (void *cls,
587                                  const struct GNUNET_CONFIGURATION_Handle *cfg)
588 {
589   struct GNUNET_RPS_Handle *h;
590
591   h = GNUNET_RPS_connect (cfg);
592
593   if (NULL != cur_test_run.pre_test)
594     cur_test_run.pre_test (cls, h);
595
596   return h;
597 }
598
599
600 /**
601  * Adapter function called to destroy connection to
602  * RPS service.
603  *
604  * @param cls closure
605  * @param op_result service handle returned from the connect adapter
606  */
607 static void
608 rps_disconnect_adapter (void *cls,
609                                           void *op_result)
610 {
611   struct GNUNET_RPS_Handle *h = op_result;
612   GNUNET_RPS_disconnect (h);
613 }
614
615
616 /***********************************************************************
617  * Definition of tests
618 ***********************************************************************/
619
620 // TODO check whether tests can be stopped earlier
621 static int
622 default_eval_cb (void)
623 {
624   return evaluate (rps_peers, num_peers, 1);
625 }
626
627 static int
628 no_eval (void)
629 {
630   return 1;
631 }
632
633 /**
634  * Callback to call on receipt of a reply
635  *
636  * @param cls closure
637  * @param n number of peers
638  * @param recv_peers the received peers
639  */
640 static void
641 default_reply_handle (void *cls,
642                       uint64_t n,
643                       const struct GNUNET_PeerIdentity *recv_peers)
644 {
645   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
646   unsigned int i;
647
648   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
649               "[%s] got %" PRIu64 " peers:\n",
650               GNUNET_i2s (rps_peer->peer_id),
651               n);
652   
653   for (i = 0 ; i < n ; i++)
654   {
655     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
656                 "%u: %s\n",
657                 i,
658                 GNUNET_i2s (&recv_peers[i]));
659
660     GNUNET_array_append (rps_peer->rec_ids, rps_peer->num_rec_ids, recv_peers[i]);
661   }
662 }
663
664 /**
665  * Request random peers.
666  */
667 static void
668 request_peers (void *cls,
669                const struct GNUNET_SCHEDULER_TaskContext *tc)
670 {
671   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
672
673   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
674               "Requesting one peer\n");
675
676   GNUNET_free (GNUNET_RPS_request_peers (rps_peer->rps_handle,
677                                          1,
678                                          cur_test_run.reply_handle,
679                                          rps_peer));
680   //rps_peer->req_handle = GNUNET_RPS_request_peers (rps_peer->rps_handle, 1, handle_reply, rps_peer);
681 }
682
683
684 /***********************************
685  * MALICIOUS
686 ***********************************/
687 static void
688 mal_pre (void *cls, struct GNUNET_RPS_Handle *h)
689 {
690   #ifdef ENABLE_MALICIOUS
691   uint32_t num_mal_peers;
692   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
693
694   GNUNET_assert (1 >= portion
695                  && 0 <  portion);
696   num_mal_peers = round (portion * num_peers);
697
698   if (rps_peer->index < num_mal_peers)
699   {
700     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
701                 "%u. peer [%s] of %" PRIu32 " malicious peers turning malicious\n",
702                 rps_peer->index,
703                 GNUNET_i2s (rps_peer->peer_id),
704                 num_mal_peers);
705
706     GNUNET_RPS_act_malicious (h, mal_type, num_mal_peers, rps_peer_ids);
707   }
708   #endif /* ENABLE_MALICIOUS */
709 }
710
711 static void
712 mal_cb (struct RPSPeer *rps_peer)
713 {
714   uint32_t num_mal_peers;
715
716   #ifdef ENABLE_MALICIOUS
717   GNUNET_assert (1 >= portion
718                  && 0 <  portion);
719   num_mal_peers = round (portion * num_peers);
720
721   if (rps_peer->index >= num_mal_peers)
722   { /* It's useless to ask a malicious peer about a random sample -
723        it's not sampling */
724     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
725                                   seed_peers, rps_peer);
726     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
727                                   request_peers, rps_peer);
728   }
729   #endif /* ENABLE_MALICIOUS */
730 }
731
732 static int
733 mal_eval (void)
734 {
735   unsigned int num_mal_peers;
736
737   num_mal_peers = round (num_peers * portion);
738   return evaluate (&rps_peers[num_mal_peers],
739                    num_peers - (num_mal_peers),
740                    1);
741 }
742
743
744 /***********************************
745  * SINGLE_REQUEST
746 ***********************************/
747 static void
748 single_req_cb (struct RPSPeer *rps_peer)
749 {
750   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
751                                 request_peers, rps_peer);
752 }
753
754 /***********************************
755  * DELAYED_REQUESTS
756 ***********************************/
757 static void
758 delay_req_cb (struct RPSPeer *rps_peer)
759 {
760   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
761                                 request_peers, rps_peer);
762   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
763                                 request_peers, rps_peer);
764 }
765
766 /***********************************
767  * SEED
768 ***********************************/
769 static void
770 seed_cb (struct RPSPeer *rps_peer)
771 {
772   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
773                                 seed_peers, rps_peer);
774 }
775
776 /***********************************
777  * SEED_BIG
778 ***********************************/
779 static void
780 seed_big_cb (struct RPSPeer *rps_peer)
781 {
782   // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
783 }
784
785 /***********************************
786  * SINGLE_PEER_SEED
787 ***********************************/
788 static void
789 single_peer_seed_cb (struct RPSPeer *rps_peer)
790 {
791   // TODO
792 }
793
794 /***********************************
795  * SEED_REQUEST
796 ***********************************/
797 static void
798 seed_req_cb (struct RPSPeer *rps_peer)
799 {
800   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
801                                 seed_peers, rps_peer);
802   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15),
803                                 request_peers, rps_peer);
804 }
805
806 //TODO start big mal
807
808 /***********************************
809  * REQUEST_CANCEL
810 ***********************************/
811 static void
812 req_cancel_cb (struct RPSPeer *rps_peer)
813 {
814   // TODO
815 }
816
817 /***********************************
818  * PROFILER
819 ***********************************/
820 static void
821 churn (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
822 {
823   struct OpListEntry *entry;
824   unsigned int i;
825   unsigned int j;
826   double portion_online;
827   unsigned int *permut;
828   double prob_go_offline;
829   double portion_go_online;
830   double portion_go_offline;
831   uint32_t prob;
832
833   /* Compute the probability for an online peer to go offline
834    * this round */
835   portion_online = num_peers_online * 1.0 / num_peers;
836   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
837               "Portion online: %f\n",
838               portion_online);
839   portion_go_online = ((1 - portion_online) * .5 * .66);
840   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
841               "Portion that should go online: %f\n",
842               portion_go_online);
843   portion_go_offline = (portion_online + portion_go_online) - .75;
844   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
845               "Portion that probably goes offline: %f\n",
846               portion_go_offline);
847   prob_go_offline = portion_go_offline / (portion_online * .5);
848   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
849               "Probability of a selected online peer to go offline: %f\n",
850               prob_go_offline);
851
852   permut = GNUNET_CRYPTO_random_permute (GNUNET_CRYPTO_QUALITY_WEAK,
853                                          (unsigned int) num_peers);
854
855   /* Go over 50% randomly chosen peers */
856   for (i = 0 ; i < .5 * num_peers ; i++)
857   {
858     j = permut[i];
859
860     /* If online, shut down with certain probability */
861     if (GNUNET_YES == rps_peers[j].online)
862     {
863       prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
864                                        UINT32_MAX);
865       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
866                   "%u. selected peer (%u: %s) is online.\n",
867                   i,
868                   j,
869                   GNUNET_i2s (rps_peers[j].peer_id));
870       if (prob < prob_go_offline * UINT32_MAX)
871       {
872         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
873                     "%s goes offline\n",
874                     GNUNET_i2s (rps_peers[j].peer_id));
875
876         entry = make_oplist_entry ();
877         entry->delta = -1;
878         entry->index = j;
879         entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
880                                                         testbed_peers[j],
881                                                         "rps",
882                                                         &churn_cb,
883                                                         entry,
884                                                         0);
885       }
886    }
887
888    /* If offline, restart with certain probability */
889    else if (GNUNET_NO == rps_peers[j].online)
890    {
891      prob = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
892                                       UINT32_MAX);
893      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
894                  "%u. selected peer (%u: %s) is offline.\n",
895                  i,
896                  j,
897                  GNUNET_i2s (rps_peers[j].peer_id));
898      if (prob < .66 * UINT32_MAX)
899      {
900        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
901                    "%s goes online\n",
902                    GNUNET_i2s (rps_peers[j].peer_id));
903
904        entry = make_oplist_entry ();
905        entry->delta = 1;
906        entry->index = j;
907        entry->op = GNUNET_TESTBED_peer_manage_service (NULL,
908                                                        testbed_peers[j],
909                                                        "rps",
910                                                        &churn_cb,
911                                                        entry,
912                                                        1);
913      }
914    }
915   }
916
917   GNUNET_free (permut);
918
919   churn_task = GNUNET_SCHEDULER_add_delayed (
920         GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
921         churn,
922         NULL);
923 }
924
925
926 static void
927 profiler_pre (void *cls, struct GNUNET_RPS_Handle *h)
928 {
929   //churn_task = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
930   //                                                                          10),
931   //                                           churn, NULL);
932   mal_pre (cls, h);
933
934   /* if (NULL == churn_task)
935   {
936     churn_task = GNUNET_SCHEDULER_add_delayed (
937           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
938           churn,
939           NULL);
940   } */
941 }
942
943
944 /**
945  * Callback to call on receipt of a reply
946  *
947  * @param cls closure
948  * @param n number of peers
949  * @param recv_peers the received peers
950  */
951 static void
952 profiler_reply_handle (void *cls,
953                       uint64_t n,
954                       const struct GNUNET_PeerIdentity *recv_peers)
955 {
956   struct RPSPeer *rps_peer = (struct RPSPeer *) cls;
957   char *file_name;
958   unsigned int i;
959
960   file_name = "/tmp/rps/received_ids";
961
962   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
963               "[%s] got %" PRIu64 " peers:\n",
964               GNUNET_i2s (rps_peer->peer_id),
965               n);
966   
967   for (i = 0 ; i < n ; i++)
968   {
969     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
970                 "%u: %s\n",
971                 i,
972                 GNUNET_i2s (&recv_peers[i]));
973
974     /* GNUNET_array_append (rps_peer->rec_ids, rps_peer->num_rec_ids, recv_peers[i]); */
975     to_file (file_name,
976              "%s\n",
977              GNUNET_i2s_full (&recv_peers[i]));
978   }
979 }
980
981
982 static void
983 profiler_cb (struct RPSPeer *rps_peer)
984 {
985   uint32_t i;
986
987   /* Churn only at peers that do not request peers for evaluation */
988   if (NULL == churn_task &&
989       rps_peer->index != num_peers - 2)
990   {
991     churn_task = GNUNET_SCHEDULER_add_delayed (
992           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
993           churn,
994           NULL);
995   }
996
997   /* Only request peer ids at one peer.
998    * (It's the before-last because last one is target of the focussed attack.)
999    */
1000   if (rps_peer->index == num_peers - 2)
1001   {
1002     for (i = 0 ; i < cur_test_run.num_requests ; i++)
1003     {
1004       GNUNET_SCHEDULER_add_delayed (
1005           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
1006                                          cur_test_run.request_interval * i),
1007           request_peers,
1008           rps_peer);
1009     }
1010   }
1011 }
1012
1013
1014 /***********************************************************************
1015  * /Definition of tests
1016 ***********************************************************************/
1017
1018
1019 /**
1020  * Actual "main" function for the testcase.
1021  *
1022  * @param cls closure
1023  * @param h the run handle
1024  * @param n_peers number of peers in 'peers'
1025  * @param peers handle to peers run in the testbed
1026  * @param links_succeeded the number of overlay link connection attempts that
1027  *          succeeded
1028  * @param links_failed the number of overlay link connection attempts that
1029  *          failed
1030  */
1031 static void
1032 run (void *cls,
1033      struct GNUNET_TESTBED_RunHandle *h,
1034      unsigned int n_peers,
1035      struct GNUNET_TESTBED_Peer **peers,
1036      unsigned int links_succeeded,
1037      unsigned int links_failed)
1038 {
1039   unsigned int i;
1040   struct OpListEntry *entry;
1041
1042   testbed_peers = peers;
1043   num_peers_online = 0;
1044
1045   for (i = 0 ; i < num_peers ; i++)
1046   {
1047     entry = make_oplist_entry ();
1048     entry->index = i;
1049     entry->op = GNUNET_TESTBED_peer_get_information (peers[i],
1050                                                      GNUNET_TESTBED_PIT_IDENTITY,
1051                                                      &info_cb,
1052                                                      entry);
1053   }
1054
1055
1056   // This seems not to work
1057   //if (NULL != strstr (cur_test_run.name, "profiler"))
1058   //{
1059   //  churn_task = GNUNET_SCHEDULER_add_delayed (
1060   //      GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 5),
1061   //      churn,
1062   //      NULL);
1063   //}
1064
1065   GNUNET_assert (num_peers == n_peers);
1066   for (i = 0 ; i < n_peers ; i++)
1067   {
1068     rps_peers[i].index = i;
1069     rps_peers[i].op =
1070       GNUNET_TESTBED_service_connect (&rps_peers[i],
1071                                                                           peers[i],
1072                                                                           "rps",
1073                                                                           &rps_connect_complete_cb,
1074                                                                           &rps_peers[i],
1075                                                                           &rps_connect_adapter,
1076                                                                           &rps_disconnect_adapter,
1077                                                                           &rps_peers[i]);
1078   }
1079
1080   if (NULL != churn_task)
1081     GNUNET_SCHEDULER_cancel (churn_task);
1082
1083   GNUNET_SCHEDULER_add_delayed (timeout, &shutdown_task, NULL);
1084 }
1085
1086
1087 /**
1088  * Entry point for the testcase, sets up the testbed.
1089  *
1090  * @param argc unused
1091  * @param argv unused
1092  * @return 0 on success
1093  */
1094 int
1095 main (int argc, char *argv[])
1096 {
1097   cur_test_run.name = "test-rps-default";
1098   cur_test_run.pre_test = NULL;
1099   cur_test_run.reply_handle = default_reply_handle;
1100   cur_test_run.eval_cb = default_eval_cb;
1101   churn_task = NULL;
1102
1103   num_peers = 5;
1104   timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30);
1105
1106   if (strstr (argv[0], "malicious") != NULL)
1107   {
1108     cur_test_run.pre_test = mal_pre;
1109     cur_test_run.main_test = mal_cb;
1110     cur_test_run.eval_cb = mal_eval;
1111
1112     if (strstr (argv[0], "_1") != NULL)
1113     {
1114       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 1\n");
1115       cur_test_run.name = "test-rps-malicious_1";
1116       mal_type = 1;
1117     }
1118     else if (strstr (argv[0], "_2") != NULL)
1119     {
1120       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 2\n");
1121       cur_test_run.name = "test-rps-malicious_2";
1122       mal_type = 2;
1123     }
1124     else if (strstr (argv[0], "_3") != NULL)
1125     {
1126       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test malicious peer type 3\n");
1127       cur_test_run.name = "test-rps-malicious_3";
1128       mal_type = 3;
1129     }
1130   }
1131
1132   else if (strstr (argv[0], "_single_req") != NULL)
1133   {
1134     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Test single request\n");
1135     cur_test_run.name = "test-rps-single-req";
1136     cur_test_run.main_test = single_req_cb;
1137   }
1138
1139   else if (strstr (argv[0], "_delayed_reqs") != NULL)
1140   {
1141     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test delayed requests\n");
1142     cur_test_run.name = "test-rps-delayed-reqs";
1143     cur_test_run.main_test = delay_req_cb;
1144   }
1145
1146   else if (strstr (argv[0], "_seed_big") != NULL)
1147   {
1148     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding (num_peers > GNUNET_SERVER_MAX_MESSAGE_SIZE)\n");
1149     cur_test_run.name = "test-rps-seed-big";
1150     cur_test_run.main_test = seed_big_cb;
1151   }
1152
1153   else if (strstr (argv[0], "_single_peer_seed") != NULL)
1154   {
1155     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on a single peer\n");
1156     cur_test_run.name = "test-rps-single-peer-seed";
1157     cur_test_run.main_test = single_peer_seed_cb;
1158   }
1159
1160   else if (strstr (argv[0], "_seed_request") != NULL)
1161   {
1162     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding and requesting on multiple peers\n");
1163     cur_test_run.name = "test-rps-seed-request";
1164     cur_test_run.main_test = seed_req_cb;
1165   }
1166
1167   else if (strstr (argv[0], "_seed") != NULL)
1168   {
1169     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test seeding\n");
1170     cur_test_run.name = "test-rps-seed";
1171     cur_test_run.main_test = seed_cb;
1172     cur_test_run.eval_cb = no_eval;
1173   }
1174
1175   else if (strstr (argv[0], "_req_cancel") != NULL)
1176   {
1177     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test cancelling a request\n");
1178     cur_test_run.name = "test-rps-req-cancel";
1179     cur_test_run.main_test = req_cancel_cb;
1180   }
1181
1182   else if (strstr (argv[0], "profiler") != NULL)
1183   {
1184     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "This is the profiler\n");
1185     cur_test_run.name = "test-rps-profiler";
1186     mal_type = 3;
1187     cur_test_run.pre_test = profiler_pre;
1188     cur_test_run.main_test = profiler_cb;
1189     cur_test_run.reply_handle = profiler_reply_handle;
1190     cur_test_run.eval_cb = no_eval;
1191     cur_test_run.request_interval = 2;
1192     cur_test_run.num_requests = 50;
1193
1194     num_peers = 50;
1195
1196     (void) GNUNET_DISK_directory_remove ("/tmp/rps/");
1197     GNUNET_DISK_directory_create ("/tmp/rps/");
1198     timeout = GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90);
1199   }
1200
1201   rps_peers = GNUNET_new_array (num_peers, struct RPSPeer);
1202   rps_peer_ids = GNUNET_new_array (num_peers, struct GNUNET_PeerIdentity);
1203
1204   ok = 1;
1205   (void) GNUNET_TESTBED_test_run (cur_test_run.name,
1206                                   "test_rps.conf",
1207                                   num_peers,
1208                                   0, NULL, NULL,
1209                                   &run, NULL);
1210
1211   return cur_test_run.eval_cb();
1212 }
1213
1214 /* end of test_rps_multipeer.c */