paragraph for gnunet devs that don't know how to use the web
[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 it
6  * under the terms of the GNU Affero General Public License as published
7  * by the Free Software Foundation, either version 3 of the License,
8  * or (at your 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  * Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 /**
20  * @file psyc/test_psyc_api_join.c
21  * @brief Testbed test for the PSYC API.
22  * @author xrs
23  */
24
25 /**
26  * Lessons Learned:
27  * - define topology in config
28  * - psyc slave join needs part to end (same with master)
29  * - GNUNET_SCHEDULER_add_delayed return value will outdate at call time
30  * - main can not contain GNUNET_log()
31  */
32
33 #include "platform.h"
34 #include "gnunet_crypto_lib.h"
35 #include "gnunet_common.h"
36 #include "gnunet_util_lib.h"
37 #include "gnunet_testbed_service.h"
38 #include "gnunet_psyc_util_lib.h"
39 #include "gnunet_psyc_service.h"
40 #include "psyc_test_lib.h"
41
42 static struct pctx PEERS[2];
43
44 static int pids;
45
46
47 static void 
48 shutdown_task (void *cls)
49 {
50   if (NULL != timeout_task_id) {
51     GNUNET_SCHEDULER_cancel (timeout_task_id);
52     timeout_task_id = NULL;
53   }
54
55   for (int i=0;i<2;i++) {
56     GNUNET_free (PEERS[i].channel_pub_key);
57
58     if (NULL != PEERS[i].psyc)
59     {
60       if (0 == i) 
61         GNUNET_PSYC_master_stop (PEERS[i].psyc, GNUNET_NO, NULL, NULL);
62       else 
63         GNUNET_PSYC_slave_part (PEERS[i].psyc, GNUNET_NO, NULL, NULL);
64     }
65   }
66
67   for (int i=0;i<MAX_TESTBED_OPS;i++)
68     if (NULL != op[i])
69       GNUNET_TESTBED_operation_done (op[i]);
70
71   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Shut down!\n");
72 }
73
74 static void
75 timeout_task (void *cls)
76 {
77   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Timeout!\n");
78
79   timeout_task_id = NULL;
80
81   result = GNUNET_SYSERR;
82   GNUNET_SCHEDULER_shutdown ();
83 }
84
85 static void
86 join_decision_cb (void *cls,
87                   const struct GNUNET_PSYC_JoinDecisionMessage *dcsn,
88                   int is_admitted,
89                   const struct GNUNET_PSYC_Message *join_msg)
90 {
91   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
92               "slave: got join decision: %s\n", 
93               (GNUNET_YES == is_admitted) ? "admitted":"rejected");
94
95   result = (GNUNET_YES == is_admitted) ? GNUNET_OK : GNUNET_SYSERR;
96
97   GNUNET_SCHEDULER_shutdown ();
98 }
99
100 static void
101 join_request_cb (void *cls,
102                  const struct GNUNET_PSYC_JoinRequestMessage *req,
103                  const struct GNUNET_CRYPTO_EcdsaPublicKey *slave_key,
104                  const struct GNUNET_PSYC_Message *join_msg,
105                  struct GNUNET_PSYC_JoinHandle *jh)
106 {
107   struct GNUNET_HashCode slave_key_hash;
108
109   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "master: got join request.\n");
110
111   GNUNET_CRYPTO_hash (slave_key, sizeof (*slave_key), &slave_key_hash);
112
113   GNUNET_PSYC_join_decision (jh, GNUNET_YES, 0, NULL, NULL);
114 }
115
116 static void
117 psyc_da ()
118 {
119   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "disconnect form PSYC service\n");
120 }
121
122 static void *
123 psyc_ca (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg) 
124 {
125   struct pctx *peer = (struct pctx*) cls;
126
127   // Case: master role
128   if (0 == peer->idx) {
129     GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as master ...\n");
130
131     peer->psyc = (struct GNUNET_PSYC_Master *) 
132       GNUNET_PSYC_master_start (cfg,
133                                 peer->channel_key,
134                                 GNUNET_PSYC_CHANNEL_PRIVATE,
135                                 NULL,
136                                 join_request_cb,
137                                 NULL,
138                                 NULL,
139                                 cls);
140     return peer->psyc;
141   }
142
143   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connecting to PSYC as slave ...\n");
144
145   struct GNUNET_PSYC_Environment *env = GNUNET_PSYC_env_create ();
146   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo", "bar baz", 7);
147   GNUNET_PSYC_env_add (env, GNUNET_PSYC_OP_ASSIGN, "_foo_bar", "foo bar baz", 11);
148
149   struct GNUNET_PSYC_Message *
150     join_msg = GNUNET_PSYC_message_create ("_request_join", env, "some data", 40);
151
152   peer->psyc = (struct GNUNET_PSYC_Slave *)
153     GNUNET_PSYC_slave_join (cfg,
154                             peer->channel_pub_key,
155                             peer->id_key,
156                             GNUNET_PSYC_SLAVE_JOIN_NONE,
157                             peer->peer_id_master, 
158                             0,
159                             NULL,
160                             NULL,
161                             NULL,
162                             NULL,
163                             join_decision_cb,
164                             cls,
165                             join_msg);
166
167   GNUNET_free (join_msg);
168   peer->channel = GNUNET_PSYC_slave_get_channel (peer->psyc);
169   GNUNET_PSYC_env_destroy (env);
170
171   return peer->psyc;
172 }
173
174 static void
175 service_connect (void *cls,
176                  struct GNUNET_TESTBED_Operation *op,
177                  void *ca_result,
178                  const char *emsg)
179 {
180   GNUNET_assert (NULL != ca_result);
181
182   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to the service\n");
183 }
184
185 static void 
186 connect_to_services (void *cls)
187 {
188   for (int i = 0; i < 2; i++)
189   {
190     PEERS[i].peer_id_master = PEERS[0].peer_id;
191
192     op[op_cnt++] = 
193       GNUNET_TESTBED_service_connect (NULL, PEERS[i].testbed_peer, "psyc", 
194                                       &service_connect, &PEERS[i], &psyc_ca, 
195                                       &psyc_da, &PEERS[i]);
196   }
197 }
198
199 static void
200 pinfo_cb (void *cls,
201           struct GNUNET_TESTBED_Operation *operation,
202           const struct GNUNET_TESTBED_PeerInformation *pinfo,
203           const char *emsg)
204 {
205   struct pctx *peer = (struct pctx*) cls;
206
207   peer->peer_id = pinfo->result.id;
208
209   pids++;
210   if (pids < 2)
211     return;
212   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Got all IDs, starting test\n");
213
214   GNUNET_SCHEDULER_add_now (&connect_to_services, NULL);
215 }
216
217 static void
218 testbed_master (void *cls,
219      struct GNUNET_TESTBED_RunHandle *h,
220      unsigned int num_peers,
221      struct GNUNET_TESTBED_Peer **p,
222      unsigned int links_succeeded,
223      unsigned int links_failed)
224 {
225   struct GNUNET_CRYPTO_EddsaPrivateKey *channel_key = NULL;
226
227   GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Connected to testbed_master\n");
228
229   // Set up shutdown logic
230   GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); 
231   timeout_task_id = 
232     GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 15),
233                                   &timeout_task, NULL);
234   GNUNET_assert (NULL != timeout_task_id);
235
236   // Set up channel key
237   channel_key = GNUNET_CRYPTO_eddsa_key_create ();
238   GNUNET_assert (NULL != channel_key);
239   
240   // Set up information contexts for peers
241   for (int i=0 ; i < 2 ; i++)
242   {
243     PEERS[i].idx = i;
244     PEERS[i].testbed_peer = p[i];
245
246     // Create "egos"
247     PEERS[i].id_key = GNUNET_CRYPTO_ecdsa_key_create ();
248
249     // Set up channel keys shared by master and slave
250     PEERS[i].channel_key = channel_key; 
251
252     PEERS[i].channel_pub_key = 
253       GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EddsaPublicKey));
254     // Get public key 
255     GNUNET_CRYPTO_eddsa_key_get_public (PEERS[i].channel_key, 
256                                         PEERS[i].channel_pub_key);
257     // Get peerinfo
258     op[op_cnt++] = 
259       GNUNET_TESTBED_peer_get_information (p[i], 
260                                            GNUNET_TESTBED_PIT_IDENTITY, 
261                                            pinfo_cb, &PEERS[i]);
262   }
263 }
264
265 int 
266 main (int argc, char *argv[])
267 {
268   int ret; 
269
270   ret = GNUNET_TESTBED_test_run ("test_psyc_api_join", "test_psyc.conf",
271                                  2, 0LL, NULL, NULL, 
272                                  &testbed_master, NULL);
273
274   if ( (GNUNET_OK != ret) || (GNUNET_OK != result) )
275     return 1;
276
277   return 0;
278 }
279
280 /* end of test_psyc_api_join.c */