(no commit message)
[oweals/gnunet.git] / src / transport / test_plugin_transport_http.c
1 /*
2      This file is part of GNUnet.
3      (C) 2010 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 transport/test_plugin_transport_http.c
22  * @brief testcase for plugin_transport_http.c
23  * @author Matthias Wachs
24  */
25
26 #include "platform.h"
27 #include "gnunet_constants.h"
28 #include "gnunet_getopt_lib.h"
29 #include "gnunet_hello_lib.h"
30 #include "gnunet_os_lib.h"
31 #include "gnunet_peerinfo_service.h"
32 #include "gnunet_plugin_lib.h"
33 #include "gnunet_protocols.h"
34 #include "gnunet_program_lib.h"
35 #include "gnunet_signatures.h"
36 #include "gnunet_service_lib.h"
37 #include "plugin_transport.h"
38 #include "gnunet_statistics_service.h"
39 #include "transport.h"
40 #include <curl/curl.h>
41
42 #define VERBOSE GNUNET_YES
43 #define DEBUG GNUNET_YES
44
45 /**
46  * How long until we give up on transmitting the message?
47  */
48 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
49
50 /**
51  * How long until we give up on transmitting the message?
52  */
53 #define STAT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
54
55 /**
56  * Our public key.
57  */
58 /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */
59
60 /**
61  * Our identity.
62  */
63 static struct GNUNET_PeerIdentity my_identity;
64
65 /**
66  * Our private key.
67  */
68 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
69
70 /**
71  * Our scheduler.
72  */
73 struct GNUNET_SCHEDULER_Handle *sched;
74
75 /**
76  * Our statistics handle.
77  */
78 struct GNUNET_STATISTICS_Handle *stats;
79
80
81 /**
82  * Our configuration.
83  */
84 const struct GNUNET_CONFIGURATION_Handle *cfg;
85
86 /**
87  * Number of neighbours we'd like to have.
88  */
89 static uint32_t max_connect_per_transport;
90
91 /**
92  * Environment for this plugin.
93  */
94 static struct GNUNET_TRANSPORT_PluginEnvironment env;
95
96 /**
97  *handle for the api provided by this plugin
98  */
99 static struct GNUNET_TRANSPORT_PluginFunctions *api;
100
101 /**
102  * Did the test pass or fail?
103  */
104 static int fail;
105
106 pid_t pid;
107
108 /**
109  * ID of the task controlling the locking between two hostlist tests
110  */
111 static GNUNET_SCHEDULER_TaskIdentifier ti_check_stat;
112
113 static unsigned int timeout_count;
114
115 /**
116  * Initialize Environment for this plugin
117  */
118 static struct GNUNET_TIME_Relative
119 receive (void *cls,
120          const struct GNUNET_PeerIdentity * peer,
121          const struct GNUNET_MessageHeader * message,
122          uint32_t distance,
123          struct Session *session,
124          const char *sender_address,
125          uint16_t sender_address_len)
126 {
127   /* do nothing */
128   return GNUNET_TIME_UNIT_ZERO;
129 }
130
131 void
132 notify_address (void *cls,
133                 const char *name,
134                 const void *addr,
135                 uint16_t addrlen, 
136                 struct GNUNET_TIME_Relative expires)
137 {
138 }
139
140 /**
141  * Simple example test that invokes
142  * the check_address function of the plugin.
143  */
144 /* FIXME: won't work on IPv6 enabled systems where IPv4 mapping
145  * isn't enabled (eg. FreeBSD > 4)
146  */
147 static void
148 shutdown_clean ()
149 {
150   GNUNET_assert (NULL ==
151                  GNUNET_PLUGIN_unload ("libgnunet_plugin_transport_http",
152                                        api));
153   if (my_private_key != NULL)
154     GNUNET_CRYPTO_rsa_key_free (my_private_key);
155
156   if (ti_check_stat != GNUNET_SCHEDULER_NO_TASK)
157     GNUNET_SCHEDULER_cancel(sched, ti_check_stat);
158   GNUNET_SCHEDULER_shutdown(sched);
159   return;
160 }
161
162 static void
163 setup_plugin_environment ()
164 {
165   env.cfg = cfg;
166   env.sched = sched;
167   env.stats = stats;
168   env.my_identity = &my_identity;
169   env.cls = &env;
170   env.receive = &receive;
171   env.notify_address = &notify_address;
172   env.max_connections = max_connect_per_transport;
173 }
174
175 static int
176 process_stat (void *cls,
177               const char *subsystem,
178               const char *name,
179               uint64_t value,
180               int is_persistent)
181 {
182   if (value==1)
183     {
184     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown, plugin failed \n");
185     fail = GNUNET_YES;
186     shutdown_clean();
187     return GNUNET_YES;
188     }
189   if (value==2)
190     {
191     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown, plugin not failed \n");
192     shutdown_clean();
193     return GNUNET_YES;
194     }
195   return GNUNET_YES;
196 }
197
198
199 /**
200  * Task that checks if we should try to download a hostlist.
201  * If so, we initiate the download, otherwise we schedule
202  * this task again for a later time.
203  */
204 static void
205 task_check_stat (void *cls,
206             const struct GNUNET_SCHEDULER_TaskContext *tc)
207 {
208
209   ti_check_stat = GNUNET_SCHEDULER_NO_TASK;
210   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
211     return;
212
213   if ( timeout_count > 10 )
214   {
215     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n",  timeout_count);
216     fail = GNUNET_YES;
217     shutdown_clean();
218     return;
219   }
220   timeout_count++;
221
222   GNUNET_STATISTICS_get (stats,
223                          "http-transport",
224                          gettext_noop("shutdown"),
225                          GNUNET_TIME_UNIT_MINUTES,
226                          NULL,
227                          &process_stat,
228                          NULL);
229
230   ti_check_stat = GNUNET_SCHEDULER_add_delayed (sched, STAT_INTERVALL, &task_check_stat, NULL);
231   return;
232 }
233
234 /**
235  * Runs the test.
236  *
237  * @param cls closure
238  * @param s scheduler to use
239  * @param c configuration to use
240  */
241 static void
242 run (void *cls,
243      struct GNUNET_SCHEDULER_Handle *s,
244      char *const *args,
245      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
246 {
247   unsigned long long tneigh;
248   char *keyfile;
249   char *libname;
250
251   sched = s;
252   cfg = c;
253
254   /* parse configuration */
255   if ((GNUNET_OK !=
256        GNUNET_CONFIGURATION_get_value_number (c,
257                                               "TRANSPORT",
258                                               "NEIGHBOUR_LIMIT",
259                                               &tneigh)) ||
260       (GNUNET_OK !=
261        GNUNET_CONFIGURATION_get_value_filename (c,
262                                                 "GNUNETD",
263                                                 "HOSTKEY", &keyfile)))
264     {
265       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
266                   _("Transport service is lacking key configuration settings.  Exiting.\n"));
267       GNUNET_SCHEDULER_shutdown (s);
268       return;
269     }
270
271   pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-statistics",
272                                  "gnunet-service-statistics",
273                                  "-L", "DEBUG",
274                                  "-c", "test_plugin_transport_data_http.conf", NULL);
275
276
277   if ( pid == -1)
278   {
279     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
280                      _("Failed to start service for `%s' http transport plugin test.\n"),
281                      "statistics");
282     GNUNET_SCHEDULER_shutdown (s);
283     return;
284   }
285
286   stats = GNUNET_STATISTICS_create (sched, "http-transport", cfg);
287   env.stats = stats;
288   /*
289   max_connect_per_transport = (uint32_t) tneigh;
290   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
291   GNUNET_free (keyfile);
292
293   if (my_private_key == NULL)
294     {
295       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
296                   _
297                   ("Transport service could not access hostkey.  Exiting.\n"));
298       GNUNET_SCHEDULER_shutdown (s);
299       return;
300     }
301   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
302   GNUNET_CRYPTO_hash (&my_public_key,
303                       sizeof (my_public_key), &my_identity.hashPubKey);
304   */
305   /* load plugins... */
306   setup_plugin_environment ();
307
308   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
309
310   api = GNUNET_PLUGIN_load (libname, &env);
311   if (api != NULL )
312   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
313               "Loading http transport plugin `%s' was successful\n",libname);
314
315   GNUNET_free (libname);
316   if (api == NULL)
317     {
318       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
319                   _("Failed to load http transport plugin\n"));
320       fail = GNUNET_YES;
321       shutdown_clean ();
322       return;
323
324     }
325   fail = GNUNET_NO;
326
327   char * test_message  = "Hello World!";
328   size_t bs = 0;
329   size_t size = strlen(test_message) +1;
330
331   /* Testing to send */
332   bs = api->send(NULL, &my_identity,test_message,size,0, TIMEOUT, NULL, NULL, 0, GNUNET_NO, NULL, NULL);
333   GNUNET_assert ( bs == size);
334
335   /* check statistics */
336   ti_check_stat = GNUNET_SCHEDULER_add_now(sched, &task_check_stat, NULL);
337
338   return;
339 }
340
341
342 /**
343  * The main function for the transport service.
344  *
345  * @param argc number of arguments from the command line
346  * @param argv command line arguments
347  * @return 0 ok, 1 on error
348  */
349 int
350 main (int argc, char *const *argv)
351 {
352   static struct GNUNET_GETOPT_CommandLineOption options[] = {
353     GNUNET_GETOPT_OPTION_END
354   };
355   int ret;
356   char *const argv_prog[] = {
357     "test_plugin_transport_http",
358     "-c",
359     "test_plugin_transport_data_http.conf",
360     "-L",
361 #if VERBOSE
362     "DEBUG",
363 #else
364     "WARNING",
365 #endif
366     NULL
367   };
368   GNUNET_log_setup ("test_plugin_transport_http",
369 #if VERBOSE
370                     "DEBUG",
371 #else
372                     "WARNING",
373 #endif
374                     NULL);
375   fail = GNUNET_YES;
376   ret = (GNUNET_OK ==
377          GNUNET_PROGRAM_run (5,
378                              argv_prog,
379                              "test_plugin_transport_http",
380                              "testcase", options, &run, NULL)) ? fail : 1;
381   GNUNET_DISK_directory_remove ("/tmp/test_plugin_transport_http");
382
383   if (0 != PLIBC_KILL (pid, SIGTERM))
384   {
385     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "kill");
386     fail = 1;
387   }
388   return fail;
389 }
390
391 /* end of test_plugin_transport_http.c */