(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, 5)
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   /* FIXME: */ fail = GNUNET_NO;
157   return;
158 }
159
160 /**
161  * Continuation called after plugin send message
162  * @cls closure
163  * @target target
164  * @result GNUNET_OK or GNUNET_SYSERR
165  */
166 static void task_send_cont (void *cls,
167                             const struct GNUNET_PeerIdentity * target,
168                             int result)
169 {
170   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message was sent!\n");
171   fail = GNUNET_NO;
172   shutdown_clean();
173 }
174
175 /**
176  * Task sending recieved message back to peer
177  * @cls closure
178  * @tc task context
179  */
180 static void
181 task_send (void *cls,
182             const struct GNUNET_SCHEDULER_TaskContext *tc)
183 {
184   ti_timeout = GNUNET_SCHEDULER_NO_TASK;
185   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
186     return;
187
188   if (GNUNET_YES==sent)
189     return;
190
191   struct GNUNET_MessageHeader * msg = cls;
192   unsigned int len = ntohs(msg->size);
193   const char * msgc = (const char *) msg;
194
195   api->send(api->cls, p, msgc, len, 0, TIMEOUT, NULL,NULL, 0, GNUNET_NO, &task_send_cont, NULL);
196   sent = GNUNET_YES;
197
198 }
199
200 /**
201  * Recieves messages from plugin, in real world transport
202  */
203 static struct GNUNET_TIME_Relative
204 receive (void *cls,
205          const struct GNUNET_PeerIdentity * peer,
206          const struct GNUNET_MessageHeader * message,
207          uint32_t distance,
208          struct Session *session,
209          const char *sender_address,
210          uint16_t sender_address_len)
211 {
212   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));
213
214   /* take recieved message and send it back to peer */
215   p = peer;
216   void * c = (void *) message;
217   ti_send =GNUNET_SCHEDULER_add_delayed (sched, WAIT_INTERVALL, &task_send, c);
218
219   return GNUNET_TIME_UNIT_ZERO;
220 }
221
222 void
223 notify_address (void *cls,
224                 const char *name,
225                 const void *addr,
226                 uint16_t addrlen,
227                 struct GNUNET_TIME_Relative expires)
228 {
229
230 }
231
232 /**
233  * Setup plugin environment
234  */
235 static void
236 setup_plugin_environment ()
237 {
238   env.cfg = cfg;
239   env.sched = sched;
240   env.stats = stats;
241   env.my_identity = &my_identity;
242   env.cls = &env;
243   env.receive = &receive;
244   env.notify_address = &notify_address;
245   env.max_connections = max_connect_per_transport;
246 }
247
248
249 /**
250  * Task shutting down testcase if it a timeout occurs
251  */
252 static void
253 task_timeout (void *cls,
254             const struct GNUNET_SCHEDULER_TaskContext *tc)
255 {
256   ti_timeout = GNUNET_SCHEDULER_NO_TASK;
257   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
258     return;
259
260   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n");
261   fail = GNUNET_YES;
262   shutdown_clean();
263   return;
264 }
265
266 /**
267  * Runs the test.
268  *
269  * @param cls closure
270  * @param s scheduler to use
271  * @param c configuration to use
272  */
273 static void
274 run (void *cls,
275      struct GNUNET_SCHEDULER_Handle *s,
276      char *const *args,
277      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
278 {
279   char * libname;
280   sched = s;
281   cfg = c;
282   char *keyfile;
283   unsigned long long tneigh;
284
285   /* parse configuration */
286   if ((GNUNET_OK !=
287        GNUNET_CONFIGURATION_get_value_number (c,
288                                               "TRANSPORT",
289                                               "NEIGHBOUR_LIMIT",
290                                               &tneigh)) ||
291       (GNUNET_OK !=
292        GNUNET_CONFIGURATION_get_value_filename (c,
293                                                 "GNUNETD",
294                                                 "HOSTKEY", &keyfile)))
295     {
296       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
297                   _
298                   ("Transport service is lacking key configuration settings.  Exiting.\n"));
299       GNUNET_SCHEDULER_shutdown (s);
300       return;
301     }
302   max_connect_per_transport = (uint32_t) tneigh;
303   my_private_key = GNUNET_CRYPTO_rsa_key_create_from_file (keyfile);
304   GNUNET_free (keyfile);
305   if (my_private_key == NULL)
306     {
307       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
308                   _
309                   ("Transport service could not access hostkey.  Exiting.\n"));
310       GNUNET_SCHEDULER_shutdown (s);
311       return;
312     }
313   GNUNET_CRYPTO_rsa_key_get_public (my_private_key, &my_public_key);
314   GNUNET_CRYPTO_hash (&my_public_key,
315                       sizeof (my_public_key), &my_identity.hashPubKey);
316
317   /* load plugins... */
318   setup_plugin_environment ();
319   GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading HTTP transport plugin `%s'\n"),"libgnunet_plugin_transport_http");
320   GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
321   api = GNUNET_PLUGIN_load (libname, &env);
322   GNUNET_free (libname);
323   if (api == NULL)
324   {
325     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
326                 _("Failed to load transport plugin for http\n"));
327     fail = GNUNET_YES;
328     return;
329   }
330
331   ti_timeout = GNUNET_SCHEDULER_add_delayed (sched, TEST_TIMEOUT, &task_timeout, NULL);
332   return;
333 }
334
335
336 /**
337  * The main function for the transport service.
338  *
339  * @param argc number of arguments from the command line
340  * @param argv command line arguments
341  * @return 0 ok, 1 on error
342  */
343 int
344 main (int argc, char *const *argv)
345 {
346
347   static struct GNUNET_GETOPT_CommandLineOption options[] = {
348     GNUNET_GETOPT_OPTION_END
349   };
350   int ret;
351   char *const argv_prog[] = {
352     "test_plugin_transport_http",
353     "-c",
354     "test_plugin_transport_data_http.conf",
355     "-L",
356 #if VERBOSE
357     "DEBUG",
358 #else
359     "WARNING",
360 #endif
361     NULL
362   };
363   GNUNET_log_setup ("test_plugin_transport_http",
364 #if VERBOSE
365                     "DEBUG",
366 #else
367                     "WARNING",
368 #endif
369                     NULL);
370
371   ret = (GNUNET_OK ==
372          GNUNET_PROGRAM_run (5,
373                              argv_prog,
374                              "test_plugin_transport_http",
375                              "testcase", options, &run, NULL)) ? GNUNET_NO : GNUNET_YES;
376
377     GNUNET_DISK_directory_remove ("/tmp/test_plugin_transport_http");
378
379   return fail;
380 }
381
382 /* end of test_plugin_transport_http.c */