690c94aeaa1145512fb2ed2df14121f24ba9cd80
[oweals/gnunet.git] / src / psyc / test_psyc_api_join.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 psyc/test_psyc_api_join.c
23  * @brief Testbed test for the PSYC API.
24  * @author xrs
25  */
26
27 #include "platform.h"
28 #include "gnunet_crypto_lib.h"
29 #include "gnunet_common.h"
30 #include "gnunet_util_lib.h"
31 #include "gnunet_testbed_service.h"
32 #include "gnunet_psyc_util_lib.h"
33 #include "gnunet_psyc_service.h"
34 #include "psyc_test_lib.h"
35
36 static struct pctx PEERS[2];
37
38 static int pids;
39
40 static void
41 mst_stop_cb ()
42 {
43   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "master stopped\n");
44 }
45
46 static void
47 slv_part_cb ()
48 {
49   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "slave parted\n");
50 }
51
52 static void 
53 shutdown_task (void *cls)
54 {
55   if (NULL != timeout_task_id) {
56     GNUNET_SCHEDULER_cancel (timeout_task_id);
57     timeout_task_id = NULL;
58   }
59
60   for (int i=0;i<2;i++) {
61     GNUNET_free (PEERS[i].channel_pub_key);
62
63     if (NULL != PEERS[i].psyc)
64       if (0 == i) 
65         GNUNET_PSYC_master_stop (PEERS[i].psyc, GNUNET_NO, mst_stop_cb, NULL);
66       else 
67         GNUNET_PSYC_slave_part (PEERS[i].psyc, GNUNET_NO, slv_part_cb, NULL);
68   }
69
70   for (int i=0;i<MAX_TESTBED_OPS;i++)
71     if (NULL != op[i])
72       GNUNET_TESTBED_operation_done (op[i]);
73
74   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shut down!\n");
75 }
76
77 static void
78 timeout_task (void *cls)
79 {
80   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Timeout!\n");
81
82   timeout_task_id = NULL;
83
84   result = GNUNET_SYSERR;
85   GNUNET_SCHEDULER_shutdown ();
86 }
87
88 static void
89 mst_connect_cb ()
90 {
91   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "mst_connect_cb()\n");
92 }
93
94 static void
95 slv_connect_cb (void *cls, int result, uint64_t max_message_id)
96 {
97   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "slv_connect_cb()\n");
98 }
99
100 static void
101 join_decision_cb (void *cls,
102                   const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
103                   int is_admitted,
104                   const struct GNUNET_PSYC_Message *join_msg)
105 {
106   result = GNUNET_OK;
107   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
108               "Slave got join decision: %d\n", is_admitted);
109   GNUNET_SCHEDULER_shutdown ();
110 }
111
112 static void
113 join_request_cb ()
114 {
115   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "join_request_cb()\n");
116 }
117
118 static void
119 message_cb ()
120 {
121   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "message_cb()\n");
122 }
123
124 static void
125 message_part_cb ()
126 {
127   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "message_part_cb()\n");
128 }
129
130 static void
131 psyc_da ()
132 {
133   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "disconnect form PSYC service\n");
134 }
135
136 static void *
137 psyc_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) 
138 {
139   struct pctx *peer = (struct pctx*) cls;
140
141   // Case: master role
142   if (0 == peer->idx) {
143     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as master ...\n");
144
145     peer->psyc = (struct GNUNET_PSYC_Master *) 
146       GNUNET_PSYC_master_start (cfg,
147                                 peer->channel_key,
148                                 GNUNET_PSYC_CHANNEL_PRIVATE,
149                                 mst_connect_cb,
150                                 join_request_cb,
151                                 message_cb,
152                                 message_part_cb,
153                                 cls);
154     return peer->psyc;
155   }
156
157   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as slave ...\n");
158
159   struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
160   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo", "bar baz", 7);
161   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo_bar", "foo bar baz", 11);
162
163   struct GNUNET_PSYC_Message *
164     join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 40);
165
166   // THOUGHT: It's possible, that psyc slave is to fast and can not connect
167   // to master! ask tg and grothoff about message queueing
168   peer->psyc = (struct GNUNET_PSYC_Slave *)
169     GNUNET_PSYC_slave_join (cfg,
170                             peer->channel_pub_key,
171                             peer->id_key,
172                             GNUNET_PSYC_SLAVE_JOIN_NONE,
173                             peer->peer_id_master, 
174                             0,
175                             NULL,
176                             message_cb,
177                             message_part_cb,
178                             slv_connect_cb,
179                             join_decision_cb,
180                             cls,
181                             join_msg);
182
183   GNUNET_free (join_msg);
184   peer->channel = GNUNET_PSYC_slave_get_channel (peer->psyc);
185   GNUNET_PSYC_env_destroy (env);
186
187   return peer->psyc;
188 }
189
190 static void
191 service_connect (void *cls,
192                  struct GNUNET_TESTBED_Operation *op,
193                  void *ca_result,
194                  const char *emsg)
195 {
196   GNUNET_assert (NULL != ca_result);
197
198   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to the service\n");
199 }
200
201 static void 
202 connect_to_services (void *cls)
203 {
204   for (int i = 0; i < 2; i++)
205   {
206     PEERS[i].peer_id_master = PEERS[0].peer_id;
207
208     op[op_cnt++] = 
209       GNUNET_TESTBED_service_connect (NULL, PEERS[i].testbed_peer, "psyc", 
210                                       &service_connect, &PEERS[i], &psyc_ca, 
211                                       &psyc_da, &PEERS[i]);
212   }
213 }
214
215 static void
216 pinfo_cb (void *cls,
217           struct GNUNET_TESTBED_Operation *operation,
218           const struct GNUNET_TESTBED_PeerInformation *pinfo,
219           const char *emsg)
220 {
221   struct pctx *peer = (struct pctx*) cls;
222
223   peer->peer_id = pinfo->result.id;
224
225   pids++;
226   if (pids < 2)
227     return;
228   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting test\n");
229
230   GNUNET_SCHEDULER_add_now (&connect_to_services, NULL);
231 }
232
233 static void
234 testbed_master (void *cls,
235      struct GNUNET_TESTBED_RunHandle *h,
236      unsigned int num_peers,
237      struct GNUNET_TESTBED_Peer **p,
238      unsigned int links_succeeded,
239      unsigned int links_failed)
240 {
241   struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key = NULL;
242
243   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to testbed_master\n");
244
245   // Set up shutdown logic
246   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 
247   timeout_task_id = 
248     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 10),
249                                   &timeout_task, NULL);
250   GNUNET_assert (NULL != timeout_task_id);
251
252   channel_key = GNUNET_CRYPTO_eddsa_key_create ();
253   GNUNET_assert (NULL != channel_key);
254   
255   // Set up information contexts for peers
256   for (int i=0 ; i < 2 ; i++)
257   {
258     PEERS[i].idx = i;
259     PEERS[i].testbed_peer = p[i];
260
261     // Create "egos"
262     PEERS[i].id_key = GNUNET_CRYPTO_ecdsa_key_create ();
263
264     // Set up channel keys shared by master and slave
265     PEERS[i].channel_key = channel_key; 
266
267     PEERS[i].channel_pub_key = 
268       GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
269     // Get public key 
270     GNUNET_CRYPTO_eddsa_key_get_public (PEERS[i].channel_key, 
271                                         PEERS[i].channel_pub_key);
272     // Get peerinfo
273     op[op_cnt++] = 
274       GNUNET_TESTBED_peer_get_information (p[i], 
275                                            GNUNET_TESTBED_PIT_IDENTITY, 
276                                            pinfo_cb, &PEERS[i]);
277   }
278 }
279
280 int 
281 main (int argc, char *argv[])
282 {
283   int ret; 
284
285   ret = GNUNET_TESTBED_test_run ("test-psyc-api-join", "test_psyc.conf",
286                                  2, 0LL, NULL, NULL, 
287                                  &testbed_master, NULL);
288
289   if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
290     return 1;
291
292   return 0;
293 }
294
295 /* end of test_psyc_api_join.c */