(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 #define PLUGIN libgnunet_plugin_transport_template
46
47 /**
48  * How long until we give up on transmitting the message?
49  */
50 #define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90)
51
52 /**
53  * How long until we give up on transmitting the message?
54  */
55 #define TEST_TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 20)
56
57 /**
58  * How long between recieve and send?
59  */
60 #define WAIT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 1)
61
62 /**
63  * Our public key.
64  */
65 /* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */
66
67 /**
68  * Our public key.
69  */
70 static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key;
71
72 /**
73  * Our identity.
74  */
75 static struct GNUNET_PeerIdentity my_identity;
76
77 /**
78  * Our private key.
79  */
80 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
81
82
83 /**
84  * Our scheduler.
85  */
86 struct GNUNET_SCHEDULER_Handle *sched;
87
88 /**
89  * Our statistics handle.
90  */
91 struct GNUNET_STATISTICS_Handle *stats;
92
93
94 /**
95  * Our configuration.
96  */
97 const struct GNUNET_CONFIGURATION_Handle *cfg;
98
99 /**
100  * Number of neighbours we'd like to have.
101  */
102 static uint32_t max_connect_per_transport;
103
104 /**
105  * Environment for this plugin.
106  */
107 static struct GNUNET_TRANSPORT_PluginEnvironment env;
108
109 /**
110  *handle for the api provided by this plugin
111  */
112 static struct GNUNET_TRANSPORT_PluginFunctions *api;
113
114 /**
115  * ID of the task controlling the testcase timeout
116  */
117 static GNUNET_SCHEDULER_TaskIdentifier ti_timeout;
118
119
120 static GNUNET_SCHEDULER_TaskIdentifier ti_send;
121
122 const struct GNUNET_PeerIdentity * p;
123
124 /**
125  * Did the test pass or fail?
126  */
127 static int fail;
128
129 /**
130  * Recieved message already returned to sender?
131  */
132 static int sent;
133
134 /**
135  * Shutdown testcase
136  */
137 static void
138 shutdown_clean ()
139 {
140   if (ti_send != GNUNET_SCHEDULER_NO_TASK)
141   {
142     GNUNET_SCHEDULER_cancel(sched,ti_send);
143     ti_send = GNUNET_SCHEDULER_NO_TASK;
144   }
145
146   if (ti_timeout != GNUNET_SCHEDULER_NO_TASK)
147   {
148     GNUNET_SCHEDULER_cancel(sched,ti_timeout);
149     ti_timeout = GNUNET_SCHEDULER_NO_TASK;
150   }
151
152   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unloading http plugin\n");
153   GNUNET_assert (NULL == GNUNET_PLUGIN_unload ("libgnunet_plugin_transport_http", api));
154
155   GNUNET_SCHEDULER_shutdown(sched);
156   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exiting testcase\n");
157   exit(fail);
158   return;
159 }
160
161 /**
162  * Continuation called after plugin send message
163  * @cls closure
164  * @target target
165  * @result GNUNET_OK or GNUNET_SYSERR
166  */
167 static void task_send_cont (void *cls,
168                             const struct GNUNET_PeerIdentity * target,
169                             int result)
170 {
171   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message was sent!\n");
172   fail = GNUNET_NO;
173   shutdown_clean();
174 }
175
176 /**
177  * Task sending recieved message back to peer
178  * @cls closure
179  * @tc task context
180  */
181 static void
182 task_send (void *cls,
183             const struct GNUNET_SCHEDULER_TaskContext *tc)
184 {
185   ti_timeout = GNUNET_SCHEDULER_NO_TASK;
186   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
187     return;
188
189   if (GNUNET_YES==sent)
190     return;
191
192   struct GNUNET_MessageHeader * msg = cls;
193   unsigned int len = ntohs(msg->size);
194   const char * msgc = (const char *) msg;
195
196   api->send(api->cls, p, msgc, len, 0, TIMEOUT, NULL,NULL, 0, GNUNET_NO, &task_send_cont, NULL);
197   sent = GNUNET_YES;
198
199 }
200
201 /**
202  * Recieves messages from plugin, in real world transport
203  */
204 static struct GNUNET_TIME_Relative
205 receive (void *cls,
206          const struct GNUNET_PeerIdentity * peer,
207          const struct GNUNET_MessageHeader * message,
208          uint32_t distance,
209          struct Session *session,
210          const char *sender_address,
211          uint16_t sender_address_len)
212 {
213   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase recieved new message from peer `%s' with type %u and length %u\n",  GNUNET_i2s(peer),ntohs(message->type),ntohs(message->size));
214
215   /* take recieved message and send it back to peer */
216   p = peer;
217   void * c = (void *) message;
218   ti_send =GNUNET_SCHEDULER_add_delayed (sched, WAIT_INTERVALL, &task_send, c);
219
220   return GNUNET_TIME_UNIT_ZERO;
221 }
222
223 void
224 notify_address (void *cls,
225                 const char *name,
226                 const void *addr,
227                 uint16_t addrlen,
228                 struct GNUNET_TIME_Relative expires)
229 {
230
231 }
232
233 /**
234  * Setup plugin environment
235  */
236 static void
237 setup_plugin_environment ()
238 {
239   env.cfg = cfg;
240   env.sched = sched;
241   env.stats = stats;
242   env.my_identity = &my_identity;
243   env.cls = &env;
244   env.receive = &receive;
245   env.notify_address = &notify_address;
246   env.max_connections = max_connect_per_transport;
247 }
248
249
250 /**
251  * Task shutting down testcase if it a timeout occurs
252  */
253 static void
254 task_timeout (void *cls,
255             const struct GNUNET_SCHEDULER_TaskContext *tc)
256 {
257   ti_timeout = GNUNET_SCHEDULER_NO_TASK;
258   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
259     return;
260
261   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
262   fail = GNUNET_YES;
263   shutdown_clean();
264   return;
265 }
266
267
268 /**
269  * Runs the test.
270  *
271  * @param cls closure
272  * @param s scheduler to use
273  * @param c configuration to use
274  */
275 static void
276 run (void *cls,
277      struct GNUNET_SCHEDULER_Handle *s,
278      char *const *args,
279      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
280 {
281   char * libname;
282   sched = s;
283   cfg = c;
284   char *keyfile;
285   unsigned long long tneigh;
286
287   /* parse configuration */
288   if ((GNUNET_OK !=
289        GNUNET_CONFIGURATION_get_value_number (c,
290                                               "TRANSPORT",
291                                               "NEIGHBOUR_LIMIT",
292                                               &tneigh)) ||
293       (GNUNET_OK !=
294        GNUNET_CONFIGURATION_get_value_filename (c,
295                                                 "GNUNETD",
296                                                 "HOSTKEY", &keyfile)))
297     {
298       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
299                   _
300                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
301       GNUNET_SCHEDULER_shutdown (s);
302       fail = 1;
303       return;
304     }
305   max_connect_per_transport = (uint32_t) tneigh;
306   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
307   GNUNET_free (keyfile);
308   if (my_private_key == NULL)
309     {
310       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
311                   _
312                   ("Transport service could not access hostkey.  Exiting.\n"));
313       GNUNET_SCHEDULER_shutdown (s);
314       fail = 1;
315       return;
316     }
317   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
318   GNUNET_CRYPTO_hash (&my_public_key,
319                       sizeof (my_public_key), &my_identity.hashPubKey);
320
321   /* load plugins... */
322   setup_plugin_environment ();
323   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading HTTP transport plugin `%s'\n"),"libgnunet_plugin_transport_http");
324   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
325   api = GNUNET_PLUGIN_load (libname, &env);
326   GNUNET_free (libname);
327   if (api == NULL)
328   {
329     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
330                 _("Failed to load transport plugin for http\n"));
331     fail = 1;
332     return;
333   }
334
335   ti_timeout = GNUNET_SCHEDULER_add_delayed (sched, TEST_TIMEOUT, &task_timeout, NULL);
336
337   /* testing plugin functionality */
338
339
340   /* testing finished, shutting down */
341   shutdown_clean();
342
343   fail = 0;
344   return;
345 }
346
347
348 /**
349  * The main function for the transport service.
350  *
351  * @param argc number of arguments from the command line
352  * @param argv command line arguments
353  * @return 0 ok, 1 on error
354  */
355 int
356 main (int argc, char *const *argv)
357 {
358
359   static struct GNUNET_GETOPT_CommandLineOption options[] = {
360     GNUNET_GETOPT_OPTION_END
361   };
362   int ret;
363   char *const argv_prog[] = {
364     "test_plugin_transport_http",
365     "-c",
366     "test_plugin_transport_data_http.conf",
367     "-L",
368 #if VERBOSE
369     "DEBUG",
370 #else
371     "WARNING",
372 #endif
373     NULL
374   };
375   GNUNET_log_setup ("test_plugin_transport_http",
376 #if VERBOSE
377                     "DEBUG",
378 #else
379                     "WARNING",
380 #endif
381                     NULL);
382
383   ret = (GNUNET_OK ==
384          GNUNET_PROGRAM_run (5,
385                              argv_prog,
386                              "test_plugin_transport_http",
387                              "testcase", options, &run, NULL)) ? GNUNET_NO : GNUNET_YES;
388
389     GNUNET_DISK_directory_remove ("/tmp/test_plugin_transport_http");
390
391   return fail;
392 }
393
394 /* end of test_plugin_transport_http.c */