-bringing copyright tags up to FSF standard
[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,
136                const struct GNUNET_SCHEDULER_TaskContext *tc)
137 {
138   unsigned int amount;
139   struct RPSPeer *peer = (struct RPSPeer *) cls;
140
141   GNUNET_assert (1 >= portion &&
142                  0 <  portion);
143                 
144   amount = portion * NUM_PEERS;
145
146   // TODO log
147
148   GNUNET_RPS_seed_ids (peer->rps_handle, amount, rps_peer_ids);
149 }
150
151
152 /**
153  * Get the id of peer i.
154  */
155   void
156 info_cb (void *cb_cls,
157          struct GNUNET_TESTBED_Operation *op,
158          const struct GNUNET_TESTBED_PeerInformation *pinfo,
159          const char *emsg)
160 {
161   unsigned int *i = (unsigned int *) cb_cls;
162
163   if (NULL == pinfo || NULL != emsg)
164   {
165     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Got Error: %s\n", emsg);
166     return;
167   }
168
169   rps_peer_ids[*i] = *(pinfo->result.id);
170
171   GNUNET_free (cb_cls);
172 }
173
174
175 /**
176  * Callback to be called when RPS service connect operation is completed
177  *
178  * @param cls the callback closure from functions generating an operation
179  * @param op the operation that has been finished
180  * @param ca_result the RPS service handle returned from rps_connect_adapter
181  * @param emsg error message in case the operation has failed; will be NULL if
182  *          operation has executed successfully.
183  */
184 static void
185 rps_connect_complete_cb (void *cls,
186                          struct GNUNET_TESTBED_Operation *op,
187                          void *ca_result,
188                          const char *emsg)
189 {
190   struct RPSPeer *peer = cls;
191   struct GNUNET_RPS_Handle *rps = ca_result;
192   struct GNUNET_RPS_Request_Handle *req_handle;
193
194   peer->rps_handle = rps;
195
196   GNUNET_assert (op == peer->op);
197   if (NULL != emsg)
198     {
199       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
200                   "Failed to connect to RPS service: %s\n",
201                   emsg);
202       ok = 1;
203       GNUNET_SCHEDULER_shutdown ();
204       return;
205     }
206   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Started client successfully\n");
207
208   req_handle = GNUNET_RPS_request_peers (rps, 1, handle_reply, NULL);
209   GNUNET_free (req_handle);
210
211   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
212                                 request_peers, peer);
213   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 10),
214                                 seed_peers, peer);
215   // TODO test seeding > GNUNET_SERVER_MAX_MESSAGE_SIZE peers
216 }
217
218
219 /**
220  * Adapter function called to establish a connection to
221  * the RPS service.
222  *
223  * @param cls closure
224  * @param cfg configuration of the peer to connect to; will be available until
225  *          GNUNET_TESTBED_operation_done() is called on the operation returned
226  *          from GNUNET_TESTBED_service_connect()
227  * @return service handle to return in 'op_result', NULL on error
228  */
229 static void *
230 rps_connect_adapter (void *cls,
231                      const struct GNUNET_CONFIGURATION_Handle *cfg)
232 {
233   return GNUNET_RPS_connect (cfg);
234 }
235
236
237 /**
238  * Adapter function called to destroy connection to
239  * RPS service.
240  *
241  * @param cls closure
242  * @param op_result service handle returned from the connect adapter
243  */
244 static void
245 rps_disconnect_adapter (void *cls,
246                         void *op_result)
247 {
248   struct GNUNET_RPS_Handle *h = op_result;
249   GNUNET_RPS_disconnect (h);
250 }
251
252
253 /**
254  * Actual "main" function for the testcase.
255  *
256  * @param cls closure
257  * @param h the run handle
258  * @param num_peers number of peers in 'peers'
259  * @param peers handle to peers run in the testbed
260  * @param links_succeeded the number of overlay link connection attempts that
261  *          succeeded
262  * @param links_failed the number of overlay link connection attempts that
263  *          failed
264  */
265 static void
266 run (void *cls,
267      struct GNUNET_TESTBED_RunHandle *h,
268      unsigned int num_peers,
269      struct GNUNET_TESTBED_Peer **peers,
270      unsigned int links_succeeded,
271      unsigned int links_failed)
272 {
273   unsigned int i;
274   unsigned int *tmp_i;
275
276   for ( i = 0 ; i < NUM_PEERS ; i++ )
277   {
278     tmp_i = GNUNET_new (unsigned int);
279     *tmp_i = i;
280
281     (void) GNUNET_TESTBED_peer_get_information (peers[i],
282                                                 GNUNET_TESTBED_PIT_IDENTITY,
283                                                 &info_cb, tmp_i);
284   }
285
286   GNUNET_assert (NUM_PEERS == num_peers);
287   for (i=0;i<num_peers;i++)
288     //rps_peers[i].peer_index = i;
289     rps_peers[i].op = GNUNET_TESTBED_service_connect (&rps_peers[i],
290                                                       peers[i],
291                                                       "rps",
292                                                       &rps_connect_complete_cb,
293                                                       &rps_peers[i],
294                                                       &rps_connect_adapter,
295                                                       &rps_disconnect_adapter,
296                                                       &rps_peers[i]);
297   GNUNET_SCHEDULER_add_delayed (TIMEOUT, &shutdown_task, NULL);
298 }
299
300
301 /**
302  * Entry point for the testcase, sets up the testbed.
303  *
304  * @param argc unused
305  * @param argv unused
306  * @return 0 on success
307  */
308 int
309 main (int argc, char *argv[])
310 {
311   ok = 1;
312   (void) GNUNET_TESTBED_test_run ("test-rps-multipeer",
313                                   "test_rps.conf",
314                                   NUM_PEERS,
315                                   0, NULL, NULL,
316                                   &run, NULL);
317   return ok;
318 }
319
320 /* end of test_rps_multipeer.c */