working on hostlist
[oweals/gnunet.git] / src / hostlist / test_gnunet_daemon_hostlist.c
1 /*
2      This file is part of GNUnet
3      (C) 2009 Christian Grothoff (and other contributing authors)
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 2, 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., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20 /**
21  * @file hostlist/test_gnunet_daemon_hostlist.c
22  * @brief test for gnunet_daemon_hostslist.c
23  * @author Christian Grothoff
24  */
25 #include "platform.h"
26 #include "gnunet_util_lib.h"
27 #include "gnunet_arm_service.h"
28 #include "gnunet_transport_service.h"
29
30 #define VERBOSE GNUNET_YES
31
32 #define START_ARM GNUNET_YES
33
34
35 /**
36  * How long until we give up on transmitting the message?
37  */
38 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 15)
39
40 static int ok;
41
42 static struct GNUNET_SCHEDULER_Handle *sched;
43
44 static GNUNET_SCHEDULER_TaskIdentifier timeout_task;
45     
46 struct PeerContext
47 {
48   struct GNUNET_CONFIGURATION_Handle *cfg;
49   struct GNUNET_TRANSPORT_Handle *th;
50   struct GNUNET_MessageHeader *hello;
51   struct GNUNET_ARM_Handle *arm;
52 #if START_ARM
53   pid_t arm_pid;
54 #endif
55 };
56
57 static struct PeerContext p1;
58
59 static struct PeerContext p2;
60
61
62
63 /**
64  * Timeout, give up.
65  */
66 static void
67 timeout_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
68 {
69   timeout_task = GNUNET_SCHEDULER_NO_TASK;
70   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
71               "Timeout trying to connect peers, test failed.\n");
72   GNUNET_TRANSPORT_disconnect (p1.th);
73   p1.th = NULL;
74   GNUNET_TRANSPORT_disconnect (p2.th);
75   p2.th = NULL;
76   GNUNET_SCHEDULER_shutdown (sched);
77 }
78
79
80 /**
81  * Function called to notify transport users that another
82  * peer connected to us.
83  *
84  * @param cls closure
85  * @param peer the peer that connected
86  * @param latency current latency of the connection
87  */
88 static void
89 notify_connect (void *cls,
90                 const struct GNUNET_PeerIdentity * peer,
91                 struct GNUNET_TIME_Relative latency)
92 {
93   if (peer == NULL)
94     return;
95   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
96               "Peers connected, shutting down.\n");
97   GNUNET_assert (ok == 4);
98   ok = 0;
99
100   GNUNET_SCHEDULER_cancel (sched,
101                            timeout_task);
102   GNUNET_TRANSPORT_disconnect (p1.th);
103   p1.th = NULL;
104   GNUNET_TRANSPORT_disconnect (p2.th);
105   p2.th = NULL;
106 }
107
108
109 static void
110 process_hello (void *cls,
111                struct GNUNET_TIME_Relative latency,
112                const struct GNUNET_PeerIdentity *peer,
113                const struct GNUNET_MessageHeader *message)
114 {
115   struct PeerContext *p = cls;
116
117   if (message == NULL)
118     return;
119   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
120               "Received HELLO, starting hostlist service.\n");
121   GNUNET_assert ( (ok >= 2) && (ok <= 3) );
122   ok++;
123   GNUNET_ARM_start_services (p->cfg, sched, "hostlist", NULL);
124 }
125
126
127 static void
128 setup_peer (struct PeerContext *p, const char *cfgname)
129 {
130   p->cfg = GNUNET_CONFIGURATION_create ();
131 #if START_ARM
132   p->arm_pid = GNUNET_OS_start_process ("gnunet-service-arm",
133                                         "gnunet-service-arm",
134 #if VERBOSE
135                                         "-L", "DEBUG",
136 #endif
137                                         "-c", cfgname, NULL);
138 #endif
139   GNUNET_assert (GNUNET_OK == GNUNET_CONFIGURATION_load (p->cfg, cfgname));
140   GNUNET_ARM_start_services (p->cfg, sched, "core", NULL);
141   p->th = GNUNET_TRANSPORT_connect (sched, p->cfg, p, NULL, 
142                                     &notify_connect, NULL);
143   GNUNET_assert (p->th != NULL);
144   GNUNET_TRANSPORT_get_hello (p->th, TIMEOUT, &process_hello, p);
145 }
146
147
148 static void
149 waitpid_task (void *cls, 
150               const struct GNUNET_SCHEDULER_TaskContext *tc)
151 {
152   struct PeerContext *p = cls;
153
154 #if START_ARM 
155   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
156               "Killing ARM process.\n");
157   if (0 != PLIBC_KILL (p->arm_pid, SIGTERM))
158     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
159   if (GNUNET_OS_process_wait(p->arm_pid) != GNUNET_OK)
160     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
161   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
162               "ARM process %u stopped\n", p->arm_pid);
163 #endif
164   GNUNET_CONFIGURATION_destroy (p->cfg);
165 }
166
167
168 static void
169 stop_cb (void *cls, 
170          int success)
171 {
172   struct PeerContext *p = cls;
173
174   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
175               success 
176               ? "ARM stopped core service\n" 
177               : "ARM failed to stop core service\n");
178   GNUNET_ARM_disconnect (p->arm);
179   p->arm = NULL;
180   /* make sure this runs after all other tasks are done */
181   GNUNET_SCHEDULER_add_delayed (sched,
182                                 GNUNET_TIME_UNIT_SECONDS,
183                                 &waitpid_task, p);
184 }
185
186
187 static void
188 stop_arm (struct PeerContext *p)
189 {
190   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
191               "Asking ARM to stop core service\n");
192   p->arm = GNUNET_ARM_connect (p->cfg, sched, NULL);
193   GNUNET_ARM_stop_service (p->arm, "core", GNUNET_TIME_UNIT_SECONDS,
194                            &stop_cb, p);
195 }
196
197
198 /**
199  * Try again to connect to transport service.
200  */
201 static void
202 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
203 {
204   stop_arm (&p1);
205   stop_arm (&p2);
206 }
207
208
209 static void
210 run (void *cls,
211      struct GNUNET_SCHEDULER_Handle *s,
212      char *const *args,
213      const char *cfgfile, 
214      const struct GNUNET_CONFIGURATION_Handle *cfg)
215 {
216   GNUNET_assert (ok == 1);
217   ok++;
218   sched = s;
219   timeout_task = GNUNET_SCHEDULER_add_delayed (sched,
220                                                GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
221                                                                               15),
222                                                &timeout_error,
223                                                NULL);
224   GNUNET_SCHEDULER_add_delayed (sched,
225                                 GNUNET_TIME_UNIT_FOREVER_REL,
226                                 &shutdown_task,
227                                 NULL);
228   setup_peer (&p1, "test_gnunet_daemon_hostlist_peer1.conf");
229   setup_peer (&p2, "test_gnunet_daemon_hostlist_peer2.conf");
230 }
231
232
233 static int
234 check ()
235 {
236   char *const argv[] = { "test-gnunet-daemon-hostlist",
237     "-c", "test_gnunet_daemon_hostlist_data.conf",
238 #if VERBOSE
239     "-L", "DEBUG",
240 #endif
241     NULL
242   };
243   struct GNUNET_GETOPT_CommandLineOption options[] = {
244     GNUNET_GETOPT_OPTION_END
245   };
246   ok = 1;
247   GNUNET_PROGRAM_run ((sizeof (argv) / sizeof (char *)) - 1,
248                       argv, "test-gnunet-daemon-hostlist",
249                       "nohelp", options, &run, &ok);
250   return ok;
251 }
252
253
254 int
255 main (int argc, char *argv[])
256 {
257   
258   int ret;
259
260   GNUNET_log_setup ("test-gnunet-daemon-hostlist",
261 #if VERBOSE
262                     "DEBUG",
263 #else
264                     "WARNING",
265 #endif
266                     NULL);
267   ret = check ();
268   return ret; 
269 }
270
271 /* end of test_gnunet_daemon_hostlist.c */