multicast: logging, test fix
[oweals/gnunet.git] / src / multicast / test_multicast_multipeer.c
1 /*
2  * This file is part of GNUnet
3  * Copyright (C) 2013 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 /**
22  * @file multicast/test_multicast_multipeers.c
23  * @brief Tests for the Multicast API with multiple peers.
24  * @author xrs
25  */
26
27 #include <inttypes.h>
28
29 #include "platform.h"
30 #include "gnunet_crypto_lib.h"
31 #include "gnunet_common.h"
32 #include "gnunet_util_lib.h"
33 #include "gnunet_testbed_service.h"
34 #include "gnunet_multicast_service.h"
35
36 #define NUM_PEERS 2
37
38 static struct GNUNET_TESTBED_Operation *op0;
39 static struct GNUNET_TESTBED_Operation *op1;
40 static struct GNUNET_TESTBED_Operation *pi_op0;
41 static struct GNUNET_TESTBED_Operation *pi_op1;
42
43 static struct GNUNET_TESTBED_Peer **peers;
44 const struct GNUNET_PeerIdentity *peer_id[2];
45
46 static struct GNUNET_SCHEDULER_Task *timeout_tid;
47
48 static struct GNUNET_MULTICAST_Origin *origin;
49 static struct GNUNET_MULTICAST_Member *member;
50
51 struct GNUNET_CRYPTO_EddsaPrivateKey *group_key;
52 struct GNUNET_CRYPTO_EddsaPublicKey group_pub_key;
53
54 struct GNUNET_CRYPTO_EcdsaPrivateKey *member_key;
55 struct GNUNET_CRYPTO_EcdsaPublicKey member_pub_key;
56
57
58 enum
59 {
60   TEST_INIT          = 0,
61   TEST_ORIGIN_START  = 1,
62   TEST_MEMBER_JOIN   = 2,
63 } test;
64
65
66 /**
67  * Global result for testcase.
68  */
69 static int result;
70
71
72 /**
73  * Function run on CTRL-C or shutdown (i.e. success/timeout/etc.).
74  * Cleans up.
75  */
76 static void
77 shutdown_task (void *cls)
78 {
79   if (NULL != op0)
80   {
81     GNUNET_TESTBED_operation_done (op0);
82     op0 = NULL;
83   }
84   if (NULL != op1)
85   {
86     GNUNET_TESTBED_operation_done (op1);
87     op1 = NULL;
88   }
89   if (NULL != pi_op0)
90   {
91     GNUNET_TESTBED_operation_done (pi_op0);
92     pi_op0 = NULL;
93   }
94   if (NULL != pi_op1)
95   {
96     GNUNET_TESTBED_operation_done (pi_op1);
97     pi_op1 = NULL;
98   }
99   if (NULL != timeout_tid)
100     {
101       GNUNET_SCHEDULER_cancel (timeout_tid);
102       timeout_tid = NULL;
103     }
104 }
105
106
107 static void
108 timeout_task (void *cls)
109 {
110   timeout_tid = NULL;
111   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
112               "Timeout!\n");
113   result = GNUNET_SYSERR;
114   GNUNET_SCHEDULER_shutdown ();
115 }
116
117
118 static void
119 member_join_request (void *cls,
120                      const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
121                      const struct GNUNET_MessageHeader *join_msg,
122                      struct GNUNET_MULTICAST_JoinHandle *jh)
123 {
124   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
125               "Member sent a join request.\n");
126
127 }
128
129
130 static void
131 member_join_decision (void *cls,
132                       int is_admitted,
133                       const struct GNUNET_PeerIdentity *peer,
134                       uint16_t relay_count,
135                       const struct GNUNET_PeerIdentity *relays,
136                       const struct GNUNET_MessageHeader *join_msg)
137 {
138   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
139               "Member received a decision from origin: %s\n", (GNUNET_YES == is_admitted)?"accepted":"rejected");
140
141   result = GNUNET_OK;
142   GNUNET_SCHEDULER_shutdown ();
143 }
144
145 static void
146 member_replay_frag ()
147 {
148   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
149               "member replay frag...\n");
150 }
151
152 static void
153 member_replay_msg ()
154 {
155   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
156               "member replay msg...\n");
157 }
158
159 static void
160 member_message ()
161 {
162   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
163               "member message...\n");
164 }
165
166 static void
167 origin_join_request (void *cls,
168                  const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
169                  const struct GNUNET_MessageHeader *join_msg,
170                  struct GNUNET_MULTICAST_JoinHandle *jh)
171 {
172   struct GNUNET_MessageHeader *join_resp;
173
174   uint8_t data_size = ntohs (join_msg->size);
175
176   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
177               "Dizzy: Mh, got a join request...\n");
178   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
179               "'%s'\n", (char *)&join_msg[1]);
180   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
181               "Dizzy: Oh, it's Bird! Let's get him in.\n");
182
183   char data[] = "Hi, Bird. Come in!";
184   data_size = strlen (data) + 1;
185   join_resp = GNUNET_malloc (sizeof (join_resp) + data_size);
186   join_resp->size = htons (sizeof (join_resp) + data_size);
187   join_resp->type = htons (123);
188   GNUNET_memcpy (&join_resp[1], data, data_size);
189
190   GNUNET_MULTICAST_join_decision (jh,
191                                   GNUNET_YES,
192                                   0,
193                                   NULL,
194                                   join_resp);
195
196   result = GNUNET_OK;
197 }
198
199 static void
200 origin_replay_frag (void *cls,
201                 const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
202                 uint64_t fragment_id,
203                 uint64_t flags,
204                 struct GNUNET_MULTICAST_ReplayHandle *rh)
205 {
206   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay fraq msg\n");
207 }
208
209 static void
210 origin_replay_msg (void *cls,
211                const struct GNUNET_CRYPTO_EcdsaPublicKey *member_pub_key,
212                uint64_t message_id,
213                uint64_t fragment_offset,
214                uint64_t flags,
215                struct GNUNET_MULTICAST_ReplayHandle *rh)
216 {
217
218   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin replay msg\n");
219 }
220
221 static void
222 origin_request (void *cls,
223             const struct GNUNET_MULTICAST_RequestHeader *req)
224 {
225   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin request msg\n");
226
227 }
228
229 static void
230 origin_message (void *cls,
231             const struct GNUNET_MULTICAST_MessageHeader *msg)
232 {
233   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "origin message msg\n");
234 }
235
236
237 static void
238 service_connect1 (void *cls,
239                   struct GNUNET_TESTBED_Operation *op,
240                   void *ca_result,
241                   const char *emsg)
242 {
243   member = ca_result;
244
245   if (NULL != member)
246     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to multicast service of member\n");
247   else
248     result = GNUNET_SYSERR;
249 }
250
251 static void
252 multicast_da1 (void *cls,
253                void * op_result)
254 {
255   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
256               "Member parting from multicast group\n");
257
258   GNUNET_MULTICAST_member_part (member, NULL, NULL);
259 }
260
261
262 static void *
263 multicast_ca1 (void *cls,
264                const struct GNUNET_CONFIGURATION_Handle *cfg)
265 {
266   struct GNUNET_MessageHeader *join_msg;
267
268   // Get members keys
269   member_key = GNUNET_CRYPTO_ecdsa_key_create ();
270   GNUNET_CRYPTO_ecdsa_key_get_public (member_key, &member_pub_key);
271
272   char data[] = "Whut's up, Dizzy!";
273   uint8_t data_size = strlen (data) + 1;
274   join_msg = GNUNET_malloc (sizeof (join_msg) + data_size);
275   join_msg->size = htons (sizeof (join_msg) + data_size);
276   join_msg->type = htons (123);
277   GNUNET_memcpy (&join_msg[1], data, data_size);
278
279   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
280               "Members tries to join multicast group\n");
281
282   return GNUNET_MULTICAST_member_join (cfg,
283                                        &group_pub_key,
284                                        member_key,
285                                        peer_id[0],
286                                        0,
287                                        NULL,
288                                        join_msg, /* join message */
289                                        member_join_request,
290                                        member_join_decision,
291                                        member_replay_frag,
292                                        member_replay_msg,
293                                        member_message,
294                                        NULL);
295 }
296
297
298 static void
299 peer_information_cb (void *cls,
300                      struct GNUNET_TESTBED_Operation *op,
301                      const struct GNUNET_TESTBED_PeerInformation *pinfo,
302                      const char *emsg)
303 {
304   int i = (int) (long) cls;
305
306   if (NULL == pinfo) {
307     result = GNUNET_SYSERR;
308     GNUNET_SCHEDULER_shutdown ();
309   }
310
311   peer_id[i] = pinfo->result.id;
312
313   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
314               "Got peer information of %s (%s)\n", (0==i)?"origin":"member" ,GNUNET_i2s(pinfo->result.id));
315
316   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
317               "Create member peer\n");
318
319   if (0 == i) {
320   /* connect to multicast service of member */
321   op1 = GNUNET_TESTBED_service_connect (NULL,                    /* Closure for operation */
322                                         peers[1],                /* The peer whose service to connect to */
323                                         "multicast",             /* The name of the service */
324                                         service_connect1,   /* callback to call after a handle to service
325                                                                is opened */
326                                         NULL,                    /* closure for the above callback */
327                                         multicast_ca1,      /* callback to call with peer's configuration;
328                                                                this should open the needed service connection */
329                                         multicast_da1,     /* callback to be called when closing the
330                                                               opened service connection */
331                                         NULL);                   /* closure for the above two callbacks */
332   }
333 }
334
335 /**
336  * Test logic of peer "0" being origin starts here.
337  *
338  * @param cls closure, for the example: NULL
339  * @param op should be equal to "dht_op"
340  * @param ca_result result of the connect operation, the
341  *        connection to the DHT service
342  * @param emsg error message, if testbed somehow failed to
343  *        connect to the DHT.
344  */
345 static void
346 service_connect0 (void *cls,
347                   struct GNUNET_TESTBED_Operation *op,
348                   void *ca_result,
349                   const char *emsg)
350 {
351   origin = ca_result;
352
353   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
354               "Connected to multicast service of origin\n");
355
356   // Get GNUnet identity of origin
357   pi_op0 = GNUNET_TESTBED_peer_get_information (peers[0],
358                                                GNUNET_TESTBED_PIT_IDENTITY,
359                                                peer_information_cb,
360                                                (void *) 0);
361   // Get GNUnet identity of member
362   pi_op1 = GNUNET_TESTBED_peer_get_information (peers[1],
363                                                GNUNET_TESTBED_PIT_IDENTITY,
364                                                peer_information_cb,
365                                                (void *) 1);
366
367   /* Connection to service successful. Here we'd usually do something with
368    * the service. */
369   result = GNUNET_OK;
370   //GNUNET_SCHEDULER_shutdown (); /* Also kills the testbed */
371 }
372
373
374
375 /**
376  * Function run when service multicast has started and is providing us
377  * with a configuration file.
378  */
379 static void *
380 multicast_ca0 (void *cls,
381                const struct GNUNET_CONFIGURATION_Handle *cfg)
382 {
383   group_key = GNUNET_CRYPTO_eddsa_key_create ();
384   GNUNET_CRYPTO_eddsa_key_get_public (group_key, &group_pub_key);
385
386   return GNUNET_MULTICAST_origin_start (cfg,
387                                         group_key,
388                                         0,
389                                         origin_join_request,
390                                         origin_replay_frag,
391                                         origin_replay_msg,
392                                         origin_request,
393                                         origin_message,
394                                         NULL);
395 }
396
397 static void
398 multicast_da0 (void *cls,
399                void *op_result)
400 {
401   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
402               "Origin closes multicast group\n");
403
404   GNUNET_MULTICAST_origin_stop (origin, NULL, NULL);
405 }
406
407
408 /**
409  * Main function inovked from TESTBED once all of the
410  * peers are up and running.  This one then connects
411  * just to the multicast service of peer 0 and 1.
412  * Peer 0 is going to be origin.
413  * Peer 1 is going to be one member.
414  * Origin will start a multicast group and the member will try to join it.
415  * After that we execute some multicast test.
416  *
417  * @param cls closure
418  * @param h the run handle
419  * @param peers started peers for the test
420  * @param num_peers size of the 'peers' array
421  * @param links_succeeded number of links between peers that were created
422  * @param links_failed number of links testbed was unable to establish
423  */
424 static void
425 testbed_master (void *cls,
426      struct GNUNET_TESTBED_RunHandle *h,
427      unsigned int num_peers,
428      struct GNUNET_TESTBED_Peer **p,
429      unsigned int links_succeeded,
430      unsigned int links_failed)
431 {
432   /* Testbed is ready with peers running and connected in a pre-defined overlay
433      topology (FIXME)  */
434   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
435               "Connected to testbed_master()\n");
436
437   peers = p;
438
439   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
440               "Create origin peer\n");
441   op0 = GNUNET_TESTBED_service_connect (NULL,                    /* Closure for operation */
442                                         peers[0],                /* The peer whose service to connect to */
443                                         "multicast",             /* The name of the service */
444                                         service_connect0,   /* callback to call after a handle to service
445                                                                is opened */
446                                         NULL,                    /* closure for the above callback */
447                                         multicast_ca0,      /* callback to call with peer's configuration;
448                                                                this should open the needed service connection */
449                                         multicast_da0,     /* callback to be called when closing the
450                                                               opened service connection */
451                                         NULL);                   /* closure for the above two callbacks */
452
453   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); /* Schedule a new task on shutdown */
454
455   /* Schedule the shutdown task with a delay of a few Seconds */
456   timeout_tid = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 40),
457                                               &timeout_task, NULL);
458 }
459
460
461 int
462 main (int argc, char *argv[])
463 {
464   int ret;
465
466   result = GNUNET_SYSERR;
467   ret = GNUNET_TESTBED_test_run
468       ("test-multicast-multipeer",  /* test case name */
469        "test_multicast.conf", /* template configuration */
470        NUM_PEERS,       /* number of peers to start */
471        0LL, /* Event mask - set to 0 for no event notifications */
472        NULL, /* Controller event callback */
473        NULL, /* Closure for controller event callback */
474        testbed_master, /* continuation callback to be called when testbed setup is complete */
475        NULL); /* Closure for the test_master callback */
476   if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
477     return 1;
478   return 0;
479 }
480
481 /* end of test_multicast_multipeer.c */