baseline for test with malicious peers
[oweals/gnunet.git] / src / rps / test_rps_multipeer.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_testbed_service.h"
29 #include "gnunet_rps_service.h"
30 #include <time.h>
31
32
33 /**
34  * How many peers do we start?
35  */
36 #define NUM_PEERS 5
37
38 /**
39  * How long do we run the test?
40  */
41 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 60)
42
43
44 /**
45  * Portion of malicious peers
46  */
47 static double portion = .1;
48
49
50 /**
51  * Information we track for each peer.
52  */
53 struct RPSPeer
54 {
55   /**
56    * Handle for RPS connect operation.
57    */
58   struct GNUNET_TESTBED_Operation *op;
59
60   /**
61    * Handle to RPS service.
62    */
63   struct GNUNET_RPS_Handle *rps_handle;
64 };
65
66
67 /**
68  * Information for all the peers.
69  */
70 static struct RPSPeer rps_peers[NUM_PEERS];
71
72 /**
73  * IDs of the peers.
74  */
75 static struct GNUNET_PeerIdentity rps_peer_ids[NUM_PEERS];
76
77 /**
78  * Return value from 'main'.
79  */
80 static int ok;
81
82
83 /**
84  * Task run on timeout to shut everything down.
85  */
86 static void
87 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
88 {
89   unsigned int i;
90
91   for (i=0;i<NUM_PEERS;i++)
92     GNUNET_TESTBED_operation_done (rps_peers[i].op);
93   GNUNET_SCHEDULER_shutdown ();
94 }
95
96
97 /**
98  * Callback to call when network size estimate is updated.
99  *
100  * @param cls closure
101  * @param timestamp server timestamp
102  * @param estimate the value of the current network size estimate
103  * @param std_dev standard deviation (rounded down to nearest integer)
104  *                of the size estimation values seen
105  *
106  */
107 static void
108 handle_reply (void *cls, uint64_t n, const struct GNUNET_PeerIdentity *peers)
109 {
110   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got peer %s\n", GNUNET_i2s (peers));
111   
112   ok = 0;
113 }
114
115
116 /**
117  * (Randomly) request random peers.
118  */
119   void
120 request_peers (void *cls,
121                const struct GNUNET_SCHEDULER_TaskContext *tc)
122 {
123   struct RPSPeer *peer = (struct RPSPeer *) cls;
124   struct GNUNET_RPS_Request_Handle *req_handle;
125
126   req_handle = GNUNET_RPS_request_peers (peer->rps_handle, 1, handle_reply, NULL);
127   GNUNET_free (req_handle);
128 }
129
130
131 /**
132  * Seed peers.
133  */
134   void
135 seed_peers (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
136 {
137   unsigned int amount;
138   struct RPSPeer *peer = (struct RPSPeer *) cls;
139   unsigned int i;
140
141   GNUNET_assert (1 >= portion
142                  && 0 <  portion);
143                 
144   amount = round (portion * NUM_PEERS);
145
146   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding peers:\n");
147   for (i = 0 ; i < amount ; i++)
148     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Seeding %u. peer: %s\n",
149                 i,
150                 GNUNET_i2s (&rps_peer_ids[i]));
151
152   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
153 }
154
155
156 /**
157  * Get the id of peer i.
158  */
159   void
160 info_cb (void *cb_cls,
161          struct GNUNET_TESTBED_Operation *op,
162          const struct GNUNET_TESTBED_PeerInformation *pinfo,
163          const char *emsg)
164 {
165   unsigned int *i = (unsigned int *) cb_cls;
166
167   if (NULL == pinfo || NULL != emsg)
168   {
169     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
170     return;
171   }
172
173   rps_peer_ids[*i] = *(pinfo->result.id);
174
175   GNUNET_free (cb_cls);
176 }
177
178
179 /**
180  * Callback to be called when RPS service connect operation is completed
181  *
182  * @param cls the callback closure from functions generating an operation
183  * @param op the operation that has been finished
184  * @param ca_result the RPS service handle returned from rps_connect_adapter
185  * @param emsg error message in case the operation has failed; will be NULL if
186  *          operation has executed successfully.
187  */
188 static void
189 rps_connect_complete_cb (void *cls,
190                          struct GNUNET_TESTBED_Operation *op,
191                          void *ca_result,
192                          const char *emsg)
193 {
194   struct RPSPeer *peer = cls;
195   struct GNUNET_RPS_Handle *rps = ca_result;
196   struct GNUNET_RPS_Request_Handle *req_handle;
197
198   peer->rps_handle = rps;
199
200   GNUNET_assert (op == peer->op);
201   if (NULL != emsg)
202     {
203       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
204                   "Failed to connect to RPS service: %s\n",
205                   emsg);
206       ok = 1;
207       GNUNET_SCHEDULER_shutdown ();
208       return;
209     }
210   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
211
212   req_handle = GNUNET_RPS_request_peers (rps, 1, handle_reply, NULL);
213   GNUNET_free (req_handle);
214
215   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
216                                 request_peers, peer);
217   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
218                                 seed_peers, peer);
219   // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
220 }
221
222
223 /**
224  * Adapter function called to establish a connection to
225  * the RPS service.
226  *
227  * @param cls closure
228  * @param cfg configuration of the peer to connect to; will be available until
229  *          GNUNET_TESTBED_operation_done() is called on the operation returned
230  *          from GNUNET_TESTBED_service_connect()
231  * @return service handle to return in 'op_result', NULL on error
232  */
233 static void *
234 rps_connect_adapter (void *cls,
235                      const struct GNUNET_CONFIGURATION_Handle *cfg)
236 {
237   return GNUNET_RPS_connect (cfg);
238 }
239
240
241 /**
242  * Adapter function called to destroy connection to
243  * RPS service.
244  *
245  * @param cls closure
246  * @param op_result service handle returned from the connect adapter
247  */
248 static void
249 rps_disconnect_adapter (void *cls,
250                         void *op_result)
251 {
252   struct GNUNET_RPS_Handle *h = op_result;
253   GNUNET_RPS_disconnect (h);
254 }
255
256
257 /**
258  * Actual "main" function for the testcase.
259  *
260  * @param cls closure
261  * @param h the run handle
262  * @param num_peers number of peers in 'peers'
263  * @param peers handle to peers run in the testbed
264  * @param links_succeeded the number of overlay link connection attempts that
265  *          succeeded
266  * @param links_failed the number of overlay link connection attempts that
267  *          failed
268  */
269 static void
270 run (void *cls,
271      struct GNUNET_TESTBED_RunHandle *h,
272      unsigned int num_peers,
273      struct GNUNET_TESTBED_Peer **peers,
274      unsigned int links_succeeded,
275      unsigned int links_failed)
276 {
277   unsigned int i;
278   unsigned int *tmp_i;
279
280   for ( i = 0 ; i < NUM_PEERS ; i++ )
281   {
282     tmp_i = GNUNET_new (unsigned int);
283     *tmp_i = i;
284
285     (void) GNUNET_TESTBED_peer_get_information (peers[i],
286                                                 GNUNET_TESTBED_PIT_IDENTITY,
287                                                 &info_cb, tmp_i);
288   }
289
290   GNUNET_assert (NUM_PEERS == num_peers);
291   for (i=0;i<num_peers;i++)
292     //rps_peers[i].peer_index = i;
293     rps_peers[i].op = GNUNET_TESTBED_service_connect (&rps_peers[i],
294                                                       peers[i],
295                                                       "rps",
296                                                       &rps_connect_complete_cb,
297                                                       &rps_peers[i],
298                                                       &rps_connect_adapter,
299                                                       &rps_disconnect_adapter,
300                                                       &rps_peers[i]);
301   GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, NULL);
302 }
303
304
305 /**
306  * Entry point for the testcase, sets up the testbed.
307  *
308  * @param argc unused
309  * @param argv unused
310  * @return 0 on success
311  */
312 int
313 main (int argc, char *argv[])
314 {
315   ok = 1;
316   (void) GNUNET_TESTBED_test_run ("test-rps-multipeer",
317                                   "test_rps.conf",
318                                   NUM_PEERS,
319                                   0, NULL, NULL,
320                                   &run, NULL);
321   return ok;
322 }
323
324 /* end of test_rps_multipeer.c */