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