uncrustify as demanded.
[oweals/gnunet.git] / src / core / test_core_api.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2009, 2010, 2015, 2016 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      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20 /**
21  * @file core/test_core_api.c
22  * @brief testcase for core_api.c
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_arm_service.h"
27 #include "gnunet_core_service.h"
28 #include "gnunet_util_lib.h"
29 #include "gnunet_transport_service.h"
30 #include "gnunet_transport_hello_service.h"
31 #include "gnunet_ats_service.h"
32
33 #define MTYPE 12345
34
35 struct PeerContext {
36   struct GNUNET_CONFIGURATION_Handle *cfg;
37   struct GNUNET_CORE_Handle *ch;
38   struct GNUNET_PeerIdentity id;
39   struct GNUNET_TRANSPORT_OfferHelloHandle *oh;
40   struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
41   struct GNUNET_ATS_ConnectivityHandle *ats;
42   struct GNUNET_ATS_ConnectivitySuggestHandle *ats_sh;
43   struct GNUNET_MessageHeader *hello;
44   int connect_status;
45   struct GNUNET_OS_Process *arm_proc;
46 };
47
48 static struct PeerContext p1;
49
50 static struct PeerContext p2;
51
52 static struct GNUNET_SCHEDULER_Task *err_task;
53
54 static int ok;
55
56 #define OKPP                                  \
57   do                                          \
58     {                                           \
59       ok++;                                     \
60       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,      \
61                  "Now at stage %u at %s:%u\n", \
62                  ok,                           \
63                  __FILE__,                     \
64                  __LINE__);                    \
65     } while (0)
66
67
68 static void
69 offer_hello_done(void *cls)
70 {
71   struct PeerContext *p = cls;
72
73   p->oh = NULL;
74 }
75
76
77 static void
78 process_hello(void *cls, const struct GNUNET_MessageHeader *message)
79 {
80   struct PeerContext *p = cls;
81
82   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
83              "Received (my) HELLO from transport service\n");
84   GNUNET_assert(message != NULL);
85   if ((p == &p1) && (NULL == p2.oh))
86     p2.oh =
87       GNUNET_TRANSPORT_offer_hello(p2.cfg, message, &offer_hello_done, &p2);
88   if ((p == &p2) && (NULL == p1.oh))
89     p1.oh =
90       GNUNET_TRANSPORT_offer_hello(p1.cfg, message, &offer_hello_done, &p1);
91 }
92
93
94 static void
95 terminate_peer(struct PeerContext *p)
96 {
97   if (NULL != p->ch)
98     {
99       GNUNET_CORE_disconnect(p->ch);
100       p->ch = NULL;
101     }
102   if (NULL != p->ghh)
103     {
104       GNUNET_TRANSPORT_hello_get_cancel(p->ghh);
105       p->ghh = NULL;
106     }
107   if (NULL != p->oh)
108     {
109       GNUNET_TRANSPORT_offer_hello_cancel(p->oh);
110       p->oh = NULL;
111     }
112   if (NULL != p->ats_sh)
113     {
114       GNUNET_ATS_connectivity_suggest_cancel(p->ats_sh);
115       p->ats_sh = NULL;
116     }
117   if (NULL != p->ats)
118     {
119       GNUNET_ATS_connectivity_done(p->ats);
120       p->ats = NULL;
121     }
122 }
123
124
125 static void
126 terminate_task(void *cls)
127 {
128   GNUNET_assert(ok == 6);
129   terminate_peer(&p1);
130   terminate_peer(&p2);
131   ok = 0;
132 }
133
134
135 static void
136 terminate_task_error(void *cls)
137 {
138   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "ENDING ANGRILY %u\n", ok);
139   GNUNET_break(0);
140   terminate_peer(&p1);
141   terminate_peer(&p2);
142   ok = 42;
143 }
144
145
146 static void *
147 connect_notify(void *cls,
148                const struct GNUNET_PeerIdentity *peer,
149                struct GNUNET_MQ_Handle *mq)
150 {
151   struct PeerContext *pc = cls;
152   struct GNUNET_MQ_Envelope *env;
153   struct GNUNET_MessageHeader *msg;
154
155   if (0 == memcmp(&pc->id, peer, sizeof(struct GNUNET_PeerIdentity)))
156     return (void *)peer;
157   GNUNET_assert(pc->connect_status == 0);
158   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
159              "Encrypted connection established to peer `%s'\n",
160              GNUNET_i2s(peer));
161   pc->connect_status = 1;
162   if (pc == &p1)
163     {
164       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
165                  "Asking core (1) for transmission to peer `%s'\n",
166                  GNUNET_i2s(&p2.id));
167       env = GNUNET_MQ_msg(msg, MTYPE);
168       /* enable corking for this test */
169       GNUNET_MQ_env_set_options(env,
170                                 GNUNET_MQ_PRIO_BEST_EFFORT |
171                                 GNUNET_MQ_PREF_CORK_ALLOWED);
172       /* now actually transmit message */
173       GNUNET_assert(ok == 4);
174       OKPP;
175       GNUNET_MQ_send(mq, env);
176     }
177   return (void *)peer;
178 }
179
180
181 static void
182 disconnect_notify(void *cls,
183                   const struct GNUNET_PeerIdentity *peer,
184                   void *internal_cls)
185 {
186   struct PeerContext *pc = cls;
187
188   if (0 == memcmp(&pc->id, peer, sizeof(struct GNUNET_PeerIdentity)))
189     return;
190   pc->connect_status = 0;
191   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
192              "Encrypted connection to `%s' cut\n",
193              GNUNET_i2s(peer));
194 }
195
196
197 static void
198 handle_test(void *cls, const struct GNUNET_MessageHeader *message)
199 {
200   const struct GNUNET_PeerIdentity *peer = cls;
201
202   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
203              "Receiving message from `%s'.\n",
204              GNUNET_i2s(peer));
205   GNUNET_assert(ok == 5);
206   OKPP;
207   GNUNET_SCHEDULER_cancel(err_task);
208   err_task = GNUNET_SCHEDULER_add_now(&terminate_task, NULL);
209 }
210
211
212 static void
213 init_notify(void *cls, const struct GNUNET_PeerIdentity *my_identity)
214 {
215   struct PeerContext *p = cls;
216   struct GNUNET_MQ_MessageHandler handlers[] =
217   { GNUNET_MQ_hd_fixed_size(test, MTYPE, struct GNUNET_MessageHeader, NULL),
218     GNUNET_MQ_handler_end() };
219
220   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
221              "Core connection to `%s' established\n",
222              GNUNET_i2s(my_identity));
223   p->id = *my_identity;
224   if (cls == &p1)
225     {
226       GNUNET_assert(ok == 2);
227       OKPP;
228       /* connect p2 */
229       p2.ch = GNUNET_CORE_connect(p2.cfg,
230                                   &p2,
231                                   &init_notify,
232                                   &connect_notify,
233                                   &disconnect_notify,
234                                   handlers);
235     }
236   else
237     {
238       GNUNET_assert(ok == 3);
239       OKPP;
240       GNUNET_assert(cls == &p2);
241       p1.ats_sh = GNUNET_ATS_connectivity_suggest(p1.ats, &p2.id, 1);
242     }
243 }
244
245
246 static void
247 setup_peer(struct PeerContext *p, const char *cfgname)
248 {
249   char *binary;
250
251   binary = GNUNET_OS_get_libexec_binary_path("gnunet-service-arm");
252   p->cfg = GNUNET_CONFIGURATION_create();
253   p->arm_proc = GNUNET_OS_start_process(GNUNET_YES,
254                                         GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
255                                         NULL,
256                                         NULL,
257                                         NULL,
258                                         binary,
259                                         "gnunet-service-arm",
260                                         "-c",
261                                         cfgname,
262                                         NULL);
263   GNUNET_assert(GNUNET_OK == GNUNET_CONFIGURATION_load(p->cfg, cfgname));
264   p->ats = GNUNET_ATS_connectivity_init(p->cfg);
265   GNUNET_assert(NULL != p->ats);
266   p->ghh = GNUNET_TRANSPORT_hello_get(p->cfg,
267                                       GNUNET_TRANSPORT_AC_ANY,
268                                       &process_hello,
269                                       p);
270   GNUNET_free(binary);
271 }
272
273
274 static void
275 run(void *cls,
276     char *const *args,
277     const char *cfgfile,
278     const struct GNUNET_CONFIGURATION_Handle *cfg)
279 {
280   struct GNUNET_MQ_MessageHandler handlers[] =
281   { GNUNET_MQ_hd_fixed_size(test, MTYPE, struct GNUNET_MessageHeader, NULL),
282     GNUNET_MQ_handler_end() };
283
284   GNUNET_assert(ok == 1);
285   OKPP;
286   setup_peer(&p1, "test_core_api_peer1.conf");
287   setup_peer(&p2, "test_core_api_peer2.conf");
288   err_task = GNUNET_SCHEDULER_add_delayed(
289     GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 300),
290     &terminate_task_error,
291     NULL);
292   p1.ch = GNUNET_CORE_connect(p1.cfg,
293                               &p1,
294                               &init_notify,
295                               &connect_notify,
296                               &disconnect_notify,
297                               handlers);
298 }
299
300
301 static void
302 stop_arm(struct PeerContext *p)
303 {
304   if (0 != GNUNET_OS_process_kill(p->arm_proc, GNUNET_TERM_SIG))
305     GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "kill");
306   if (GNUNET_OK != GNUNET_OS_process_wait(p->arm_proc))
307     GNUNET_log_strerror(GNUNET_ERROR_TYPE_WARNING, "waitpid");
308   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
309              "ARM process %u stopped\n",
310              GNUNET_OS_process_get_pid(p->arm_proc));
311   GNUNET_OS_process_destroy(p->arm_proc);
312   p->arm_proc = NULL;
313   GNUNET_CONFIGURATION_destroy(p->cfg);
314 }
315
316
317 int
318 main(int argc, char *argv1[])
319 {
320   char *const argv[] = { "test-core-api", "-c", "test_core_api_data.conf", NULL };
321   struct GNUNET_GETOPT_CommandLineOption options[] = { GNUNET_GETOPT_OPTION_END };
322
323   ok = 1;
324   GNUNET_log_setup("test-core-api", "WARNING", NULL);
325   GNUNET_PROGRAM_run((sizeof(argv) / sizeof(char *)) - 1,
326                      argv,
327                      "test-core-api",
328                      "nohelp",
329                      options,
330                      &run,
331                      &ok);
332   stop_arm(&p1);
333   stop_arm(&p2);
334   GNUNET_DISK_directory_remove("/tmp/test-gnunet-core-peer-1");
335   GNUNET_DISK_directory_remove("/tmp/test-gnunet-core-peer-2");
336
337   return ok;
338 }
339
340 /* end of test_core_api.c */