first batch of license fixes (boring)
[oweals/gnunet.git] / src / hostlist / test_gnunet_daemon_hostlist_reconnect.c
1 /*
2      This file is part of GNUnet
3      Copyright (C) 2010, 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 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  * @file hostlist/test_gnunet_daemon_hostlist_reconnect.c
17  * @brief test for gnunet-daemon-hostslist.c; tries to re-start the peers
18  *        and connect a second time
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet_arm_service.h"
24 #include "gnunet_transport_core_service.h"
25 #include "gnunet_transport_hello_service.h"
26
27 /**
28  * How long until we give up on transmitting the message?
29  */
30 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 150)
31
32 static int ok;
33
34 static struct GNUNET_SCHEDULER_Task *timeout_task;
35
36 struct PeerContext
37 {
38   struct GNUNET_CONFIGURATION_Handle *cfg;
39   struct GNUNET_TRANSPORT_CoreHandle *th;
40   struct GNUNET_MessageHeader *hello;
41   struct GNUNET_TRANSPORT_HelloGetHandle *ghh;
42   struct GNUNET_OS_Process *arm_proc;
43 };
44
45 static struct PeerContext p1;
46
47 static struct PeerContext p2;
48
49
50 /**
51  * Timeout, give up.
52  */
53 static void
54 timeout_error (void *cls)
55 {
56   timeout_task = NULL;
57   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
58               "Timeout trying to connect peers, test failed.\n");
59   GNUNET_SCHEDULER_shutdown ();
60 }
61
62
63 /**
64  * Function called to notify transport users that another
65  * peer connected to us.
66  *
67  * @param cls closure
68  * @param peer the peer that connected
69  * @param mq message queue to send to @a peer
70  * @return NULL
71  */
72 static void *
73 notify_connect (void *cls,
74                 const struct GNUNET_PeerIdentity *peer,
75                 struct GNUNET_MQ_Handle *mq)
76 {
77   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
78               "Peers connected, shutting down.\n");
79   ok = 0;
80   GNUNET_SCHEDULER_shutdown ();
81   return NULL;
82 }
83
84
85 static void
86 process_hello (void *cls,
87                const struct GNUNET_MessageHeader *message)
88 {
89   struct PeerContext *p = cls;
90
91   GNUNET_TRANSPORT_hello_get_cancel (p->ghh);
92   p->ghh = NULL;
93   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
94               "Received HELLO, starting hostlist service.\n");
95 }
96
97
98 static void
99 setup_peer (struct PeerContext *p,
100             const char *cfgname)
101 {
102   char *binary;
103
104   binary = GNUNET_OS_get_libexec_binary_path ("gnunet-service-arm");
105   p->cfg = GNUNET_CONFIGURATION_create ();
106   p->arm_proc =
107     GNUNET_OS_start_process (GNUNET_YES,
108                              GNUNET_OS_INHERIT_STD_OUT_AND_ERR,
109                              NULL,
110                              NULL,
111                              NULL,
112                              binary,
113                              "gnunet-service-arm",
114                              "-c",
115                              cfgname,
116                              NULL);
117   GNUNET_assert (GNUNET_OK ==
118                  GNUNET_CONFIGURATION_load (p->cfg,
119                                             cfgname));
120   p->th = GNUNET_TRANSPORT_core_connect (p->cfg,
121                                          NULL,
122                                          NULL,
123                                          p,
124                                          &notify_connect,
125                                          NULL,
126                                          NULL);
127   GNUNET_assert (NULL != p->th);
128   p->ghh = GNUNET_TRANSPORT_hello_get (p->cfg,
129                                        GNUNET_TRANSPORT_AC_ANY,
130                                        &process_hello,
131                                        p);
132   GNUNET_free (binary);
133 }
134
135
136 static void
137 waitpid_task (void *cls)
138 {
139   struct PeerContext *p = cls;
140
141   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
142               "Killing ARM process.\n");
143   if (0 != GNUNET_OS_process_kill (p->arm_proc,
144                                    GNUNET_TERM_SIG))
145     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
146                          "kill");
147   if (GNUNET_OK !=
148       GNUNET_OS_process_wait (p->arm_proc))
149     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
150                          "waitpid");
151   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
152               "ARM process %u stopped\n",
153               GNUNET_OS_process_get_pid (p->arm_proc));
154   GNUNET_OS_process_destroy (p->arm_proc);
155   p->arm_proc = NULL;
156   GNUNET_CONFIGURATION_destroy (p->cfg);
157 }
158
159
160 static void
161 stop_arm (struct PeerContext *p)
162 {
163   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
164               "Asking ARM to stop core service\n");
165   GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS,
166                                 &waitpid_task,
167                                 p);
168 }
169
170
171 /**
172  * Try again to connect to transport service.
173  */
174 static void
175 shutdown_task (void *cls)
176 {
177   if (NULL != timeout_task)
178   {
179     GNUNET_SCHEDULER_cancel (timeout_task);
180     timeout_task = NULL;
181   }
182   if (NULL != p1.ghh)
183   {
184     GNUNET_TRANSPORT_hello_get_cancel (p1.ghh);
185     p1.ghh = NULL;
186   }
187   if (NULL != p1.th)
188   {
189     GNUNET_TRANSPORT_core_disconnect (p1.th);
190     p1.th = NULL;
191   }
192   if (NULL != p2.ghh)
193   {
194     GNUNET_TRANSPORT_hello_get_cancel (p2.ghh);
195     p2.ghh = NULL;
196   }
197   if (NULL != p2.th)
198   {
199     GNUNET_TRANSPORT_core_disconnect (p2.th);
200     p2.th = NULL;
201   }
202   stop_arm (&p1);
203   stop_arm (&p2);
204 }
205
206
207 static void
208 run (void *cls,
209      char *const *args,
210      const char *cfgfile,
211      const struct GNUNET_CONFIGURATION_Handle *cfg)
212 {
213   GNUNET_assert (ok == 1);
214   ok++;
215   timeout_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
216                                                &timeout_error,
217                                                NULL);
218   GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
219                                  NULL);
220   setup_peer (&p1,
221               "test_gnunet_daemon_hostlist_peer1.conf");
222   setup_peer (&p2,
223               "test_gnunet_daemon_hostlist_peer2.conf");
224 }
225
226
227 int
228 main (int argcx,
229       char *argvx[])
230 {
231   static char *const argv[] = {
232     "test-gnunet-daemon-hostlist",
233     "-c", "test_gnunet_daemon_hostlist_data.conf",
234     NULL
235   };
236   static struct GNUNET_GETOPT_CommandLineOption options[] = {
237     GNUNET_GETOPT_OPTION_END
238   };
239
240   GNUNET_DISK_purge_cfg_dir ("test_gnunet_daemon_hostlist_peer1.conf",
241                              "GNUNET_TEST_HOME");
242   GNUNET_DISK_purge_cfg_dir ("test_gnunet_daemon_hostlist_peer2.conf",
243                              "GNUNET_TEST_HOME");
244   GNUNET_DISK_purge_cfg_dir ("test_gnunet_daemon_hostlist_data.conf",
245                              "GNUNET_TEST_HOME");
246   GNUNET_log_setup ("test-gnunet-daemon-hostlist",
247                     "WARNING",
248                     NULL);
249   ok = 1;
250   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
251                       argv,
252                       "test-gnunet-daemon-hostlist",
253                       "nohelp",
254                       options,
255                       &run,
256                       &ok);
257   if (0 == ok)
258   {
259     FPRINTF (stderr, "%s",  ".");
260     /* now do it again */
261     ok = 1;
262     GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
263                         argv,
264                         "test-gnunet-daemon-hostlist",
265                         "nohelp",
266                         options,
267                         &run,
268                         &ok);
269     FPRINTF (stderr,
270              "%s",
271              ".\n");
272   }
273   GNUNET_DISK_purge_cfg_dir ("test_gnunet_daemon_hostlist_peer1.conf",
274                              "GNUNET_TEST_HOME");
275   GNUNET_DISK_purge_cfg_dir ("test_gnunet_daemon_hostlist_peer2.conf",
276                              "GNUNET_TEST_HOME");
277   GNUNET_DISK_purge_cfg_dir ("test_gnunet_daemon_hostlist_data.conf",
278                              "GNUNET_TEST_HOME");
279   return ok;
280 }
281
282 /* end of test_gnunet_daemon_hostlist_reconnect.c */